From cd3780b7f5b46f03b121dff6172adb445bd748e5 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Tue, 7 Oct 2025 12:04:53 +0000 Subject: [PATCH 1/7] ignore: update download stats 2025-10-07 --- STATS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/STATS.md b/STATS.md index af7357da0..6d1d68a43 100644 --- a/STATS.md +++ b/STATS.md @@ -101,3 +101,4 @@ | 2025-10-04 | 452,561 (+5,732) | 370,386 (+10,449) | 822,947 (+16,181) | | 2025-10-05 | 455,559 (+2,998) | 374,745 (+4,359) | 830,304 (+7,357) | | 2025-10-06 | 460,927 (+5,368) | 379,489 (+4,744) | 840,416 (+10,112) | +| 2025-10-07 | 467,336 (+6,409) | 385,438 (+5,949) | 852,774 (+12,358) | From 6c99b833e443ba1531845a7fcf4f74247a0837bc Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 7 Oct 2025 09:17:05 -0400 Subject: [PATCH 2/7] wip: zen --- .../src/routes/workspace/member-section.tsx | 83 +- .../console/app/src/routes/zen/handler.ts | 49 +- .../migrations/0029_panoramic_harrier.sql | 3 + .../core/migrations/meta/0029_snapshot.json | 730 ++++++++++++++++++ .../core/migrations/meta/_journal.json | 7 + packages/console/core/src/billing.ts | 2 +- packages/console/core/src/schema/user.sql.ts | 5 +- packages/console/core/src/user.ts | 7 +- 8 files changed, 865 insertions(+), 21 deletions(-) create mode 100644 packages/console/core/migrations/0029_panoramic_harrier.sql create mode 100644 packages/console/core/migrations/meta/0029_snapshot.json diff --git a/packages/console/app/src/routes/workspace/member-section.tsx b/packages/console/app/src/routes/workspace/member-section.tsx index 9fc57621c..ddaac7348 100644 --- a/packages/console/app/src/routes/workspace/member-section.tsx +++ b/packages/console/app/src/routes/workspace/member-section.tsx @@ -56,25 +56,36 @@ const removeMember = action(async (form: FormData) => { ) }, "member.remove") -const updateMemberRole = action(async (form: FormData) => { +const updateMember = action(async (form: FormData) => { "use server" + console.log("!@#!@ Form data entries:") + for (const [key, value] of form.entries()) { + console.log(`!@#!@ ${key}:`, value) + } + const id = form.get("id")?.toString() if (!id) return { error: "ID is required" } const workspaceID = form.get("workspaceID")?.toString() if (!workspaceID) return { error: "Workspace ID is required" } const role = form.get("role")?.toString() as (typeof UserRole)[number] if (!role) return { error: "Role is required" } + const limit = form.get("limit")?.toString() + const monthlyLimit = limit && limit.trim() !== "" ? parseInt(limit) : null + if (monthlyLimit !== null && monthlyLimit < 0) return { error: "Set a valid monthly limit" } + + console.log({ id, role, monthlyLimit, limit }) + return json( await withActor( () => - User.updateRole({ id, role }) + User.update({ id, role, monthlyLimit }) .then((data) => ({ error: undefined, data })) .catch((e) => ({ error: e.message as string })), workspaceID, ), { revalidate: listMembers.key }, ) -}, "member.updateRole") +}, "member.update") export function MemberCreateForm() { const params = useParams() @@ -155,7 +166,7 @@ export function MemberCreateForm() { function MemberRow(props: { member: any; workspaceID: string; currentUserID: string | null }) { const [editing, setEditing] = createSignal(false) - const submission = useSubmission(updateMemberRole) + const submission = useSubmission(updateMember) const isCurrentUser = () => props.currentUserID === props.member.id createEffect(() => { @@ -164,6 +175,29 @@ function MemberRow(props: { member: any; workspaceID: string; currentUserID: str } }) + function getUsageDisplay() { + const currentUsage = (() => { + const dateLastUsed = props.member.timeMonthlyUsageUpdated + if (!dateLastUsed) return 0 + + const current = new Date().toLocaleDateString("en-US", { + year: "numeric", + month: "long", + timeZone: "UTC", + }) + const lastUsed = dateLastUsed.toLocaleDateString("en-US", { + year: "numeric", + month: "long", + timeZone: "UTC", + }) + if (current !== lastUsed) return 0 + return ((props.member.monthlyUsage ?? 0) / 100000000).toFixed(2) + })() + + const limit = props.member.monthlyLimit ? `$${props.member.monthlyLimit}` : "no limit" + return `$${currentUsage} / ${limit}` + } + return ( {props.member.accountEmail ?? props.member.email} {props.member.role} + {getUsageDisplay()} }> invited @@ -190,12 +225,21 @@ function MemberRow(props: { member: any; workspaceID: string; currentUserID: str } > - -
+ +
{props.member.accountEmail ?? props.member.email}
- Role: {props.member.role}}> + + +
Role: {props.member.role}
+ + + } + >
+ +
+ +
+ {(err) =>
{err()}
}
+
- - - +
@@ -258,6 +316,7 @@ export function MemberSection() { Email Role + Usage diff --git a/packages/console/app/src/routes/zen/handler.ts b/packages/console/app/src/routes/zen/handler.ts index 9d08ccdf9..feb0c9c3e 100644 --- a/packages/console/app/src/routes/zen/handler.ts +++ b/packages/console/app/src/routes/zen/handler.ts @@ -11,6 +11,7 @@ import { Billing } from "../../../../core/src/billing" import { Actor } from "@opencode-ai/console-core/actor.js" import { WorkspaceTable } from "@opencode-ai/console-core/schema/workspace.sql.js" import { ZenModel } from "@opencode-ai/console-core/model.js" +import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js" export async function handler( input: APIEvent, @@ -33,6 +34,7 @@ export async function handler( class AuthError extends Error {} class CreditsError extends Error {} class MonthlyLimitError extends Error {} + class UserLimitError extends Error {} class ModelError extends Error {} type Model = z.infer @@ -181,6 +183,7 @@ export async function handler( error instanceof AuthError || error instanceof CreditsError || error instanceof MonthlyLimitError || + error instanceof UserLimitError || error instanceof ModelError ) return new Response( @@ -243,10 +246,15 @@ export async function handler( monthlyLimit: BillingTable.monthlyLimit, monthlyUsage: BillingTable.monthlyUsage, timeMonthlyUsageUpdated: BillingTable.timeMonthlyUsageUpdated, + userID: UserTable.id, + userMonthlyLimit: UserTable.monthlyLimit, + userMonthlyUsage: UserTable.monthlyUsage, + timeUserMonthlyUsageUpdated: UserTable.timeMonthlyUsageUpdated, }) .from(KeyTable) .innerJoin(WorkspaceTable, eq(WorkspaceTable.id, KeyTable.workspaceID)) .innerJoin(BillingTable, eq(BillingTable.workspaceID, KeyTable.workspaceID)) + .innerJoin(UserTable, and(eq(UserTable.workspaceID, KeyTable.workspaceID), eq(UserTable.id, KeyTable.userID))) .where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted))) .then((rows) => rows[0]), ) @@ -269,6 +277,12 @@ export async function handler( monthlyUsage: data.monthlyUsage, timeMonthlyUsageUpdated: data.timeMonthlyUsageUpdated, }, + user: { + id: data.userID, + monthlyLimit: data.userMonthlyLimit, + monthlyUsage: data.userMonthlyUsage, + timeMonthlyUsageUpdated: data.timeUserMonthlyUsageUpdated, + }, isFree, } } @@ -280,19 +294,34 @@ export async function handler( const billing = authInfo.billing if (!billing.paymentMethodID) throw new CreditsError("No payment method") if (billing.balance <= 0) throw new CreditsError("Insufficient balance") + + const now = new Date() + const currentYear = now.getUTCFullYear() + const currentMonth = now.getUTCMonth() if ( billing.monthlyLimit && billing.monthlyUsage && billing.timeMonthlyUsageUpdated && billing.monthlyUsage >= centsToMicroCents(billing.monthlyLimit * 100) ) { - const now = new Date() - const currentYear = now.getUTCFullYear() - const currentMonth = now.getUTCMonth() const dateYear = billing.timeMonthlyUsageUpdated.getUTCFullYear() const dateMonth = billing.timeMonthlyUsageUpdated.getUTCMonth() if (currentYear === dateYear && currentMonth === dateMonth) - throw new MonthlyLimitError(`You have reached your monthly spending limit of $${billing.monthlyLimit}.`) + throw new MonthlyLimitError( + `Your workspace has reached its monthly spending limit of $${billing.monthlyLimit}.`, + ) + } + + if ( + authInfo.user.monthlyLimit && + authInfo.user.monthlyUsage && + authInfo.user.timeMonthlyUsageUpdated && + authInfo.user.monthlyUsage >= centsToMicroCents(authInfo.user.monthlyLimit * 100) + ) { + const dateYear = authInfo.user.timeMonthlyUsageUpdated.getUTCFullYear() + const dateMonth = authInfo.user.timeMonthlyUsageUpdated.getUTCMonth() + if (currentYear === dateYear && currentMonth === dateMonth) + throw new UserLimitError(`You have reached your monthly spending limit of $${authInfo.user.monthlyLimit}.`) } } @@ -386,6 +415,18 @@ export async function handler( timeMonthlyUsageUpdated: sql`now()`, }) .where(eq(BillingTable.workspaceID, authInfo.workspaceID)) + await tx + .update(UserTable) + .set({ + monthlyUsage: sql` + CASE + WHEN MONTH(${UserTable.timeMonthlyUsageUpdated}) = MONTH(now()) AND YEAR(${UserTable.timeMonthlyUsageUpdated}) = YEAR(now()) THEN ${UserTable.monthlyUsage} + ${cost} + ELSE ${cost} + END + `, + timeMonthlyUsageUpdated: sql`now()`, + }) + .where(and(eq(UserTable.workspaceID, authInfo.workspaceID), eq(UserTable.id, authInfo.user.id))) }) await Database.use((tx) => diff --git a/packages/console/core/migrations/0029_panoramic_harrier.sql b/packages/console/core/migrations/0029_panoramic_harrier.sql new file mode 100644 index 000000000..5a7bbc3be --- /dev/null +++ b/packages/console/core/migrations/0029_panoramic_harrier.sql @@ -0,0 +1,3 @@ +ALTER TABLE `user` ADD `monthly_limit` int;--> statement-breakpoint +ALTER TABLE `user` ADD `monthly_usage` bigint;--> statement-breakpoint +ALTER TABLE `user` ADD `time_monthly_usage_updated` timestamp(3); \ No newline at end of file diff --git a/packages/console/core/migrations/meta/0029_snapshot.json b/packages/console/core/migrations/meta/0029_snapshot.json new file mode 100644 index 000000000..959004f33 --- /dev/null +++ b/packages/console/core/migrations/meta/0029_snapshot.json @@ -0,0 +1,730 @@ +{ + "version": "5", + "dialect": "mysql", + "id": "33551b4c-fc2e-4753-8d9d-0971f333e65d", + "prevId": "a331e38c-c2e3-406d-a1ff-b0af7229cd85", + "tables": { + "account": { + "name": "account", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "email": { + "name": "email", + "columns": [ + "email" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "billing": { + "name": "billing", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "customer_id": { + "name": "customer_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "payment_method_id": { + "name": "payment_method_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "payment_method_last4": { + "name": "payment_method_last4", + "type": "varchar(4)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "balance": { + "name": "balance", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "monthly_limit": { + "name": "monthly_limit", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "monthly_usage": { + "name": "monthly_usage", + "type": "bigint", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "time_monthly_usage_updated": { + "name": "time_monthly_usage_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "reload": { + "name": "reload", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "reload_error": { + "name": "reload_error", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "time_reload_error": { + "name": "time_reload_error", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "time_reload_locked_till": { + "name": "time_reload_locked_till", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "global_customer_id": { + "name": "global_customer_id", + "columns": [ + "customer_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "billing_workspace_id_id_pk": { + "name": "billing_workspace_id_id_pk", + "columns": [ + "workspace_id", + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "payment": { + "name": "payment", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "customer_id": { + "name": "customer_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "invoice_id": { + "name": "invoice_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "payment_id": { + "name": "payment_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "amount": { + "name": "amount", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_refunded": { + "name": "time_refunded", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "payment_workspace_id_id_pk": { + "name": "payment_workspace_id_id_pk", + "columns": [ + "workspace_id", + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "usage": { + "name": "usage", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "model": { + "name": "model", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider": { + "name": "provider", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "input_tokens": { + "name": "input_tokens", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "output_tokens": { + "name": "output_tokens", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reasoning_tokens": { + "name": "reasoning_tokens", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cache_read_tokens": { + "name": "cache_read_tokens", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cache_write_5m_tokens": { + "name": "cache_write_5m_tokens", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cache_write_1h_tokens": { + "name": "cache_write_1h_tokens", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cost": { + "name": "cost", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "usage_workspace_id_id_pk": { + "name": "usage_workspace_id_id_pk", + "columns": [ + "workspace_id", + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "key": { + "name": "key", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_used": { + "name": "time_used", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "global_key": { + "name": "global_key", + "columns": [ + "key" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "key_workspace_id_id_pk": { + "name": "key_workspace_id_id_pk", + "columns": [ + "workspace_id", + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "user": { + "name": "user", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_seen": { + "name": "time_seen", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "color": { + "name": "color", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "enum('admin','member')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "monthly_limit": { + "name": "monthly_limit", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "monthly_usage": { + "name": "monthly_usage", + "type": "bigint", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "time_monthly_usage_updated": { + "name": "time_monthly_usage_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "user_account_id": { + "name": "user_account_id", + "columns": [ + "workspace_id", + "account_id" + ], + "isUnique": true + }, + "user_email": { + "name": "user_email", + "columns": [ + "workspace_id", + "email" + ], + "isUnique": true + }, + "global_account_id": { + "name": "global_account_id", + "columns": [ + "account_id" + ], + "isUnique": false + }, + "global_email": { + "name": "global_email", + "columns": [ + "email" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "user_workspace_id_id_pk": { + "name": "user_workspace_id_id_pk", + "columns": [ + "workspace_id", + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "workspace": { + "name": "workspace", + "columns": { + "id": { + "name": "id", + "type": "varchar(30)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "time_created": { + "name": "time_created", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "time_updated": { + "name": "time_updated", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "time_deleted": { + "name": "time_deleted", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "slug": { + "name": "slug", + "columns": [ + "slug" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "workspace_id": { + "name": "workspace_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + } + }, + "views": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "tables": {}, + "indexes": {} + } +} \ No newline at end of file diff --git a/packages/console/core/migrations/meta/_journal.json b/packages/console/core/migrations/meta/_journal.json index eaa28ddf6..221718250 100644 --- a/packages/console/core/migrations/meta/_journal.json +++ b/packages/console/core/migrations/meta/_journal.json @@ -204,6 +204,13 @@ "when": 1759805025276, "tag": "0028_careful_cerise", "breakpoints": true + }, + { + "idx": 29, + "version": "5", + "when": 1759811835558, + "tag": "0029_panoramic_harrier", + "breakpoints": true } ] } \ No newline at end of file diff --git a/packages/console/core/src/billing.ts b/packages/console/core/src/billing.ts index 644e3bd83..0b77e4c30 100644 --- a/packages/console/core/src/billing.ts +++ b/packages/console/core/src/billing.ts @@ -1,5 +1,5 @@ import { Stripe } from "stripe" -import { and, Database, eq, sql } from "./drizzle" +import { Database, eq, sql } from "./drizzle" import { BillingTable, PaymentTable, UsageTable } from "./schema/billing.sql" import { Actor } from "./actor" import { fn } from "./util/fn" diff --git a/packages/console/core/src/schema/user.sql.ts b/packages/console/core/src/schema/user.sql.ts index 121199f72..7fd7f5e1e 100644 --- a/packages/console/core/src/schema/user.sql.ts +++ b/packages/console/core/src/schema/user.sql.ts @@ -1,4 +1,4 @@ -import { mysqlTable, uniqueIndex, varchar, int, mysqlEnum, index } from "drizzle-orm/mysql-core" +import { mysqlTable, uniqueIndex, varchar, int, mysqlEnum, index, bigint } from "drizzle-orm/mysql-core" import { timestamps, ulid, utc, workspaceColumns } from "../drizzle/types" import { workspaceIndexes } from "./workspace.sql" @@ -15,6 +15,9 @@ export const UserTable = mysqlTable( timeSeen: utc("time_seen"), color: int("color"), role: mysqlEnum("role", UserRole).notNull(), + monthlyLimit: int("monthly_limit"), + monthlyUsage: bigint("monthly_usage", { mode: "number" }), + timeMonthlyUsageUpdated: utc("time_monthly_usage_updated"), }, (table) => [ ...workspaceIndexes(table), diff --git a/packages/console/core/src/user.ts b/packages/console/core/src/user.ts index d4a0da0f8..5e7605e94 100644 --- a/packages/console/core/src/user.ts +++ b/packages/console/core/src/user.ts @@ -174,18 +174,19 @@ export namespace User { ) }) - export const updateRole = fn( + export const update = fn( z.object({ id: z.string(), role: z.enum(UserRole), + monthlyLimit: z.number().nullable(), }), - async ({ id, role }) => { + async ({ id, role, monthlyLimit }) => { await assertAdmin() if (role === "member") assertNotSelf(id) return await Database.use((tx) => tx .update(UserTable) - .set({ role }) + .set({ role, monthlyLimit }) .where(and(eq(UserTable.id, id), eq(UserTable.workspaceID, Actor.workspace()))), ) }, From 1f725cc3ed8418912a157fb14146fd79cc3066ad Mon Sep 17 00:00:00 2001 From: Sai <74868837+sai-sy@users.noreply.github.com> Date: Tue, 7 Oct 2025 11:08:52 -0400 Subject: [PATCH 3/7] docs: add agent specific permission example (#3009) --- packages/web/src/content/docs/permissions.mdx | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/web/src/content/docs/permissions.mdx b/packages/web/src/content/docs/permissions.mdx index 44dbc92ef..68ae8b087 100644 --- a/packages/web/src/content/docs/permissions.mdx +++ b/packages/web/src/content/docs/permissions.mdx @@ -111,5 +111,23 @@ For example. } } ``` - This configuration allows all commands by default (`"*": "allow"`) but requires approval for `git push` commands. + +### Agents + +Configure agent specific permissions + +```json +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "plan": { + "permission": { + "bash": { + "echo *": "allow" + } + } + } + } +} +``` From b6c9df970a8c207089efe09292857ec1b7138d7a Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Tue, 7 Oct 2025 11:50:37 -0500 Subject: [PATCH 4/7] docs: troubleshooting ProviderModelNotFoundError (#3016) --- packages/web/src/content/docs/troubleshooting.mdx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/web/src/content/docs/troubleshooting.mdx b/packages/web/src/content/docs/troubleshooting.mdx index 98615823a..fb8e964ba 100644 --- a/packages/web/src/content/docs/troubleshooting.mdx +++ b/packages/web/src/content/docs/troubleshooting.mdx @@ -86,6 +86,18 @@ Here are some common issues and how to resolve them. 2. Verify the model name in your config is correct 3. Some models may require specific access or subscriptions +If you encounter `ProviderModelNotFoundError` you are most likely incorrectly +referencing a model somewhere. +Models should be referenced like so: `/` + + +Examples: +- `openai/gpt-4.1` +- `openrouter/google/gemini-2.5-flash` +- `opencode/kimi-k2` + +To figure out what models you have access to, run `opencode models` + --- ### ProviderInitError From 508067ba5da9afa82bff401dd8478be2145d61a4 Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 7 Oct 2025 13:37:36 -0400 Subject: [PATCH 5/7] wip: zen --- .../console/app/src/routes/workspace/member-section.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/console/app/src/routes/workspace/member-section.tsx b/packages/console/app/src/routes/workspace/member-section.tsx index ddaac7348..6774bb48e 100644 --- a/packages/console/app/src/routes/workspace/member-section.tsx +++ b/packages/console/app/src/routes/workspace/member-section.tsx @@ -58,10 +58,6 @@ const removeMember = action(async (form: FormData) => { const updateMember = action(async (form: FormData) => { "use server" - console.log("!@#!@ Form data entries:") - for (const [key, value] of form.entries()) { - console.log(`!@#!@ ${key}:`, value) - } const id = form.get("id")?.toString() if (!id) return { error: "ID is required" } @@ -73,8 +69,6 @@ const updateMember = action(async (form: FormData) => { const monthlyLimit = limit && limit.trim() !== "" ? parseInt(limit) : null if (monthlyLimit !== null && monthlyLimit < 0) return { error: "Set a valid monthly limit" } - console.log({ id, role, monthlyLimit, limit }) - return json( await withActor( () => From dca3a5d80d9d22400b48c217098a632d72bf2122 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Tue, 7 Oct 2025 15:51:59 -0400 Subject: [PATCH 6/7] fix issue with blank new version popup --- packages/sdk/go/.github/workflows/ci.yml | 14 +- packages/sdk/go/.release-please-manifest.json | 4 +- packages/sdk/go/.stats.yml | 4 +- packages/sdk/go/CHANGELOG.md | 161 ++++++---- packages/sdk/go/CONTRIBUTING.md | 2 +- packages/sdk/go/README.md | 4 +- packages/sdk/go/agent.go | 3 +- packages/sdk/go/app.go | 5 +- packages/sdk/go/client.go | 3 +- packages/sdk/go/command.go | 3 +- packages/sdk/go/config.go | 3 +- packages/sdk/go/event.go | 282 ++++++++++++------ packages/sdk/go/file.go | 7 +- packages/sdk/go/find.go | 7 +- packages/sdk/go/go.mod | 2 +- packages/sdk/go/internal/apijson/decoder.go | 2 +- packages/sdk/go/internal/apijson/encoder.go | 14 +- packages/sdk/go/internal/apijson/json_test.go | 2 +- packages/sdk/go/internal/version.go | 2 +- packages/sdk/go/path.go | 3 +- packages/sdk/go/project.go | 5 +- packages/sdk/go/release-please-config.json | 7 +- packages/sdk/go/scripts/bootstrap | 14 +- packages/sdk/go/session.go | 75 ++--- packages/sdk/go/session_test.go | 21 +- packages/sdk/go/sessionpermission.go | 3 +- packages/sdk/go/tui.go | 19 +- 27 files changed, 417 insertions(+), 254 deletions(-) diff --git a/packages/sdk/go/.github/workflows/ci.yml b/packages/sdk/go/.github/workflows/ci.yml index 0f5d45dc2..4bf1e907c 100644 --- a/packages/sdk/go/.github/workflows/ci.yml +++ b/packages/sdk/go/.github/workflows/ci.yml @@ -2,15 +2,15 @@ name: CI on: push: branches-ignore: - - "generated" - - "codegen/**" - - "integrated/**" - - "stl-preview-head/**" - - "stl-preview-base/**" + - 'generated' + - 'codegen/**' + - 'integrated/**' + - 'stl-preview-head/**' + - 'stl-preview-base/**' pull_request: branches-ignore: - - "stl-preview-head/**" - - "stl-preview-base/**" + - 'stl-preview-head/**' + - 'stl-preview-base/**' jobs: lint: diff --git a/packages/sdk/go/.release-please-manifest.json b/packages/sdk/go/.release-please-manifest.json index f87262aa8..6f2b40185 100644 --- a/packages/sdk/go/.release-please-manifest.json +++ b/packages/sdk/go/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.15.0" -} + ".": "0.16.2" +} \ No newline at end of file diff --git a/packages/sdk/go/.stats.yml b/packages/sdk/go/.stats.yml index f4ae16705..911073ed4 100644 --- a/packages/sdk/go/.stats.yml +++ b/packages/sdk/go/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 43 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-ad911ed0bdbeca62807509f364f25fcafd7a83e0b43e027ec0a85f72b7a4d963.yml -openapi_spec_hash: 15152513b4246bf4b5f8546fa6f1603f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-273fc9fea965af661dfed0902d00f10d6ed844f0681ca861a58821c4902eac2f.yml +openapi_spec_hash: c6144f23a1bac75f79be86edd405552b config_hash: 026ef000d34bf2f930e7b41e77d2d3ff diff --git a/packages/sdk/go/CHANGELOG.md b/packages/sdk/go/CHANGELOG.md index f82dffa42..27affc4f0 100644 --- a/packages/sdk/go/CHANGELOG.md +++ b/packages/sdk/go/CHANGELOG.md @@ -1,12 +1,43 @@ # Changelog +## 0.16.2 (2025-09-26) + +Full Changelog: [v0.16.1...v0.16.2](https://github.com/sst/opencode-sdk-go/compare/v0.16.1...v0.16.2) + +### Bug Fixes + +* bugfix for setting JSON keys with special characters ([ac9a36f](https://github.com/sst/opencode-sdk-go/commit/ac9a36feb1c185ebf766d76909d0b86ac805e8a6)) + +## 0.16.1 (2025-09-20) + +Full Changelog: [v0.16.0...v0.16.1](https://github.com/sst/opencode-sdk-go/compare/v0.16.0...v0.16.1) + +### Bug Fixes + +* use slices.Concat instead of sometimes modifying r.Options ([12e8b40](https://github.com/sst/opencode-sdk-go/commit/12e8b40809071095b0abb9b8031686353c8ac149)) + + +### Chores + +* bump minimum go version to 1.22 ([1a61c5c](https://github.com/sst/opencode-sdk-go/commit/1a61c5cc7e8f68cc1b0c219738cab530cb6aa3a2)) +* do not install brew dependencies in ./scripts/bootstrap by default ([f6d3eaf](https://github.com/sst/opencode-sdk-go/commit/f6d3eafffc20e124bbfae6ac5ddc1b1122ad3e27)) +* update more docs for 1.22 ([a3d0b0f](https://github.com/sst/opencode-sdk-go/commit/a3d0b0f26ed92ce1a6433f5bcf37a6436d268ba5)) + +## 0.16.0 (2025-09-17) + +Full Changelog: [v0.15.0...v0.16.0](https://github.com/sst/opencode-sdk-go/compare/v0.15.0...v0.16.0) + +### Features + +* **api:** api update ([46e978e](https://github.com/sst/opencode-sdk-go/commit/46e978e43aee733d5c1c09dc5be6d8ac2a752427)) + ## 0.15.0 (2025-09-16) Full Changelog: [v0.14.0...v0.15.0](https://github.com/sst/opencode-sdk-go/compare/v0.14.0...v0.15.0) ### Features -- **api:** api update ([397048f](https://github.com/sst/opencode-sdk-go/commit/397048faca7a1de7a028edd2254a0ad7797b151f)) +* **api:** api update ([397048f](https://github.com/sst/opencode-sdk-go/commit/397048faca7a1de7a028edd2254a0ad7797b151f)) ## 0.14.0 (2025-09-14) @@ -14,7 +45,7 @@ Full Changelog: [v0.13.0...v0.14.0](https://github.com/sst/opencode-sdk-go/compa ### Features -- **api:** api update ([dad0bc3](https://github.com/sst/opencode-sdk-go/commit/dad0bc3da99f20a0d002a6b94e049fb70f8e6a77)) +* **api:** api update ([dad0bc3](https://github.com/sst/opencode-sdk-go/commit/dad0bc3da99f20a0d002a6b94e049fb70f8e6a77)) ## 0.13.0 (2025-09-14) @@ -22,7 +53,7 @@ Full Changelog: [v0.12.0...v0.13.0](https://github.com/sst/opencode-sdk-go/compa ### Features -- **api:** api update ([80da4fb](https://github.com/sst/opencode-sdk-go/commit/80da4fb4ea9c6afb51a7e7135d9f5560ce6f2a6c)) +* **api:** api update ([80da4fb](https://github.com/sst/opencode-sdk-go/commit/80da4fb4ea9c6afb51a7e7135d9f5560ce6f2a6c)) ## 0.12.0 (2025-09-14) @@ -30,7 +61,7 @@ Full Changelog: [v0.11.0...v0.12.0](https://github.com/sst/opencode-sdk-go/compa ### Features -- **api:** api update ([7e3808b](https://github.com/sst/opencode-sdk-go/commit/7e3808ba349dc653174b32b48a1120c18d2975c2)) +* **api:** api update ([7e3808b](https://github.com/sst/opencode-sdk-go/commit/7e3808ba349dc653174b32b48a1120c18d2975c2)) ## 0.11.0 (2025-09-14) @@ -38,7 +69,7 @@ Full Changelog: [v0.10.0...v0.11.0](https://github.com/sst/opencode-sdk-go/compa ### Features -- **api:** api update ([a3d37f5](https://github.com/sst/opencode-sdk-go/commit/a3d37f5671545866547d351fc21b49809cc8b3c2)) +* **api:** api update ([a3d37f5](https://github.com/sst/opencode-sdk-go/commit/a3d37f5671545866547d351fc21b49809cc8b3c2)) ## 0.10.0 (2025-09-11) @@ -46,7 +77,7 @@ Full Changelog: [v0.9.0...v0.10.0](https://github.com/sst/opencode-sdk-go/compar ### Features -- **api:** api update ([0dc01f6](https://github.com/sst/opencode-sdk-go/commit/0dc01f6695c9b8400a4dc92166c5002bb120cf50)) +* **api:** api update ([0dc01f6](https://github.com/sst/opencode-sdk-go/commit/0dc01f6695c9b8400a4dc92166c5002bb120cf50)) ## 0.9.0 (2025-09-10) @@ -54,7 +85,7 @@ Full Changelog: [v0.8.0...v0.9.0](https://github.com/sst/opencode-sdk-go/compare ### Features -- **api:** api update ([2d3a28d](https://github.com/sst/opencode-sdk-go/commit/2d3a28df5657845aa4d73087e1737d1fc8c3ce1c)) +* **api:** api update ([2d3a28d](https://github.com/sst/opencode-sdk-go/commit/2d3a28df5657845aa4d73087e1737d1fc8c3ce1c)) ## 0.8.0 (2025-09-01) @@ -62,7 +93,7 @@ Full Changelog: [v0.7.0...v0.8.0](https://github.com/sst/opencode-sdk-go/compare ### Features -- **api:** api update ([ae87a71](https://github.com/sst/opencode-sdk-go/commit/ae87a71949994590ace8285a39f0991ef34b664d)) +* **api:** api update ([ae87a71](https://github.com/sst/opencode-sdk-go/commit/ae87a71949994590ace8285a39f0991ef34b664d)) ## 0.7.0 (2025-09-01) @@ -70,7 +101,7 @@ Full Changelog: [v0.6.0...v0.7.0](https://github.com/sst/opencode-sdk-go/compare ### Features -- **api:** api update ([64bb1b1](https://github.com/sst/opencode-sdk-go/commit/64bb1b1ee0cbe153abc6fb7bd9703b47911724d4)) +* **api:** api update ([64bb1b1](https://github.com/sst/opencode-sdk-go/commit/64bb1b1ee0cbe153abc6fb7bd9703b47911724d4)) ## 0.6.0 (2025-09-01) @@ -78,7 +109,7 @@ Full Changelog: [v0.5.0...v0.6.0](https://github.com/sst/opencode-sdk-go/compare ### Features -- **api:** api update ([928e384](https://github.com/sst/opencode-sdk-go/commit/928e3843355f96899f046f002b84372281dad0c8)) +* **api:** api update ([928e384](https://github.com/sst/opencode-sdk-go/commit/928e3843355f96899f046f002b84372281dad0c8)) ## 0.5.0 (2025-08-31) @@ -86,7 +117,7 @@ Full Changelog: [v0.4.0...v0.5.0](https://github.com/sst/opencode-sdk-go/compare ### Features -- **api:** api update ([44b281d](https://github.com/sst/opencode-sdk-go/commit/44b281d0bb39c5022a984ac9d0fca1529ccc0604)) +* **api:** api update ([44b281d](https://github.com/sst/opencode-sdk-go/commit/44b281d0bb39c5022a984ac9d0fca1529ccc0604)) ## 0.4.0 (2025-08-31) @@ -94,7 +125,7 @@ Full Changelog: [v0.3.0...v0.4.0](https://github.com/sst/opencode-sdk-go/compare ### Features -- **api:** api update ([fa9d6ec](https://github.com/sst/opencode-sdk-go/commit/fa9d6ec6472e62f4f6605d0a71a7aa8bf8a24559)) +* **api:** api update ([fa9d6ec](https://github.com/sst/opencode-sdk-go/commit/fa9d6ec6472e62f4f6605d0a71a7aa8bf8a24559)) ## 0.3.0 (2025-08-31) @@ -102,7 +133,7 @@ Full Changelog: [v0.2.0...v0.3.0](https://github.com/sst/opencode-sdk-go/compare ### Features -- **api:** api update ([aae1c06](https://github.com/sst/opencode-sdk-go/commit/aae1c06bb5a93a1cd9c589846a84b3f16246f5da)) +* **api:** api update ([aae1c06](https://github.com/sst/opencode-sdk-go/commit/aae1c06bb5a93a1cd9c589846a84b3f16246f5da)) ## 0.2.0 (2025-08-31) @@ -110,7 +141,7 @@ Full Changelog: [v0.1.0...v0.2.0](https://github.com/sst/opencode-sdk-go/compare ### Features -- **api:** api update ([1472790](https://github.com/sst/opencode-sdk-go/commit/1472790542515f47bd46e2a9e28d8afea024cf9c)) +* **api:** api update ([1472790](https://github.com/sst/opencode-sdk-go/commit/1472790542515f47bd46e2a9e28d8afea024cf9c)) ## 0.1.0 (2025-08-31) @@ -118,59 +149,61 @@ Full Changelog: [v0.0.1...v0.1.0](https://github.com/sst/opencode-sdk-go/compare ### Features -- **api:** api update ([3f03ddd](https://github.com/sst/opencode-sdk-go/commit/3f03dddd5ec0de98f99ce48679077dcae9ceffd6)) -- **api:** api update ([e9f79c4](https://github.com/sst/opencode-sdk-go/commit/e9f79c4792b21ef64ab0431ffd76f5a71e04d182)) -- **api:** api update ([139a686](https://github.com/sst/opencode-sdk-go/commit/139a6862d2f0ab0c8ea791663d736868be3e96e6)) -- **api:** api update ([2ed0800](https://github.com/sst/opencode-sdk-go/commit/2ed0800b2c5b99877e9f7fde669a6c005fad6b77)) -- **api:** api update ([88a87a4](https://github.com/sst/opencode-sdk-go/commit/88a87a458f56ce0c18b502c73da933f614f56e8b)) -- **api:** api update ([0e5d65b](https://github.com/sst/opencode-sdk-go/commit/0e5d65b571e7b30dc6347e6730098878ebba3a42)) -- **api:** api update ([ba381f1](https://github.com/sst/opencode-sdk-go/commit/ba381f1e07aad24e9824df7d53befae2a644f69f)) -- **api:** api update ([3f429f5](https://github.com/sst/opencode-sdk-go/commit/3f429f5b4be5607433ef5fdc0d5bf67fe590d039)) -- **api:** api update ([9f34787](https://github.com/sst/opencode-sdk-go/commit/9f347876b35b7f898060c1a5f71c322e95978e3e)) -- **api:** api update ([379c8e0](https://github.com/sst/opencode-sdk-go/commit/379c8e00197e13aebaf2f2d61277b125f1f90011)) -- **api:** api update ([550511c](https://github.com/sst/opencode-sdk-go/commit/550511c4c5b5055ac8ff22b7b11731331bd9d088)) -- **api:** api update ([547f0c2](https://github.com/sst/opencode-sdk-go/commit/547f0c262f2df1ce83eaa7267d68be64bb29b841)) -- **api:** api update ([b7b0720](https://github.com/sst/opencode-sdk-go/commit/b7b07204bff314da24b1819c128835a43ef64065)) -- **api:** api update ([7250ffc](https://github.com/sst/opencode-sdk-go/commit/7250ffcba262b916c958ddecc2a42927982db39f)) -- **api:** api update ([17fbab7](https://github.com/sst/opencode-sdk-go/commit/17fbab73111a3eae488737c69b12370bc69c65f7)) -- **api:** api update ([1270b5c](https://github.com/sst/opencode-sdk-go/commit/1270b5cd81e6ac769dcd92ade6d877891bf51bd5)) -- **api:** api update ([a238d4a](https://github.com/sst/opencode-sdk-go/commit/a238d4abd6ed7d15f3547d27a4b6ecf4aec8431e)) -- **api:** api update ([7475655](https://github.com/sst/opencode-sdk-go/commit/7475655aca577fe4f807c2f02f92171f6a358e9c)) -- **api:** api update ([429d258](https://github.com/sst/opencode-sdk-go/commit/429d258bb56e9cdeb1528be3944bf5537ac26a96)) -- **api:** api update ([f250915](https://github.com/sst/opencode-sdk-go/commit/f2509157eaf1b453e741ee9482127cad2e3ace25)) -- **api:** api update ([5efc987](https://github.com/sst/opencode-sdk-go/commit/5efc987353801d1e772c20edf162b1c75da32743)) -- **api:** api update ([98a8350](https://github.com/sst/opencode-sdk-go/commit/98a83504f7cfc361e83314c3e79a4e9ff53f0560)) -- **api:** api update ([6da8bf8](https://github.com/sst/opencode-sdk-go/commit/6da8bf8bfe91d45991fb580753d77c5534fc0b1b)) -- **api:** api update ([f8c7148](https://github.com/sst/opencode-sdk-go/commit/f8c7148ae56143823186e2675a78e82676154956)) -- **api:** manual updates ([7cf038f](https://github.com/sst/opencode-sdk-go/commit/7cf038ffae5da1b77e1cef11b5fa166a53b467f2)) -- **api:** update via SDK Studio ([068a0eb](https://github.com/sst/opencode-sdk-go/commit/068a0eb025010da0c8d86fa1bb496a39dbedcef9)) -- **api:** update via SDK Studio ([ca651ed](https://github.com/sst/opencode-sdk-go/commit/ca651edaf71d1f3678f929287474f5bc4f1aad10)) -- **api:** update via SDK Studio ([13550a5](https://github.com/sst/opencode-sdk-go/commit/13550a5c65d77325e945ed99fe0799cd1107b775)) -- **api:** update via SDK Studio ([7b73730](https://github.com/sst/opencode-sdk-go/commit/7b73730c7fa62ba966dda3541c3e97b49be8d2bf)) -- **api:** update via SDK Studio ([9e39a59](https://github.com/sst/opencode-sdk-go/commit/9e39a59b3d5d1bd5e64633732521fb28362cc70e)) -- **api:** update via SDK Studio ([9609d1b](https://github.com/sst/opencode-sdk-go/commit/9609d1b1db7806d00cb846c9914cb4935cdedf52)) -- **api:** update via SDK Studio ([51315fa](https://github.com/sst/opencode-sdk-go/commit/51315fa2eae424743ea79701e67d44447c44144d)) -- **api:** update via SDK Studio ([af07955](https://github.com/sst/opencode-sdk-go/commit/af0795543240aefaf04fc7663a348825541c79ed)) -- **api:** update via SDK Studio ([5e3468a](https://github.com/sst/opencode-sdk-go/commit/5e3468a0aaa5ed3b13e019c3a24e0ba9147d1675)) -- **api:** update via SDK Studio ([0a73e04](https://github.com/sst/opencode-sdk-go/commit/0a73e04c23c90b2061611edaa8fd6282dc0ce397)) -- **api:** update via SDK Studio ([9b7883a](https://github.com/sst/opencode-sdk-go/commit/9b7883a144eeac526d9d04538e0876a9d18bb844)) -- **client:** expand max streaming buffer size ([76303e5](https://github.com/sst/opencode-sdk-go/commit/76303e51067e78e732af26ced9d83b8bad7655c3)) -- **client:** support optional json html escaping ([449748f](https://github.com/sst/opencode-sdk-go/commit/449748f35a1d8cb6f91dc36d25bf9489f4f371bd)) +* **api:** api update ([3f03ddd](https://github.com/sst/opencode-sdk-go/commit/3f03dddd5ec0de98f99ce48679077dcae9ceffd6)) +* **api:** api update ([e9f79c4](https://github.com/sst/opencode-sdk-go/commit/e9f79c4792b21ef64ab0431ffd76f5a71e04d182)) +* **api:** api update ([139a686](https://github.com/sst/opencode-sdk-go/commit/139a6862d2f0ab0c8ea791663d736868be3e96e6)) +* **api:** api update ([2ed0800](https://github.com/sst/opencode-sdk-go/commit/2ed0800b2c5b99877e9f7fde669a6c005fad6b77)) +* **api:** api update ([88a87a4](https://github.com/sst/opencode-sdk-go/commit/88a87a458f56ce0c18b502c73da933f614f56e8b)) +* **api:** api update ([0e5d65b](https://github.com/sst/opencode-sdk-go/commit/0e5d65b571e7b30dc6347e6730098878ebba3a42)) +* **api:** api update ([ba381f1](https://github.com/sst/opencode-sdk-go/commit/ba381f1e07aad24e9824df7d53befae2a644f69f)) +* **api:** api update ([3f429f5](https://github.com/sst/opencode-sdk-go/commit/3f429f5b4be5607433ef5fdc0d5bf67fe590d039)) +* **api:** api update ([9f34787](https://github.com/sst/opencode-sdk-go/commit/9f347876b35b7f898060c1a5f71c322e95978e3e)) +* **api:** api update ([379c8e0](https://github.com/sst/opencode-sdk-go/commit/379c8e00197e13aebaf2f2d61277b125f1f90011)) +* **api:** api update ([550511c](https://github.com/sst/opencode-sdk-go/commit/550511c4c5b5055ac8ff22b7b11731331bd9d088)) +* **api:** api update ([547f0c2](https://github.com/sst/opencode-sdk-go/commit/547f0c262f2df1ce83eaa7267d68be64bb29b841)) +* **api:** api update ([b7b0720](https://github.com/sst/opencode-sdk-go/commit/b7b07204bff314da24b1819c128835a43ef64065)) +* **api:** api update ([7250ffc](https://github.com/sst/opencode-sdk-go/commit/7250ffcba262b916c958ddecc2a42927982db39f)) +* **api:** api update ([17fbab7](https://github.com/sst/opencode-sdk-go/commit/17fbab73111a3eae488737c69b12370bc69c65f7)) +* **api:** api update ([1270b5c](https://github.com/sst/opencode-sdk-go/commit/1270b5cd81e6ac769dcd92ade6d877891bf51bd5)) +* **api:** api update ([a238d4a](https://github.com/sst/opencode-sdk-go/commit/a238d4abd6ed7d15f3547d27a4b6ecf4aec8431e)) +* **api:** api update ([7475655](https://github.com/sst/opencode-sdk-go/commit/7475655aca577fe4f807c2f02f92171f6a358e9c)) +* **api:** api update ([429d258](https://github.com/sst/opencode-sdk-go/commit/429d258bb56e9cdeb1528be3944bf5537ac26a96)) +* **api:** api update ([f250915](https://github.com/sst/opencode-sdk-go/commit/f2509157eaf1b453e741ee9482127cad2e3ace25)) +* **api:** api update ([5efc987](https://github.com/sst/opencode-sdk-go/commit/5efc987353801d1e772c20edf162b1c75da32743)) +* **api:** api update ([98a8350](https://github.com/sst/opencode-sdk-go/commit/98a83504f7cfc361e83314c3e79a4e9ff53f0560)) +* **api:** api update ([6da8bf8](https://github.com/sst/opencode-sdk-go/commit/6da8bf8bfe91d45991fb580753d77c5534fc0b1b)) +* **api:** api update ([f8c7148](https://github.com/sst/opencode-sdk-go/commit/f8c7148ae56143823186e2675a78e82676154956)) +* **api:** manual updates ([7cf038f](https://github.com/sst/opencode-sdk-go/commit/7cf038ffae5da1b77e1cef11b5fa166a53b467f2)) +* **api:** update via SDK Studio ([068a0eb](https://github.com/sst/opencode-sdk-go/commit/068a0eb025010da0c8d86fa1bb496a39dbedcef9)) +* **api:** update via SDK Studio ([ca651ed](https://github.com/sst/opencode-sdk-go/commit/ca651edaf71d1f3678f929287474f5bc4f1aad10)) +* **api:** update via SDK Studio ([13550a5](https://github.com/sst/opencode-sdk-go/commit/13550a5c65d77325e945ed99fe0799cd1107b775)) +* **api:** update via SDK Studio ([7b73730](https://github.com/sst/opencode-sdk-go/commit/7b73730c7fa62ba966dda3541c3e97b49be8d2bf)) +* **api:** update via SDK Studio ([9e39a59](https://github.com/sst/opencode-sdk-go/commit/9e39a59b3d5d1bd5e64633732521fb28362cc70e)) +* **api:** update via SDK Studio ([9609d1b](https://github.com/sst/opencode-sdk-go/commit/9609d1b1db7806d00cb846c9914cb4935cdedf52)) +* **api:** update via SDK Studio ([51315fa](https://github.com/sst/opencode-sdk-go/commit/51315fa2eae424743ea79701e67d44447c44144d)) +* **api:** update via SDK Studio ([af07955](https://github.com/sst/opencode-sdk-go/commit/af0795543240aefaf04fc7663a348825541c79ed)) +* **api:** update via SDK Studio ([5e3468a](https://github.com/sst/opencode-sdk-go/commit/5e3468a0aaa5ed3b13e019c3a24e0ba9147d1675)) +* **api:** update via SDK Studio ([0a73e04](https://github.com/sst/opencode-sdk-go/commit/0a73e04c23c90b2061611edaa8fd6282dc0ce397)) +* **api:** update via SDK Studio ([9b7883a](https://github.com/sst/opencode-sdk-go/commit/9b7883a144eeac526d9d04538e0876a9d18bb844)) +* **client:** expand max streaming buffer size ([76303e5](https://github.com/sst/opencode-sdk-go/commit/76303e51067e78e732af26ced9d83b8bad7655c3)) +* **client:** support optional json html escaping ([449748f](https://github.com/sst/opencode-sdk-go/commit/449748f35a1d8cb6f91dc36d25bf9489f4f371bd)) + ### Bug Fixes -- **client:** process custom base url ahead of time ([9b360d6](https://github.com/sst/opencode-sdk-go/commit/9b360d642cf6f302104308af5622e17099899e5f)) -- **client:** resolve lint errors in streaming tests ([4d36cb0](https://github.com/sst/opencode-sdk-go/commit/4d36cb09fc9d436734d5dab1c499acaa88568ff7)) -- close body before retrying ([4da3f7f](https://github.com/sst/opencode-sdk-go/commit/4da3f7f372bad222a189ba3eabcfde3373166ae5)) -- don't try to deserialize as json when ResponseBodyInto is []byte ([595291f](https://github.com/sst/opencode-sdk-go/commit/595291f6dba6af472f160b9f8e3d145002f43a4a)) +* **client:** process custom base url ahead of time ([9b360d6](https://github.com/sst/opencode-sdk-go/commit/9b360d642cf6f302104308af5622e17099899e5f)) +* **client:** resolve lint errors in streaming tests ([4d36cb0](https://github.com/sst/opencode-sdk-go/commit/4d36cb09fc9d436734d5dab1c499acaa88568ff7)) +* close body before retrying ([4da3f7f](https://github.com/sst/opencode-sdk-go/commit/4da3f7f372bad222a189ba3eabcfde3373166ae5)) +* don't try to deserialize as json when ResponseBodyInto is []byte ([595291f](https://github.com/sst/opencode-sdk-go/commit/595291f6dba6af472f160b9f8e3d145002f43a4a)) + ### Chores -- **ci:** only run for pushes and fork pull requests ([bea59b8](https://github.com/sst/opencode-sdk-go/commit/bea59b886800ef555f89c47a9256d6392ed2e53d)) -- **internal:** codegen related update ([6a22ce6](https://github.com/sst/opencode-sdk-go/commit/6a22ce6df155f5003e80b8a75686a9e513a5568a)) -- **internal:** fix lint script for tests ([391c482](https://github.com/sst/opencode-sdk-go/commit/391c482148ed0a77c4ad52807abeb2d540b56797)) -- **internal:** update comment in script ([b7f1c3e](https://github.com/sst/opencode-sdk-go/commit/b7f1c3e16935c71e243004b8f321d661cd8e9474)) -- lint tests ([616796b](https://github.com/sst/opencode-sdk-go/commit/616796b761704bde6be5c6c2428f28c79c7f05ff)) -- lint tests in subpackages ([50c82ff](https://github.com/sst/opencode-sdk-go/commit/50c82ff0757c973834b68adc22566b70f767b611)) -- sync repo ([2f34d5d](https://github.com/sst/opencode-sdk-go/commit/2f34d5d53e56e9cdc3df99be7ee7efc83dd977a3)) -- update @stainless-api/prism-cli to v5.15.0 ([2f24852](https://github.com/sst/opencode-sdk-go/commit/2f2485216d4f4891d1fbfbc23ff8410c2f35152a)) +* **ci:** only run for pushes and fork pull requests ([bea59b8](https://github.com/sst/opencode-sdk-go/commit/bea59b886800ef555f89c47a9256d6392ed2e53d)) +* **internal:** codegen related update ([6a22ce6](https://github.com/sst/opencode-sdk-go/commit/6a22ce6df155f5003e80b8a75686a9e513a5568a)) +* **internal:** fix lint script for tests ([391c482](https://github.com/sst/opencode-sdk-go/commit/391c482148ed0a77c4ad52807abeb2d540b56797)) +* **internal:** update comment in script ([b7f1c3e](https://github.com/sst/opencode-sdk-go/commit/b7f1c3e16935c71e243004b8f321d661cd8e9474)) +* lint tests ([616796b](https://github.com/sst/opencode-sdk-go/commit/616796b761704bde6be5c6c2428f28c79c7f05ff)) +* lint tests in subpackages ([50c82ff](https://github.com/sst/opencode-sdk-go/commit/50c82ff0757c973834b68adc22566b70f767b611)) +* sync repo ([2f34d5d](https://github.com/sst/opencode-sdk-go/commit/2f34d5d53e56e9cdc3df99be7ee7efc83dd977a3)) +* update @stainless-api/prism-cli to v5.15.0 ([2f24852](https://github.com/sst/opencode-sdk-go/commit/2f2485216d4f4891d1fbfbc23ff8410c2f35152a)) diff --git a/packages/sdk/go/CONTRIBUTING.md b/packages/sdk/go/CONTRIBUTING.md index 34620a3c1..a812b482a 100644 --- a/packages/sdk/go/CONTRIBUTING.md +++ b/packages/sdk/go/CONTRIBUTING.md @@ -9,7 +9,7 @@ $ ./scripts/build This will install all the required dependencies and build the SDK. -You can also [install go 1.18+ manually](https://go.dev/doc/install). +You can also [install go 1.22+ manually](https://go.dev/doc/install). ## Modifying/Adding code diff --git a/packages/sdk/go/README.md b/packages/sdk/go/README.md index 39c358371..2de28f6ce 100644 --- a/packages/sdk/go/README.md +++ b/packages/sdk/go/README.md @@ -24,14 +24,14 @@ Or to pin the version: ```sh -go get -u 'github.com/sst/opencode-sdk-go@v0.15.0' +go get -u 'github.com/sst/opencode-sdk-go@v0.16.2' ``` ## Requirements -This library requires Go 1.18+. +This library requires Go 1.22+. ## Usage diff --git a/packages/sdk/go/agent.go b/packages/sdk/go/agent.go index 5e8f4957c..3413b5666 100644 --- a/packages/sdk/go/agent.go +++ b/packages/sdk/go/agent.go @@ -6,6 +6,7 @@ import ( "context" "net/http" "net/url" + "slices" "github.com/sst/opencode-sdk-go/internal/apijson" "github.com/sst/opencode-sdk-go/internal/apiquery" @@ -35,7 +36,7 @@ func NewAgentService(opts ...option.RequestOption) (r *AgentService) { // List all agents func (r *AgentService) List(ctx context.Context, query AgentListParams, opts ...option.RequestOption) (res *[]Agent, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "agent" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return diff --git a/packages/sdk/go/app.go b/packages/sdk/go/app.go index 62d86f93f..19662f100 100644 --- a/packages/sdk/go/app.go +++ b/packages/sdk/go/app.go @@ -6,6 +6,7 @@ import ( "context" "net/http" "net/url" + "slices" "github.com/sst/opencode-sdk-go/internal/apijson" "github.com/sst/opencode-sdk-go/internal/apiquery" @@ -35,7 +36,7 @@ func NewAppService(opts ...option.RequestOption) (r *AppService) { // Write a log entry to the server logs func (r *AppService) Log(ctx context.Context, params AppLogParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "log" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, params, &res, opts...) return @@ -43,7 +44,7 @@ func (r *AppService) Log(ctx context.Context, params AppLogParams, opts ...optio // List all providers func (r *AppService) Providers(ctx context.Context, query AppProvidersParams, opts ...option.RequestOption) (res *AppProvidersResponse, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "config/providers" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return diff --git a/packages/sdk/go/client.go b/packages/sdk/go/client.go index c66b86bba..a7b86428e 100644 --- a/packages/sdk/go/client.go +++ b/packages/sdk/go/client.go @@ -6,6 +6,7 @@ import ( "context" "net/http" "os" + "slices" "github.com/sst/opencode-sdk-go/internal/requestconfig" "github.com/sst/opencode-sdk-go/option" @@ -95,7 +96,7 @@ func NewClient(opts ...option.RequestOption) (r *Client) { // For even greater flexibility, see [option.WithResponseInto] and // [option.WithResponseBodyInto]. func (r *Client) Execute(ctx context.Context, method string, path string, params interface{}, res interface{}, opts ...option.RequestOption) error { - opts = append(r.Options, opts...) + opts = slices.Concat(r.Options, opts) return requestconfig.ExecuteNewRequest(ctx, method, path, params, res, opts...) } diff --git a/packages/sdk/go/command.go b/packages/sdk/go/command.go index 44e3beb1c..2f64489ad 100644 --- a/packages/sdk/go/command.go +++ b/packages/sdk/go/command.go @@ -6,6 +6,7 @@ import ( "context" "net/http" "net/url" + "slices" "github.com/sst/opencode-sdk-go/internal/apijson" "github.com/sst/opencode-sdk-go/internal/apiquery" @@ -35,7 +36,7 @@ func NewCommandService(opts ...option.RequestOption) (r *CommandService) { // List all commands func (r *CommandService) List(ctx context.Context, query CommandListParams, opts ...option.RequestOption) (res *[]Command, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "command" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return diff --git a/packages/sdk/go/config.go b/packages/sdk/go/config.go index c79de17f0..561a35a0f 100644 --- a/packages/sdk/go/config.go +++ b/packages/sdk/go/config.go @@ -7,6 +7,7 @@ import ( "net/http" "net/url" "reflect" + "slices" "github.com/sst/opencode-sdk-go/internal/apijson" "github.com/sst/opencode-sdk-go/internal/apiquery" @@ -38,7 +39,7 @@ func NewConfigService(opts ...option.RequestOption) (r *ConfigService) { // Get config info func (r *ConfigService) Get(ctx context.Context, query ConfigGetParams, opts ...option.RequestOption) (res *Config, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "config" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return diff --git a/packages/sdk/go/event.go b/packages/sdk/go/event.go index 35b4353cf..ac5231c7f 100644 --- a/packages/sdk/go/event.go +++ b/packages/sdk/go/event.go @@ -7,6 +7,7 @@ import ( "net/http" "net/url" "reflect" + "slices" "github.com/sst/opencode-sdk-go/internal/apijson" "github.com/sst/opencode-sdk-go/internal/apiquery" @@ -43,7 +44,7 @@ func (r *EventService) ListStreaming(ctx context.Context, query EventListParams, raw *http.Response err error ) - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) opts = append([]option.RequestOption{option.WithHeader("Accept", "text/event-stream")}, opts...) path := "event" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &raw, opts...) @@ -61,11 +62,12 @@ type EventListResponse struct { // [EventListResponseEventSessionCompactedProperties], [Permission], // [EventListResponseEventPermissionRepliedProperties], // [EventListResponseEventFileEditedProperties], + // [EventListResponseEventFileWatcherUpdatedProperties], + // [EventListResponseEventTodoUpdatedProperties], // [EventListResponseEventSessionIdleProperties], // [EventListResponseEventSessionUpdatedProperties], // [EventListResponseEventSessionDeletedProperties], // [EventListResponseEventSessionErrorProperties], [interface{}], - // [EventListResponseEventFileWatcherUpdatedProperties], // [EventListResponseEventIdeInstalledProperties]. Properties interface{} `json:"properties,required"` Type EventListResponseType `json:"type,required"` @@ -107,11 +109,10 @@ func (r *EventListResponse) UnmarshalJSON(data []byte) (err error) { // [EventListResponseEventSessionCompacted], // [EventListResponseEventPermissionUpdated], // [EventListResponseEventPermissionReplied], [EventListResponseEventFileEdited], +// [EventListResponseEventFileWatcherUpdated], [EventListResponseEventTodoUpdated], // [EventListResponseEventSessionIdle], [EventListResponseEventSessionUpdated], // [EventListResponseEventSessionDeleted], [EventListResponseEventSessionError], -// [EventListResponseEventServerConnected], -// [EventListResponseEventFileWatcherUpdated], -// [EventListResponseEventIdeInstalled]. +// [EventListResponseEventServerConnected], [EventListResponseEventIdeInstalled]. func (r EventListResponse) AsUnion() EventListResponseUnion { return r.union } @@ -124,11 +125,10 @@ func (r EventListResponse) AsUnion() EventListResponseUnion { // [EventListResponseEventSessionCompacted], // [EventListResponseEventPermissionUpdated], // [EventListResponseEventPermissionReplied], [EventListResponseEventFileEdited], +// [EventListResponseEventFileWatcherUpdated], [EventListResponseEventTodoUpdated], // [EventListResponseEventSessionIdle], [EventListResponseEventSessionUpdated], // [EventListResponseEventSessionDeleted], [EventListResponseEventSessionError], -// [EventListResponseEventServerConnected], -// [EventListResponseEventFileWatcherUpdated] or -// [EventListResponseEventIdeInstalled]. +// [EventListResponseEventServerConnected] or [EventListResponseEventIdeInstalled]. type EventListResponseUnion interface { implementsEventListResponse() } @@ -177,6 +177,14 @@ func init() { TypeFilter: gjson.JSON, Type: reflect.TypeOf(EventListResponseEventFileEdited{}), }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(EventListResponseEventFileWatcherUpdated{}), + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(EventListResponseEventTodoUpdated{}), + }, apijson.UnionVariant{ TypeFilter: gjson.JSON, Type: reflect.TypeOf(EventListResponseEventSessionIdle{}), @@ -197,10 +205,6 @@ func init() { TypeFilter: gjson.JSON, Type: reflect.TypeOf(EventListResponseEventServerConnected{}), }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(EventListResponseEventFileWatcherUpdated{}), - }, apijson.UnionVariant{ TypeFilter: gjson.JSON, Type: reflect.TypeOf(EventListResponseEventIdeInstalled{}), @@ -799,6 +803,177 @@ func (r EventListResponseEventFileEditedType) IsKnown() bool { return false } +type EventListResponseEventFileWatcherUpdated struct { + Properties EventListResponseEventFileWatcherUpdatedProperties `json:"properties,required"` + Type EventListResponseEventFileWatcherUpdatedType `json:"type,required"` + JSON eventListResponseEventFileWatcherUpdatedJSON `json:"-"` +} + +// eventListResponseEventFileWatcherUpdatedJSON contains the JSON metadata for the +// struct [EventListResponseEventFileWatcherUpdated] +type eventListResponseEventFileWatcherUpdatedJSON struct { + Properties apijson.Field + Type apijson.Field + raw string + ExtraFields map[string]apijson.Field +} + +func (r *EventListResponseEventFileWatcherUpdated) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) +} + +func (r eventListResponseEventFileWatcherUpdatedJSON) RawJSON() string { + return r.raw +} + +func (r EventListResponseEventFileWatcherUpdated) implementsEventListResponse() {} + +type EventListResponseEventFileWatcherUpdatedProperties struct { + Event EventListResponseEventFileWatcherUpdatedPropertiesEvent `json:"event,required"` + File string `json:"file,required"` + JSON eventListResponseEventFileWatcherUpdatedPropertiesJSON `json:"-"` +} + +// eventListResponseEventFileWatcherUpdatedPropertiesJSON contains the JSON +// metadata for the struct [EventListResponseEventFileWatcherUpdatedProperties] +type eventListResponseEventFileWatcherUpdatedPropertiesJSON struct { + Event apijson.Field + File apijson.Field + raw string + ExtraFields map[string]apijson.Field +} + +func (r *EventListResponseEventFileWatcherUpdatedProperties) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) +} + +func (r eventListResponseEventFileWatcherUpdatedPropertiesJSON) RawJSON() string { + return r.raw +} + +type EventListResponseEventFileWatcherUpdatedPropertiesEvent string + +const ( + EventListResponseEventFileWatcherUpdatedPropertiesEventAdd EventListResponseEventFileWatcherUpdatedPropertiesEvent = "add" + EventListResponseEventFileWatcherUpdatedPropertiesEventChange EventListResponseEventFileWatcherUpdatedPropertiesEvent = "change" + EventListResponseEventFileWatcherUpdatedPropertiesEventUnlink EventListResponseEventFileWatcherUpdatedPropertiesEvent = "unlink" +) + +func (r EventListResponseEventFileWatcherUpdatedPropertiesEvent) IsKnown() bool { + switch r { + case EventListResponseEventFileWatcherUpdatedPropertiesEventAdd, EventListResponseEventFileWatcherUpdatedPropertiesEventChange, EventListResponseEventFileWatcherUpdatedPropertiesEventUnlink: + return true + } + return false +} + +type EventListResponseEventFileWatcherUpdatedType string + +const ( + EventListResponseEventFileWatcherUpdatedTypeFileWatcherUpdated EventListResponseEventFileWatcherUpdatedType = "file.watcher.updated" +) + +func (r EventListResponseEventFileWatcherUpdatedType) IsKnown() bool { + switch r { + case EventListResponseEventFileWatcherUpdatedTypeFileWatcherUpdated: + return true + } + return false +} + +type EventListResponseEventTodoUpdated struct { + Properties EventListResponseEventTodoUpdatedProperties `json:"properties,required"` + Type EventListResponseEventTodoUpdatedType `json:"type,required"` + JSON eventListResponseEventTodoUpdatedJSON `json:"-"` +} + +// eventListResponseEventTodoUpdatedJSON contains the JSON metadata for the struct +// [EventListResponseEventTodoUpdated] +type eventListResponseEventTodoUpdatedJSON struct { + Properties apijson.Field + Type apijson.Field + raw string + ExtraFields map[string]apijson.Field +} + +func (r *EventListResponseEventTodoUpdated) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) +} + +func (r eventListResponseEventTodoUpdatedJSON) RawJSON() string { + return r.raw +} + +func (r EventListResponseEventTodoUpdated) implementsEventListResponse() {} + +type EventListResponseEventTodoUpdatedProperties struct { + SessionID string `json:"sessionID,required"` + Todos []EventListResponseEventTodoUpdatedPropertiesTodo `json:"todos,required"` + JSON eventListResponseEventTodoUpdatedPropertiesJSON `json:"-"` +} + +// eventListResponseEventTodoUpdatedPropertiesJSON contains the JSON metadata for +// the struct [EventListResponseEventTodoUpdatedProperties] +type eventListResponseEventTodoUpdatedPropertiesJSON struct { + SessionID apijson.Field + Todos apijson.Field + raw string + ExtraFields map[string]apijson.Field +} + +func (r *EventListResponseEventTodoUpdatedProperties) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) +} + +func (r eventListResponseEventTodoUpdatedPropertiesJSON) RawJSON() string { + return r.raw +} + +type EventListResponseEventTodoUpdatedPropertiesTodo struct { + // Unique identifier for the todo item + ID string `json:"id,required"` + // Brief description of the task + Content string `json:"content,required"` + // Priority level of the task: high, medium, low + Priority string `json:"priority,required"` + // Current status of the task: pending, in_progress, completed, cancelled + Status string `json:"status,required"` + JSON eventListResponseEventTodoUpdatedPropertiesTodoJSON `json:"-"` +} + +// eventListResponseEventTodoUpdatedPropertiesTodoJSON contains the JSON metadata +// for the struct [EventListResponseEventTodoUpdatedPropertiesTodo] +type eventListResponseEventTodoUpdatedPropertiesTodoJSON struct { + ID apijson.Field + Content apijson.Field + Priority apijson.Field + Status apijson.Field + raw string + ExtraFields map[string]apijson.Field +} + +func (r *EventListResponseEventTodoUpdatedPropertiesTodo) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) +} + +func (r eventListResponseEventTodoUpdatedPropertiesTodoJSON) RawJSON() string { + return r.raw +} + +type EventListResponseEventTodoUpdatedType string + +const ( + EventListResponseEventTodoUpdatedTypeTodoUpdated EventListResponseEventTodoUpdatedType = "todo.updated" +) + +func (r EventListResponseEventTodoUpdatedType) IsKnown() bool { + switch r { + case EventListResponseEventTodoUpdatedTypeTodoUpdated: + return true + } + return false +} + type EventListResponseEventSessionIdle struct { Properties EventListResponseEventSessionIdleProperties `json:"properties,required"` Type EventListResponseEventSessionIdleType `json:"type,required"` @@ -1210,84 +1385,6 @@ func (r EventListResponseEventServerConnectedType) IsKnown() bool { return false } -type EventListResponseEventFileWatcherUpdated struct { - Properties EventListResponseEventFileWatcherUpdatedProperties `json:"properties,required"` - Type EventListResponseEventFileWatcherUpdatedType `json:"type,required"` - JSON eventListResponseEventFileWatcherUpdatedJSON `json:"-"` -} - -// eventListResponseEventFileWatcherUpdatedJSON contains the JSON metadata for the -// struct [EventListResponseEventFileWatcherUpdated] -type eventListResponseEventFileWatcherUpdatedJSON struct { - Properties apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *EventListResponseEventFileWatcherUpdated) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) -} - -func (r eventListResponseEventFileWatcherUpdatedJSON) RawJSON() string { - return r.raw -} - -func (r EventListResponseEventFileWatcherUpdated) implementsEventListResponse() {} - -type EventListResponseEventFileWatcherUpdatedProperties struct { - Event EventListResponseEventFileWatcherUpdatedPropertiesEvent `json:"event,required"` - File string `json:"file,required"` - JSON eventListResponseEventFileWatcherUpdatedPropertiesJSON `json:"-"` -} - -// eventListResponseEventFileWatcherUpdatedPropertiesJSON contains the JSON -// metadata for the struct [EventListResponseEventFileWatcherUpdatedProperties] -type eventListResponseEventFileWatcherUpdatedPropertiesJSON struct { - Event apijson.Field - File apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *EventListResponseEventFileWatcherUpdatedProperties) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) -} - -func (r eventListResponseEventFileWatcherUpdatedPropertiesJSON) RawJSON() string { - return r.raw -} - -type EventListResponseEventFileWatcherUpdatedPropertiesEvent string - -const ( - EventListResponseEventFileWatcherUpdatedPropertiesEventAdd EventListResponseEventFileWatcherUpdatedPropertiesEvent = "add" - EventListResponseEventFileWatcherUpdatedPropertiesEventChange EventListResponseEventFileWatcherUpdatedPropertiesEvent = "change" - EventListResponseEventFileWatcherUpdatedPropertiesEventUnlink EventListResponseEventFileWatcherUpdatedPropertiesEvent = "unlink" -) - -func (r EventListResponseEventFileWatcherUpdatedPropertiesEvent) IsKnown() bool { - switch r { - case EventListResponseEventFileWatcherUpdatedPropertiesEventAdd, EventListResponseEventFileWatcherUpdatedPropertiesEventChange, EventListResponseEventFileWatcherUpdatedPropertiesEventUnlink: - return true - } - return false -} - -type EventListResponseEventFileWatcherUpdatedType string - -const ( - EventListResponseEventFileWatcherUpdatedTypeFileWatcherUpdated EventListResponseEventFileWatcherUpdatedType = "file.watcher.updated" -) - -func (r EventListResponseEventFileWatcherUpdatedType) IsKnown() bool { - switch r { - case EventListResponseEventFileWatcherUpdatedTypeFileWatcherUpdated: - return true - } - return false -} - type EventListResponseEventIdeInstalled struct { Properties EventListResponseEventIdeInstalledProperties `json:"properties,required"` Type EventListResponseEventIdeInstalledType `json:"type,required"` @@ -1361,18 +1458,19 @@ const ( EventListResponseTypePermissionUpdated EventListResponseType = "permission.updated" EventListResponseTypePermissionReplied EventListResponseType = "permission.replied" EventListResponseTypeFileEdited EventListResponseType = "file.edited" + EventListResponseTypeFileWatcherUpdated EventListResponseType = "file.watcher.updated" + EventListResponseTypeTodoUpdated EventListResponseType = "todo.updated" EventListResponseTypeSessionIdle EventListResponseType = "session.idle" EventListResponseTypeSessionUpdated EventListResponseType = "session.updated" EventListResponseTypeSessionDeleted EventListResponseType = "session.deleted" EventListResponseTypeSessionError EventListResponseType = "session.error" EventListResponseTypeServerConnected EventListResponseType = "server.connected" - EventListResponseTypeFileWatcherUpdated EventListResponseType = "file.watcher.updated" EventListResponseTypeIdeInstalled EventListResponseType = "ide.installed" ) func (r EventListResponseType) IsKnown() bool { switch r { - case EventListResponseTypeInstallationUpdated, EventListResponseTypeLspClientDiagnostics, EventListResponseTypeMessageUpdated, EventListResponseTypeMessageRemoved, EventListResponseTypeMessagePartUpdated, EventListResponseTypeMessagePartRemoved, EventListResponseTypeSessionCompacted, EventListResponseTypePermissionUpdated, EventListResponseTypePermissionReplied, EventListResponseTypeFileEdited, EventListResponseTypeSessionIdle, EventListResponseTypeSessionUpdated, EventListResponseTypeSessionDeleted, EventListResponseTypeSessionError, EventListResponseTypeServerConnected, EventListResponseTypeFileWatcherUpdated, EventListResponseTypeIdeInstalled: + case EventListResponseTypeInstallationUpdated, EventListResponseTypeLspClientDiagnostics, EventListResponseTypeMessageUpdated, EventListResponseTypeMessageRemoved, EventListResponseTypeMessagePartUpdated, EventListResponseTypeMessagePartRemoved, EventListResponseTypeSessionCompacted, EventListResponseTypePermissionUpdated, EventListResponseTypePermissionReplied, EventListResponseTypeFileEdited, EventListResponseTypeFileWatcherUpdated, EventListResponseTypeTodoUpdated, EventListResponseTypeSessionIdle, EventListResponseTypeSessionUpdated, EventListResponseTypeSessionDeleted, EventListResponseTypeSessionError, EventListResponseTypeServerConnected, EventListResponseTypeIdeInstalled: return true } return false diff --git a/packages/sdk/go/file.go b/packages/sdk/go/file.go index bc36075f1..8833f425b 100644 --- a/packages/sdk/go/file.go +++ b/packages/sdk/go/file.go @@ -6,6 +6,7 @@ import ( "context" "net/http" "net/url" + "slices" "github.com/sst/opencode-sdk-go/internal/apijson" "github.com/sst/opencode-sdk-go/internal/apiquery" @@ -35,7 +36,7 @@ func NewFileService(opts ...option.RequestOption) (r *FileService) { // List files and directories func (r *FileService) List(ctx context.Context, query FileListParams, opts ...option.RequestOption) (res *[]FileNode, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "file" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return @@ -43,7 +44,7 @@ func (r *FileService) List(ctx context.Context, query FileListParams, opts ...op // Read a file func (r *FileService) Read(ctx context.Context, query FileReadParams, opts ...option.RequestOption) (res *FileReadResponse, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "file/content" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return @@ -51,7 +52,7 @@ func (r *FileService) Read(ctx context.Context, query FileReadParams, opts ...op // Get file status func (r *FileService) Status(ctx context.Context, query FileStatusParams, opts ...option.RequestOption) (res *[]File, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "file/status" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return diff --git a/packages/sdk/go/find.go b/packages/sdk/go/find.go index e869116b4..3833ec55a 100644 --- a/packages/sdk/go/find.go +++ b/packages/sdk/go/find.go @@ -6,6 +6,7 @@ import ( "context" "net/http" "net/url" + "slices" "github.com/sst/opencode-sdk-go/internal/apijson" "github.com/sst/opencode-sdk-go/internal/apiquery" @@ -35,7 +36,7 @@ func NewFindService(opts ...option.RequestOption) (r *FindService) { // Find files func (r *FindService) Files(ctx context.Context, query FindFilesParams, opts ...option.RequestOption) (res *[]string, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "find/file" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return @@ -43,7 +44,7 @@ func (r *FindService) Files(ctx context.Context, query FindFilesParams, opts ... // Find workspace symbols func (r *FindService) Symbols(ctx context.Context, query FindSymbolsParams, opts ...option.RequestOption) (res *[]Symbol, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "find/symbol" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return @@ -51,7 +52,7 @@ func (r *FindService) Symbols(ctx context.Context, query FindSymbolsParams, opts // Find text in files func (r *FindService) Text(ctx context.Context, query FindTextParams, opts ...option.RequestOption) (res *[]FindTextResponse, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "find" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return diff --git a/packages/sdk/go/go.mod b/packages/sdk/go/go.mod index 2817d3013..5b6eb403f 100644 --- a/packages/sdk/go/go.mod +++ b/packages/sdk/go/go.mod @@ -1,6 +1,6 @@ module github.com/sst/opencode-sdk-go -go 1.21 +go 1.22 require ( github.com/tidwall/gjson v1.14.4 diff --git a/packages/sdk/go/internal/apijson/decoder.go b/packages/sdk/go/internal/apijson/decoder.go index 68b7ed6be..bf01bf6b4 100644 --- a/packages/sdk/go/internal/apijson/decoder.go +++ b/packages/sdk/go/internal/apijson/decoder.go @@ -224,7 +224,7 @@ func (d *decoderBuilder) newUnionDecoder(t reflect.Type) decoderFunc { } if len(unionEntry.discriminatorKey) != 0 { - discriminatorValue := n.Get(unionEntry.discriminatorKey).Value() + discriminatorValue := n.Get(EscapeSJSONKey(unionEntry.discriminatorKey)).Value() if discriminatorValue == variant.DiscriminatorValue { inner := reflect.New(variant.Type).Elem() err := decoder(n, inner, state) diff --git a/packages/sdk/go/internal/apijson/encoder.go b/packages/sdk/go/internal/apijson/encoder.go index 0e5f89e17..66b319b66 100644 --- a/packages/sdk/go/internal/apijson/encoder.go +++ b/packages/sdk/go/internal/apijson/encoder.go @@ -18,6 +18,10 @@ import ( var encoders sync.Map // map[encoderEntry]encoderFunc +// If we want to set a literal key value into JSON using sjson, we need to make sure it doesn't have +// special characters that sjson interprets as a path. +var EscapeSJSONKey = strings.NewReplacer("\\", "\\\\", "|", "\\|", "#", "\\#", "@", "\\@", "*", "\\*", ".", "\\.", ":", "\\:", "?", "\\?").Replace + func Marshal(value interface{}) ([]byte, error) { e := &encoder{dateFormat: time.RFC3339} return e.marshal(value) @@ -276,7 +280,7 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc { if encoded == nil { continue } - json, err = sjson.SetRawBytes(json, ef.tag.name, encoded) + json, err = sjson.SetRawBytes(json, EscapeSJSONKey(ef.tag.name), encoded) if err != nil { return nil, err } @@ -354,7 +358,7 @@ func (e *encoder) encodeMapEntries(json []byte, v reflect.Value) ([]byte, error) } encodedKeyString = string(encodedKeyBytes) } - encodedKey := []byte(sjsonReplacer.Replace(encodedKeyString)) + encodedKey := []byte(encodedKeyString) pairs = append(pairs, mapPair{key: encodedKey, value: iter.Value()}) } @@ -372,7 +376,7 @@ func (e *encoder) encodeMapEntries(json []byte, v reflect.Value) ([]byte, error) if len(encodedValue) == 0 { continue } - json, err = sjson.SetRawBytes(json, string(p.key), encodedValue) + json, err = sjson.SetRawBytes(json, EscapeSJSONKey(string(p.key)), encodedValue) if err != nil { return nil, err } @@ -392,7 +396,3 @@ func (e *encoder) newMapEncoder(t reflect.Type) encoderFunc { return json, nil } } - -// If we want to set a literal key value into JSON using sjson, we need to make sure it doesn't have -// special characters that sjson interprets as a path. -var sjsonReplacer *strings.Replacer = strings.NewReplacer(".", "\\.", ":", "\\:", "*", "\\*") diff --git a/packages/sdk/go/internal/apijson/json_test.go b/packages/sdk/go/internal/apijson/json_test.go index e6563448f..d4c628359 100644 --- a/packages/sdk/go/internal/apijson/json_test.go +++ b/packages/sdk/go/internal/apijson/json_test.go @@ -362,7 +362,7 @@ var tests = map[string]struct { "date_time_nano_missing_t_coerce": {`"2007-03-01 13:03:05.123456789Z"`, time.Date(2007, time.March, 1, 13, 3, 5, 123456789, time.UTC)}, "map_string": {`{"foo":"bar"}`, map[string]string{"foo": "bar"}}, - "map_string_with_sjson_path_chars": {`{":a.b.c*:d*-1e.f":"bar"}`, map[string]string{":a.b.c*:d*-1e.f": "bar"}}, + "map_string_with_sjson_path_chars": {`{":a.b.c*:d*-1e.f@g?h":"bar"}`, map[string]string{":a.b.c*:d*-1e.f@g?h": "bar"}}, "map_interface": {`{"a":1,"b":"str","c":false}`, map[string]interface{}{"a": float64(1), "b": "str", "c": false}}, "primitive_struct": { diff --git a/packages/sdk/go/internal/version.go b/packages/sdk/go/internal/version.go index 1f338c33e..93a271b9e 100644 --- a/packages/sdk/go/internal/version.go +++ b/packages/sdk/go/internal/version.go @@ -2,4 +2,4 @@ package internal -const PackageVersion = "0.15.0" // x-release-please-version +const PackageVersion = "0.16.2" // x-release-please-version diff --git a/packages/sdk/go/path.go b/packages/sdk/go/path.go index 63e502626..6b64a43bf 100644 --- a/packages/sdk/go/path.go +++ b/packages/sdk/go/path.go @@ -6,6 +6,7 @@ import ( "context" "net/http" "net/url" + "slices" "github.com/sst/opencode-sdk-go/internal/apijson" "github.com/sst/opencode-sdk-go/internal/apiquery" @@ -35,7 +36,7 @@ func NewPathService(opts ...option.RequestOption) (r *PathService) { // Get the current path func (r *PathService) Get(ctx context.Context, query PathGetParams, opts ...option.RequestOption) (res *Path, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "path" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return diff --git a/packages/sdk/go/project.go b/packages/sdk/go/project.go index 3b349dadd..319cfe30b 100644 --- a/packages/sdk/go/project.go +++ b/packages/sdk/go/project.go @@ -6,6 +6,7 @@ import ( "context" "net/http" "net/url" + "slices" "github.com/sst/opencode-sdk-go/internal/apijson" "github.com/sst/opencode-sdk-go/internal/apiquery" @@ -35,7 +36,7 @@ func NewProjectService(opts ...option.RequestOption) (r *ProjectService) { // List all projects func (r *ProjectService) List(ctx context.Context, query ProjectListParams, opts ...option.RequestOption) (res *[]Project, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "project" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return @@ -43,7 +44,7 @@ func (r *ProjectService) List(ctx context.Context, query ProjectListParams, opts // Get the current project func (r *ProjectService) Current(ctx context.Context, query ProjectCurrentParams, opts ...option.RequestOption) (res *Project, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "project/current" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return diff --git a/packages/sdk/go/release-please-config.json b/packages/sdk/go/release-please-config.json index 32960ce27..a38198eca 100644 --- a/packages/sdk/go/release-please-config.json +++ b/packages/sdk/go/release-please-config.json @@ -60,5 +60,8 @@ } ], "release-type": "go", - "extra-files": ["internal/version.go", "README.md"] -} + "extra-files": [ + "internal/version.go", + "README.md" + ] +} \ No newline at end of file diff --git a/packages/sdk/go/scripts/bootstrap b/packages/sdk/go/scripts/bootstrap index d6ac16540..5ab30665f 100755 --- a/packages/sdk/go/scripts/bootstrap +++ b/packages/sdk/go/scripts/bootstrap @@ -4,10 +4,18 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { - echo "==> Installing Homebrew dependencies…" - brew bundle + echo -n "==> Install Homebrew dependencies? (y/N): " + read -r response + case "$response" in + [yY][eE][sS]|[yY]) + brew bundle + ;; + *) + ;; + esac + echo } fi diff --git a/packages/sdk/go/session.go b/packages/sdk/go/session.go index 260724e9a..0ee81faad 100644 --- a/packages/sdk/go/session.go +++ b/packages/sdk/go/session.go @@ -9,6 +9,7 @@ import ( "net/http" "net/url" "reflect" + "slices" "github.com/sst/opencode-sdk-go/internal/apijson" "github.com/sst/opencode-sdk-go/internal/apiquery" @@ -42,7 +43,7 @@ func NewSessionService(opts ...option.RequestOption) (r *SessionService) { // Create a new session func (r *SessionService) New(ctx context.Context, params SessionNewParams, opts ...option.RequestOption) (res *Session, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "session" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, params, &res, opts...) return @@ -50,7 +51,7 @@ func (r *SessionService) New(ctx context.Context, params SessionNewParams, opts // Update session properties func (r *SessionService) Update(ctx context.Context, id string, params SessionUpdateParams, opts ...option.RequestOption) (res *Session, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -62,7 +63,7 @@ func (r *SessionService) Update(ctx context.Context, id string, params SessionUp // List all sessions func (r *SessionService) List(ctx context.Context, query SessionListParams, opts ...option.RequestOption) (res *[]Session, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "session" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) return @@ -70,7 +71,7 @@ func (r *SessionService) List(ctx context.Context, query SessionListParams, opts // Delete a session and all its data func (r *SessionService) Delete(ctx context.Context, id string, body SessionDeleteParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -82,7 +83,7 @@ func (r *SessionService) Delete(ctx context.Context, id string, body SessionDele // Abort a session func (r *SessionService) Abort(ctx context.Context, id string, body SessionAbortParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -94,7 +95,7 @@ func (r *SessionService) Abort(ctx context.Context, id string, body SessionAbort // Get a session's children func (r *SessionService) Children(ctx context.Context, id string, query SessionChildrenParams, opts ...option.RequestOption) (res *[]Session, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -106,7 +107,7 @@ func (r *SessionService) Children(ctx context.Context, id string, query SessionC // Send a new command to a session func (r *SessionService) Command(ctx context.Context, id string, params SessionCommandParams, opts ...option.RequestOption) (res *SessionCommandResponse, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -118,7 +119,7 @@ func (r *SessionService) Command(ctx context.Context, id string, params SessionC // Get session func (r *SessionService) Get(ctx context.Context, id string, query SessionGetParams, opts ...option.RequestOption) (res *Session, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -130,7 +131,7 @@ func (r *SessionService) Get(ctx context.Context, id string, query SessionGetPar // Analyze the app and create an AGENTS.md file func (r *SessionService) Init(ctx context.Context, id string, params SessionInitParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -142,7 +143,7 @@ func (r *SessionService) Init(ctx context.Context, id string, params SessionInit // Get a message from a session func (r *SessionService) Message(ctx context.Context, id string, messageID string, query SessionMessageParams, opts ...option.RequestOption) (res *SessionMessageResponse, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -158,7 +159,7 @@ func (r *SessionService) Message(ctx context.Context, id string, messageID strin // List messages for a session func (r *SessionService) Messages(ctx context.Context, id string, query SessionMessagesParams, opts ...option.RequestOption) (res *[]SessionMessagesResponse, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -170,7 +171,7 @@ func (r *SessionService) Messages(ctx context.Context, id string, query SessionM // Create and send a new message to a session func (r *SessionService) Prompt(ctx context.Context, id string, params SessionPromptParams, opts ...option.RequestOption) (res *SessionPromptResponse, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -182,7 +183,7 @@ func (r *SessionService) Prompt(ctx context.Context, id string, params SessionPr // Revert a message func (r *SessionService) Revert(ctx context.Context, id string, params SessionRevertParams, opts ...option.RequestOption) (res *Session, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -194,7 +195,7 @@ func (r *SessionService) Revert(ctx context.Context, id string, params SessionRe // Share a session func (r *SessionService) Share(ctx context.Context, id string, body SessionShareParams, opts ...option.RequestOption) (res *Session, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -206,7 +207,7 @@ func (r *SessionService) Share(ctx context.Context, id string, body SessionShare // Run a shell command func (r *SessionService) Shell(ctx context.Context, id string, params SessionShellParams, opts ...option.RequestOption) (res *AssistantMessage, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -218,7 +219,7 @@ func (r *SessionService) Shell(ctx context.Context, id string, params SessionShe // Summarize the session func (r *SessionService) Summarize(ctx context.Context, id string, params SessionSummarizeParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -230,7 +231,7 @@ func (r *SessionService) Summarize(ctx context.Context, id string, params Sessio // Restore all reverted messages func (r *SessionService) Unrevert(ctx context.Context, id string, body SessionUnrevertParams, opts ...option.RequestOption) (res *Session, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -242,7 +243,7 @@ func (r *SessionService) Unrevert(ctx context.Context, id string, body SessionUn // Unshare the session func (r *SessionService) Unshare(ctx context.Context, id string, body SessionUnshareParams, opts ...option.RequestOption) (res *Session, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return @@ -1724,14 +1725,15 @@ func (r SymbolSourceRangeStartParam) MarshalJSON() (data []byte, err error) { } type TextPart struct { - ID string `json:"id,required"` - MessageID string `json:"messageID,required"` - SessionID string `json:"sessionID,required"` - Text string `json:"text,required"` - Type TextPartType `json:"type,required"` - Synthetic bool `json:"synthetic"` - Time TextPartTime `json:"time"` - JSON textPartJSON `json:"-"` + ID string `json:"id,required"` + MessageID string `json:"messageID,required"` + SessionID string `json:"sessionID,required"` + Text string `json:"text,required"` + Type TextPartType `json:"type,required"` + Metadata map[string]interface{} `json:"metadata"` + Synthetic bool `json:"synthetic"` + Time TextPartTime `json:"time"` + JSON textPartJSON `json:"-"` } // textPartJSON contains the JSON metadata for the struct [TextPart] @@ -1741,6 +1743,7 @@ type textPartJSON struct { SessionID apijson.Field Text apijson.Field Type apijson.Field + Metadata apijson.Field Synthetic apijson.Field Time apijson.Field raw string @@ -1797,6 +1800,7 @@ type TextPartInputParam struct { Text param.Field[string] `json:"text,required"` Type param.Field[TextPartInputType] `json:"type,required"` ID param.Field[string] `json:"id"` + Metadata param.Field[map[string]interface{}] `json:"metadata"` Synthetic param.Field[bool] `json:"synthetic"` Time param.Field[TextPartInputTimeParam] `json:"time"` } @@ -1831,14 +1835,15 @@ func (r TextPartInputTimeParam) MarshalJSON() (data []byte, err error) { } type ToolPart struct { - ID string `json:"id,required"` - CallID string `json:"callID,required"` - MessageID string `json:"messageID,required"` - SessionID string `json:"sessionID,required"` - State ToolPartState `json:"state,required"` - Tool string `json:"tool,required"` - Type ToolPartType `json:"type,required"` - JSON toolPartJSON `json:"-"` + ID string `json:"id,required"` + CallID string `json:"callID,required"` + MessageID string `json:"messageID,required"` + SessionID string `json:"sessionID,required"` + State ToolPartState `json:"state,required"` + Tool string `json:"tool,required"` + Type ToolPartType `json:"type,required"` + Metadata map[string]interface{} `json:"metadata"` + JSON toolPartJSON `json:"-"` } // toolPartJSON contains the JSON metadata for the struct [ToolPart] @@ -1850,6 +1855,7 @@ type toolPartJSON struct { State apijson.Field Tool apijson.Field Type apijson.Field + Metadata apijson.Field raw string ExtraFields map[string]apijson.Field } @@ -2556,6 +2562,7 @@ type SessionPromptParamsPart struct { Type param.Field[SessionPromptParamsPartsType] `json:"type,required"` ID param.Field[string] `json:"id"` Filename param.Field[string] `json:"filename"` + Metadata param.Field[interface{}] `json:"metadata"` Mime param.Field[string] `json:"mime"` Name param.Field[string] `json:"name"` Source param.Field[interface{}] `json:"source"` diff --git a/packages/sdk/go/session_test.go b/packages/sdk/go/session_test.go index 61404d8b5..f2263c7bc 100644 --- a/packages/sdk/go/session_test.go +++ b/packages/sdk/go/session_test.go @@ -27,7 +27,7 @@ func TestSessionNewWithOptionalParams(t *testing.T) { ) _, err := client.Session.New(context.TODO(), opencode.SessionNewParams{ Directory: opencode.F("directory"), - ParentID: opencode.F("parentID"), + ParentID: opencode.F("sesJ!"), Title: opencode.F("title"), }) if err != nil { @@ -106,7 +106,7 @@ func TestSessionDeleteWithOptionalParams(t *testing.T) { ) _, err := client.Session.Delete( context.TODO(), - "id", + "sesJ!", opencode.SessionDeleteParams{ Directory: opencode.F("directory"), }, @@ -162,7 +162,7 @@ func TestSessionChildrenWithOptionalParams(t *testing.T) { ) _, err := client.Session.Children( context.TODO(), - "id", + "sesJ!", opencode.SessionChildrenParams{ Directory: opencode.F("directory"), }, @@ -223,7 +223,7 @@ func TestSessionGetWithOptionalParams(t *testing.T) { ) _, err := client.Session.Get( context.TODO(), - "id", + "sesJ!", opencode.SessionGetParams{ Directory: opencode.F("directory"), }, @@ -253,7 +253,7 @@ func TestSessionInitWithOptionalParams(t *testing.T) { context.TODO(), "id", opencode.SessionInitParams{ - MessageID: opencode.F("messageID"), + MessageID: opencode.F("msgJ!"), ModelID: opencode.F("modelID"), ProviderID: opencode.F("providerID"), Directory: opencode.F("directory"), @@ -342,9 +342,12 @@ func TestSessionPromptWithOptionalParams(t *testing.T) { "id", opencode.SessionPromptParams{ Parts: opencode.F([]opencode.SessionPromptParamsPartUnion{opencode.TextPartInputParam{ - Text: opencode.F("text"), - Type: opencode.F(opencode.TextPartInputTypeText), - ID: opencode.F("id"), + Text: opencode.F("text"), + Type: opencode.F(opencode.TextPartInputTypeText), + ID: opencode.F("id"), + Metadata: opencode.F(map[string]interface{}{ + "foo": "bar", + }), Synthetic: opencode.F(true), Time: opencode.F(opencode.TextPartInputTimeParam{ Start: opencode.F(0.000000), @@ -533,7 +536,7 @@ func TestSessionUnshareWithOptionalParams(t *testing.T) { ) _, err := client.Session.Unshare( context.TODO(), - "id", + "sesJ!", opencode.SessionUnshareParams{ Directory: opencode.F("directory"), }, diff --git a/packages/sdk/go/sessionpermission.go b/packages/sdk/go/sessionpermission.go index 4dbfe1d2d..51d18e228 100644 --- a/packages/sdk/go/sessionpermission.go +++ b/packages/sdk/go/sessionpermission.go @@ -9,6 +9,7 @@ import ( "net/http" "net/url" "reflect" + "slices" "github.com/sst/opencode-sdk-go/internal/apijson" "github.com/sst/opencode-sdk-go/internal/apiquery" @@ -40,7 +41,7 @@ func NewSessionPermissionService(opts ...option.RequestOption) (r *SessionPermis // Respond to a permission request func (r *SessionPermissionService) Respond(ctx context.Context, id string, permissionID string, params SessionPermissionRespondParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) if id == "" { err = errors.New("missing required id parameter") return diff --git a/packages/sdk/go/tui.go b/packages/sdk/go/tui.go index b7a8483f0..cd323c7cb 100644 --- a/packages/sdk/go/tui.go +++ b/packages/sdk/go/tui.go @@ -6,6 +6,7 @@ import ( "context" "net/http" "net/url" + "slices" "github.com/sst/opencode-sdk-go/internal/apijson" "github.com/sst/opencode-sdk-go/internal/apiquery" @@ -35,7 +36,7 @@ func NewTuiService(opts ...option.RequestOption) (r *TuiService) { // Append prompt to the TUI func (r *TuiService) AppendPrompt(ctx context.Context, params TuiAppendPromptParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "tui/append-prompt" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, params, &res, opts...) return @@ -43,7 +44,7 @@ func (r *TuiService) AppendPrompt(ctx context.Context, params TuiAppendPromptPar // Clear the prompt func (r *TuiService) ClearPrompt(ctx context.Context, body TuiClearPromptParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "tui/clear-prompt" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) return @@ -51,7 +52,7 @@ func (r *TuiService) ClearPrompt(ctx context.Context, body TuiClearPromptParams, // Execute a TUI command (e.g. agent_cycle) func (r *TuiService) ExecuteCommand(ctx context.Context, params TuiExecuteCommandParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "tui/execute-command" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, params, &res, opts...) return @@ -59,7 +60,7 @@ func (r *TuiService) ExecuteCommand(ctx context.Context, params TuiExecuteComman // Open the help dialog func (r *TuiService) OpenHelp(ctx context.Context, body TuiOpenHelpParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "tui/open-help" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) return @@ -67,7 +68,7 @@ func (r *TuiService) OpenHelp(ctx context.Context, body TuiOpenHelpParams, opts // Open the model dialog func (r *TuiService) OpenModels(ctx context.Context, body TuiOpenModelsParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "tui/open-models" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) return @@ -75,7 +76,7 @@ func (r *TuiService) OpenModels(ctx context.Context, body TuiOpenModelsParams, o // Open the session dialog func (r *TuiService) OpenSessions(ctx context.Context, body TuiOpenSessionsParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "tui/open-sessions" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) return @@ -83,7 +84,7 @@ func (r *TuiService) OpenSessions(ctx context.Context, body TuiOpenSessionsParam // Open the theme dialog func (r *TuiService) OpenThemes(ctx context.Context, body TuiOpenThemesParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "tui/open-themes" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) return @@ -91,7 +92,7 @@ func (r *TuiService) OpenThemes(ctx context.Context, body TuiOpenThemesParams, o // Show a toast notification in the TUI func (r *TuiService) ShowToast(ctx context.Context, params TuiShowToastParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "tui/show-toast" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, params, &res, opts...) return @@ -99,7 +100,7 @@ func (r *TuiService) ShowToast(ctx context.Context, params TuiShowToastParams, o // Submit the prompt func (r *TuiService) SubmitPrompt(ctx context.Context, body TuiSubmitPromptParams, opts ...option.RequestOption) (res *bool, err error) { - opts = append(r.Options[:], opts...) + opts = slices.Concat(r.Options, opts) path := "tui/submit-prompt" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) return From 6dad7c5574587294fa0de48980b861d74c46b5d9 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Tue, 7 Oct 2025 16:16:19 -0400 Subject: [PATCH 7/7] add free workspace --- packages/console/app/src/routes/zen/handler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/console/app/src/routes/zen/handler.ts b/packages/console/app/src/routes/zen/handler.ts index feb0c9c3e..4a658cd9d 100644 --- a/packages/console/app/src/routes/zen/handler.ts +++ b/packages/console/app/src/routes/zen/handler.ts @@ -41,6 +41,7 @@ export async function handler( const FREE_WORKSPACES = [ "wrk_01K46JDFR0E75SG2Q8K172KF3Y", // frank + "wrk_01K6W1A3VE0KMNVSCQT43BG2SX", // opencode bench ] const logger = {