From ef205c366062fbf89ec49c9fc7f2a4b4c5223614 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Sat, 14 Feb 2026 12:29:01 -0600 Subject: [PATCH 01/11] bump vertex ai packages (#13625) --- bun.lock | 10 +++++++--- packages/opencode/package.json | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/bun.lock b/bun.lock index 061e36e143..2e5d13dd82 100644 --- a/bun.lock +++ b/bun.lock @@ -276,7 +276,7 @@ "@ai-sdk/deepinfra": "1.0.36", "@ai-sdk/gateway": "2.0.30", "@ai-sdk/google": "2.0.52", - "@ai-sdk/google-vertex": "3.0.98", + "@ai-sdk/google-vertex": "3.0.103", "@ai-sdk/groq": "2.0.34", "@ai-sdk/mistral": "2.0.27", "@ai-sdk/openai": "2.0.89", @@ -594,7 +594,7 @@ "@ai-sdk/google": ["@ai-sdk/google@2.0.52", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-2XUnGi3f7TV4ujoAhA+Fg3idUoG/+Y2xjCRg70a1/m0DH1KSQqYaCboJ1C19y6ZHGdf5KNT20eJdswP6TvrY2g=="], - "@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@3.0.98", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.58", "@ai-sdk/google": "2.0.52", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-uuv0RHkdJ5vTzeH1+iuBlv7GAjRcOPd2jiqtGLz6IKOUDH+PRQoE3ExrvOysVnKuhhTBMqvawkktDhMDQE6sVQ=="], + "@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@3.0.103", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.63", "@ai-sdk/google": "2.0.53", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.21", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MPZRSVOJFxYGHE4s6XjSWaiUPru7u2i/LUUA1Ih2nzNYZaei8c46Z56imOCD/KQjQX3afRA2iZh6P5McsmwhqA=="], "@ai-sdk/groq": ["@ai-sdk/groq@2.0.34", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-wfCYkVgmVjxNA32T57KbLabVnv9aFUflJ4urJ7eWgTwbnmGQHElCTu+rJ3ydxkXSqxOkXPwMOttDm7XNrvPjmg=="], @@ -4208,7 +4208,11 @@ "@ai-sdk/fireworks/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.21", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-veuMwTLxsgh31Jjn0SnBABnM1f7ebHhRWcV2ZuY3hP3iJDCZ8VXBaYqcHXoOQDqUXTCas08sKQcHyWK+zl882Q=="], - "@ai-sdk/google-vertex/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.58", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-CkNW5L1Arv8gPtPlEmKd+yf/SG9ucJf0XQdpMG8OiYEtEMc2smuCA+tyCp8zI7IBVg/FE7nUfFHntQFaOjRwJQ=="], + "@ai-sdk/google-vertex/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.63", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-zXlUPCkumnvp8lWS9VFcen/MLF6CL/t1zAKDhpobYj9y/nmylQrKtRvn3RwH871Wd3dF3KYEUXd6M2c6dfCKOA=="], + + "@ai-sdk/google-vertex/@ai-sdk/google": ["@ai-sdk/google@2.0.53", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ccCxr5mrd3AC2CjLq4e1ST7+UiN5T2Pdmgi0XdWM3QohmNBwUQ/RBG7BvL+cB/ex/j6y64tkMmpYz9zBw/SEFQ=="], + + "@ai-sdk/google-vertex/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.21", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-veuMwTLxsgh31Jjn0SnBABnM1f7ebHhRWcV2ZuY3hP3iJDCZ8VXBaYqcHXoOQDqUXTCas08sKQcHyWK+zl882Q=="], "@ai-sdk/openai/@ai-sdk/provider": ["@ai-sdk/provider@2.0.0", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA=="], diff --git a/packages/opencode/package.json b/packages/opencode/package.json index bf372379bd..bb1ce546b5 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -62,7 +62,7 @@ "@ai-sdk/deepinfra": "1.0.36", "@ai-sdk/gateway": "2.0.30", "@ai-sdk/google": "2.0.52", - "@ai-sdk/google-vertex": "3.0.98", + "@ai-sdk/google-vertex": "3.0.103", "@ai-sdk/groq": "2.0.34", "@ai-sdk/mistral": "2.0.27", "@ai-sdk/openai": "2.0.89", From 759ec104b6e537235afd3177acd28b6c9694e496 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Sat, 14 Feb 2026 12:32:29 -0600 Subject: [PATCH 02/11] fix vercel gateway variants (#13541) Co-authored-by: Benjamin Woodruff " --- packages/opencode/src/provider/transform.ts | 97 +++++- .../opencode/test/provider/transform.test.ts | 293 ++++++++++++++++++ 2 files changed, 380 insertions(+), 10 deletions(-) diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index 8091f731f0..b4eb14a2ff 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -171,7 +171,7 @@ export namespace ProviderTransform { return msgs } - function applyCaching(msgs: ModelMessage[], providerID: string): ModelMessage[] { + function applyCaching(msgs: ModelMessage[], model: Provider.Model): ModelMessage[] { const system = msgs.filter((msg) => msg.role === "system").slice(0, 2) const final = msgs.filter((msg) => msg.role !== "system").slice(-2) @@ -194,7 +194,7 @@ export namespace ProviderTransform { } for (const msg of unique([...system, ...final])) { - const useMessageLevelOptions = providerID === "anthropic" || providerID.includes("bedrock") + const useMessageLevelOptions = model.providerID === "anthropic" || model.providerID.includes("bedrock") const shouldUseContentOptions = !useMessageLevelOptions && Array.isArray(msg.content) && msg.content.length > 0 if (shouldUseContentOptions) { @@ -253,14 +253,15 @@ export namespace ProviderTransform { msgs = unsupportedParts(msgs, model) msgs = normalizeMessages(msgs, model, options) if ( - model.providerID === "anthropic" || - model.api.id.includes("anthropic") || - model.api.id.includes("claude") || - model.id.includes("anthropic") || - model.id.includes("claude") || - model.api.npm === "@ai-sdk/anthropic" + (model.providerID === "anthropic" || + model.api.id.includes("anthropic") || + model.api.id.includes("claude") || + model.id.includes("anthropic") || + model.id.includes("claude") || + model.api.npm === "@ai-sdk/anthropic") && + model.api.npm !== "@ai-sdk/gateway" ) { - msgs = applyCaching(msgs, model.providerID) + msgs = applyCaching(msgs, model) } // Remap providerOptions keys from stored providerID to expected SDK key @@ -363,8 +364,50 @@ export namespace ProviderTransform { if (!model.id.includes("gpt") && !model.id.includes("gemini-3")) return {} return Object.fromEntries(OPENAI_EFFORTS.map((effort) => [effort, { reasoning: { effort } }])) - // TODO: YOU CANNOT SET max_tokens if this is set!!! case "@ai-sdk/gateway": + if (model.id.includes("anthropic")) { + return { + high: { + thinking: { + type: "enabled", + budgetTokens: 16000, + }, + }, + max: { + thinking: { + type: "enabled", + budgetTokens: 31999, + }, + }, + } + } + if (model.id.includes("google")) { + if (id.includes("2.5")) { + return { + high: { + thinkingConfig: { + includeThoughts: true, + thinkingBudget: 16000, + }, + }, + max: { + thinkingConfig: { + includeThoughts: true, + thinkingBudget: 24576, + }, + }, + } + } + return Object.fromEntries( + ["low", "high"].map((effort) => [ + effort, + { + includeThoughts: true, + thinkingLevel: effort, + }, + ]), + ) + } return Object.fromEntries(OPENAI_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }])) case "@ai-sdk/github-copilot": @@ -720,6 +763,12 @@ export namespace ProviderTransform { result["promptCacheKey"] = input.sessionID } + if (input.model.api.npm === "@ai-sdk/gateway") { + result["gateway"] = { + caching: "auto", + } + } + return result } @@ -754,6 +803,34 @@ export namespace ProviderTransform { } export function providerOptions(model: Provider.Model, options: { [x: string]: any }) { + if (model.api.npm === "@ai-sdk/gateway") { + // Gateway providerOptions are split across two namespaces: + // - `gateway`: gateway-native routing/caching controls + // - ``: provider-specific model options (anthropic/openai/...) + // We keep `gateway` as-is and route every other top-level option under the + // model-derived upstream slug so variants/options can stay flat internally. + const i = model.api.id.indexOf("/") + const slug = i > 0 ? model.api.id.slice(0, i) : undefined + const gateway = options.gateway + const rest = Object.fromEntries(Object.entries(options).filter(([k]) => k !== "gateway")) + const has = Object.keys(rest).length > 0 + + const result: Record = {} + if (gateway !== undefined) result.gateway = gateway + + if (has) { + if (slug) { + result[slug] = rest + } else if (gateway && typeof gateway === "object" && !Array.isArray(gateway)) { + result.gateway = { ...gateway, ...rest } + } else { + result.gateway = rest + } + } + + return result + } + const key = sdkKey(model.api.npm) ?? model.providerID return { [key]: options } } diff --git a/packages/opencode/test/provider/transform.test.ts b/packages/opencode/test/provider/transform.test.ts index 02bb5278fc..99acfcc817 100644 --- a/packages/opencode/test/provider/transform.test.ts +++ b/packages/opencode/test/provider/transform.test.ts @@ -175,6 +175,174 @@ describe("ProviderTransform.options - gpt-5 textVerbosity", () => { }) }) +describe("ProviderTransform.options - gateway", () => { + const sessionID = "test-session-123" + + const createModel = (id: string) => + ({ + id, + providerID: "vercel", + api: { + id, + url: "https://ai-gateway.vercel.sh/v3/ai", + npm: "@ai-sdk/gateway", + }, + name: id, + capabilities: { + temperature: true, + reasoning: true, + attachment: true, + toolcall: true, + input: { text: true, audio: false, image: true, video: false, pdf: true }, + output: { text: true, audio: false, image: false, video: false, pdf: false }, + interleaved: false, + }, + cost: { + input: 0.001, + output: 0.002, + cache: { read: 0.0001, write: 0.0002 }, + }, + limit: { + context: 200_000, + output: 8192, + }, + status: "active", + options: {}, + headers: {}, + release_date: "2024-01-01", + }) as any + + test("puts gateway defaults under gateway key", () => { + const model = createModel("anthropic/claude-sonnet-4") + const result = ProviderTransform.options({ model, sessionID, providerOptions: {} }) + expect(result).toEqual({ + gateway: { + caching: "auto", + }, + }) + }) +}) + +describe("ProviderTransform.providerOptions", () => { + const createModel = (overrides: Partial = {}) => + ({ + id: "test/test-model", + providerID: "test", + api: { + id: "test-model", + url: "https://api.test.com", + npm: "@ai-sdk/openai", + }, + name: "Test Model", + capabilities: { + temperature: true, + reasoning: true, + attachment: true, + toolcall: true, + input: { text: true, audio: false, image: true, video: false, pdf: false }, + output: { text: true, audio: false, image: false, video: false, pdf: false }, + interleaved: false, + }, + cost: { + input: 0.001, + output: 0.002, + cache: { read: 0.0001, write: 0.0002 }, + }, + limit: { + context: 200_000, + output: 64_000, + }, + status: "active", + options: {}, + headers: {}, + release_date: "2024-01-01", + ...overrides, + }) as any + + test("uses sdk key for non-gateway models", () => { + const model = createModel({ + providerID: "my-bedrock", + api: { + id: "anthropic.claude-sonnet-4", + url: "https://bedrock.aws", + npm: "@ai-sdk/amazon-bedrock", + }, + }) + + expect(ProviderTransform.providerOptions(model, { cachePoint: { type: "default" } })).toEqual({ + bedrock: { cachePoint: { type: "default" } }, + }) + }) + + test("uses gateway model provider slug for gateway models", () => { + const model = createModel({ + providerID: "vercel", + api: { + id: "anthropic/claude-sonnet-4", + url: "https://ai-gateway.vercel.sh/v3/ai", + npm: "@ai-sdk/gateway", + }, + }) + + expect(ProviderTransform.providerOptions(model, { thinking: { type: "enabled", budgetTokens: 12_000 } })).toEqual({ + anthropic: { thinking: { type: "enabled", budgetTokens: 12_000 } }, + }) + }) + + test("falls back to gateway key when gateway api id is unscoped", () => { + const model = createModel({ + id: "anthropic/claude-sonnet-4", + providerID: "vercel", + api: { + id: "claude-sonnet-4", + url: "https://ai-gateway.vercel.sh/v3/ai", + npm: "@ai-sdk/gateway", + }, + }) + + expect(ProviderTransform.providerOptions(model, { thinking: { type: "enabled", budgetTokens: 12_000 } })).toEqual({ + gateway: { thinking: { type: "enabled", budgetTokens: 12_000 } }, + }) + }) + + test("splits gateway routing options from provider-specific options", () => { + const model = createModel({ + providerID: "vercel", + api: { + id: "anthropic/claude-sonnet-4", + url: "https://ai-gateway.vercel.sh/v3/ai", + npm: "@ai-sdk/gateway", + }, + }) + + expect( + ProviderTransform.providerOptions(model, { + gateway: { order: ["vertex", "anthropic"] }, + thinking: { type: "enabled", budgetTokens: 12_000 }, + }), + ).toEqual({ + gateway: { order: ["vertex", "anthropic"] }, + anthropic: { thinking: { type: "enabled", budgetTokens: 12_000 } }, + } as any) + }) + + test("falls back to gateway key when model id has no provider slug", () => { + const model = createModel({ + id: "claude-sonnet-4", + providerID: "vercel", + api: { + id: "claude-sonnet-4", + url: "https://ai-gateway.vercel.sh/v3/ai", + npm: "@ai-sdk/gateway", + }, + }) + + expect(ProviderTransform.providerOptions(model, { reasoningEffort: "high" })).toEqual({ + gateway: { reasoningEffort: "high" }, + }) + }) +}) + describe("ProviderTransform.schema - gemini array items", () => { test("adds missing items for array properties", () => { const geminiModel = { @@ -1232,6 +1400,105 @@ describe("ProviderTransform.message - claude w/bedrock custom inference profile" }) }) +describe("ProviderTransform.message - cache control on gateway", () => { + const createModel = (overrides: Partial = {}) => + ({ + id: "anthropic/claude-sonnet-4", + providerID: "vercel", + api: { + id: "anthropic/claude-sonnet-4", + url: "https://ai-gateway.vercel.sh/v3/ai", + npm: "@ai-sdk/gateway", + }, + name: "Claude Sonnet 4", + capabilities: { + temperature: true, + reasoning: true, + attachment: true, + toolcall: true, + input: { text: true, audio: false, image: true, video: false, pdf: true }, + output: { text: true, audio: false, image: false, video: false, pdf: false }, + interleaved: false, + }, + cost: { input: 0.001, output: 0.002, cache: { read: 0.0001, write: 0.0002 } }, + limit: { context: 200_000, output: 8192 }, + status: "active", + options: {}, + headers: {}, + ...overrides, + }) as any + + test("gateway does not set cache control for anthropic models", () => { + const model = createModel() + const msgs = [ + { + role: "system", + content: [{ type: "text", text: "You are a helpful assistant" }], + }, + { + role: "user", + content: "Hello", + }, + ] as any[] + + const result = ProviderTransform.message(msgs, model, {}) as any[] + + expect(result[0].content[0].providerOptions).toBeUndefined() + expect(result[0].providerOptions).toBeUndefined() + }) + + test("non-gateway anthropic keeps existing cache control behavior", () => { + const model = createModel({ + providerID: "anthropic", + api: { + id: "claude-sonnet-4", + url: "https://api.anthropic.com", + npm: "@ai-sdk/anthropic", + }, + }) + const msgs = [ + { + role: "system", + content: "You are a helpful assistant", + }, + { + role: "user", + content: "Hello", + }, + ] as any[] + + const result = ProviderTransform.message(msgs, model, {}) as any[] + + expect(result[0].providerOptions).toEqual({ + anthropic: { + cacheControl: { + type: "ephemeral", + }, + }, + openrouter: { + cacheControl: { + type: "ephemeral", + }, + }, + bedrock: { + cachePoint: { + type: "default", + }, + }, + openaiCompatible: { + cache_control: { + type: "ephemeral", + }, + }, + copilot: { + copilot_cache_control: { + type: "ephemeral", + }, + }, + }) + }) +}) + describe("ProviderTransform.variants", () => { const createMockModel = (overrides: Partial = {}): any => ({ id: "test/test-model", @@ -1408,6 +1675,32 @@ describe("ProviderTransform.variants", () => { }) describe("@ai-sdk/gateway", () => { + test("anthropic models return anthropic thinking options", () => { + const model = createMockModel({ + id: "anthropic/claude-sonnet-4", + providerID: "gateway", + api: { + id: "anthropic/claude-sonnet-4", + url: "https://gateway.ai", + npm: "@ai-sdk/gateway", + }, + }) + const result = ProviderTransform.variants(model) + expect(Object.keys(result)).toEqual(["high", "max"]) + expect(result.high).toEqual({ + thinking: { + type: "enabled", + budgetTokens: 16000, + }, + }) + expect(result.max).toEqual({ + thinking: { + type: "enabled", + budgetTokens: 31999, + }, + }) + }) + test("returns OPENAI_EFFORTS with reasoningEffort", () => { const model = createMockModel({ id: "gateway/gateway-model", From 306fc77076fa3ac0930efefc842e2f61cd5ddd19 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Sat, 14 Feb 2026 18:38:18 +0000 Subject: [PATCH 03/11] chore: update nix node_modules hashes --- nix/hashes.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/hashes.json b/nix/hashes.json index ef0b63897d..9abd070a8c 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,8 +1,8 @@ { "nodeModules": { - "x86_64-linux": "sha256-hVf8rBEqy3q4xexOqyKDtKmlMydl1hFoDV0JiEvmfgs=", - "aarch64-linux": "sha256-4m3UZllEmfJXB70cOgIoyWRIYMXxGzzenyOfF3kEQKk=", - "aarch64-darwin": "sha256-27xGR9+FVnC0rsUIyepk2tCP1eEUmGvqWUGAZ+rk7IQ=", - "x86_64-darwin": "sha256-+At7bHSeg6QJu6yGawyvzt53Tu/fddDg6Ms+xhaMLhY=" + "x86_64-linux": "sha256-3pSRWyuQUn2s889IHKcL58BfO3y1dgZMOrqYgHgeHqc=", + "aarch64-linux": "sha256-AuBO4b9JLxOL+GJTK4dLwImZUx+Kpv4JdaX0FqKyLuI=", + "aarch64-darwin": "sha256-9toJpgkLovUYCoDa7mdGHa3ElVg7s6s+8rQSO3LH58w=", + "x86_64-darwin": "sha256-Zjt2gFBuXXeSY4dGZQQNBs7cDFlcQ9yiIVMc52lxb1Y=" } } From 68bb8ce1da922229e6ab4dde4207b431cf9d76a8 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sat, 14 Feb 2026 13:40:49 -0500 Subject: [PATCH 04/11] core: filter sessions at database level to improve session list loading performance --- .../opencode/src/server/routes/session.ts | 14 +++---- packages/opencode/src/session/index.ts | 38 ++++++++++++++----- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/packages/opencode/src/server/routes/session.ts b/packages/opencode/src/server/routes/session.ts index 2cf5473f22..1195529e06 100644 --- a/packages/opencode/src/server/routes/session.ts +++ b/packages/opencode/src/server/routes/session.ts @@ -53,15 +53,15 @@ export const SessionRoutes = lazy(() => ), async (c) => { const query = c.req.valid("query") - const term = query.search?.toLowerCase() const sessions: Session.Info[] = [] - for await (const session of Session.list()) { - if (query.directory !== undefined && session.directory !== query.directory) continue - if (query.roots && session.parentID) continue - if (query.start !== undefined && session.time.updated < query.start) continue - if (term !== undefined && !session.title.toLowerCase().includes(term)) continue + for await (const session of Session.list({ + directory: query.directory, + roots: query.roots, + start: query.start, + search: query.search, + limit: query.limit, + })) { sessions.push(session) - if (query.limit !== undefined && sessions.length >= query.limit) break } return c.json(sessions) }, diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index 38007a0a7f..255f4dd460 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -10,7 +10,7 @@ import { Flag } from "../flag/flag" import { Identifier } from "../id/id" import { Installation } from "../installation" -import { Database, NotFoundError, eq, and, or, like } from "../storage/db" +import { Database, NotFoundError, eq, and, or, gte, isNull, desc, like } from "../storage/db" import { SessionTable, MessageTable, PartTable } from "./session.sql" import { Storage } from "@/storage/storage" import { Log } from "../util/log" @@ -505,20 +505,38 @@ export namespace Session { }, ) - export function* list() { + export function* list(input?: { + directory?: string + roots?: boolean + start?: number + search?: string + limit?: number + }) { const project = Instance.project - // const rel = path.relative(Instance.worktree, Instance.directory) - // const suffix = path.sep + rel + const conditions = [eq(SessionTable.project_id, project.id)] + + if (input?.directory) { + conditions.push(eq(SessionTable.directory, input.directory)) + } + if (input?.roots) { + conditions.push(isNull(SessionTable.parent_id)) + } + if (input?.start) { + conditions.push(gte(SessionTable.time_updated, input.start)) + } + if (input?.search) { + conditions.push(like(SessionTable.title, `%${input.search}%`)) + } + + const limit = input?.limit ?? 100 + const rows = Database.use((db) => db .select() .from(SessionTable) - .where( - and( - eq(SessionTable.project_id, project.id), - // or(eq(SessionTable.directory, Instance.directory), like(SessionTable.directory, `%${suffix}`)), - ), - ) + .where(and(...conditions)) + .orderBy(desc(SessionTable.time_updated)) + .limit(limit) .all(), ) for (const row of rows) { From 8631d6c01d8c8f5e8c616e09e85e5a27791d1a56 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sat, 14 Feb 2026 13:43:41 -0500 Subject: [PATCH 05/11] core: add comprehensive test coverage for Session.list() filters Adds test cases for filtering sessions by directory, root sessions only, start time, search terms, and result limits to ensure the listing functionality works correctly for all filter combinations. --- .../opencode/test/server/session-list.test.ts | 73 ++++++++++++++++--- 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/packages/opencode/test/server/session-list.test.ts b/packages/opencode/test/server/session-list.test.ts index 623c16a811..675a89011f 100644 --- a/packages/opencode/test/server/session-list.test.ts +++ b/packages/opencode/test/server/session-list.test.ts @@ -1,20 +1,17 @@ import { describe, expect, test } from "bun:test" import path from "path" import { Instance } from "../../src/project/instance" -import { Server } from "../../src/server/server" import { Session } from "../../src/session" import { Log } from "../../src/util/log" const projectRoot = path.join(__dirname, "../..") Log.init({ print: false }) -describe("session.list", () => { +describe("Session.list", () => { test("filters by directory", async () => { await Instance.provide({ directory: projectRoot, fn: async () => { - const app = Server.App() - const first = await Session.create({}) const otherDir = path.join(projectRoot, "..", "__session_list_other") @@ -23,17 +20,71 @@ describe("session.list", () => { fn: async () => Session.create({}), }) - const response = await app.request(`/session?directory=${encodeURIComponent(projectRoot)}`) - expect(response.status).toBe(200) - - const body = (await response.json()) as unknown[] - const ids = body - .map((s) => (typeof s === "object" && s && "id" in s ? (s as { id: string }).id : undefined)) - .filter((x): x is string => typeof x === "string") + const sessions = [...Session.list({ directory: projectRoot })] + const ids = sessions.map((s) => s.id) expect(ids).toContain(first.id) expect(ids).not.toContain(second.id) }, }) }) + + test("filters root sessions", async () => { + await Instance.provide({ + directory: projectRoot, + fn: async () => { + const root = await Session.create({ title: "root-session" }) + const child = await Session.create({ title: "child-session", parentID: root.id }) + + const sessions = [...Session.list({ roots: true })] + const ids = sessions.map((s) => s.id) + + expect(ids).toContain(root.id) + expect(ids).not.toContain(child.id) + }, + }) + }) + + test("filters by start time", async () => { + await Instance.provide({ + directory: projectRoot, + fn: async () => { + const session = await Session.create({ title: "new-session" }) + const futureStart = Date.now() + 86400000 + + const sessions = [...Session.list({ start: futureStart })] + expect(sessions.length).toBe(0) + }, + }) + }) + + test("filters by search term", async () => { + await Instance.provide({ + directory: projectRoot, + fn: async () => { + await Session.create({ title: "unique-search-term-abc" }) + await Session.create({ title: "other-session-xyz" }) + + const sessions = [...Session.list({ search: "unique-search" })] + const titles = sessions.map((s) => s.title) + + expect(titles).toContain("unique-search-term-abc") + expect(titles).not.toContain("other-session-xyz") + }, + }) + }) + + test("respects limit parameter", async () => { + await Instance.provide({ + directory: projectRoot, + fn: async () => { + await Session.create({ title: "session-1" }) + await Session.create({ title: "session-2" }) + await Session.create({ title: "session-3" }) + + const sessions = [...Session.list({ limit: 2 })] + expect(sessions.length).toBe(2) + }, + }) + }) }) From 3b6b3e6fc8a8a4da5798c9f00027e954263a483e Mon Sep 17 00:00:00 2001 From: opencode Date: Sat, 14 Feb 2026 19:08:58 +0000 Subject: [PATCH 06/11] release: v1.2.2 --- bun.lock | 30 +++++++++++++------------- packages/app/package.json | 2 +- packages/console/app/package.json | 2 +- packages/console/core/package.json | 2 +- packages/console/function/package.json | 2 +- packages/console/mail/package.json | 2 +- packages/desktop/package.json | 2 +- packages/enterprise/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +++++------ packages/function/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/slack/package.json | 2 +- packages/ui/package.json | 2 +- packages/util/package.json | 2 +- packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- 18 files changed, 37 insertions(+), 37 deletions(-) diff --git a/bun.lock b/bun.lock index 2e5d13dd82..2b4c4993aa 100644 --- a/bun.lock +++ b/bun.lock @@ -23,7 +23,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -73,7 +73,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -107,7 +107,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -134,7 +134,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -158,7 +158,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -182,7 +182,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -215,7 +215,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -244,7 +244,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -260,7 +260,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.2.1", + "version": "1.2.2", "bin": { "opencode": "./bin/opencode", }, @@ -369,7 +369,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -389,7 +389,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.2.1", + "version": "1.2.2", "devDependencies": { "@hey-api/openapi-ts": "0.90.10", "@tsconfig/node22": "catalog:", @@ -400,7 +400,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -413,7 +413,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -455,7 +455,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "zod": "catalog:", }, @@ -466,7 +466,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/app/package.json b/packages/app/package.json index e8c24c08ba..b2f2f23246 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "1.2.1", + "version": "1.2.2", "description": "", "type": "module", "exports": { diff --git a/packages/console/app/package.json b/packages/console/app/package.json index a6267c73ef..ea16083326 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.2.1", + "version": "1.2.2", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 85f9c200a7..8c71ca77b2 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/console-core", - "version": "1.2.1", + "version": "1.2.2", "private": true, "type": "module", "license": "MIT", diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 02aa6f76ef..debba52bab 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.2.1", + "version": "1.2.2", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/console/mail/package.json b/packages/console/mail/package.json index 115d365f7e..e361cc0e73 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.2.1", + "version": "1.2.2", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 858dbf5c4d..f9ab28cfca 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop", "private": true, - "version": "1.2.1", + "version": "1.2.2", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index 7aa3bb90d1..173688eb1d 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.2.1", + "version": "1.2.2", "private": true, "type": "module", "license": "MIT", diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index fdb66d69bf..9498ce1269 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "opencode" name = "OpenCode" description = "The open source coding agent." -version = "1.2.1" +version = "1.2.2" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/anomalyco/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.1/opencode-darwin-arm64.zip" +archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.2/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.1/opencode-darwin-x64.zip" +archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.2/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.1/opencode-linux-arm64.tar.gz" +archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.2/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.1/opencode-linux-x64.tar.gz" +archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.2/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.1/opencode-windows-x64.zip" +archive = "https://github.com/anomalyco/opencode/releases/download/v1.2.2/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index 242ce353f3..1718b791a6 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.2.1", + "version": "1.2.2", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index bb1ce546b5..728ec38385 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.2.1", + "version": "1.2.2", "name": "opencode", "type": "module", "license": "MIT", diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 481404969c..d078c0028e 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/plugin", - "version": "1.2.1", + "version": "1.2.2", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index e141774821..a03d8382db 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/sdk", - "version": "1.2.1", + "version": "1.2.2", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/slack/package.json b/packages/slack/package.json index d9234899d9..8a6d289ec0 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.2.1", + "version": "1.2.2", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/ui/package.json b/packages/ui/package.json index a0e5c2af25..8771b397ce 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.2.1", + "version": "1.2.2", "type": "module", "license": "MIT", "exports": { diff --git a/packages/util/package.json b/packages/util/package.json index bf0cb074be..c610140398 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.2.1", + "version": "1.2.2", "private": true, "type": "module", "license": "MIT", diff --git a/packages/web/package.json b/packages/web/package.json index 6bdecea178..79858de586 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -2,7 +2,7 @@ "name": "@opencode-ai/web", "type": "module", "license": "MIT", - "version": "1.2.1", + "version": "1.2.2", "scripts": { "dev": "astro dev", "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index d19dcbf467..e91d1a324d 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "1.2.1", + "version": "1.2.2", "publisher": "sst-dev", "repository": { "type": "git", From 933a491adeeed875d3ba4cbc88ed301a60456734 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Sat, 14 Feb 2026 13:18:52 -0600 Subject: [PATCH 07/11] fix: ensure vercel variants pass amazon models under bedrock key (#13631) --- packages/opencode/src/provider/transform.ts | 14 +++++++-- .../opencode/test/provider/transform.test.ts | 30 +++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index b4eb14a2ff..1c92f528ee 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -802,15 +802,22 @@ export namespace ProviderTransform { return {} } + // Maps model ID prefix to provider slug used in providerOptions. + // Example: "amazon/nova-2-lite" → "bedrock" + const SLUG_OVERRIDES: Record = { + amazon: "bedrock", + } + export function providerOptions(model: Provider.Model, options: { [x: string]: any }) { if (model.api.npm === "@ai-sdk/gateway") { // Gateway providerOptions are split across two namespaces: - // - `gateway`: gateway-native routing/caching controls + // - `gateway`: gateway-native routing/caching controls (order, only, byok, etc.) // - ``: provider-specific model options (anthropic/openai/...) // We keep `gateway` as-is and route every other top-level option under the - // model-derived upstream slug so variants/options can stay flat internally. + // model-derived upstream slug. const i = model.api.id.indexOf("/") - const slug = i > 0 ? model.api.id.slice(0, i) : undefined + const rawSlug = i > 0 ? model.api.id.slice(0, i) : undefined + const slug = rawSlug ? (SLUG_OVERRIDES[rawSlug] ?? rawSlug) : undefined const gateway = options.gateway const rest = Object.fromEntries(Object.entries(options).filter(([k]) => k !== "gateway")) const has = Object.keys(rest).length > 0 @@ -820,6 +827,7 @@ export namespace ProviderTransform { if (has) { if (slug) { + // Route model-specific options under the provider slug result[slug] = rest } else if (gateway && typeof gateway === "object" && !Array.isArray(gateway)) { result.gateway = { ...gateway, ...rest } diff --git a/packages/opencode/test/provider/transform.test.ts b/packages/opencode/test/provider/transform.test.ts index 99acfcc817..3494cb56fd 100644 --- a/packages/opencode/test/provider/transform.test.ts +++ b/packages/opencode/test/provider/transform.test.ts @@ -341,6 +341,36 @@ describe("ProviderTransform.providerOptions", () => { gateway: { reasoningEffort: "high" }, }) }) + + test("maps amazon slug to bedrock for provider options", () => { + const model = createModel({ + providerID: "vercel", + api: { + id: "amazon/nova-2-lite", + url: "https://ai-gateway.vercel.sh/v3/ai", + npm: "@ai-sdk/gateway", + }, + }) + + expect(ProviderTransform.providerOptions(model, { reasoningConfig: { type: "enabled" } })).toEqual({ + bedrock: { reasoningConfig: { type: "enabled" } }, + }) + }) + + test("uses groq slug for groq models", () => { + const model = createModel({ + providerID: "vercel", + api: { + id: "groq/llama-3.3-70b-versatile", + url: "https://ai-gateway.vercel.sh/v3/ai", + npm: "@ai-sdk/gateway", + }, + }) + + expect(ProviderTransform.providerOptions(model, { reasoningFormat: "parsed" })).toEqual({ + groq: { reasoningFormat: "parsed" }, + }) + }) }) describe("ProviderTransform.schema - gemini array items", () => { From 575f2cf2a5e2246175a38dbf96bb1fed33186edc Mon Sep 17 00:00:00 2001 From: Alberto Valverde Date: Sat, 14 Feb 2026 20:21:31 +0100 Subject: [PATCH 08/11] chore: bump nixpkgs to get bun 1.3.9 (#13302) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 10fa973cfe..9efa1883b1 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1770073757, - "narHash": "sha256-Vy+G+F+3E/Tl+GMNgiHl9Pah2DgShmIUBJXmbiQPHbI=", + "lastModified": 1770812194, + "narHash": "sha256-OH+lkaIKAvPXR3nITO7iYZwew2nW9Y7Xxq0yfM/UcUU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "47472570b1e607482890801aeaf29bfb749884f6", + "rev": "8482c7ded03bae7550f3d69884f1e611e3bd19e8", "type": "github" }, "original": { From 67c985ce82b3a0ef3b22bef435f58884a3aab990 Mon Sep 17 00:00:00 2001 From: Dax Date: Sat, 14 Feb 2026 14:33:08 -0500 Subject: [PATCH 09/11] fix: add WAL checkpoint on database open (#13633) --- packages/opencode/src/storage/db.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/opencode/src/storage/db.ts b/packages/opencode/src/storage/db.ts index 50aa76384e..387e93b376 100644 --- a/packages/opencode/src/storage/db.ts +++ b/packages/opencode/src/storage/db.ts @@ -74,6 +74,7 @@ export namespace Database { sqlite.run("PRAGMA busy_timeout = 5000") sqlite.run("PRAGMA cache_size = -64000") sqlite.run("PRAGMA foreign_keys = ON") + sqlite.run("PRAGMA wal_checkpoint(PASSIVE)") const db = drizzle({ client: sqlite, schema }) From 839c5cda12fa978d4c7ba85c7cf51600ec853bc8 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Sat, 14 Feb 2026 14:30:07 -0600 Subject: [PATCH 10/11] fix: ensure anthropic models on OR also have variant support (#13498) --- bun.lock | 1 + package.json | 3 +- packages/opencode/src/provider/transform.ts | 5 +- .../@openrouter%2Fai-sdk-provider@1.5.4.patch | 128 ++++++++++++++++++ 4 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 patches/@openrouter%2Fai-sdk-provider@1.5.4.patch diff --git a/bun.lock b/bun.lock index 2b4c4993aa..c29176596d 100644 --- a/bun.lock +++ b/bun.lock @@ -504,6 +504,7 @@ "tree-sitter-bash", ], "patchedDependencies": { + "@openrouter/ai-sdk-provider@1.5.4": "patches/@openrouter%2Fai-sdk-provider@1.5.4.patch", "@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch", }, "overrides": { diff --git a/package.json b/package.json index c4408e264b..5d93205056 100644 --- a/package.json +++ b/package.json @@ -103,6 +103,7 @@ "@types/node": "catalog:" }, "patchedDependencies": { - "@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch" + "@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch", + "@openrouter/ai-sdk-provider@1.5.4": "patches/@openrouter%2Fai-sdk-provider@1.5.4.patch" } } diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index 1c92f528ee..853d03c1d8 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -361,7 +361,7 @@ export namespace ProviderTransform { switch (model.api.npm) { case "@openrouter/ai-sdk-provider": - if (!model.id.includes("gpt") && !model.id.includes("gemini-3")) return {} + if (!model.id.includes("gpt") && !model.id.includes("gemini-3") && !model.id.includes("claude")) return {} return Object.fromEntries(OPENAI_EFFORTS.map((effort) => [effort, { reasoning: { effort } }])) case "@ai-sdk/gateway": @@ -763,6 +763,9 @@ export namespace ProviderTransform { result["promptCacheKey"] = input.sessionID } + if (input.model.providerID === "openrouter") { + result["prompt_cache_key"] = input.sessionID + } if (input.model.api.npm === "@ai-sdk/gateway") { result["gateway"] = { caching: "auto", diff --git a/patches/@openrouter%2Fai-sdk-provider@1.5.4.patch b/patches/@openrouter%2Fai-sdk-provider@1.5.4.patch new file mode 100644 index 0000000000..6226bf790c --- /dev/null +++ b/patches/@openrouter%2Fai-sdk-provider@1.5.4.patch @@ -0,0 +1,128 @@ +diff --git a/dist/index.js b/dist/index.js +index f33510a50d11a2cb92a90ea70cc0ac84c89f29b9..e887a60352c0c08ab794b1e6821854dfeefd20cc 100644 +--- a/dist/index.js ++++ b/dist/index.js +@@ -2110,7 +2110,12 @@ var OpenRouterChatLanguageModel = class { + if (reasoningStarted && !textStarted) { + controller.enqueue({ + type: "reasoning-end", +- id: reasoningId || generateId() ++ id: reasoningId || generateId(), ++ providerMetadata: accumulatedReasoningDetails.length > 0 ? { ++ openrouter: { ++ reasoning_details: accumulatedReasoningDetails ++ } ++ } : undefined + }); + reasoningStarted = false; + } +@@ -2307,7 +2312,12 @@ var OpenRouterChatLanguageModel = class { + if (reasoningStarted) { + controller.enqueue({ + type: "reasoning-end", +- id: reasoningId || generateId() ++ id: reasoningId || generateId(), ++ providerMetadata: accumulatedReasoningDetails.length > 0 ? { ++ openrouter: { ++ reasoning_details: accumulatedReasoningDetails ++ } ++ } : undefined + }); + } + if (textStarted) { +diff --git a/dist/index.mjs b/dist/index.mjs +index 8a688331b88b4af738ee4ca8062b5f24124d3d81..6310cb8b7c8d0a728d86e1eed09906c6b4c91ae2 100644 +--- a/dist/index.mjs ++++ b/dist/index.mjs +@@ -2075,7 +2075,12 @@ var OpenRouterChatLanguageModel = class { + if (reasoningStarted && !textStarted) { + controller.enqueue({ + type: "reasoning-end", +- id: reasoningId || generateId() ++ id: reasoningId || generateId(), ++ providerMetadata: accumulatedReasoningDetails.length > 0 ? { ++ openrouter: { ++ reasoning_details: accumulatedReasoningDetails ++ } ++ } : undefined + }); + reasoningStarted = false; + } +@@ -2272,7 +2277,12 @@ var OpenRouterChatLanguageModel = class { + if (reasoningStarted) { + controller.enqueue({ + type: "reasoning-end", +- id: reasoningId || generateId() ++ id: reasoningId || generateId(), ++ providerMetadata: accumulatedReasoningDetails.length > 0 ? { ++ openrouter: { ++ reasoning_details: accumulatedReasoningDetails ++ } ++ } : undefined + }); + } + if (textStarted) { +diff --git a/dist/internal/index.js b/dist/internal/index.js +index d40fa66125941155ac13a4619503caba24d89f8a..8dd86d1b473f2fa31c1acd9881d72945b294a197 100644 +--- a/dist/internal/index.js ++++ b/dist/internal/index.js +@@ -2064,7 +2064,12 @@ var OpenRouterChatLanguageModel = class { + if (reasoningStarted && !textStarted) { + controller.enqueue({ + type: "reasoning-end", +- id: reasoningId || generateId() ++ id: reasoningId || generateId(), ++ providerMetadata: accumulatedReasoningDetails.length > 0 ? { ++ openrouter: { ++ reasoning_details: accumulatedReasoningDetails ++ } ++ } : undefined + }); + reasoningStarted = false; + } +@@ -2261,7 +2266,12 @@ var OpenRouterChatLanguageModel = class { + if (reasoningStarted) { + controller.enqueue({ + type: "reasoning-end", +- id: reasoningId || generateId() ++ id: reasoningId || generateId(), ++ providerMetadata: accumulatedReasoningDetails.length > 0 ? { ++ openrouter: { ++ reasoning_details: accumulatedReasoningDetails ++ } ++ } : undefined + }); + } + if (textStarted) { +diff --git a/dist/internal/index.mjs b/dist/internal/index.mjs +index b0ed9d113549c5c55ea3b1e08abb3db6f92ae5a7..5695930a8e038facc071d58a4179a369a29be9c7 100644 +--- a/dist/internal/index.mjs ++++ b/dist/internal/index.mjs +@@ -2030,7 +2030,12 @@ var OpenRouterChatLanguageModel = class { + if (reasoningStarted && !textStarted) { + controller.enqueue({ + type: "reasoning-end", +- id: reasoningId || generateId() ++ id: reasoningId || generateId(), ++ providerMetadata: accumulatedReasoningDetails.length > 0 ? { ++ openrouter: { ++ reasoning_details: accumulatedReasoningDetails ++ } ++ } : undefined + }); + reasoningStarted = false; + } +@@ -2227,7 +2232,12 @@ var OpenRouterChatLanguageModel = class { + if (reasoningStarted) { + controller.enqueue({ + type: "reasoning-end", +- id: reasoningId || generateId() ++ id: reasoningId || generateId(), ++ providerMetadata: accumulatedReasoningDetails.length > 0 ? { ++ openrouter: { ++ reasoning_details: accumulatedReasoningDetails ++ } ++ } : undefined + }); + } + if (textStarted) { From 7911cb62abe424337d934c03e48bc431199401e7 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Sat, 14 Feb 2026 20:38:57 +0000 Subject: [PATCH 11/11] chore: update nix node_modules hashes --- nix/hashes.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/hashes.json b/nix/hashes.json index 9abd070a8c..fde268ba83 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,8 +1,8 @@ { "nodeModules": { - "x86_64-linux": "sha256-3pSRWyuQUn2s889IHKcL58BfO3y1dgZMOrqYgHgeHqc=", - "aarch64-linux": "sha256-AuBO4b9JLxOL+GJTK4dLwImZUx+Kpv4JdaX0FqKyLuI=", - "aarch64-darwin": "sha256-9toJpgkLovUYCoDa7mdGHa3ElVg7s6s+8rQSO3LH58w=", - "x86_64-darwin": "sha256-Zjt2gFBuXXeSY4dGZQQNBs7cDFlcQ9yiIVMc52lxb1Y=" + "x86_64-linux": "sha256-5pgd2xuvIIkTbIOGIdK5MIXo6O9qRpvk1RKQZ1e1R+8=", + "aarch64-linux": "sha256-FZiHwihM4b82ipQ9XfW08X+sd5CvZhx/+pU/8X1zsns=", + "aarch64-darwin": "sha256-iZv0w1NthV53pY5uvuf3JlI14GeKmCu7WHwGSRdEQeM=", + "x86_64-darwin": "sha256-c3Zm3P1goFPgg3vNAZPMFOhHX/gyTmsCN/PKbGO/v0E=" } }