From 57120e69edadb5dd6a03538ee8dfb85a228d5173 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 11 Dec 2025 23:41:04 -0500 Subject: [PATCH 01/30] Zen: sync --- infra/console.ts | 1 + .../routes/workspace/[id]/model-section.tsx | 7 ++++-- .../app/src/routes/zen/util/handler.ts | 15 +++++++---- .../app/src/routes/zen/util/trialLimiter.ts | 18 ++++++++----- .../console/core/script/promote-models.ts | 5 +++- packages/console/core/script/pull-models.ts | 5 +++- packages/console/core/script/update-models.ts | 11 +++++--- packages/console/core/src/model.ts | 25 +++++++++++++------ packages/console/core/sst-env.d.ts | 12 ++++++--- packages/console/function/sst-env.d.ts | 12 ++++++--- packages/console/resource/sst-env.d.ts | 12 ++++++--- packages/enterprise/sst-env.d.ts | 12 ++++++--- packages/function/sst-env.d.ts | 12 ++++++--- sst-env.d.ts | 12 ++++++--- 14 files changed, 109 insertions(+), 50 deletions(-) diff --git a/infra/console.ts b/infra/console.ts index 0a98ab0723..8f54823f84 100644 --- a/infra/console.ts +++ b/infra/console.ts @@ -102,6 +102,7 @@ const ZEN_MODELS = [ new sst.Secret("ZEN_MODELS2"), new sst.Secret("ZEN_MODELS3"), new sst.Secret("ZEN_MODELS4"), + new sst.Secret("ZEN_MODELS5"), ] const STRIPE_SECRET_KEY = new sst.Secret("STRIPE_SECRET_KEY") const AUTH_API_URL = new sst.Linkable("AUTH_API_URL", { diff --git a/packages/console/app/src/routes/workspace/[id]/model-section.tsx b/packages/console/app/src/routes/workspace/[id]/model-section.tsx index 30815336d6..e760ccea25 100644 --- a/packages/console/app/src/routes/workspace/[id]/model-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/model-section.tsx @@ -43,9 +43,12 @@ const getModelsInfo = query(async (workspaceID: string) => { const pA = getPriority(idA) const pB = getPriority(idB) if (pA !== pB) return pA - pB - return modelA.name.localeCompare(modelB.name) + + const modelAName = Array.isArray(modelA) ? modelA[0].name : modelA.name + const modelBName = Array.isArray(modelB) ? modelB[0].name : modelB.name + return modelAName.localeCompare(modelBName) }) - .map(([id, model]) => ({ id, name: model.name })), + .map(([id, model]) => ({ id, name: Array.isArray(model) ? model[0].name : model.name })), disabled: await Model.listDisabled(), } }, workspaceID) diff --git a/packages/console/app/src/routes/zen/util/handler.ts b/packages/console/app/src/routes/zen/util/handler.ts index 7d7767b8df..5e9c877cc3 100644 --- a/packages/console/app/src/routes/zen/util/handler.ts +++ b/packages/console/app/src/routes/zen/util/handler.ts @@ -57,15 +57,17 @@ export async function handler( const sessionId = input.request.headers.get("x-opencode-session") ?? "" const requestId = input.request.headers.get("x-opencode-request") ?? "" const projectId = input.request.headers.get("x-opencode-project") ?? "" + const ocClient = input.request.headers.get("x-opencode-client") ?? "" logger.metric({ is_tream: isStream, session: sessionId, request: requestId, + client: ocClient, }) const zenData = ZenData.list() const modelInfo = validateModel(zenData, model) const dataDumper = createDataDumper(sessionId, requestId, projectId) - const trialLimiter = createTrialLimiter(modelInfo.trial?.limit, ip) + const trialLimiter = createTrialLimiter(modelInfo.trial, ip, ocClient) const isTrial = await trialLimiter?.isTrial() const rateLimiter = createRateLimiter(modelInfo.id, modelInfo.rateLimit, ip) await rateLimiter?.check() @@ -286,11 +288,14 @@ export async function handler( } function validateModel(zenData: ZenData, reqModel: string) { - if (!(reqModel in zenData.models)) { - throw new ModelError(`Model ${reqModel} not supported`) - } + if (!(reqModel in zenData.models)) throw new ModelError(`Model ${reqModel} not supported`) + const modelId = reqModel as keyof typeof zenData.models - const modelData = zenData.models[modelId] + const modelData = Array.isArray(zenData.models[modelId]) + ? zenData.models[modelId].find((model) => opts.format === model.formatFilter) + : zenData.models[modelId] + + if (!modelData) throw new ModelError(`Model ${reqModel} not supported for format ${opts.format}`) logger.metric({ model: modelId }) diff --git a/packages/console/app/src/routes/zen/util/trialLimiter.ts b/packages/console/app/src/routes/zen/util/trialLimiter.ts index 15561c9f6b..531e5cf0c3 100644 --- a/packages/console/app/src/routes/zen/util/trialLimiter.ts +++ b/packages/console/app/src/routes/zen/util/trialLimiter.ts @@ -1,12 +1,18 @@ import { Database, eq, sql } from "@opencode-ai/console-core/drizzle/index.js" import { IpTable } from "@opencode-ai/console-core/schema/ip.sql.js" import { UsageInfo } from "./provider/provider" +import { ZenData } from "@opencode-ai/console-core/model.js" -export function createTrialLimiter(limit: number | undefined, ip: string) { - if (!limit) return +export function createTrialLimiter(trial: ZenData.Trial | undefined, ip: string, client: string) { + if (!trial) return if (!ip) return - let trial: boolean + const limit = + trial.limits.find((limit) => limit.client === client)?.limit ?? + trial.limits.find((limit) => limit.client === undefined)?.limit + if (!limit) return + + let _isTrial: boolean return { isTrial: async () => { @@ -20,11 +26,11 @@ export function createTrialLimiter(limit: number | undefined, ip: string) { .then((rows) => rows[0]), ) - trial = (data?.usage ?? 0) < limit - return trial + _isTrial = (data?.usage ?? 0) < limit + return _isTrial }, track: async (usageInfo: UsageInfo) => { - if (!trial) return + if (!_isTrial) return const usage = usageInfo.inputTokens + usageInfo.outputTokens + diff --git a/packages/console/core/script/promote-models.ts b/packages/console/core/script/promote-models.ts index 0ff859df8e..bebef5cfb5 100755 --- a/packages/console/core/script/promote-models.ts +++ b/packages/console/core/script/promote-models.ts @@ -16,16 +16,19 @@ const value1 = lines.find((line) => line.startsWith("ZEN_MODELS1"))?.split("=")[ const value2 = lines.find((line) => line.startsWith("ZEN_MODELS2"))?.split("=")[1] const value3 = lines.find((line) => line.startsWith("ZEN_MODELS3"))?.split("=")[1] const value4 = lines.find((line) => line.startsWith("ZEN_MODELS4"))?.split("=")[1] +const value5 = lines.find((line) => line.startsWith("ZEN_MODELS5"))?.split("=")[1] if (!value1) throw new Error("ZEN_MODELS1 not found") if (!value2) throw new Error("ZEN_MODELS2 not found") if (!value3) throw new Error("ZEN_MODELS3 not found") if (!value4) throw new Error("ZEN_MODELS4 not found") +if (!value5) throw new Error("ZEN_MODELS5 not found") // validate value -ZenData.validate(JSON.parse(value1 + value2 + value3 + value4)) +ZenData.validate(JSON.parse(value1 + value2 + value3 + value4 + value5)) // update the secret await $`bun sst secret set ZEN_MODELS1 ${value1} --stage ${stage}` await $`bun sst secret set ZEN_MODELS2 ${value2} --stage ${stage}` await $`bun sst secret set ZEN_MODELS3 ${value3} --stage ${stage}` await $`bun sst secret set ZEN_MODELS4 ${value4} --stage ${stage}` +await $`bun sst secret set ZEN_MODELS5 ${value5} --stage ${stage}` diff --git a/packages/console/core/script/pull-models.ts b/packages/console/core/script/pull-models.ts index a89e3951c8..afa865625b 100755 --- a/packages/console/core/script/pull-models.ts +++ b/packages/console/core/script/pull-models.ts @@ -16,16 +16,19 @@ const value1 = lines.find((line) => line.startsWith("ZEN_MODELS1"))?.split("=")[ const value2 = lines.find((line) => line.startsWith("ZEN_MODELS2"))?.split("=")[1] const value3 = lines.find((line) => line.startsWith("ZEN_MODELS3"))?.split("=")[1] const value4 = lines.find((line) => line.startsWith("ZEN_MODELS4"))?.split("=")[1] +const value5 = lines.find((line) => line.startsWith("ZEN_MODELS5"))?.split("=")[1] if (!value1) throw new Error("ZEN_MODELS1 not found") if (!value2) throw new Error("ZEN_MODELS2 not found") if (!value3) throw new Error("ZEN_MODELS3 not found") if (!value4) throw new Error("ZEN_MODELS4 not found") +if (!value5) throw new Error("ZEN_MODELS5 not found") // validate value -ZenData.validate(JSON.parse(value1 + value2 + value3 + value4)) +ZenData.validate(JSON.parse(value1 + value2 + value3 + value4 + value5)) // update the secret await $`bun sst secret set ZEN_MODELS1 ${value1}` await $`bun sst secret set ZEN_MODELS2 ${value2}` await $`bun sst secret set ZEN_MODELS3 ${value3}` await $`bun sst secret set ZEN_MODELS4 ${value4}` +await $`bun sst secret set ZEN_MODELS5 ${value5}` diff --git a/packages/console/core/script/update-models.ts b/packages/console/core/script/update-models.ts index a8523a5f20..5d40b4d5a3 100755 --- a/packages/console/core/script/update-models.ts +++ b/packages/console/core/script/update-models.ts @@ -14,15 +14,17 @@ const oldValue1 = lines.find((line) => line.startsWith("ZEN_MODELS1"))?.split("= const oldValue2 = lines.find((line) => line.startsWith("ZEN_MODELS2"))?.split("=")[1] const oldValue3 = lines.find((line) => line.startsWith("ZEN_MODELS3"))?.split("=")[1] const oldValue4 = lines.find((line) => line.startsWith("ZEN_MODELS4"))?.split("=")[1] +const oldValue5 = lines.find((line) => line.startsWith("ZEN_MODELS5"))?.split("=")[1] if (!oldValue1) throw new Error("ZEN_MODELS1 not found") if (!oldValue2) throw new Error("ZEN_MODELS2 not found") if (!oldValue3) throw new Error("ZEN_MODELS3 not found") if (!oldValue4) throw new Error("ZEN_MODELS4 not found") +if (!oldValue5) throw new Error("ZEN_MODELS5 not found") // store the prettified json to a temp file const filename = `models-${Date.now()}.json` const tempFile = Bun.file(path.join(os.tmpdir(), filename)) -await tempFile.write(JSON.stringify(JSON.parse(oldValue1 + oldValue2 + oldValue3 + oldValue4), null, 2)) +await tempFile.write(JSON.stringify(JSON.parse(oldValue1 + oldValue2 + oldValue3 + oldValue4 + oldValue5), null, 2)) console.log("tempFile", tempFile.name) // open temp file in vim and read the file on close @@ -31,12 +33,15 @@ const newValue = JSON.stringify(JSON.parse(await tempFile.text())) ZenData.validate(JSON.parse(newValue)) // update the secret -const chunk = Math.ceil(newValue.length / 4) +const chunk = Math.ceil(newValue.length / 5) const newValue1 = newValue.slice(0, chunk) const newValue2 = newValue.slice(chunk, chunk * 2) const newValue3 = newValue.slice(chunk * 2, chunk * 3) -const newValue4 = newValue.slice(chunk * 3) +const newValue4 = newValue.slice(chunk * 3, chunk * 4) +const newValue5 = newValue.slice(chunk * 4) + await $`bun sst secret set ZEN_MODELS1 ${newValue1}` await $`bun sst secret set ZEN_MODELS2 ${newValue2}` await $`bun sst secret set ZEN_MODELS3 ${newValue3}` await $`bun sst secret set ZEN_MODELS4 ${newValue4}` +await $`bun sst secret set ZEN_MODELS5 ${newValue5}` diff --git a/packages/console/core/src/model.ts b/packages/console/core/src/model.ts index 47ba3e9d83..55d6c895c5 100644 --- a/packages/console/core/src/model.ts +++ b/packages/console/core/src/model.ts @@ -9,7 +9,17 @@ import { Resource } from "@opencode-ai/console-resource" export namespace ZenData { const FormatSchema = z.enum(["anthropic", "google", "openai", "oa-compat"]) + const TrialSchema = z.object({ + provider: z.string(), + limits: z.array( + z.object({ + limit: z.number(), + client: z.enum(["cli", "desktop"]).optional(), + }), + ), + }) export type Format = z.infer + export type Trial = z.infer const ModelCostSchema = z.object({ input: z.number(), @@ -26,12 +36,7 @@ export namespace ZenData { allowAnonymous: z.boolean().optional(), byokProvider: z.enum(["openai", "anthropic", "google"]).optional(), stickyProvider: z.boolean().optional(), - trial: z - .object({ - limit: z.number(), - provider: z.string(), - }) - .optional(), + trial: TrialSchema.optional(), rateLimit: z.number().optional(), fallbackProvider: z.string().optional(), providers: z.array( @@ -53,7 +58,7 @@ export namespace ZenData { }) const ModelsSchema = z.object({ - models: z.record(z.string(), ModelSchema), + models: z.record(z.string(), z.union([ModelSchema, z.array(ModelSchema.extend({ formatFilter: FormatSchema }))])), providers: z.record(z.string(), ProviderSchema), }) @@ -63,7 +68,11 @@ export namespace ZenData { export const list = fn(z.void(), () => { const json = JSON.parse( - Resource.ZEN_MODELS1.value + Resource.ZEN_MODELS2.value + Resource.ZEN_MODELS3.value + Resource.ZEN_MODELS4.value, + Resource.ZEN_MODELS1.value + + Resource.ZEN_MODELS2.value + + Resource.ZEN_MODELS3.value + + Resource.ZEN_MODELS4.value + + Resource.ZEN_MODELS5.value, ) return ModelsSchema.parse(json) }) diff --git a/packages/console/core/sst-env.d.ts b/packages/console/core/sst-env.d.ts index 0b09bfd0cd..632ea3fbe7 100644 --- a/packages/console/core/sst-env.d.ts +++ b/packages/console/core/sst-env.d.ts @@ -50,10 +50,6 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } - "Enterprise": { - "type": "sst.cloudflare.SolidStart" - "url": string - } "GITHUB_APP_ID": { "type": "sst.sst.Secret" "value": string @@ -94,6 +90,10 @@ declare module "sst" { "type": "sst.sst.Linkable" "value": string } + "Teams": { + "type": "sst.cloudflare.SolidStart" + "url": string + } "Web": { "type": "sst.cloudflare.Astro" "url": string @@ -114,6 +114,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS5": { + "type": "sst.sst.Secret" + "value": string + } } } // cloudflare diff --git a/packages/console/function/sst-env.d.ts b/packages/console/function/sst-env.d.ts index 0b09bfd0cd..632ea3fbe7 100644 --- a/packages/console/function/sst-env.d.ts +++ b/packages/console/function/sst-env.d.ts @@ -50,10 +50,6 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } - "Enterprise": { - "type": "sst.cloudflare.SolidStart" - "url": string - } "GITHUB_APP_ID": { "type": "sst.sst.Secret" "value": string @@ -94,6 +90,10 @@ declare module "sst" { "type": "sst.sst.Linkable" "value": string } + "Teams": { + "type": "sst.cloudflare.SolidStart" + "url": string + } "Web": { "type": "sst.cloudflare.Astro" "url": string @@ -114,6 +114,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS5": { + "type": "sst.sst.Secret" + "value": string + } } } // cloudflare diff --git a/packages/console/resource/sst-env.d.ts b/packages/console/resource/sst-env.d.ts index 0b09bfd0cd..632ea3fbe7 100644 --- a/packages/console/resource/sst-env.d.ts +++ b/packages/console/resource/sst-env.d.ts @@ -50,10 +50,6 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } - "Enterprise": { - "type": "sst.cloudflare.SolidStart" - "url": string - } "GITHUB_APP_ID": { "type": "sst.sst.Secret" "value": string @@ -94,6 +90,10 @@ declare module "sst" { "type": "sst.sst.Linkable" "value": string } + "Teams": { + "type": "sst.cloudflare.SolidStart" + "url": string + } "Web": { "type": "sst.cloudflare.Astro" "url": string @@ -114,6 +114,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS5": { + "type": "sst.sst.Secret" + "value": string + } } } // cloudflare diff --git a/packages/enterprise/sst-env.d.ts b/packages/enterprise/sst-env.d.ts index 0b09bfd0cd..632ea3fbe7 100644 --- a/packages/enterprise/sst-env.d.ts +++ b/packages/enterprise/sst-env.d.ts @@ -50,10 +50,6 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } - "Enterprise": { - "type": "sst.cloudflare.SolidStart" - "url": string - } "GITHUB_APP_ID": { "type": "sst.sst.Secret" "value": string @@ -94,6 +90,10 @@ declare module "sst" { "type": "sst.sst.Linkable" "value": string } + "Teams": { + "type": "sst.cloudflare.SolidStart" + "url": string + } "Web": { "type": "sst.cloudflare.Astro" "url": string @@ -114,6 +114,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS5": { + "type": "sst.sst.Secret" + "value": string + } } } // cloudflare diff --git a/packages/function/sst-env.d.ts b/packages/function/sst-env.d.ts index 0b09bfd0cd..632ea3fbe7 100644 --- a/packages/function/sst-env.d.ts +++ b/packages/function/sst-env.d.ts @@ -50,10 +50,6 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } - "Enterprise": { - "type": "sst.cloudflare.SolidStart" - "url": string - } "GITHUB_APP_ID": { "type": "sst.sst.Secret" "value": string @@ -94,6 +90,10 @@ declare module "sst" { "type": "sst.sst.Linkable" "value": string } + "Teams": { + "type": "sst.cloudflare.SolidStart" + "url": string + } "Web": { "type": "sst.cloudflare.Astro" "url": string @@ -114,6 +114,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS5": { + "type": "sst.sst.Secret" + "value": string + } } } // cloudflare diff --git a/sst-env.d.ts b/sst-env.d.ts index 247b0ba810..2c182ec355 100644 --- a/sst-env.d.ts +++ b/sst-env.d.ts @@ -65,10 +65,6 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } - "Enterprise": { - "type": "sst.cloudflare.SolidStart" - "url": string - } "EnterpriseStorage": { "name": string "type": "sst.cloudflare.Bucket" @@ -120,6 +116,10 @@ declare module "sst" { "type": "sst.sst.Linkable" "value": string } + "Teams": { + "type": "sst.cloudflare.SolidStart" + "url": string + } "Web": { "type": "sst.cloudflare.Astro" "url": string @@ -140,6 +140,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "ZEN_MODELS5": { + "type": "sst.sst.Secret" + "value": string + } "ZenData": { "name": string "type": "sst.cloudflare.Bucket" From 7ec48dfd1512e8a70bd03aaa1994f14da209aac5 Mon Sep 17 00:00:00 2001 From: Viktor Forsman Date: Fri, 12 Dec 2025 13:20:38 +0800 Subject: [PATCH 02/30] fix: debug lsp diagnostics cmd for certain lsps (#5420) --- packages/opencode/src/cli/cmd/debug/lsp.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/opencode/src/cli/cmd/debug/lsp.ts b/packages/opencode/src/cli/cmd/debug/lsp.ts index 2f59771958..97cb1a0f3b 100644 --- a/packages/opencode/src/cli/cmd/debug/lsp.ts +++ b/packages/opencode/src/cli/cmd/debug/lsp.ts @@ -17,6 +17,7 @@ const DiagnosticsCommand = cmd({ async handler(args) { await bootstrap(process.cwd(), async () => { await LSP.touchFile(args.file, true) + await Bun.sleep(1000) process.stdout.write(JSON.stringify(await LSP.diagnostics(), null, 2) + EOL) }) }, From 0b1731142e8dd126d464238d9c807a1bf124bb2a Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Fri, 12 Dec 2025 16:58:37 +0800 Subject: [PATCH 03/30] tauri: initialise store and window-state plugins --- bun.lock | 6 +++ packages/tauri/package.json | 2 + packages/tauri/src-tauri/Cargo.lock | 45 +++++++++++++++++++ packages/tauri/src-tauri/Cargo.toml | 4 +- .../tauri/src-tauri/capabilities/default.json | 8 +++- packages/tauri/src-tauri/src/lib.rs | 2 + 6 files changed, 64 insertions(+), 3 deletions(-) diff --git a/bun.lock b/bun.lock index 5b3d864de5..eba116719c 100644 --- a/bun.lock +++ b/bun.lock @@ -357,7 +357,9 @@ "@tauri-apps/plugin-opener": "^2", "@tauri-apps/plugin-process": "~2", "@tauri-apps/plugin-shell": "~2", + "@tauri-apps/plugin-store": "~2", "@tauri-apps/plugin-updater": "~2", + "@tauri-apps/plugin-window-state": "~2", "solid-js": "catalog:", }, "devDependencies": { @@ -1662,8 +1664,12 @@ "@tauri-apps/plugin-shell": ["@tauri-apps/plugin-shell@2.3.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-Xod+pRcFxmOWFWEnqH5yZcA7qwAMuaaDkMR1Sply+F8VfBj++CGnj2xf5UoialmjZ2Cvd8qrvSCbU+7GgNVsKQ=="], + "@tauri-apps/plugin-store": ["@tauri-apps/plugin-store@2.4.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-ckGSEzZ5Ii4Hf2D5x25Oqnm2Zf9MfDWAzR+volY0z/OOBz6aucPKEY0F649JvQ0Vupku6UJo7ugpGRDOFOunkA=="], + "@tauri-apps/plugin-updater": ["@tauri-apps/plugin-updater@2.9.0", "", { "dependencies": { "@tauri-apps/api": "^2.6.0" } }, "sha512-j++sgY8XpeDvzImTrzWA08OqqGqgkNyxczLD7FjNJJx/uXxMZFz5nDcfkyoI/rCjYuj2101Tci/r/HFmOmoxCg=="], + "@tauri-apps/plugin-window-state": ["@tauri-apps/plugin-window-state@2.4.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-OuvdrzyY8Q5Dbzpj+GcrnV1iCeoZbcFdzMjanZMMcAEUNy/6PH5pxZPXpaZLOR7whlzXiuzx0L9EKZbH7zpdRw=="], + "@thisbeyond/solid-dnd": ["@thisbeyond/solid-dnd@0.7.5", "", { "peerDependencies": { "solid-js": "^1.5" } }, "sha512-DfI5ff+yYGpK9M21LhYwIPlbP2msKxN2ARwuu6GF8tT1GgNVDTI8VCQvH4TJFoVApP9d44izmAcTh/iTCH2UUw=="], "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], diff --git a/packages/tauri/package.json b/packages/tauri/package.json index fa98238b85..7e0f670b48 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -18,7 +18,9 @@ "@tauri-apps/plugin-opener": "^2", "@tauri-apps/plugin-process": "~2", "@tauri-apps/plugin-shell": "~2", + "@tauri-apps/plugin-store": "~2", "@tauri-apps/plugin-updater": "~2", + "@tauri-apps/plugin-window-state": "~2", "solid-js": "catalog:" }, "devDependencies": { diff --git a/packages/tauri/src-tauri/Cargo.lock b/packages/tauri/src-tauri/Cargo.lock index 57d463355e..b42329d750 100644 --- a/packages/tauri/src-tauri/Cargo.lock +++ b/packages/tauri/src-tauri/Cargo.lock @@ -2513,7 +2513,9 @@ dependencies = [ "tauri-plugin-opener", "tauri-plugin-process", "tauri-plugin-shell", + "tauri-plugin-store", "tauri-plugin-updater", + "tauri-plugin-window-state", "tokio", ] @@ -4175,6 +4177,22 @@ dependencies = [ "tokio", ] +[[package]] +name = "tauri-plugin-store" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a77036340a97eb5bbe1b3209c31e5f27f75e6f92a52fd9dd4b211ef08bf310" +dependencies = [ + "dunce", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.17", + "tokio", + "tracing", +] + [[package]] name = "tauri-plugin-updater" version = "2.9.0" @@ -4207,6 +4225,21 @@ dependencies = [ "zip", ] +[[package]] +name = "tauri-plugin-window-state" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73736611e14142408d15353e21e3cca2f12a3cfb523ad0ce85999b6d2ef1a704" +dependencies = [ + "bitflags 2.10.0", + "log", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.17", +] + [[package]] name = "tauri-runtime" version = "2.9.1" @@ -4440,10 +4473,22 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "socket2", + "tokio-macros", "tracing", "windows-sys 0.61.2", ] +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "tokio-rustls" version = "0.26.4" diff --git a/packages/tauri/src-tauri/Cargo.toml b/packages/tauri/src-tauri/Cargo.toml index c6b0e409b0..f72e5f428d 100644 --- a/packages/tauri/src-tauri/Cargo.toml +++ b/packages/tauri/src-tauri/Cargo.toml @@ -23,9 +23,11 @@ tauri-plugin-opener = "2" tauri-plugin-shell = "2" tauri-plugin-dialog = "2" tauri-plugin-updater = "2" +tauri-plugin-process = "2" +tauri-plugin-store = "2" +tauri-plugin-window-state = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = "1.48.0" listeners = "0.3" -tauri-plugin-process = "2" diff --git a/packages/tauri/src-tauri/capabilities/default.json b/packages/tauri/src-tauri/capabilities/default.json index ef5a207b4e..bd4ede0582 100644 --- a/packages/tauri/src-tauri/capabilities/default.json +++ b/packages/tauri/src-tauri/capabilities/default.json @@ -2,7 +2,9 @@ "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "description": "Capability for the main window", - "windows": ["main"], + "windows": [ + "main" + ], "permissions": [ "core:default", "opener:default", @@ -11,6 +13,8 @@ "shell:default", "updater:default", "dialog:default", - "process:default" + "process:default", + "store:default", + "window-state:default" ] } diff --git a/packages/tauri/src-tauri/src/lib.rs b/packages/tauri/src-tauri/src/lib.rs index 5c4304d51a..c04faafab6 100644 --- a/packages/tauri/src-tauri/src/lib.rs +++ b/packages/tauri/src-tauri/src/lib.rs @@ -107,6 +107,8 @@ pub fn run() { let updater_enabled = option_env!("TAURI_SIGNING_PRIVATE_KEY").is_some(); let mut builder = tauri::Builder::default() + .plugin(tauri_plugin_window_state::Builder::new().build()) + .plugin(tauri_plugin_store::Builder::new().build()) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_process::init()) From 9a70eb538b13687747cd00c7f377486964ceb73e Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Fri, 12 Dec 2025 08:59:18 +0000 Subject: [PATCH 04/30] chore: format code --- packages/tauri/src-tauri/capabilities/default.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/tauri/src-tauri/capabilities/default.json b/packages/tauri/src-tauri/capabilities/default.json index bd4ede0582..320586de4c 100644 --- a/packages/tauri/src-tauri/capabilities/default.json +++ b/packages/tauri/src-tauri/capabilities/default.json @@ -2,9 +2,7 @@ "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "description": "Capability for the main window", - "windows": [ - "main" - ], + "windows": ["main"], "permissions": [ "core:default", "opener:default", From 147111c9c660f4d6e8f25f80d235e12d3441068e Mon Sep 17 00:00:00 2001 From: Github Action Date: Fri, 12 Dec 2025 09:00:19 +0000 Subject: [PATCH 05/30] Update Nix flake.lock and hashes --- flake.lock | 6 +++--- nix/hashes.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 4822d9da57..58344d82c4 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1765270179, - "narHash": "sha256-g2a4MhRKu4ymR4xwo+I+auTknXt/+j37Lnf0Mvfl1rE=", + "lastModified": 1765425892, + "narHash": "sha256-jlQpSkg2sK6IJVzTQBDyRxQZgKADC2HKMRfGCSgNMHo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "677fbe97984e7af3175b6c121f3c39ee5c8d62c9", + "rev": "5d6bdbddb4695a62f0d00a3620b37a15275a5093", "type": "github" }, "original": { diff --git a/nix/hashes.json b/nix/hashes.json index 53a696f851..18d4621edd 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,3 +1,3 @@ { - "nodeModules": "sha256-3GaqUwomnIUW8MqUi1jDVPHQ/C5Z+D9wMR//tAGxvSQ=" + "nodeModules": "sha256-b6AEbARiEcI/Pu1g0LbRfH1Oo5rClncW44Ug0d4oP0w=" } From f9d5e1879056dd9507bb1a1645da5b5ede87fcca Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Fri, 12 Dec 2025 17:04:00 +0800 Subject: [PATCH 06/30] tauri: create window with full screen size --- packages/tauri/src-tauri/src/lib.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/tauri/src-tauri/src/lib.rs b/packages/tauri/src-tauri/src/lib.rs index c04faafab6..eb712235ec 100644 --- a/packages/tauri/src-tauri/src/lib.rs +++ b/packages/tauri/src-tauri/src/lib.rs @@ -4,7 +4,7 @@ use std::{ sync::{Arc, Mutex}, time::{Duration, Instant}, }; -use tauri::{AppHandle, Manager, RunEvent, WebviewUrl, WebviewWindow}; +use tauri::{AppHandle, LogicalSize, Manager, Monitor, RunEvent, WebviewUrl, WebviewWindow}; use tauri_plugin_dialog::{DialogExt, MessageDialogButtons, MessageDialogResult}; use tauri_plugin_shell::process::{CommandChild, CommandEvent}; use tauri_plugin_shell::ShellExt; @@ -169,10 +169,15 @@ pub fn run() { None }; + let primary_monitor = app.primary_monitor().ok().flatten(); + let size = primary_monitor + .map(|m| m.size().to_logical(m.scale_factor())) + .unwrap_or(LogicalSize::new(1920, 1080)); + let mut window_builder = WebviewWindow::builder(&app, "main", WebviewUrl::App("/".into())) .title("OpenCode") - .inner_size(800.0, 600.0) + .inner_size(size.width as f64, size.height as f64) .decorations(true) .zoom_hotkeys_enabled(true) .initialization_script(format!( From b803a9732d93375100c704b5e665a28efa2ddd08 Mon Sep 17 00:00:00 2001 From: David Hill Date: Fri, 12 Dec 2025 09:43:41 +0000 Subject: [PATCH 07/30] fix: make the logo on the home screen non-selectable --- packages/opencode/src/cli/cmd/tui/component/logo.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/logo.tsx b/packages/opencode/src/cli/cmd/tui/component/logo.tsx index 4f51215965..d1be06a7f2 100644 --- a/packages/opencode/src/cli/cmd/tui/component/logo.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/logo.tsx @@ -1,4 +1,3 @@ -import { Installation } from "@/installation" import { TextAttributes } from "@opentui/core" import { For } from "solid-js" import { useTheme } from "@tui/context/theme" @@ -14,8 +13,10 @@ export function Logo() { {(line, index) => ( - {line} - + + {line} + + {LOGO_RIGHT[index()]} From 4c02d515a1e15a99fc009587e821087e042bd45b Mon Sep 17 00:00:00 2001 From: David Hill Date: Fri, 12 Dec 2025 09:44:04 +0000 Subject: [PATCH 08/30] wip: desktop sidebar icon updates --- packages/desktop/src/pages/layout.tsx | 4 ++-- packages/ui/src/components/icon.tsx | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx index 39917c4208..257cfc8a3d 100644 --- a/packages/desktop/src/pages/layout.tsx +++ b/packages/desktop/src/pages/layout.tsx @@ -498,7 +498,7 @@ export default function Layout(props: ParentProps) { @@ -196,14 +248,7 @@ export default function Layout(props: ParentProps) { data-selected={props.project.worktree === currentDirectory()} onClick={() => navigateToProject(props.project.worktree)} > -
- -
+ @@ -211,35 +256,30 @@ export default function Layout(props: ParentProps) { } const SortableProject = (props: { project: Project & { expanded: boolean } }): JSX.Element => { + const notification = useNotification() const sortable = createSortable(props.project.worktree) const [projectStore] = globalSync.child(props.project.worktree) const slug = createMemo(() => base64Encode(props.project.worktree)) const name = createMemo(() => getFilename(props.project.worktree)) + const [expanded, setExpanded] = createSignal(true) return ( // @ts-ignore
- + diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx index ad39880308..0dbd7a6500 100644 --- a/packages/ui/src/components/icon.tsx +++ b/packages/ui/src/components/icon.tsx @@ -4,6 +4,7 @@ const icons = { "align-right": ``, "arrow-up": ``, "arrow-left": ``, + archive: ``, "bubble-5": ``, "bullet-list": ``, "check-small": ``, From 59d4041aa4221e4fbb2f347ee5b8e82eb82e434a Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Fri, 12 Dec 2025 23:37:17 +0800 Subject: [PATCH 16/30] tauri: add basic custom titlebar (#5438) --- bun.lock | 3 + nix/hashes.json | 2 +- packages/desktop/index.html | 4 +- packages/desktop/src/pages/layout.tsx | 4 +- packages/tauri/index.html | 4 +- packages/tauri/package.json | 1 + packages/tauri/src-tauri/Cargo.lock | 84 +++++++++++++++++++ packages/tauri/src-tauri/Cargo.toml | 1 + .../tauri/src-tauri/capabilities/default.json | 3 +- packages/tauri/src-tauri/src/lib.rs | 6 +- packages/tauri/src/index.tsx | 4 + 11 files changed, 107 insertions(+), 9 deletions(-) diff --git a/bun.lock b/bun.lock index d9cdd91d9e..9d5819b153 100644 --- a/bun.lock +++ b/bun.lock @@ -356,6 +356,7 @@ "@tauri-apps/api": "^2", "@tauri-apps/plugin-dialog": "~2", "@tauri-apps/plugin-opener": "^2", + "@tauri-apps/plugin-os": "~2", "@tauri-apps/plugin-process": "~2", "@tauri-apps/plugin-shell": "~2", "@tauri-apps/plugin-store": "~2", @@ -1663,6 +1664,8 @@ "@tauri-apps/plugin-opener": ["@tauri-apps/plugin-opener@2.5.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-ei/yRRoCklWHImwpCcDK3VhNXx+QXM9793aQ64YxpqVF0BDuuIlXhZgiAkc15wnPVav+IbkYhmDJIv5R326Mew=="], + "@tauri-apps/plugin-os": ["@tauri-apps/plugin-os@2.3.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-n+nXWeuSeF9wcEsSPmRnBEGrRgOy6jjkSU+UVCOV8YUGKb2erhDOxis7IqRXiRVHhY8XMKks00BJ0OAdkpf6+A=="], + "@tauri-apps/plugin-process": ["@tauri-apps/plugin-process@2.3.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-nCa4fGVaDL/B9ai03VyPOjfAHRHSBz5v6F/ObsB73r/dA3MHHhZtldaDMIc0V/pnUw9ehzr2iEG+XkSEyC0JJA=="], "@tauri-apps/plugin-shell": ["@tauri-apps/plugin-shell@2.3.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-Xod+pRcFxmOWFWEnqH5yZcA7qwAMuaaDkMR1Sply+F8VfBj++CGnj2xf5UoialmjZ2Cvd8qrvSCbU+7GgNVsKQ=="], diff --git a/nix/hashes.json b/nix/hashes.json index 14ea1d55da..b640219471 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,3 +1,3 @@ { - "nodeModules": "sha256-JiPLmRyjpwiAJSDO6Sah/cMdncMicqQqGrBVOAVHMWA=" + "nodeModules": "sha256-3CG0wAMQp2E6ghPUXbYaYifJorp9b1WvCtHD+o8Nhck=" } diff --git a/packages/desktop/index.html b/packages/desktop/index.html index b9d3e53512..9803517a07 100644 --- a/packages/desktop/index.html +++ b/packages/desktop/index.html @@ -14,7 +14,7 @@ - + -
+
diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx index c34904e119..d270068357 100644 --- a/packages/desktop/src/pages/layout.tsx +++ b/packages/desktop/src/pages/layout.tsx @@ -426,7 +426,7 @@ export default function Layout(props: ParentProps) { } return ( -
+ -
+
- + -
+
diff --git a/packages/tauri/package.json b/packages/tauri/package.json index 7e0f670b48..d712f15f4a 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -16,6 +16,7 @@ "@tauri-apps/api": "^2", "@tauri-apps/plugin-dialog": "~2", "@tauri-apps/plugin-opener": "^2", + "@tauri-apps/plugin-os": "~2", "@tauri-apps/plugin-process": "~2", "@tauri-apps/plugin-shell": "~2", "@tauri-apps/plugin-store": "~2", diff --git a/packages/tauri/src-tauri/Cargo.lock b/packages/tauri/src-tauri/Cargo.lock index b42329d750..42a7dae81d 100644 --- a/packages/tauri/src-tauri/Cargo.lock +++ b/packages/tauri/src-tauri/Cargo.lock @@ -1256,6 +1256,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix", + "windows-link 0.2.1", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -2309,6 +2319,16 @@ dependencies = [ "objc2-foundation 0.3.2", ] +[[package]] +name = "objc2-core-location" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" +dependencies = [ + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + [[package]] name = "objc2-core-text" version = "0.3.2" @@ -2440,6 +2460,7 @@ checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ "bitflags 2.10.0", "objc2 0.6.3", + "objc2-core-foundation", "objc2-foundation 0.3.2", ] @@ -2461,8 +2482,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ "bitflags 2.10.0", + "block2 0.6.2", "objc2 0.6.3", + "objc2-cloud-kit", + "objc2-core-data", "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-location", + "objc2-core-text", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" +dependencies = [ + "objc2 0.6.3", "objc2-foundation 0.3.2", ] @@ -2511,6 +2551,7 @@ dependencies = [ "tauri-build", "tauri-plugin-dialog", "tauri-plugin-opener", + "tauri-plugin-os", "tauri-plugin-process", "tauri-plugin-shell", "tauri-plugin-store", @@ -2535,6 +2576,22 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "os_info" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c39b5918402d564846d5aba164c09a66cc88d232179dfd3e3c619a25a268392" +dependencies = [ + "android_system_properties", + "log", + "nix", + "objc2 0.6.3", + "objc2-foundation 0.3.2", + "objc2-ui-kit", + "serde", + "windows-sys 0.61.2", +] + [[package]] name = "os_pipe" version = "1.2.3" @@ -3872,6 +3929,15 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -4146,6 +4212,24 @@ dependencies = [ "zbus", ] +[[package]] +name = "tauri-plugin-os" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f08346c8deb39e96f86973da0e2d76cbb933d7ac9b750f6dc4daf955a6f997" +dependencies = [ + "gethostname", + "log", + "os_info", + "serde", + "serde_json", + "serialize-to-javascript", + "sys-locale", + "tauri", + "tauri-plugin", + "thiserror 2.0.17", +] + [[package]] name = "tauri-plugin-process" version = "2.3.1" diff --git a/packages/tauri/src-tauri/Cargo.toml b/packages/tauri/src-tauri/Cargo.toml index f72e5f428d..a39c220111 100644 --- a/packages/tauri/src-tauri/Cargo.toml +++ b/packages/tauri/src-tauri/Cargo.toml @@ -31,3 +31,4 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = "1.48.0" listeners = "0.3" +tauri-plugin-os = "2" diff --git a/packages/tauri/src-tauri/capabilities/default.json b/packages/tauri/src-tauri/capabilities/default.json index 320586de4c..91af8cbdce 100644 --- a/packages/tauri/src-tauri/capabilities/default.json +++ b/packages/tauri/src-tauri/capabilities/default.json @@ -13,6 +13,7 @@ "dialog:default", "process:default", "store:default", - "window-state:default" + "window-state:default", + "os:default" ] } diff --git a/packages/tauri/src-tauri/src/lib.rs b/packages/tauri/src-tauri/src/lib.rs index eb712235ec..fea3addb54 100644 --- a/packages/tauri/src-tauri/src/lib.rs +++ b/packages/tauri/src-tauri/src/lib.rs @@ -4,7 +4,9 @@ use std::{ sync::{Arc, Mutex}, time::{Duration, Instant}, }; -use tauri::{AppHandle, LogicalSize, Manager, Monitor, RunEvent, WebviewUrl, WebviewWindow}; +use tauri::{ + AppHandle, LogicalSize, Manager, Monitor, RunEvent, TitleBarStyle, WebviewUrl, WebviewWindow, +}; use tauri_plugin_dialog::{DialogExt, MessageDialogButtons, MessageDialogResult}; use tauri_plugin_shell::process::{CommandChild, CommandEvent}; use tauri_plugin_shell::ShellExt; @@ -107,6 +109,7 @@ pub fn run() { let updater_enabled = option_env!("TAURI_SIGNING_PRIVATE_KEY").is_some(); let mut builder = tauri::Builder::default() + .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_window_state::Builder::new().build()) .plugin(tauri_plugin_store::Builder::new().build()) .plugin(tauri_plugin_dialog::init()) @@ -180,6 +183,7 @@ pub fn run() { .inner_size(size.width as f64, size.height as f64) .decorations(true) .zoom_hotkeys_enabled(true) + .title_bar_style(TitleBarStyle::Overlay) .initialization_script(format!( r#" window.__OPENCODE__ ??= {{}}; diff --git a/packages/tauri/src/index.tsx b/packages/tauri/src/index.tsx index c72805fe64..84ba73c072 100644 --- a/packages/tauri/src/index.tsx +++ b/packages/tauri/src/index.tsx @@ -5,6 +5,7 @@ import { runUpdater } from "./updater" import { onMount } from "solid-js" import { open, save } from "@tauri-apps/plugin-dialog" import { open as shellOpen } from "@tauri-apps/plugin-shell" +import { type as ostype } from "@tauri-apps/plugin-os" const root = document.getElementById("root") if (import.meta.env.DEV && !(root instanceof HTMLElement)) { @@ -54,6 +55,9 @@ render(() => { return ( + {ostype() === "macos" && ( +
+ )} ) From 9017d103031fa252f5b3fce23df651d1b4ef5bc5 Mon Sep 17 00:00:00 2001 From: xu0o0 Date: Sat, 13 Dec 2025 00:43:18 +0800 Subject: [PATCH 17/30] acp: fix internal error on `/compact` (#5424) --- packages/opencode/src/acp/agent.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/opencode/src/acp/agent.ts b/packages/opencode/src/acp/agent.ts index a1e45e1d21..d20c971ebc 100644 --- a/packages/opencode/src/acp/agent.ts +++ b/packages/opencode/src/acp/agent.ts @@ -914,6 +914,8 @@ export namespace ACP { { sessionID, directory, + providerID: model.providerID, + modelID: model.modelID, }, { throwOnError: true }, ) From 9629f7464b3a1a6077e7c6b04923c4c13993ac08 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Fri, 12 Dec 2025 10:45:02 -0600 Subject: [PATCH 18/30] chore: cleanup --- packages/desktop/src/components/header.tsx | 113 +++++++++++++++++++ packages/desktop/src/context/global-sync.tsx | 70 ++++++------ packages/desktop/src/pages/layout.tsx | 101 ++--------------- 3 files changed, 158 insertions(+), 126 deletions(-) create mode 100644 packages/desktop/src/components/header.tsx diff --git a/packages/desktop/src/components/header.tsx b/packages/desktop/src/components/header.tsx new file mode 100644 index 0000000000..cc4d018166 --- /dev/null +++ b/packages/desktop/src/components/header.tsx @@ -0,0 +1,113 @@ +import { useGlobalSync } from "@/context/global-sync" +import { useLayout } from "@/context/layout" +import { Session } from "@opencode-ai/sdk/v2/client" +import { Button } from "@opencode-ai/ui/button" +import { Icon } from "@opencode-ai/ui/icon" +import { Mark } from "@opencode-ai/ui/logo" +import { Select } from "@opencode-ai/ui/select" +import { Tooltip } from "@opencode-ai/ui/tooltip" +import { base64Decode } from "@opencode-ai/util/encode" +import { getFilename } from "@opencode-ai/util/path" +import { A, useParams } from "@solidjs/router" +import { createMemo, Show } from "solid-js" + +export function Header(props: { + navigateToProject: (directory: string) => void + navigateToSession: (session: Session | undefined) => void +}) { + const globalSync = useGlobalSync() + const layout = useLayout() + const params = useParams() + const currentDirectory = createMemo(() => base64Decode(params.dir ?? "")) + const store = createMemo(() => globalSync.child(currentDirectory())[0]) + const sessions = createMemo(() => store().session ?? []) + const currentSession = createMemo(() => sessions().find((s) => s.id === params.id)) + + return ( +
+ + + +
+ 0}> +
+
+ +
/
+ project.worktree)} - current={currentDirectory()} - label={(x) => getFilename(x)} - onSelect={(x) => (x ? navigateToProject(x) : undefined)} - class="text-14-regular text-text-base" - variant="ghost" - > - {/* @ts-ignore */} - {(i) => ( -
- -
{getFilename(i)}
-
- )} - -
/
-