From 228e9095ba3988a02664c3816cb51f98584e86c2 Mon Sep 17 00:00:00 2001 From: Matthew Feroz <136640686+MatthewFeroz@users.noreply.github.com> Date: Mon, 14 Sep 2026 03:16:48 -0400 Subject: [PATCH 1/6] fix(ui): add Merge Gateway logo (#42015) --- packages/ui/src/assets/icons/provider/merge-gateway.svg | 4 ++++ packages/ui/src/components/provider-icons/sprite.svg | 8 ++++++++ packages/ui/src/components/provider-icons/types.ts | 1 + 3 files changed, 13 insertions(+) create mode 100644 packages/ui/src/assets/icons/provider/merge-gateway.svg diff --git a/packages/ui/src/assets/icons/provider/merge-gateway.svg b/packages/ui/src/assets/icons/provider/merge-gateway.svg new file mode 100644 index 0000000000..a219b55bf9 --- /dev/null +++ b/packages/ui/src/assets/icons/provider/merge-gateway.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/ui/src/components/provider-icons/sprite.svg b/packages/ui/src/components/provider-icons/sprite.svg index c8099d7ad1..3922263234 100644 --- a/packages/ui/src/components/provider-icons/sprite.svg +++ b/packages/ui/src/components/provider-icons/sprite.svg @@ -576,6 +576,14 @@ stroke-linejoin="round" > + + + + Date: Mon, 14 Sep 2026 12:08:40 -0500 Subject: [PATCH 2/6] test(app): retire legacy layout e2e coverage (#49015) Co-authored-by: rekram1-node --- .../e2e/regression/legacy-new-session.spec.ts | 41 ------------------- .../session-timeline-projection.spec.ts | 8 +--- 2 files changed, 2 insertions(+), 47 deletions(-) delete mode 100644 packages/app/e2e/regression/legacy-new-session.spec.ts diff --git a/packages/app/e2e/regression/legacy-new-session.spec.ts b/packages/app/e2e/regression/legacy-new-session.spec.ts deleted file mode 100644 index 45cd64adcc..0000000000 --- a/packages/app/e2e/regression/legacy-new-session.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { expect, test } from "@playwright/test" -import { base64Encode } from "@opencode-ai/core/util/encode" -import { mockOpenCodeServer } from "../utils/mock-server" - -const draftID = "draft_legacy_new_session" -const directory = "C:/OpenCode/LegacyNewSession" -const server = `http://${process.env.PLAYWRIGHT_SERVER_HOST ?? "127.0.0.1"}:${process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"}` - -test("redirects a draft to the legacy new-session route", async ({ page }) => { - await mockOpenCodeServer(page, { - directory, - project: { - id: "proj_legacy_new_session", - worktree: directory, - vcs: "git", - name: "legacy-new-session", - time: { created: 1700000000000, updated: 1700000000000 }, - sandboxes: [], - }, - provider: { all: [], connected: [], default: {} }, - sessions: [], - pageMessages: () => ({ items: [] }), - }) - await page.addInitScript( - ({ directory, draftID, server }) => { - localStorage.setItem("settings.v3", JSON.stringify({ general: { newLayoutDesigns: false } })) - localStorage.setItem("app-version.v1", JSON.stringify({ version: "1.17.20" })) - localStorage.setItem( - "opencode.window.browser.dat:tabs", - JSON.stringify([{ type: "draft", draftID, server, directory }]), - ) - }, - { directory, draftID, server }, - ) - - await page.goto(`/new-session?draftId=${draftID}`) - - await expect(page).toHaveURL(`/${base64Encode(directory)}/session`) - await expect(page.locator("header[data-tauri-drag-region]")).toBeVisible() - await expect(page.locator('[data-component="prompt-input"]')).toBeVisible() -}) diff --git a/packages/app/e2e/regression/session-timeline-projection.spec.ts b/packages/app/e2e/regression/session-timeline-projection.spec.ts index b1aabcc32c..54c84a2bea 100644 --- a/packages/app/e2e/regression/session-timeline-projection.spec.ts +++ b/packages/app/e2e/regression/session-timeline-projection.spec.ts @@ -128,7 +128,7 @@ test.describe("session timeline projection", () => { await expect(page.locator('[data-timeline-row="TurnGap"]')).toBeVisible() }) - test("renders comment strips and historical diff summary overflow", async ({ page }) => { + test("renders inline comments and historical diff summary overflow", async ({ page }) => { const user = userMessage( [ userText("The user made the following comment regarding lines 4 through 8 of src/a.ts: Keep this stable", { @@ -152,14 +152,10 @@ test.describe("session timeline projection", () => { parentID: "msg_2000_diff_next_user", created: 1700000011000, }) - await setupTimeline(page, { - messages: [user, assistantMessage(), nextUser, nextAssistant], - settings: { newLayoutDesigns: false }, - }) + await setupTimeline(page, { messages: [user, assistantMessage(), nextUser, nextAssistant] }) const scroller = page.locator(".scroll-view__viewport", { has: page.locator("[data-timeline-row]") }) await scroller.evaluate((element) => (element.scrollTop = 0)) - await expect(page.locator('[data-timeline-row="CommentStrip"]')).toBeVisible() await expect(page.getByText("Keep this stable", { exact: true })).toBeVisible() await expect(page.locator('[data-timeline-row="DiffSummary"]')).toBeVisible() await expect(page.getByText(/show all/i)).toBeVisible() From a97622c801f4ca571530ddc51076af659a9c32cd Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" <219766164+opencode-agent[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 13:24:08 -0400 Subject: [PATCH 3/6] fix(tui): surface remote auth startup errors (#49016) Co-authored-by: thdxr <826656+thdxr@users.noreply.github.com> --- packages/opencode/src/cli/cmd/tui.ts | 2 +- .../instance/httpapi/middleware/error.ts | 3 +- .../server/httpapi-error-middleware.test.ts | 21 +++++++ packages/tui/src/app.tsx | 4 +- packages/tui/src/util/error.ts | 11 ++++ packages/tui/test/app-lifecycle.test.tsx | 62 +++++++++++++++++++ 6 files changed, 100 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui.ts b/packages/opencode/src/cli/cmd/tui.ts index 95ffac7ea5..d5fa46bfb1 100644 --- a/packages/opencode/src/cli/cmd/tui.ts +++ b/packages/opencode/src/cli/cmd/tui.ts @@ -303,7 +303,7 @@ export const TuiThreadCommand = cmd({ unguard?.() } catch {} } - process.exit(0) + process.exit() }, }) // scratch diff --git a/packages/opencode/src/server/routes/instance/httpapi/middleware/error.ts b/packages/opencode/src/server/routes/instance/httpapi/middleware/error.ts index 21b53aba75..3bedd19704 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/middleware/error.ts +++ b/packages/opencode/src/server/routes/instance/httpapi/middleware/error.ts @@ -20,7 +20,8 @@ export const errorLayer = HttpRouter.middleware<{ handles: unknown }>()((effect) ConfigErrorV1.JsonError.isInstance(error) || ConfigErrorV1.InvalidError.isInstance(error) || ConfigErrorV1.FrontmatterError.isInstance(error) || - ConfigErrorV1.DirectoryTypoError.isInstance(error) + ConfigErrorV1.DirectoryTypoError.isInstance(error) || + ConfigErrorV1.RemoteAuthError.isInstance(error) ) { return Effect.succeed(HttpServerResponse.jsonUnsafe(error.toObject(), { status: 400 })) } diff --git a/packages/opencode/test/server/httpapi-error-middleware.test.ts b/packages/opencode/test/server/httpapi-error-middleware.test.ts index 7bfc6da032..525bf34e20 100644 --- a/packages/opencode/test/server/httpapi-error-middleware.test.ts +++ b/packages/opencode/test/server/httpapi-error-middleware.test.ts @@ -83,6 +83,27 @@ describe("HttpApi error middleware", () => { }), ) + it.live("returns remote auth defects as structured client errors", () => + Effect.gen(function* () { + const configError = new ConfigErrorV1.RemoteAuthError({ + url: "https://example.com", + remote: "https://config.example.com/opencode.json", + }) + + yield* HttpRouter.add("GET", "/remote-auth-error", Effect.die(configError)).pipe( + Layer.provide(errorLayer), + HttpRouter.serve, + Layer.build, + ) + + const response = yield* HttpClientRequest.get("/remote-auth-error").pipe(HttpClient.execute) + const body = yield* response.json + + expect(response.status).toBe(400) + expect(body).toEqual(configError.toObject()) + }), + ) + it.live("does not map storage not-found defects to 404", () => Effect.gen(function* () { yield* HttpRouter.add( diff --git a/packages/tui/src/app.tsx b/packages/tui/src/app.tsx index 3f1da522bb..6852311f9e 100644 --- a/packages/tui/src/app.tsx +++ b/packages/tui/src/app.tsx @@ -356,8 +356,10 @@ export const run = Effect.fn("Tui.run")(function* (input: TuiInput) { ) yield* Effect.sync(() => { win32FlushInputBuffer() - if (result.reason !== undefined) + if (result.reason !== undefined) { process.stderr.write((cliErrorMessage(result.reason) ?? errorFormat(result.reason)) + "\n") + process.exitCode = 1 + } if (result.epilogue) process.stdout.write(result.epilogue + "\n") }) }) diff --git a/packages/tui/src/util/error.ts b/packages/tui/src/util/error.ts index 757758a205..606bfb3bb7 100644 --- a/packages/tui/src/util/error.ts +++ b/packages/tui/src/util/error.ts @@ -47,6 +47,17 @@ export function cliErrorMessage(input: unknown): string | undefined { const frontmatter = configData(input, "ConfigFrontmatterError") if (frontmatter) return field(frontmatter, "message") ?? "" + const remoteAuth = configData(input, "ConfigRemoteAuthError") + if (remoteAuth) { + const url = field(remoteAuth, "url") + const remote = field(remoteAuth, "remote") + return [ + `Failed to load remote config${remote ? ` from ${remote}` : ""}: the server returned a login page instead of JSON.`, + "Authentication is missing or has expired (the endpoint is likely behind an SSO or identity-aware proxy).", + ...(url ? [`Run \`opencode auth login ${url}\` to re-authenticate.`] : []), + ].join("\n") + } + const invalid = configData(input, "ConfigInvalidError") if (invalid) { const path = field(invalid, "path") diff --git a/packages/tui/test/app-lifecycle.test.tsx b/packages/tui/test/app-lifecycle.test.tsx index 5706634247..8cd40315cc 100644 --- a/packages/tui/test/app-lifecycle.test.tsx +++ b/packages/tui/test/app-lifecycle.test.tsx @@ -126,3 +126,65 @@ test("app.exit prints the session epilogue after scoped cleanup", async () => { mock.restore() } }) + +test("fatal startup errors set a nonzero exit after scoped cleanup", async () => { + const setup = await createTestRenderer({ width: 80, height: 24, useThread: false }) + const core = await import("@opentui/core") + await mock.module("@opentui/core", () => ({ ...core, createCliRenderer: async () => setup.renderer })) + const events = createEventSource() + const calls = createFetch((url) => { + if (url.pathname === "/config") + return json( + { + name: "ConfigRemoteAuthError", + data: { + url: "https://example.com", + remote: "https://config.example.com/opencode.json", + }, + }, + { status: 400 }, + ) + return undefined + }) + let disposes = 0 + const originalWrite = process.stderr.write.bind(process.stderr) + const originalExitCode = process.exitCode ?? 0 + let stderr = "" + + process.stderr.write = ((chunk: string | Uint8Array) => { + stderr += String(chunk) + return true + }) as typeof process.stderr.write + + try { + const { run } = await import("../src/app") + const task = Effect.runPromise( + run({ + url: "http://test", + directory, + config: createTuiResolvedConfig({ plugin_enabled: {} }), + fetch: calls.fetch, + events: events.source, + args: {}, + pluginHost: { + async start() {}, + async dispose() { + disposes++ + }, + }, + }).pipe(Effect.provide(AppNodeBuilder.build(Global.node))), + ) + + await task + expect(stderr).toContain("Run `opencode auth login https://example.com` to re-authenticate.") + expect(stderr).not.toContain("Unexpected server error") + expect(process.exitCode).toBe(1) + expect(setup.renderer.isDestroyed).toBe(true) + expect(disposes).toBe(1) + } finally { + process.stderr.write = originalWrite + process.exitCode = originalExitCode + if (!setup.renderer.isDestroyed) setup.renderer.destroy() + mock.restore() + } +}) From a74c472ffb941e6b027e5348be50cfe2225c6c56 Mon Sep 17 00:00:00 2001 From: opencode Date: Mon, 14 Sep 2026 17:47:27 +0000 Subject: [PATCH 4/6] sync release versions for v1.18.31 --- bun.lock | 56 ++++++++++----------- packages/app/package.json | 2 +- packages/cli/package.json | 2 +- packages/codemode/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/console/support/package.json | 2 +- packages/core/package.json | 2 +- packages/desktop/package.json | 2 +- packages/effect-drizzle-sqlite/package.json | 2 +- packages/effect-sqlite-node/package.json | 2 +- packages/enterprise/package.json | 2 +- packages/function/package.json | 2 +- packages/http-recorder/package.json | 2 +- packages/llm/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/server/package.json | 2 +- packages/session-ui/package.json | 2 +- packages/slack/package.json | 2 +- packages/stats/app/package.json | 2 +- packages/stats/core/package.json | 2 +- packages/stats/server/package.json | 2 +- packages/tui/package.json | 2 +- packages/ui/package.json | 2 +- packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- 30 files changed, 57 insertions(+), 57 deletions(-) diff --git a/bun.lock b/bun.lock index a8774d3aa2..338f7f0234 100644 --- a/bun.lock +++ b/bun.lock @@ -29,7 +29,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@corvu/drawer": "catalog:", "@dnd-kit/abstract": "0.5.0", @@ -96,7 +96,7 @@ }, "packages/cli": { "name": "@opencode-ai/cli", - "version": "1.18.30", + "version": "1.18.31", "bin": { "lildax": "./bin/lildax.cjs", }, @@ -144,7 +144,7 @@ }, "packages/codemode": { "name": "@opencode-ai/codemode", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "acorn": "8.15.0", "effect": "catalog:", @@ -158,7 +158,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -195,7 +195,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -222,7 +222,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@ai-sdk/anthropic": "3.0.82", "@ai-sdk/openai": "3.0.48", @@ -245,7 +245,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -269,7 +269,7 @@ }, "packages/console/support": { "name": "@opencode-ai/console-support", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@opencode-ai/console-core": "workspace:*", @@ -289,7 +289,7 @@ }, "packages/core": { "name": "@opencode-ai/core", - "version": "1.18.30", + "version": "1.18.31", "bin": { "opencode": "./bin/opencode", }, @@ -383,7 +383,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@zip.js/zip.js": "2.7.62", "drizzle-orm": "catalog:", @@ -437,7 +437,7 @@ }, "packages/effect-drizzle-sqlite": { "name": "@opencode-ai/effect-drizzle-sqlite", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "drizzle-orm": "catalog:", "effect": "catalog:", @@ -451,7 +451,7 @@ }, "packages/effect-sqlite-node": { "name": "@opencode-ai/effect-sqlite-node", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "effect": "catalog:", }, @@ -463,7 +463,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@hono/standard-validator": "catalog:", "@opencode-ai/core": "workspace:*", @@ -495,7 +495,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -511,7 +511,7 @@ }, "packages/http-recorder": { "name": "@opencode-ai/http-recorder", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@effect/platform-node": "4.0.0-beta.83", "@effect/platform-node-shared": "4.0.0-beta.83", @@ -542,7 +542,7 @@ }, "packages/llm": { "name": "@opencode-ai/llm", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@opencode-ai/schema": "workspace:*", "@smithy/eventstream-codec": "4.2.14", @@ -561,7 +561,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.18.30", + "version": "1.18.31", "bin": { "opencode": "./bin/opencode", }, @@ -692,7 +692,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@ai-sdk/provider": "3.0.8", "@opencode-ai/sdk": "workspace:*", @@ -768,7 +768,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "cross-spawn": "catalog:", }, @@ -783,7 +783,7 @@ }, "packages/server": { "name": "@opencode-ai/server", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@opencode-ai/core": "workspace:*", "@opencode-ai/protocol": "workspace:*", @@ -798,7 +798,7 @@ }, "packages/session-ui": { "name": "@opencode-ai/session-ui", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/client": "file:../app/vendor/opencode-ai-client-1.17.13-v2.tgz", @@ -838,7 +838,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -851,7 +851,7 @@ }, "packages/stats/app": { "name": "@opencode-ai/stats-app", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@ibm/plex": "6.4.1", "@kobalte/core": "catalog:", @@ -878,7 +878,7 @@ }, "packages/stats/core": { "name": "@opencode-ai/stats-core", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@aws-sdk/client-athena": "3.933.0", "@planetscale/database": "1.19.0", @@ -897,7 +897,7 @@ }, "packages/stats/server": { "name": "@opencode-ai/stats-server", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@aws-sdk/client-firehose": "3.933.0", "@effect/platform-node": "catalog:", @@ -939,7 +939,7 @@ }, "packages/tui": { "name": "@opencode-ai/tui", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@opencode-ai/core": "workspace:*", "@opencode-ai/plugin": "workspace:*", @@ -966,7 +966,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@kobalte/core": "catalog:", "@pierre/diffs": "catalog:", @@ -1017,7 +1017,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.18.30", + "version": "1.18.31", "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 17b356ed60..97c98e9fc3 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "1.18.30", + "version": "1.18.31", "description": "", "type": "module", "exports": { diff --git a/packages/cli/package.json b/packages/cli/package.json index f6dd6bf831..7e94b23108 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/cli", - "version": "1.18.30", + "version": "1.18.31", "type": "module", "license": "MIT", "bin": { diff --git a/packages/codemode/package.json b/packages/codemode/package.json index c516b3a985..8a14b5769d 100644 --- a/packages/codemode/package.json +++ b/packages/codemode/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/codemode", - "version": "1.18.30", + "version": "1.18.31", "description": "Effect-native confined code execution over schema-described tools", "private": true, "type": "module", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 3651594fd7..b89e19a72b 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.18.30", + "version": "1.18.31", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 19aade616d..fefbe8abfd 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.18.30", + "version": "1.18.31", "private": true, "type": "module", "license": "MIT", diff --git a/packages/console/function/package.json b/packages/console/function/package.json index d77be8cb6a..1026754e63 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.18.30", + "version": "1.18.31", "$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 e35574b3e9..755102b6e7 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.18.30", + "version": "1.18.31", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/console/support/package.json b/packages/console/support/package.json index 75e8e07147..56a0099ad4 100644 --- a/packages/console/support/package.json +++ b/packages/console/support/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-support", - "version": "1.18.30", + "version": "1.18.31", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/core/package.json b/packages/core/package.json index ab20288b52..2b465e5852 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.18.30", + "version": "1.18.31", "name": "@opencode-ai/core", "type": "module", "license": "MIT", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 7c55897b74..f494e53416 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop", "private": true, - "version": "1.18.30", + "version": "1.18.31", "type": "module", "license": "MIT", "homepage": "https://opencode.ai", diff --git a/packages/effect-drizzle-sqlite/package.json b/packages/effect-drizzle-sqlite/package.json index 35cc50f97d..1dc5d0ce66 100644 --- a/packages/effect-drizzle-sqlite/package.json +++ b/packages/effect-drizzle-sqlite/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.18.30", + "version": "1.18.31", "name": "@opencode-ai/effect-drizzle-sqlite", "type": "module", "license": "MIT", diff --git a/packages/effect-sqlite-node/package.json b/packages/effect-sqlite-node/package.json index 19d0652c1a..5a425b9feb 100644 --- a/packages/effect-sqlite-node/package.json +++ b/packages/effect-sqlite-node/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.18.30", + "version": "1.18.31", "name": "@opencode-ai/effect-sqlite-node", "type": "module", "license": "MIT", diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index 9d61ae5eac..aea997e34e 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.18.30", + "version": "1.18.31", "private": true, "type": "module", "license": "MIT", diff --git a/packages/function/package.json b/packages/function/package.json index 7d9bc6548b..03348052a2 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.18.30", + "version": "1.18.31", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/http-recorder/package.json b/packages/http-recorder/package.json index cc8ae63655..1fd0b834eb 100644 --- a/packages/http-recorder/package.json +++ b/packages/http-recorder/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.18.30", + "version": "1.18.31", "name": "@opencode-ai/http-recorder", "description": "Record and replay Effect HTTP client traffic with deterministic cassettes", "type": "module", diff --git a/packages/llm/package.json b/packages/llm/package.json index 79471820d6..2b10849540 100644 --- a/packages/llm/package.json +++ b/packages/llm/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.18.30", + "version": "1.18.31", "name": "@opencode-ai/llm", "type": "module", "license": "MIT", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 8cc027275c..5e628b3c70 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.18.30", + "version": "1.18.31", "name": "opencode", "type": "module", "license": "MIT", diff --git a/packages/plugin/package.json b/packages/plugin/package.json index d06914cdc8..09c1210988 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.18.30", + "version": "1.18.31", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 9777184dfe..a471612eca 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.18.30", + "version": "1.18.31", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/server/package.json b/packages/server/package.json index 04cb235ff6..c99bd4ac87 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/server", - "version": "1.18.30", + "version": "1.18.31", "private": true, "type": "module", "license": "MIT", diff --git a/packages/session-ui/package.json b/packages/session-ui/package.json index 7db27630da..aaba6a52d8 100644 --- a/packages/session-ui/package.json +++ b/packages/session-ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/session-ui", - "version": "1.18.30", + "version": "1.18.31", "private": true, "type": "module", "license": "MIT", diff --git a/packages/slack/package.json b/packages/slack/package.json index f1aa4602ba..86fc0d763a 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.18.30", + "version": "1.18.31", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/stats/app/package.json b/packages/stats/app/package.json index 20d56aa596..bd1064c18c 100644 --- a/packages/stats/app/package.json +++ b/packages/stats/app/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/stats-app", - "version": "1.18.30", + "version": "1.18.31", "private": true, "type": "module", "license": "MIT", diff --git a/packages/stats/core/package.json b/packages/stats/core/package.json index d6ffa5fd65..3bfb642ea2 100644 --- a/packages/stats/core/package.json +++ b/packages/stats/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/stats-core", - "version": "1.18.30", + "version": "1.18.31", "private": true, "type": "module", "license": "MIT", diff --git a/packages/stats/server/package.json b/packages/stats/server/package.json index 27f5e23ec0..26efcc3aae 100644 --- a/packages/stats/server/package.json +++ b/packages/stats/server/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/stats-server", - "version": "1.18.30", + "version": "1.18.31", "private": true, "type": "module", "license": "MIT", diff --git a/packages/tui/package.json b/packages/tui/package.json index 4b9b95b35e..bc8c1181e9 100644 --- a/packages/tui/package.json +++ b/packages/tui/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/tui", - "version": "1.18.30", + "version": "1.18.31", "private": true, "type": "module", "license": "MIT", diff --git a/packages/ui/package.json b/packages/ui/package.json index 28dbce9eca..02c1573f0d 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.18.30", + "version": "1.18.31", "type": "module", "license": "MIT", "repository": { diff --git a/packages/web/package.json b/packages/web/package.json index 623f08dfca..d5716400d3 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.18.30", + "version": "1.18.31", "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 5c43de8075..779435fece 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.18.30", + "version": "1.18.31", "publisher": "sst-dev", "repository": { "type": "git", From 4ae176520de9ba6615f71bdf188ce1fe2e88388b Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" <219766164+opencode-agent[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 14:16:46 -0700 Subject: [PATCH 5/6] chore: add Alan to team members (#49054) Co-authored-by: rekram1-node --- .github/TEAM_MEMBERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/TEAM_MEMBERS b/.github/TEAM_MEMBERS index 5268ff59dd..866d466a8b 100644 --- a/.github/TEAM_MEMBERS +++ b/.github/TEAM_MEMBERS @@ -20,3 +20,4 @@ Slickstef11 usrnk1 vimtor StarpTech +vaprdev From 5cf4e13588c4af05046cbfddebe1d2d97da6cf6b Mon Sep 17 00:00:00 2001 From: vprdev Date: Mon, 14 Sep 2026 14:32:56 -0700 Subject: [PATCH 6/6] fix(console): route new Console keys to inference (#49036) --- .../console/app/src/lib/inference-proxy.ts | 76 ++++++++++--------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/packages/console/app/src/lib/inference-proxy.ts b/packages/console/app/src/lib/inference-proxy.ts index b572c361b6..1eade3ff8f 100644 --- a/packages/console/app/src/lib/inference-proxy.ts +++ b/packages/console/app/src/lib/inference-proxy.ts @@ -1,5 +1,5 @@ import { Resource } from "@opencode-ai/console-resource" -import { and, Database, eq, isNull, sql } from "@opencode-ai/console-core/drizzle/index.js" +import { and, Database, eq, isNotNull, isNull, sql } from "@opencode-ai/console-core/drizzle/index.js" import { KeyTable } from "@opencode-ai/console-core/schema/key.sql.js" import { ProviderTable } from "@opencode-ai/console-core/schema/provider.sql.js" import { WorkspaceTable } from "@opencode-ai/console-core/schema/workspace.sql.js" @@ -34,7 +34,6 @@ export async function proxyInference( : undefined) if (!path) return undefined - const go = url.pathname.startsWith("/zen/go/") const key = url.pathname.endsWith("/messages") ? request.headers.get("x-api-key") : path.startsWith("/google/") @@ -42,44 +41,23 @@ export async function proxyInference( : request.headers.get("authorization")?.split(" ")[1] if (!key || key === "public") return undefined - // Routing only; the destination owns authentication and revocation after cutover. - const workspace = await Database.use((tx) => - tx - .select({ - id: WorkspaceTable.id, - migratedAt: WorkspaceTable.migrated_at, - provider: ProviderTable.provider, - }) - .from(KeyTable) - .innerJoin(WorkspaceTable, eq(WorkspaceTable.id, KeyTable.workspaceID)) - .leftJoin( - ProviderTable, - !go && generation?.provider - ? and( - eq(ProviderTable.workspaceID, KeyTable.workspaceID), - eq(ProviderTable.provider, generation.provider), - isNull(ProviderTable.timeDeleted), - sql`length(${ProviderTable.credentials}) > 0`, - ) - : sql`false`, - ) - .where(eq(KeyTable.key, key)) - .limit(1) - .then((rows) => rows[0]), - ) - if (!workspace?.migratedAt) return undefined - const model = workspace.provider ? generation?.model : undefined - if (workspace.provider && !model) throw new Error("Legacy BYOK model mapping is unavailable") + // New Console keys are never in the legacy key table; every legacy key is `sk-`. + const legacy = !key.startsWith("oc_sk_") + const workspace = legacy ? await migratedWorkspace(key, generation?.provider) : undefined + if (legacy && !workspace) return undefined + const model = workspace?.provider ? generation?.model : undefined + if (workspace?.provider && !model) throw new Error("Legacy BYOK model mapping is unavailable") const destination = new URL(Resource.ConsoleMigration.inferenceUrl) // Imported connections must use this same workspace/provider-derived ID. - const target = model - ? `/custom/conn_${workspace.id.slice(4)}_${workspace.provider}${ - path.startsWith("/google/") - ? `/models/${encodeURIComponent(model)}${url.pathname.slice(url.pathname.lastIndexOf(":"))}` - : url.pathname.slice("/zen/v1".length) - }` - : path + const target = + model && workspace + ? `/custom/conn_${workspace.id.slice(4)}_${workspace.provider}${ + path.startsWith("/google/") + ? `/models/${encodeURIComponent(model)}${url.pathname.slice(url.pathname.lastIndexOf(":"))}` + : url.pathname.slice("/zen/v1".length) + }` + : path destination.pathname = `${destination.pathname.replace(/\/$/, "")}${target}` destination.search = url.search destination.hash = "" @@ -109,6 +87,30 @@ export async function proxyInference( return fetch(forwarded, { redirect: "manual" }) } +// Routing only; the destination owns authentication and revocation after cutover. +function migratedWorkspace(key: string, provider?: string) { + return Database.use((tx) => + tx + .select({ id: WorkspaceTable.id, provider: ProviderTable.provider }) + .from(KeyTable) + .innerJoin(WorkspaceTable, eq(WorkspaceTable.id, KeyTable.workspaceID)) + .leftJoin( + ProviderTable, + provider + ? and( + eq(ProviderTable.workspaceID, KeyTable.workspaceID), + eq(ProviderTable.provider, provider), + isNull(ProviderTable.timeDeleted), + sql`length(${ProviderTable.credentials}) > 0`, + ) + : sql`false`, + ) + .where(and(eq(KeyTable.key, key), isNotNull(WorkspaceTable.migrated_at))) + .limit(1) + .then((rows) => rows[0]), + ) +} + export function inferenceUnavailable() { return Response.json( { error: { type: "api_error", message: "Inference routing is unavailable. Please retry later." } },