From b1b8f6cf71597b3000d1b245a95dbc023687c005 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sat, 20 Dec 2025 09:57:19 -0500 Subject: [PATCH 001/112] ci --- .github/workflows/publish.yml | 3 +-- packages/tauri/scripts/prepare.ts | 3 ++- script/publish-complete.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 77d7bb30e..cdc8bd741 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -221,8 +221,7 @@ jobs: - run: ./script/publish-complete.ts env: - OPENCODE_BUMP: ${{ inputs.bump }} - OPENCODE_VERSION: ${{ inputs.version }} + OPENCODE_VERSION: ${{ needs.publish.outputs.tagName }} AUR_KEY: ${{ secrets.AUR_KEY }} GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }} OPENCODE_RELEASE_TAG: ${{ needs.publish.outputs.tagName }} diff --git a/packages/tauri/scripts/prepare.ts b/packages/tauri/scripts/prepare.ts index 23cf3dc5d..692e0dd78 100755 --- a/packages/tauri/scripts/prepare.ts +++ b/packages/tauri/scripts/prepare.ts @@ -3,13 +3,14 @@ import { $ } from "bun" import { copyBinaryToSidecarFolder, getCurrentSidecar } from "./utils" +import { Script } from "@opencode-ai/script" const sidecarConfig = getCurrentSidecar() const dir = "src-tauri/target/opencode-binaries" await $`mkdir -p ${dir}` -await $`gh release download ${Bun.env.OPENCODE_RELEASE_TAG} --pattern ${sidecarConfig.ocBinary}.${sidecarConfig.assetExt} --repo sst/opencode --skip-existing --dir ${dir}` +await $`gh release download v${Script.version} --pattern ${sidecarConfig.ocBinary}.${sidecarConfig.assetExt} --repo sst/opencode --skip-existing --dir ${dir}` if (sidecarConfig.assetExt === "tar.gz") { await $`tar -xvzf ${dir}/${sidecarConfig.ocBinary}.${sidecarConfig.assetExt} -C ${dir}` diff --git a/script/publish-complete.ts b/script/publish-complete.ts index aae1a3524..a3bdceae0 100755 --- a/script/publish-complete.ts +++ b/script/publish-complete.ts @@ -4,7 +4,7 @@ import { Script } from "@opencode-ai/script" import { $ } from "bun" if (!Script.preview) { - await $`gh release edit ${process.env.OPENCODE_RELEASE_TAG} --draft=false` + await $`gh release edit v${Script.version} --draft=false` } await $`bun install` From f29f284b3e076c337316a89dd9b0c4bfb93589eb Mon Sep 17 00:00:00 2001 From: opencode Date: Sat, 20 Dec 2025 15:00:40 +0000 Subject: [PATCH 002/112] release: v1.0.177 --- bun.lock | 30 +++++++++++++------------- 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/tauri/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 d62d9013a..94a452f75 100644 --- a/bun.lock +++ b/bun.lock @@ -20,7 +20,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.0.176", + "version": "1.0.177", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -48,7 +48,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.176", + "version": "1.0.177", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -75,7 +75,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.176", + "version": "1.0.177", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -99,7 +99,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.176", + "version": "1.0.177", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -123,7 +123,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.176", + "version": "1.0.177", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -171,7 +171,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.0.176", + "version": "1.0.177", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -200,7 +200,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.176", + "version": "1.0.177", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -216,7 +216,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.176", + "version": "1.0.177", "bin": { "opencode": "./bin/opencode", }, @@ -308,7 +308,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.176", + "version": "1.0.177", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -328,7 +328,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.176", + "version": "1.0.177", "devDependencies": { "@hey-api/openapi-ts": "0.88.1", "@tsconfig/node22": "catalog:", @@ -339,7 +339,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.176", + "version": "1.0.177", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -352,7 +352,7 @@ }, "packages/tauri": { "name": "@opencode-ai/tauri", - "version": "1.0.176", + "version": "1.0.177", "dependencies": { "@opencode-ai/desktop": "workspace:*", "@solid-primitives/storage": "catalog:", @@ -379,7 +379,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.176", + "version": "1.0.177", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -414,7 +414,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.0.176", + "version": "1.0.177", "dependencies": { "zod": "catalog:", }, @@ -425,7 +425,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.176", + "version": "1.0.177", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 10a516ed6..2e867b9ad 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.0.176", + "version": "1.0.177", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 87cc8f746..4d61d5dea 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.0.176", + "version": "1.0.177", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index e3d1eba98..ceacdff28 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.176", + "version": "1.0.177", "$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 4d6195235..85ab10b64 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.176", + "version": "1.0.177", "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 91eec2039..18e1bef96 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.176", + "version": "1.0.177", "description": "", "type": "module", "exports": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index 71ab278aa..ada31eecb 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.0.176", + "version": "1.0.177", "private": true, "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index 9700d566d..2f997f4e7 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.0.176" +version = "1.0.177" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/sst/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.176/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.177/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.176/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.177/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.176/opencode-linux-arm64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.177/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.176/opencode-linux-x64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.177/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.176/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.177/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index 7545778c2..4cfe3a725 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.176", + "version": "1.0.177", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 5fafe674c..998b24f29 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.176", + "version": "1.0.177", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index d31d5ee24..b5d85d3e8 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.0.176", + "version": "1.0.177", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 7f2728796..8287c6205 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.0.176", + "version": "1.0.177", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/slack/package.json b/packages/slack/package.json index 23aad1221..7083f55b3 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.176", + "version": "1.0.177", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/tauri/package.json b/packages/tauri/package.json index 7b0a05aac..132557609 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/tauri", "private": true, - "version": "1.0.176", + "version": "1.0.177", "type": "module", "scripts": { "typecheck": "tsgo -b", diff --git a/packages/ui/package.json b/packages/ui/package.json index 5313437f5..5215c2235 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.176", + "version": "1.0.177", "type": "module", "exports": { "./*": "./src/components/*.tsx", diff --git a/packages/util/package.json b/packages/util/package.json index b38c1f823..c6bb3c1e9 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.0.176", + "version": "1.0.177", "private": true, "type": "module", "exports": { diff --git a/packages/web/package.json b/packages/web/package.json index 27dc9ad1e..1c3b91a6b 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.176", + "version": "1.0.177", "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 ce814ffa5..a3cdd7c1d 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.0.176", + "version": "1.0.177", "publisher": "sst-dev", "repository": { "type": "git", From 6e93d14bdba29015ed8fe617bcc26d459c33a5b2 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sat, 20 Dec 2025 14:57:57 +0000 Subject: [PATCH 003/112] chore: generate --- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/package.json b/packages/plugin/package.json index b5d85d3e8..0b8f8a9d9 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} \ No newline at end of file +} diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 8287c6205..8cdcadbc9 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -29,4 +29,4 @@ "publishConfig": { "directory": "dist" } -} \ No newline at end of file +} From a7a2bbb497f9c8775bc93cbfd9c2964fe3472d79 Mon Sep 17 00:00:00 2001 From: "Tommy D. Rossi" Date: Sat, 20 Dec 2025 16:00:20 +0100 Subject: [PATCH 004/112] feat: add endpoints to delete and update message parts (#5433) --- packages/opencode/src/server/server.ts | 73 +++++++++++ packages/opencode/src/session/index.ts | 17 +++ packages/sdk/js/src/v2/gen/sdk.gen.ts | 80 ++++++++++++ packages/sdk/js/src/v2/gen/types.gen.ts | 88 +++++++++++++ packages/sdk/openapi.json | 167 ++++++++++++++++++++++++ 5 files changed, 425 insertions(+) diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 34e5c0623..77bf5085b 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -1188,6 +1188,79 @@ export namespace Server { return c.json(message) }, ) + .delete( + "/session/:sessionID/message/:messageID/part/:partID", + describeRoute({ + description: "Delete a part from a message", + operationId: "part.delete", + responses: { + 200: { + description: "Successfully deleted part", + content: { + "application/json": { + schema: resolver(z.boolean()), + }, + }, + }, + ...errors(400, 404), + }, + }), + validator( + "param", + z.object({ + sessionID: z.string().meta({ description: "Session ID" }), + messageID: z.string().meta({ description: "Message ID" }), + partID: z.string().meta({ description: "Part ID" }), + }), + ), + async (c) => { + const params = c.req.valid("param") + await Session.removePart({ + sessionID: params.sessionID, + messageID: params.messageID, + partID: params.partID, + }) + return c.json(true) + }, + ) + .patch( + "/session/:sessionID/message/:messageID/part/:partID", + describeRoute({ + description: "Update a part in a message", + operationId: "part.update", + responses: { + 200: { + description: "Successfully updated part", + content: { + "application/json": { + schema: resolver(MessageV2.Part), + }, + }, + }, + ...errors(400, 404), + }, + }), + validator( + "param", + z.object({ + sessionID: z.string().meta({ description: "Session ID" }), + messageID: z.string().meta({ description: "Message ID" }), + partID: z.string().meta({ description: "Part ID" }), + }), + ), + validator("json", MessageV2.Part), + async (c) => { + const params = c.req.valid("param") + const body = c.req.valid("json") + if (body.id !== params.partID || body.messageID !== params.messageID || body.sessionID !== params.sessionID) { + throw new Error( + `Part mismatch: body.id='${body.id}' vs partID='${params.partID}', body.messageID='${body.messageID}' vs messageID='${params.messageID}', body.sessionID='${body.sessionID}' vs sessionID='${params.sessionID}'`, + ) + } + const part = await Session.updatePart(body) + return c.json(part) + }, + ) .post( "/session/:sessionID/message", describeRoute({ diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index b1a193904..4285223bc 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -339,6 +339,23 @@ export namespace Session { }, ) + export const removePart = fn( + z.object({ + sessionID: Identifier.schema("session"), + messageID: Identifier.schema("message"), + partID: Identifier.schema("part"), + }), + async (input) => { + await Storage.remove(["part", input.messageID, input.partID]) + Bus.publish(MessageV2.Event.PartRemoved, { + sessionID: input.sessionID, + messageID: input.messageID, + partID: input.partID, + }) + return input.partID + }, + ) + const UpdatePartInput = z.union([ MessageV2.Part, z.object({ diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index 16fe07ae4..1a7128e24 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -47,6 +47,11 @@ import type { McpLocalConfig, McpRemoteConfig, McpStatusResponses, + Part as Part2, + PartDeleteErrors, + PartDeleteResponses, + PartUpdateErrors, + PartUpdateResponses, PathGetResponses, PermissionRespondErrors, PermissionRespondResponses, @@ -1486,6 +1491,79 @@ export class Session extends HeyApiClient { } } +export class Part extends HeyApiClient { + /** + * Delete a part from a message + */ + public delete( + parameters: { + sessionID: string + messageID: string + partID: string + directory?: string + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "path", key: "messageID" }, + { in: "path", key: "partID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).delete({ + url: "/session/{sessionID}/message/{messageID}/part/{partID}", + ...options, + ...params, + }) + } + + /** + * Update a part in a message + */ + public update( + parameters: { + sessionID: string + messageID: string + partID: string + directory?: string + part?: Part2 + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "path", key: "messageID" }, + { in: "path", key: "partID" }, + { in: "query", key: "directory" }, + { key: "part", map: "body" }, + ], + }, + ], + ) + return (options?.client ?? this.client).patch({ + url: "/session/{sessionID}/message/{messageID}/part/{partID}", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } +} + export class Permission extends HeyApiClient { /** * Respond to permission @@ -2588,6 +2666,8 @@ export class OpencodeClient extends HeyApiClient { session = new Session({ client: this.client }) + part = new Part({ client: this.client }) + permission = new Permission({ client: this.client }) command = new Command({ client: this.client }) diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index c96530737..cdbdfdfda 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -2915,6 +2915,94 @@ export type SessionMessageResponses = { export type SessionMessageResponse = SessionMessageResponses[keyof SessionMessageResponses] +export type PartDeleteData = { + body?: never + path: { + /** + * Session ID + */ + sessionID: string + /** + * Message ID + */ + messageID: string + /** + * Part ID + */ + partID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/message/{messageID}/part/{partID}" +} + +export type PartDeleteErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type PartDeleteError = PartDeleteErrors[keyof PartDeleteErrors] + +export type PartDeleteResponses = { + /** + * Successfully deleted part + */ + 200: boolean +} + +export type PartDeleteResponse = PartDeleteResponses[keyof PartDeleteResponses] + +export type PartUpdateData = { + body?: Part + path: { + /** + * Session ID + */ + sessionID: string + /** + * Message ID + */ + messageID: string + /** + * Part ID + */ + partID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/message/{messageID}/part/{partID}" +} + +export type PartUpdateErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type PartUpdateError = PartUpdateErrors[keyof PartUpdateErrors] + +export type PartUpdateResponses = { + /** + * Successfully updated part + */ + 200: Part +} + +export type PartUpdateResponse = PartUpdateResponses[keyof PartUpdateResponses] + export type SessionPromptAsyncData = { body?: { messageID?: string diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index 09c7ea8e9..eeb81a844 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -2126,6 +2126,173 @@ ] } }, + "/session/{sessionID}/message/{messageID}/part/{partID}": { + "delete": { + "operationId": "part.delete", + "parameters": [ + { + "in": "query", + "name": "directory", + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "sessionID", + "schema": { + "type": "string" + }, + "required": true, + "description": "Session ID" + }, + { + "in": "path", + "name": "messageID", + "schema": { + "type": "string" + }, + "required": true, + "description": "Message ID" + }, + { + "in": "path", + "name": "partID", + "schema": { + "type": "string" + }, + "required": true, + "description": "Part ID" + } + ], + "description": "Delete a part from a message", + "responses": { + "200": { + "description": "Successfully deleted part", + "content": { + "application/json": { + "schema": { + "type": "boolean" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundError" + } + } + } + } + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createOpencodeClient } from \"@opencode-ai/sdk\n\nconst client = createOpencodeClient()\nawait client.part.delete({\n ...\n})" + } + ] + }, + "patch": { + "operationId": "part.update", + "parameters": [ + { + "in": "query", + "name": "directory", + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "sessionID", + "schema": { + "type": "string" + }, + "required": true, + "description": "Session ID" + }, + { + "in": "path", + "name": "messageID", + "schema": { + "type": "string" + }, + "required": true, + "description": "Message ID" + }, + { + "in": "path", + "name": "partID", + "schema": { + "type": "string" + }, + "required": true, + "description": "Part ID" + } + ], + "description": "Update a part in a message", + "responses": { + "200": { + "description": "Successfully updated part", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Part" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundError" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Part" + } + } + } + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createOpencodeClient } from \"@opencode-ai/sdk\n\nconst client = createOpencodeClient()\nawait client.part.update({\n ...\n})" + } + ] + } + }, "/session/{sessionID}/prompt_async": { "post": { "operationId": "session.prompt_async", From 5e79b95927fa993e80c765ebbdc405d63a11a2f0 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sat, 20 Dec 2025 10:04:57 -0500 Subject: [PATCH 005/112] ci --- packages/tauri/scripts/prepare.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/tauri/scripts/prepare.ts b/packages/tauri/scripts/prepare.ts index 692e0dd78..23cf3dc5d 100755 --- a/packages/tauri/scripts/prepare.ts +++ b/packages/tauri/scripts/prepare.ts @@ -3,14 +3,13 @@ import { $ } from "bun" import { copyBinaryToSidecarFolder, getCurrentSidecar } from "./utils" -import { Script } from "@opencode-ai/script" const sidecarConfig = getCurrentSidecar() const dir = "src-tauri/target/opencode-binaries" await $`mkdir -p ${dir}` -await $`gh release download v${Script.version} --pattern ${sidecarConfig.ocBinary}.${sidecarConfig.assetExt} --repo sst/opencode --skip-existing --dir ${dir}` +await $`gh release download ${Bun.env.OPENCODE_RELEASE_TAG} --pattern ${sidecarConfig.ocBinary}.${sidecarConfig.assetExt} --repo sst/opencode --skip-existing --dir ${dir}` if (sidecarConfig.assetExt === "tar.gz") { await $`tar -xvzf ${dir}/${sidecarConfig.ocBinary}.${sidecarConfig.assetExt} -C ${dir}` From 6a4f4009d52fc6934414118a0a7cbca0d532e7ea Mon Sep 17 00:00:00 2001 From: opencode Date: Sat, 20 Dec 2025 15:08:27 +0000 Subject: [PATCH 006/112] release: v1.0.178 --- bun.lock | 30 +++++++++++++------------- 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 | 4 ++-- packages/sdk/js/package.json | 4 ++-- packages/slack/package.json | 2 +- packages/tauri/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, 39 insertions(+), 39 deletions(-) diff --git a/bun.lock b/bun.lock index 94a452f75..35921ead7 100644 --- a/bun.lock +++ b/bun.lock @@ -20,7 +20,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.0.177", + "version": "1.0.178", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -48,7 +48,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.177", + "version": "1.0.178", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -75,7 +75,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.177", + "version": "1.0.178", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -99,7 +99,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.177", + "version": "1.0.178", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -123,7 +123,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.177", + "version": "1.0.178", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -171,7 +171,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.0.177", + "version": "1.0.178", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -200,7 +200,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.177", + "version": "1.0.178", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -216,7 +216,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.177", + "version": "1.0.178", "bin": { "opencode": "./bin/opencode", }, @@ -308,7 +308,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.177", + "version": "1.0.178", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -328,7 +328,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.177", + "version": "1.0.178", "devDependencies": { "@hey-api/openapi-ts": "0.88.1", "@tsconfig/node22": "catalog:", @@ -339,7 +339,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.177", + "version": "1.0.178", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -352,7 +352,7 @@ }, "packages/tauri": { "name": "@opencode-ai/tauri", - "version": "1.0.177", + "version": "1.0.178", "dependencies": { "@opencode-ai/desktop": "workspace:*", "@solid-primitives/storage": "catalog:", @@ -379,7 +379,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.177", + "version": "1.0.178", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -414,7 +414,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.0.177", + "version": "1.0.178", "dependencies": { "zod": "catalog:", }, @@ -425,7 +425,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.177", + "version": "1.0.178", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 2e867b9ad..02f4820b9 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.0.177", + "version": "1.0.178", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 4d61d5dea..83dd3a7d7 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.0.177", + "version": "1.0.178", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index ceacdff28..585bd9cb5 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.177", + "version": "1.0.178", "$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 85ab10b64..34ae368eb 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.177", + "version": "1.0.178", "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 18e1bef96..ab96bd5eb 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.177", + "version": "1.0.178", "description": "", "type": "module", "exports": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index ada31eecb..b24776412 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.0.177", + "version": "1.0.178", "private": true, "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index 2f997f4e7..a34976e5d 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.0.177" +version = "1.0.178" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/sst/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.177/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.178/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.177/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.178/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.177/opencode-linux-arm64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.178/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.177/opencode-linux-x64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.178/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.177/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.178/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index 4cfe3a725..97336ace8 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.177", + "version": "1.0.178", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 998b24f29..433301a68 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.177", + "version": "1.0.178", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 0b8f8a9d9..b32dd2938 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.0.177", + "version": "1.0.178", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} +} \ No newline at end of file diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 8cdcadbc9..52cf422ac 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.0.177", + "version": "1.0.178", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -29,4 +29,4 @@ "publishConfig": { "directory": "dist" } -} +} \ No newline at end of file diff --git a/packages/slack/package.json b/packages/slack/package.json index 7083f55b3..99b0a1cb6 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.177", + "version": "1.0.178", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/tauri/package.json b/packages/tauri/package.json index 132557609..1e2fe43ea 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/tauri", "private": true, - "version": "1.0.177", + "version": "1.0.178", "type": "module", "scripts": { "typecheck": "tsgo -b", diff --git a/packages/ui/package.json b/packages/ui/package.json index 5215c2235..a76ab4bb8 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.177", + "version": "1.0.178", "type": "module", "exports": { "./*": "./src/components/*.tsx", diff --git a/packages/util/package.json b/packages/util/package.json index c6bb3c1e9..190d49ba9 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.0.177", + "version": "1.0.178", "private": true, "type": "module", "exports": { diff --git a/packages/web/package.json b/packages/web/package.json index 1c3b91a6b..26f7b524b 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.177", + "version": "1.0.178", "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 a3cdd7c1d..25916d486 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.0.177", + "version": "1.0.178", "publisher": "sst-dev", "repository": { "type": "git", From 8e674ae053f77d109e90b0d6e618929b7f865265 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sat, 20 Dec 2025 10:28:40 -0500 Subject: [PATCH 007/112] ci --- .github/workflows/publish.yml | 17 +++++++---------- packages/tauri/scripts/prepare.ts | 3 ++- script/publish-start.ts | 11 ++++++++--- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index cdc8bd741..59b6d2a65 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -80,8 +80,9 @@ jobs: GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }} NPM_CONFIG_PROVENANCE: false outputs: - releaseId: ${{ steps.publish.outputs.releaseId }} - tagName: ${{ steps.publish.outputs.tagName }} + release: ${{ steps.publish.outputs.release }} + tag: ${{ steps.publish.outputs.tag }} + version: ${{ steps.publish.outputs.version }} publish-tauri: needs: publish @@ -150,16 +151,13 @@ jobs: cd packages/tauri bun ./scripts/prepare.ts env: - OPENCODE_BUMP: ${{ inputs.bump }} - OPENCODE_VERSION: ${{ inputs.version }} - OPENCODE_CHANNEL: latest + OPENCODE_VERSION: ${{ needs.publish.outputs.version }} NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }} GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }} AUR_KEY: ${{ secrets.AUR_KEY }} OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} RUST_TARGET: ${{ matrix.settings.target }} GH_TOKEN: ${{ github.token }} - OPENCODE_RELEASE_TAG: ${{ needs.publish.outputs.tagName }} # Fixes AppImage build issues, can be removed when https://github.com/tauri-apps/tauri/pull/12491 is released - name: Install tauri-cli from portable appimage branch @@ -189,8 +187,8 @@ jobs: tauriScript: ${{ (contains(matrix.settings.host, 'ubuntu') && 'cargo tauri') || '' }} args: --target ${{ matrix.settings.target }} --config src-tauri/tauri.prod.conf.json updaterJsonPreferNsis: true - releaseId: ${{ needs.publish.outputs.releaseId }} - tagName: ${{ needs.publish.outputs.tagName }} + releaseId: ${{ needs.publish.outputs.release }} + tagName: ${{ needs.publish.outputs.tag }} releaseAssetNamePattern: opencode-desktop-[platform]-[arch][ext] releaseDraft: true @@ -221,7 +219,6 @@ jobs: - run: ./script/publish-complete.ts env: - OPENCODE_VERSION: ${{ needs.publish.outputs.tagName }} + OPENCODE_VERSION: ${{ needs.publish.outputs.version }} AUR_KEY: ${{ secrets.AUR_KEY }} GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }} - OPENCODE_RELEASE_TAG: ${{ needs.publish.outputs.tagName }} diff --git a/packages/tauri/scripts/prepare.ts b/packages/tauri/scripts/prepare.ts index 23cf3dc5d..692e0dd78 100755 --- a/packages/tauri/scripts/prepare.ts +++ b/packages/tauri/scripts/prepare.ts @@ -3,13 +3,14 @@ import { $ } from "bun" import { copyBinaryToSidecarFolder, getCurrentSidecar } from "./utils" +import { Script } from "@opencode-ai/script" const sidecarConfig = getCurrentSidecar() const dir = "src-tauri/target/opencode-binaries" await $`mkdir -p ${dir}` -await $`gh release download ${Bun.env.OPENCODE_RELEASE_TAG} --pattern ${sidecarConfig.ocBinary}.${sidecarConfig.assetExt} --repo sst/opencode --skip-existing --dir ${dir}` +await $`gh release download v${Script.version} --pattern ${sidecarConfig.ocBinary}.${sidecarConfig.assetExt} --repo sst/opencode --skip-existing --dir ${dir}` if (sidecarConfig.assetExt === "tar.gz") { await $`tar -xvzf ${dir}/${sidecarConfig.ocBinary}.${sidecarConfig.assetExt} -C ${dir}` diff --git a/script/publish-start.ts b/script/publish-start.ts index 1ca20ba0e..b01a1142f 100755 --- a/script/publish-start.ts +++ b/script/publish-start.ts @@ -181,6 +181,8 @@ await import(`../packages/plugin/script/publish.ts`) const dir = new URL("..", import.meta.url).pathname process.chdir(dir) +let output = `version=${Script.version}\n` + if (!Script.preview) { await $`git commit -am "release: v${Script.version}"` await $`git tag v${Script.version}` @@ -190,7 +192,10 @@ if (!Script.preview) { await new Promise((resolve) => setTimeout(resolve, 5_000)) await $`gh release create v${Script.version} -d --title "v${Script.version}" --notes ${notes.join("\n") || "No notable changes"} ./packages/opencode/dist/*.zip ./packages/opencode/dist/*.tar.gz` const release = await $`gh release view v${Script.version} --json id,tagName`.json() - if (process.env.GITHUB_OUTPUT) { - await Bun.write(process.env.GITHUB_OUTPUT, `releaseId=${release.id}\ntagName=${release.tagName}\n`) - } + output += `release=${release.id}` + output += `tag=${release.tagName}` +} + +if (process.env.GITHUB_OUTPUT) { + await Bun.write(process.env.GITHUB_OUTPUT, output) } From bab000eeb5bced5c340d418591bcccac1613795a Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sat, 20 Dec 2025 15:29:23 +0000 Subject: [PATCH 008/112] chore: generate --- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/package.json b/packages/plugin/package.json index b32dd2938..d9cc44f7b 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} \ No newline at end of file +} diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 52cf422ac..f7b86166c 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -29,4 +29,4 @@ "publishConfig": { "directory": "dist" } -} \ No newline at end of file +} From f2343a67942d25f7c78d3058ef329b5103b7e15e Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sat, 20 Dec 2025 10:34:54 -0500 Subject: [PATCH 009/112] ci --- .github/workflows/publish.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 59b6d2a65..993682142 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -104,7 +104,7 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 - ref: ${{ needs.publish.outputs.tagName }} + ref: ${{ needs.publish.outputs.tag }} - uses: apple-actions/import-codesign-certs@v2 if: ${{ runner.os == 'macOS' }} @@ -147,6 +147,7 @@ jobs: shared-key: ${{ matrix.settings.target }} - name: Prepare + if: inputs.bump || inputs.version run: | cd packages/tauri bun ./scripts/prepare.ts @@ -196,13 +197,13 @@ jobs: needs: - publish - publish-tauri - if: needs.publish.outputs.tagName + if: needs.publish.outputs.tag runs-on: blacksmith-4vcpu-ubuntu-2404 steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - ref: ${{ needs.publish.outputs.tagName }} + ref: ${{ needs.publish.outputs.tag }} - uses: ./.github/actions/setup-bun From 33d8bfc93785fc3349839dc5b77d7497a1dd2501 Mon Sep 17 00:00:00 2001 From: opencode Date: Sat, 20 Dec 2025 15:38:38 +0000 Subject: [PATCH 010/112] release: v1.0.179 --- bun.lock | 30 +++++++++++++------------- 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 | 4 ++-- packages/sdk/js/package.json | 4 ++-- packages/slack/package.json | 2 +- packages/tauri/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, 39 insertions(+), 39 deletions(-) diff --git a/bun.lock b/bun.lock index 35921ead7..bde2cf373 100644 --- a/bun.lock +++ b/bun.lock @@ -20,7 +20,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.0.178", + "version": "1.0.179", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -48,7 +48,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.178", + "version": "1.0.179", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -75,7 +75,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.178", + "version": "1.0.179", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -99,7 +99,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.178", + "version": "1.0.179", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -123,7 +123,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.178", + "version": "1.0.179", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -171,7 +171,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.0.178", + "version": "1.0.179", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -200,7 +200,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.178", + "version": "1.0.179", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -216,7 +216,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.178", + "version": "1.0.179", "bin": { "opencode": "./bin/opencode", }, @@ -308,7 +308,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.178", + "version": "1.0.179", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -328,7 +328,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.178", + "version": "1.0.179", "devDependencies": { "@hey-api/openapi-ts": "0.88.1", "@tsconfig/node22": "catalog:", @@ -339,7 +339,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.178", + "version": "1.0.179", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -352,7 +352,7 @@ }, "packages/tauri": { "name": "@opencode-ai/tauri", - "version": "1.0.178", + "version": "1.0.179", "dependencies": { "@opencode-ai/desktop": "workspace:*", "@solid-primitives/storage": "catalog:", @@ -379,7 +379,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.178", + "version": "1.0.179", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -414,7 +414,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.0.178", + "version": "1.0.179", "dependencies": { "zod": "catalog:", }, @@ -425,7 +425,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.178", + "version": "1.0.179", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 02f4820b9..2f575ee74 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.0.178", + "version": "1.0.179", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 83dd3a7d7..dcd8f152b 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.0.178", + "version": "1.0.179", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 585bd9cb5..c595c05c4 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.178", + "version": "1.0.179", "$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 34ae368eb..aaec4c3b3 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.178", + "version": "1.0.179", "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 ab96bd5eb..8400b34c8 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.178", + "version": "1.0.179", "description": "", "type": "module", "exports": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index b24776412..8b9fec146 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.0.178", + "version": "1.0.179", "private": true, "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index a34976e5d..c3107bcbe 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.0.178" +version = "1.0.179" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/sst/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.178/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.179/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.178/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.179/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.178/opencode-linux-arm64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.179/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.178/opencode-linux-x64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.179/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.178/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.179/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index 97336ace8..2674e81c0 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.178", + "version": "1.0.179", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 433301a68..a877f31c3 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.178", + "version": "1.0.179", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index d9cc44f7b..ac1b43cc3 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.0.178", + "version": "1.0.179", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} +} \ No newline at end of file diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index f7b86166c..0717bf32e 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.0.178", + "version": "1.0.179", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -29,4 +29,4 @@ "publishConfig": { "directory": "dist" } -} +} \ No newline at end of file diff --git a/packages/slack/package.json b/packages/slack/package.json index 99b0a1cb6..90b5fb2fb 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.178", + "version": "1.0.179", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/tauri/package.json b/packages/tauri/package.json index 1e2fe43ea..27fa8a6ba 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/tauri", "private": true, - "version": "1.0.178", + "version": "1.0.179", "type": "module", "scripts": { "typecheck": "tsgo -b", diff --git a/packages/ui/package.json b/packages/ui/package.json index a76ab4bb8..753716c34 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.178", + "version": "1.0.179", "type": "module", "exports": { "./*": "./src/components/*.tsx", diff --git a/packages/util/package.json b/packages/util/package.json index 190d49ba9..09fd64a72 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.0.178", + "version": "1.0.179", "private": true, "type": "module", "exports": { diff --git a/packages/web/package.json b/packages/web/package.json index 26f7b524b..f4189a0f3 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.178", + "version": "1.0.179", "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 25916d486..8a7b1e885 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.0.178", + "version": "1.0.179", "publisher": "sst-dev", "repository": { "type": "git", From 35c12e205325a01a74f6fc2d7ec935d8b99a5ba6 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sat, 20 Dec 2025 10:53:56 -0500 Subject: [PATCH 011/112] ci --- script/publish-start.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script/publish-start.ts b/script/publish-start.ts index b01a1142f..229435ddf 100755 --- a/script/publish-start.ts +++ b/script/publish-start.ts @@ -192,8 +192,8 @@ if (!Script.preview) { await new Promise((resolve) => setTimeout(resolve, 5_000)) await $`gh release create v${Script.version} -d --title "v${Script.version}" --notes ${notes.join("\n") || "No notable changes"} ./packages/opencode/dist/*.zip ./packages/opencode/dist/*.tar.gz` const release = await $`gh release view v${Script.version} --json id,tagName`.json() - output += `release=${release.id}` - output += `tag=${release.tagName}` + output += `release=${release.id}\n` + output += `tag=${release.tagName}\n` } if (process.env.GITHUB_OUTPUT) { From c87d61b5615eaf301ba6ac1e0288bd778350b920 Mon Sep 17 00:00:00 2001 From: opencode Date: Sat, 20 Dec 2025 16:00:36 +0000 Subject: [PATCH 012/112] release: v1.0.180 --- bun.lock | 30 +++++++++++++------------- 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/tauri/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 bde2cf373..089de5002 100644 --- a/bun.lock +++ b/bun.lock @@ -20,7 +20,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.0.179", + "version": "1.0.180", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -48,7 +48,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.179", + "version": "1.0.180", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -75,7 +75,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.179", + "version": "1.0.180", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -99,7 +99,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.179", + "version": "1.0.180", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -123,7 +123,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.179", + "version": "1.0.180", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -171,7 +171,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.0.179", + "version": "1.0.180", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -200,7 +200,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.179", + "version": "1.0.180", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -216,7 +216,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.179", + "version": "1.0.180", "bin": { "opencode": "./bin/opencode", }, @@ -308,7 +308,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.179", + "version": "1.0.180", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -328,7 +328,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.179", + "version": "1.0.180", "devDependencies": { "@hey-api/openapi-ts": "0.88.1", "@tsconfig/node22": "catalog:", @@ -339,7 +339,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.179", + "version": "1.0.180", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -352,7 +352,7 @@ }, "packages/tauri": { "name": "@opencode-ai/tauri", - "version": "1.0.179", + "version": "1.0.180", "dependencies": { "@opencode-ai/desktop": "workspace:*", "@solid-primitives/storage": "catalog:", @@ -379,7 +379,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.179", + "version": "1.0.180", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -414,7 +414,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.0.179", + "version": "1.0.180", "dependencies": { "zod": "catalog:", }, @@ -425,7 +425,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.179", + "version": "1.0.180", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 2f575ee74..4e8d3fd59 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.0.179", + "version": "1.0.180", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index dcd8f152b..4418597d6 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.0.179", + "version": "1.0.180", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index c595c05c4..250e2cdab 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.179", + "version": "1.0.180", "$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 aaec4c3b3..1f18ce314 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.179", + "version": "1.0.180", "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 8400b34c8..c1cf191d4 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.179", + "version": "1.0.180", "description": "", "type": "module", "exports": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index 8b9fec146..acb03ed8e 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.0.179", + "version": "1.0.180", "private": true, "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index c3107bcbe..446839565 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.0.179" +version = "1.0.180" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/sst/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.179/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.180/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.179/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.180/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.179/opencode-linux-arm64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.180/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.179/opencode-linux-x64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.180/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.179/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.180/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index 2674e81c0..b18a0f5f4 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.179", + "version": "1.0.180", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index a877f31c3..90427b7f8 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.179", + "version": "1.0.180", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index ac1b43cc3..a31f7d666 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.0.179", + "version": "1.0.180", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 0717bf32e..bec8856b2 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.0.179", + "version": "1.0.180", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/slack/package.json b/packages/slack/package.json index 90b5fb2fb..7964da49b 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.179", + "version": "1.0.180", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/tauri/package.json b/packages/tauri/package.json index 27fa8a6ba..537c3f3d5 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/tauri", "private": true, - "version": "1.0.179", + "version": "1.0.180", "type": "module", "scripts": { "typecheck": "tsgo -b", diff --git a/packages/ui/package.json b/packages/ui/package.json index 753716c34..2f42e536d 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.179", + "version": "1.0.180", "type": "module", "exports": { "./*": "./src/components/*.tsx", diff --git a/packages/util/package.json b/packages/util/package.json index 09fd64a72..19b21e7a0 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.0.179", + "version": "1.0.180", "private": true, "type": "module", "exports": { diff --git a/packages/web/package.json b/packages/web/package.json index f4189a0f3..160b27817 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.179", + "version": "1.0.180", "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 8a7b1e885..b51f976c8 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.0.179", + "version": "1.0.180", "publisher": "sst-dev", "repository": { "type": "git", From 8ffea809807dd7fa075be74e66680edf935249aa Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sat, 20 Dec 2025 15:54:39 +0000 Subject: [PATCH 013/112] chore: generate --- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/package.json b/packages/plugin/package.json index a31f7d666..647bcb563 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} \ No newline at end of file +} diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index bec8856b2..665499a6e 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -29,4 +29,4 @@ "publishConfig": { "directory": "dist" } -} \ No newline at end of file +} From 2f6d15a51eb59d107f016a4d8a768fd4d1579c69 Mon Sep 17 00:00:00 2001 From: Ryan Cassidy Date: Sat, 20 Dec 2025 16:56:27 +0000 Subject: [PATCH 014/112] feat: add cursor theme (#5850) --- .../src/cli/cmd/tui/context/theme.tsx | 2 + .../src/cli/cmd/tui/context/theme/cursor.json | 249 ++++++++++++++++++ 2 files changed, 251 insertions(+) create mode 100644 packages/opencode/src/cli/cmd/tui/context/theme/cursor.json diff --git a/packages/opencode/src/cli/cmd/tui/context/theme.tsx b/packages/opencode/src/cli/cmd/tui/context/theme.tsx index 595d3025d..8bca9fa88 100644 --- a/packages/opencode/src/cli/cmd/tui/context/theme.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/theme.tsx @@ -8,6 +8,7 @@ import ayu from "./theme/ayu.json" with { type: "json" } import catppuccin from "./theme/catppuccin.json" with { type: "json" } import catppuccinMacchiato from "./theme/catppuccin-macchiato.json" with { type: "json" } import cobalt2 from "./theme/cobalt2.json" with { type: "json" } +import cursor from "./theme/cursor.json" with { type: "json" } import dracula from "./theme/dracula.json" with { type: "json" } import everforest from "./theme/everforest.json" with { type: "json" } import flexoki from "./theme/flexoki.json" with { type: "json" } @@ -138,6 +139,7 @@ export const DEFAULT_THEMES: Record = { catppuccin, ["catppuccin-macchiato"]: catppuccinMacchiato, cobalt2, + cursor, dracula, everforest, flexoki, diff --git a/packages/opencode/src/cli/cmd/tui/context/theme/cursor.json b/packages/opencode/src/cli/cmd/tui/context/theme/cursor.json new file mode 100644 index 000000000..ab518dbe7 --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/context/theme/cursor.json @@ -0,0 +1,249 @@ +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "darkBg": "#181818", + "darkPanel": "#141414", + "darkElement": "#262626", + "darkFg": "#e4e4e4", + "darkMuted": "#e4e4e45e", + "darkBorder": "#e4e4e413", + "darkBorderActive": "#e4e4e426", + "darkCyan": "#88c0d0", + "darkBlue": "#81a1c1", + "darkGreen": "#3fa266", + "darkGreenBright": "#70b489", + "darkRed": "#e34671", + "darkRedBright": "#fc6b83", + "darkYellow": "#f1b467", + "darkOrange": "#d2943e", + "darkPink": "#E394DC", + "darkPurple": "#AAA0FA", + "darkTeal": "#82D2CE", + "darkSyntaxYellow": "#F8C762", + "darkSyntaxOrange": "#EFB080", + "darkSyntaxGreen": "#A8CC7C", + "darkSyntaxBlue": "#87C3FF", + "lightBg": "#fcfcfc", + "lightPanel": "#f3f3f3", + "lightElement": "#ededed", + "lightFg": "#141414", + "lightMuted": "#141414ad", + "lightBorder": "#14141413", + "lightBorderActive": "#14141426", + "lightTeal": "#6f9ba6", + "lightBlue": "#3c7cab", + "lightBlueDark": "#206595", + "lightGreen": "#1f8a65", + "lightGreenBright": "#55a583", + "lightRed": "#cf2d56", + "lightRedBright": "#e75e78", + "lightOrange": "#db704b", + "lightYellow": "#c08532", + "lightPurple": "#9e94d5", + "lightPurpleDark": "#6049b3", + "lightPink": "#b8448b", + "lightMagenta": "#b3003f" + }, + "theme": { + "primary": { + "dark": "darkCyan", + "light": "lightTeal" + }, + "secondary": { + "dark": "darkBlue", + "light": "lightBlue" + }, + "accent": { + "dark": "darkCyan", + "light": "lightTeal" + }, + "error": { + "dark": "darkRed", + "light": "lightRed" + }, + "warning": { + "dark": "darkYellow", + "light": "lightOrange" + }, + "success": { + "dark": "darkGreen", + "light": "lightGreen" + }, + "info": { + "dark": "darkBlue", + "light": "lightBlue" + }, + "text": { + "dark": "darkFg", + "light": "lightFg" + }, + "textMuted": { + "dark": "darkMuted", + "light": "lightMuted" + }, + "background": { + "dark": "darkBg", + "light": "lightBg" + }, + "backgroundPanel": { + "dark": "darkPanel", + "light": "lightPanel" + }, + "backgroundElement": { + "dark": "darkElement", + "light": "lightElement" + }, + "border": { + "dark": "darkBorder", + "light": "lightBorder" + }, + "borderActive": { + "dark": "darkCyan", + "light": "lightTeal" + }, + "borderSubtle": { + "dark": "#0f0f0f", + "light": "#e0e0e0" + }, + "diffAdded": { + "dark": "darkGreen", + "light": "lightGreen" + }, + "diffRemoved": { + "dark": "darkRed", + "light": "lightRed" + }, + "diffContext": { + "dark": "darkMuted", + "light": "lightMuted" + }, + "diffHunkHeader": { + "dark": "darkMuted", + "light": "lightMuted" + }, + "diffHighlightAdded": { + "dark": "darkGreenBright", + "light": "lightGreenBright" + }, + "diffHighlightRemoved": { + "dark": "darkRedBright", + "light": "lightRedBright" + }, + "diffAddedBg": { + "dark": "#3fa26633", + "light": "#1f8a651f" + }, + "diffRemovedBg": { + "dark": "#b8004933", + "light": "#cf2d5614" + }, + "diffContextBg": { + "dark": "darkPanel", + "light": "lightPanel" + }, + "diffLineNumber": { + "dark": "#e4e4e442", + "light": "#1414147a" + }, + "diffAddedLineNumberBg": { + "dark": "#3fa26633", + "light": "#1f8a651f" + }, + "diffRemovedLineNumberBg": { + "dark": "#b8004933", + "light": "#cf2d5614" + }, + "markdownText": { + "dark": "darkFg", + "light": "lightFg" + }, + "markdownHeading": { + "dark": "darkPurple", + "light": "lightBlueDark" + }, + "markdownLink": { + "dark": "darkTeal", + "light": "lightBlueDark" + }, + "markdownLinkText": { + "dark": "darkBlue", + "light": "lightMuted" + }, + "markdownCode": { + "dark": "darkPink", + "light": "lightGreen" + }, + "markdownBlockQuote": { + "dark": "darkMuted", + "light": "lightMuted" + }, + "markdownEmph": { + "dark": "darkTeal", + "light": "lightFg" + }, + "markdownStrong": { + "dark": "darkSyntaxYellow", + "light": "lightFg" + }, + "markdownHorizontalRule": { + "dark": "darkMuted", + "light": "lightMuted" + }, + "markdownListItem": { + "dark": "darkFg", + "light": "lightFg" + }, + "markdownListEnumeration": { + "dark": "darkCyan", + "light": "lightMuted" + }, + "markdownImage": { + "dark": "darkCyan", + "light": "lightBlueDark" + }, + "markdownImageText": { + "dark": "darkBlue", + "light": "lightMuted" + }, + "markdownCodeBlock": { + "dark": "darkFg", + "light": "lightFg" + }, + "syntaxComment": { + "dark": "darkMuted", + "light": "lightMuted" + }, + "syntaxKeyword": { + "dark": "darkTeal", + "light": "lightMagenta" + }, + "syntaxFunction": { + "dark": "darkSyntaxOrange", + "light": "lightOrange" + }, + "syntaxVariable": { + "dark": "darkFg", + "light": "lightFg" + }, + "syntaxString": { + "dark": "darkPink", + "light": "lightPurple" + }, + "syntaxNumber": { + "dark": "darkSyntaxYellow", + "light": "lightPink" + }, + "syntaxType": { + "dark": "darkSyntaxOrange", + "light": "lightBlueDark" + }, + "syntaxOperator": { + "dark": "darkFg", + "light": "lightFg" + }, + "syntaxPunctuation": { + "dark": "darkFg", + "light": "lightFg" + } + } +} From 34eb03f5b8d9103b456e004b4b529d7df0cbdd7b Mon Sep 17 00:00:00 2001 From: ja <51257127+anntnzrb@users.noreply.github.com> Date: Sat, 20 Dec 2025 12:39:26 -0500 Subject: [PATCH 015/112] fix: prioritize session list loading when resuming with -c (#5816) Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> --- packages/opencode/src/cli/cmd/tui/app.tsx | 3 ++- .../opencode/src/cli/cmd/tui/context/sync.tsx | 25 ++++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 028905fc3..e81de1889 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -229,7 +229,8 @@ function App() { let continued = false createEffect(() => { - if (continued || sync.status !== "complete" || !args.continue) return + // When using -c, session list is loaded in blocking phase, so we can navigate at "partial" + if (continued || sync.status === "loading" || !args.continue) return const match = sync.data.session .toSorted((a, b) => b.time.updated - a.time.updated) .find((x) => x.parentID === undefined)?.id diff --git a/packages/opencode/src/cli/cmd/tui/context/sync.tsx b/packages/opencode/src/cli/cmd/tui/context/sync.tsx index f74f787db..2528a4998 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sync.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sync.tsx @@ -22,6 +22,7 @@ import { Binary } from "@opencode-ai/util/binary" import { createSimpleContext } from "./helper" import type { Snapshot } from "@/snapshot" import { useExit } from "./exit" +import { useArgs } from "./args" import { batch, onMount } from "solid-js" import { Log } from "@/util/log" import type { Path } from "@opencode-ai/sdk" @@ -254,10 +255,18 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ }) const exit = useExit() + const args = useArgs() async function bootstrap() { - // blocking - await Promise.all([ + const sessionListPromise = sdk.client.session.list().then((x) => + setStore( + "session", + (x.data ?? []).toSorted((a, b) => a.id.localeCompare(b.id)), + ), + ) + + // blocking - include session.list when continuing a session + const blockingRequests: Promise[] = [ sdk.client.config.providers({}, { throwOnError: true }).then((x) => { batch(() => { setStore("provider", x.data!.providers) @@ -271,17 +280,15 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ }), sdk.client.app.agents({}, { throwOnError: true }).then((x) => setStore("agent", x.data ?? [])), sdk.client.config.get({}, { throwOnError: true }).then((x) => setStore("config", x.data!)), - ]) + ...(args.continue ? [sessionListPromise] : []), + ] + + await Promise.all(blockingRequests) .then(() => { if (store.status !== "complete") setStore("status", "partial") // non-blocking Promise.all([ - sdk.client.session.list().then((x) => - setStore( - "session", - (x.data ?? []).toSorted((a, b) => a.id.localeCompare(b.id)), - ), - ), + ...(args.continue ? [] : [sessionListPromise]), sdk.client.command.list().then((x) => setStore("command", x.data ?? [])), sdk.client.lsp.status().then((x) => setStore("lsp", x.data!)), sdk.client.mcp.status().then((x) => setStore("mcp", x.data!)), From d89b567b47ae2709f0fe3fd1e997860073829d72 Mon Sep 17 00:00:00 2001 From: lif <1835304752@qq.com> Date: Sun, 21 Dec 2025 01:41:52 +0800 Subject: [PATCH 016/112] fix: add transform case for gemini if mcp tool has missing array items (#5846) --- packages/opencode/src/provider/transform.ts | 4 ++++ .../opencode/test/provider/transform.test.ts | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index 320af4d39..0aacf0935 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -424,6 +424,10 @@ export namespace ProviderTransform { result.required = result.required.filter((field: any) => field in result.properties) } + if (result.type === "array" && result.items == null) { + result.items = {} + } + return result } diff --git a/packages/opencode/test/provider/transform.test.ts b/packages/opencode/test/provider/transform.test.ts index 17ae7f558..78bd296c9 100644 --- a/packages/opencode/test/provider/transform.test.ts +++ b/packages/opencode/test/provider/transform.test.ts @@ -167,6 +167,30 @@ describe("ProviderTransform.maxOutputTokens", () => { }) }) +describe("ProviderTransform.schema - gemini array items", () => { + test("adds missing items for array properties", () => { + const geminiModel = { + providerID: "google", + api: { + id: "gemini-3-pro", + }, + } as any + + const schema = { + type: "object", + properties: { + nodes: { type: "array" }, + edges: { type: "array", items: { type: "string" } }, + }, + } as any + + const result = ProviderTransform.schema(geminiModel, schema) as any + + expect(result.properties.nodes.items).toBeDefined() + expect(result.properties.edges.items.type).toBe("string") + }) +}) + describe("ProviderTransform.message - DeepSeek reasoning content", () => { test("DeepSeek with tool calls includes reasoning_content in providerOptions", () => { const msgs = [ From da6e0e60c0ca42d54595553fc1ab70f62be6e3b9 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Sat, 20 Dec 2025 11:43:59 -0600 Subject: [PATCH 017/112] ci: adjust review agent prompt to discourage bad diffs --- .github/workflows/review.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml index 36f6df54f..c0e3a5deb 100644 --- a/.github/workflows/review.yml +++ b/.github/workflows/review.yml @@ -67,6 +67,8 @@ jobs: When critiquing code style don't be a zealot, we don't like "let" statements but sometimes they are the simpliest option, if someone does a bunch of nesting with let, they should consider using iife (see packages/opencode/src/util.iife.ts) Use the gh cli to create comments on the files for the violations. Try to leave the comment on the exact line number. If you have a suggested fix include it in a suggestion code block. + If you are writing suggested fixes, BE SURE THAT the change you are recommending is actually valid typescript, often I have seen missing closing "}" or other syntax errors. + Generally, write a comment instead of writing suggested change if you can help it. Command MUST be like this. \`\`\` From 8f6c8844d742b56858823e57388e8149f665cb7a Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Sat, 20 Dec 2025 12:46:48 -0500 Subject: [PATCH 018/112] feat: support configuring a default_agent across all API/user surfaces (#5843) Co-authored-by: observerw --- github/action.yml | 5 ++++ github/index.ts | 28 ++++++++++++++++++- packages/opencode/src/acp/agent.ts | 6 ++-- packages/opencode/src/agent/agent.ts | 23 +++++++++++++++ packages/opencode/src/cli/cmd/github.ts | 2 +- packages/opencode/src/cli/cmd/run.ts | 28 +++++++++++++++++-- .../src/cli/cmd/tui/context/local.tsx | 2 +- packages/opencode/src/config/config.ts | 6 ++++ packages/opencode/src/server/server.ts | 4 +-- packages/opencode/src/session/prompt.ts | 6 ++-- packages/sdk/js/src/v2/gen/types.gen.ts | 5 ++++ packages/sdk/openapi.json | 7 +++++ packages/web/src/content/docs/config.mdx | 17 +++++++++++ packages/web/src/content/docs/github.mdx | 1 + 14 files changed, 128 insertions(+), 12 deletions(-) diff --git a/github/action.yml b/github/action.yml index cf276b51c..57e26d856 100644 --- a/github/action.yml +++ b/github/action.yml @@ -9,6 +9,10 @@ inputs: description: "Model to use" required: true + agent: + description: "Agent to use. Must be a primary agent. Falls back to default_agent from config or 'build' if not found." + required: false + share: description: "Share the opencode session (defaults to true for public repos)" required: false @@ -62,6 +66,7 @@ runs: run: opencode github run env: MODEL: ${{ inputs.model }} + AGENT: ${{ inputs.agent }} SHARE: ${{ inputs.share }} PROMPT: ${{ inputs.prompt }} USE_GITHUB_TOKEN: ${{ inputs.use_github_token }} diff --git a/github/index.ts b/github/index.ts index 6d826326e..7f6018232 100644 --- a/github/index.ts +++ b/github/index.ts @@ -318,6 +318,10 @@ function useEnvRunUrl() { return `/${repo.owner}/${repo.repo}/actions/runs/${runId}` } +function useEnvAgent() { + return process.env["AGENT"] || undefined +} + function useEnvShare() { const value = process.env["SHARE"] if (!value) return undefined @@ -578,16 +582,38 @@ async function summarize(response: string) { } } +async function resolveAgent(): Promise { + const envAgent = useEnvAgent() + if (!envAgent) return undefined + + // Validate the agent exists and is a primary agent + const agents = await client.agent.list() + const agent = agents.data?.find((a) => a.name === envAgent) + + if (!agent) { + console.warn(`agent "${envAgent}" not found. Falling back to default agent`) + return undefined + } + + if (agent.mode === "subagent") { + console.warn(`agent "${envAgent}" is a subagent, not a primary agent. Falling back to default agent`) + return undefined + } + + return envAgent +} + async function chat(text: string, files: PromptFiles = []) { console.log("Sending message to opencode...") const { providerID, modelID } = useEnvModel() + const agent = await resolveAgent() const chat = await client.session.chat({ path: session, body: { providerID, modelID, - agent: "build", + agent, parts: [ { type: "text", diff --git a/packages/opencode/src/acp/agent.ts b/packages/opencode/src/acp/agent.ts index 2817adf5d..e6419dd76 100644 --- a/packages/opencode/src/acp/agent.ts +++ b/packages/opencode/src/acp/agent.ts @@ -22,6 +22,7 @@ import { Log } from "../util/log" import { ACPSessionManager } from "./session" import type { ACPConfig, ACPSessionState } from "./types" import { Provider } from "../provider/provider" +import { Agent as AgentModule } from "../agent/agent" import { Installation } from "@/installation" import { MessageV2 } from "@/session/message-v2" import { Config } from "@/config/config" @@ -705,7 +706,8 @@ export namespace ACP { description: agent.description, })) - const currentModeId = availableModes.find((m) => m.name === "build")?.id ?? availableModes[0].id + const defaultAgentName = await AgentModule.defaultAgent() + const currentModeId = availableModes.find((m) => m.name === defaultAgentName)?.id ?? availableModes[0].id const mcpServers: Record = {} for (const server of params.mcpServers) { @@ -807,7 +809,7 @@ export namespace ACP { if (!current) { this.sessionManager.setModel(session.id, model) } - const agent = session.modeId ?? "build" + const agent = session.modeId ?? (await AgentModule.defaultAgent()) const parts: Array< { type: "text"; text: string } | { type: "file"; url: string; filename: string; mime: string } diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index add120f91..26f241fab 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -5,6 +5,9 @@ import { generateObject, type ModelMessage } from "ai" import { SystemPrompt } from "../session/system" import { Instance } from "../project/instance" import { mergeDeep } from "remeda" +import { Log } from "../util/log" + +const log = Log.create({ service: "agent" }) import PROMPT_GENERATE from "./generate.txt" import PROMPT_COMPACTION from "./prompt/compaction.txt" @@ -20,6 +23,7 @@ export namespace Agent { mode: z.enum(["subagent", "primary", "all"]), native: z.boolean().optional(), hidden: z.boolean().optional(), + default: z.boolean().optional(), topP: z.number().optional(), temperature: z.number().optional(), color: z.string().optional(), @@ -245,6 +249,19 @@ export namespace Agent { item.permission = mergeAgentPermissions(cfg.permission ?? {}, permission ?? {}) } } + + // Mark the default agent + const defaultName = cfg.default_agent ?? "build" + const defaultCandidate = result[defaultName] + if (defaultCandidate && defaultCandidate.mode !== "subagent") { + defaultCandidate.default = true + } else { + // Fall back to "build" if configured default is invalid + if (result["build"]) { + result["build"].default = true + } + } + return result }) @@ -256,6 +273,12 @@ export namespace Agent { return state().then((x) => Object.values(x)) } + export async function defaultAgent(): Promise { + const agents = await state() + const defaultCandidate = Object.values(agents).find((a) => a.default) + return defaultCandidate?.name ?? "build" + } + export async function generate(input: { description: string; model?: { providerID: string; modelID: string } }) { const cfg = await Config.get() const defaultModel = input.model ?? (await Provider.defaultModel()) diff --git a/packages/opencode/src/cli/cmd/github.ts b/packages/opencode/src/cli/cmd/github.ts index f4f026d4c..26340044c 100644 --- a/packages/opencode/src/cli/cmd/github.ts +++ b/packages/opencode/src/cli/cmd/github.ts @@ -762,7 +762,7 @@ export const GithubRunCommand = cmd({ providerID, modelID, }, - agent: "build", + // agent is omitted - server will use default_agent from config or fall back to "build" parts: [ { id: Identifier.ascending("part"), diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index 3a0b2f23f..0c371b864 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -10,6 +10,7 @@ import { select } from "@clack/prompts" import { createOpencodeClient, type OpencodeClient } from "@opencode-ai/sdk/v2" import { Server } from "../../server/server" import { Provider } from "../../provider/provider" +import { Agent } from "../../agent/agent" const TOOL: Record = { todowrite: ["Todo", UI.Style.TEXT_WARNING_BOLD], @@ -223,10 +224,33 @@ export const RunCommand = cmd({ } })() + // Validate agent if specified + const resolvedAgent = await (async () => { + if (!args.agent) return undefined + const agent = await Agent.get(args.agent) + if (!agent) { + UI.println( + UI.Style.TEXT_WARNING_BOLD + "!", + UI.Style.TEXT_NORMAL, + `agent "${args.agent}" not found. Falling back to default agent`, + ) + return undefined + } + if (agent.mode === "subagent") { + UI.println( + UI.Style.TEXT_WARNING_BOLD + "!", + UI.Style.TEXT_NORMAL, + `agent "${args.agent}" is a subagent, not a primary agent. Falling back to default agent`, + ) + return undefined + } + return args.agent + })() + if (args.command) { await sdk.session.command({ sessionID, - agent: args.agent || "build", + agent: resolvedAgent, model: args.model, command: args.command, arguments: message, @@ -235,7 +259,7 @@ export const RunCommand = cmd({ const modelParam = args.model ? Provider.parseModel(args.model) : undefined await sdk.session.prompt({ sessionID, - agent: args.agent || "build", + agent: resolvedAgent, model: modelParam, parts: [...fileParts, { type: "text", text: message }], }) diff --git a/packages/opencode/src/cli/cmd/tui/context/local.tsx b/packages/opencode/src/cli/cmd/tui/context/local.tsx index f04b79685..55c04621e 100644 --- a/packages/opencode/src/cli/cmd/tui/context/local.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/local.tsx @@ -56,7 +56,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const [agentStore, setAgentStore] = createStore<{ current: string }>({ - current: agents()[0].name, + current: agents().find((x) => x.default)?.name ?? agents()[0].name, }) const { theme } = useTheme() const colors = createMemo(() => [ diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index a01cc832a..031bdd31b 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -666,6 +666,12 @@ export namespace Config { .string() .describe("Small model to use for tasks like title generation in the format of provider/model") .optional(), + default_agent: z + .string() + .optional() + .describe( + "Default agent to use when none is specified. Must be a primary agent. Falls back to 'build' if not set or if the specified agent is invalid.", + ), username: z .string() .optional() diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 77bf5085b..2f4b3b221 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -1060,11 +1060,11 @@ export namespace Server { const sessionID = c.req.valid("param").sessionID const body = c.req.valid("json") const msgs = await Session.messages({ sessionID }) - let currentAgent = "build" + let currentAgent = await Agent.defaultAgent() for (let i = msgs.length - 1; i >= 0; i--) { const info = msgs[i].info if (info.role === "user") { - currentAgent = info.agent || "build" + currentAgent = info.agent || (await Agent.defaultAgent()) break } } diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index cbb3eedf3..ebd54a6c8 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -715,7 +715,7 @@ export namespace SessionPrompt { } async function createUserMessage(input: PromptInput) { - const agent = await Agent.get(input.agent ?? "build") + const agent = await Agent.get(input.agent ?? (await Agent.defaultAgent())) const info: MessageV2.Info = { id: input.messageID ?? Identifier.ascending("message"), role: "user", @@ -1282,7 +1282,7 @@ export namespace SessionPrompt { export async function command(input: CommandInput) { log.info("command", input) const command = await Command.get(input.command) - const agentName = command.agent ?? input.agent ?? "build" + const agentName = command.agent ?? input.agent ?? (await Agent.defaultAgent()) const raw = input.arguments.match(argsRegex) ?? [] const args = raw.map((arg) => arg.replace(quoteTrimRegex, "")) @@ -1425,7 +1425,7 @@ export namespace SessionPrompt { time: { created: Date.now(), }, - agent: input.message.info.role === "user" ? input.message.info.agent : "build", + agent: input.message.info.role === "user" ? input.message.info.agent : await Agent.defaultAgent(), model: { providerID: input.providerID, modelID: input.modelID, diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index cdbdfdfda..1b43d3f48 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -1414,6 +1414,10 @@ export type Config = { * Small model to use for tasks like title generation in the format of provider/model */ small_model?: string + /** + * Default agent to use when none is specified. Must be a primary agent. Falls back to 'build' if not set or if the specified agent is invalid. + */ + default_agent?: string /** * Custom username to display in conversations instead of system username */ @@ -1767,6 +1771,7 @@ export type Agent = { mode: "subagent" | "primary" | "all" native?: boolean hidden?: boolean + default?: boolean topP?: number temperature?: number color?: string diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index eeb81a844..f33d20069 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -8153,6 +8153,10 @@ "description": "Small model to use for tasks like title generation in the format of provider/model", "type": "string" }, + "default_agent": { + "description": "Default agent to use when none is specified. Must be a primary agent. Falls back to 'build' if not set or if the specified agent is invalid.", + "type": "string" + }, "username": { "description": "Custom username to display in conversations instead of system username", "type": "string" @@ -9152,6 +9156,9 @@ "hidden": { "type": "boolean" }, + "default": { + "type": "boolean" + }, "topP": { "type": "number" }, diff --git a/packages/web/src/content/docs/config.mdx b/packages/web/src/content/docs/config.mdx index 302d79d17..5ba22ff2d 100644 --- a/packages/web/src/content/docs/config.mdx +++ b/packages/web/src/content/docs/config.mdx @@ -194,6 +194,23 @@ You can also define agents using markdown files in `~/.config/opencode/agent/` o --- +### Default agent + +You can set the default agent using the `default_agent` option. This determines which agent is used when none is explicitly specified. + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "default_agent": "plan" +} +``` + +The default agent must be a primary agent (not a subagent). This can be a built-in agent like `"build"` or `"plan"`, or a [custom agent](/docs/agents) you've defined. If the specified agent doesn't exist or is a subagent, OpenCode will fall back to `"build"` with a warning. + +This setting applies across all interfaces: TUI, CLI (`opencode run`), desktop app, and GitHub Action. + +--- + ### Sharing You can configure the [share](/docs/share) feature through the `share` option. diff --git a/packages/web/src/content/docs/github.mdx b/packages/web/src/content/docs/github.mdx index a38df68f4..1d6078840 100644 --- a/packages/web/src/content/docs/github.mdx +++ b/packages/web/src/content/docs/github.mdx @@ -81,6 +81,7 @@ Or you can set it up manually. ## Configuration - `model`: The model to use with OpenCode. Takes the format of `provider/model`. This is **required**. +- `agent`: The agent to use. Must be a primary agent. Falls back to `default_agent` from config or `"build"` if not found. - `share`: Whether to share the OpenCode session. Defaults to **true** for public repositories. - `prompt`: Optional custom prompt to override the default behavior. Use this to customize how OpenCode processes requests. - `token`: Optional GitHub access token for performing operations such as creating comments, committing changes, and opening pull requests. By default, OpenCode uses the installation access token from the OpenCode GitHub App, so commits, comments, and pull requests appear as coming from the app. From c7cade2494a08fc64cedc9025ad10d26d00d746a Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 20 Dec 2025 12:52:46 -0500 Subject: [PATCH 019/112] zen: sync --- packages/web/src/content/docs/zen.mdx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/web/src/content/docs/zen.mdx b/packages/web/src/content/docs/zen.mdx index 2cd8f5795..134271ca1 100644 --- a/packages/web/src/content/docs/zen.mdx +++ b/packages/web/src/content/docs/zen.mdx @@ -77,7 +77,6 @@ You can also access our models through the following API endpoints. | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -110,7 +109,6 @@ We support a pay-as-you-go model. Below are the prices **per 1M tokens**. | Model | Input | Output | Cached Read | Cached Write | | --------------------------------- | ------ | ------ | ----------- | ------------ | | Big Pickle | Free | Free | Free | - | -| MiniMax M2.1 | Free | Free | Free | - | | Grok Code Fast 1 | Free | Free | Free | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | | Kimi K2 | $0.40 | $2.50 | - | - | @@ -144,7 +142,6 @@ Credit card fees are passed along at cost; we don't charge anything beyond that. The free models: - Grok Code Fast 1 is currently free on OpenCode for a limited time. The xAI team is using this time to collect feedback and improve Grok Code. -- MiniMax M2.1 is currently free on OpenCode for a limited time. The MiniMax team is using this time to collect feedback and improve M2.1. - Big Pickle is a stealth model that's free on OpenCode for a limited time. The team is using this time to collect feedback and improve the model. Contact us if you have any questions. @@ -156,7 +153,6 @@ The free models: All our models are hosted in the US. Our providers follow a zero-retention policy and do not use your data for model training, with the following exceptions: - Grok Code Fast 1: During its free period, collected data may be used to improve Grok Code. -- MiniMax M2.1: During its free period, collected data may be used to improve M2.1. - Big Pickle: During its free period, collected data may be used to improve the model. - OpenAI APIs: Requests are retained for 30 days in accordance with [OpenAI's Data Policies](https://platform.openai.com/docs/guides/your-data). - Anthropic APIs: Requests are retained for 30 days in accordance with [Anthropic's Data Policies](https://docs.anthropic.com/en/docs/claude-code/data-usage). From 426791f68a3a6a5212af5e88c932c2b41f17c294 Mon Sep 17 00:00:00 2001 From: Shpetim <32248437+ShpetimA@users.noreply.github.com> Date: Sat, 20 Dec 2025 18:53:46 +0100 Subject: [PATCH 020/112] fix: system theme flicker (#5842) Co-authored-by: Shpetim --- .../src/cli/cmd/tui/context/theme.tsx | 46 +++++++++++++++---- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/context/theme.tsx b/packages/opencode/src/cli/cmd/tui/context/theme.tsx index 8bca9fa88..cbe836b1c 100644 --- a/packages/opencode/src/cli/cmd/tui/context/theme.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/theme.tsx @@ -281,14 +281,23 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({ ready: false, }) - createEffect(async () => { - const custom = await getCustomThemes() - setStore( - produce((draft) => { - Object.assign(draft.themes, custom) - draft.ready = true - }), - ) + createEffect(() => { + getCustomThemes() + .then((custom) => { + setStore( + produce((draft) => { + Object.assign(draft.themes, custom) + }), + ) + }) + .catch(() => { + setStore("active", "opencode") + }) + .finally(() => { + if (store.active !== "system") { + setStore("ready", true) + } + }) }) const renderer = useRenderer() @@ -297,8 +306,25 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({ size: 16, }) .then((colors) => { - if (!colors.palette[0]) return - setStore("themes", "system", generateSystem(colors, store.mode)) + if (!colors.palette[0]) { + if (store.active === "system") { + setStore( + produce((draft) => { + draft.active = "opencode" + draft.ready = true + }), + ) + } + return + } + setStore( + produce((draft) => { + draft.themes.system = generateSystem(colors, store.mode) + if (store.active === "system") { + draft.ready = true + } + }), + ) }) const values = createMemo(() => { From 3b261e012547bbe33cfda83460e14ec83cf2f0d3 Mon Sep 17 00:00:00 2001 From: ja <51257127+anntnzrb@users.noreply.github.com> Date: Sat, 20 Dec 2025 12:54:49 -0500 Subject: [PATCH 021/112] docs: add name property to model configuration example (#5853) --- packages/web/src/content/docs/models.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/web/src/content/docs/models.mdx b/packages/web/src/content/docs/models.mdx index 0402d4973..002f3f558 100644 --- a/packages/web/src/content/docs/models.mdx +++ b/packages/web/src/content/docs/models.mdx @@ -117,6 +117,7 @@ You can also define custom models that extend built-in ones and can optionally u "models": { "gpt-5-high": { "id": "gpt-5", + "name": "MyGPT5 (High Reasoning)", "options": { "reasoningEffort": "high", "textVerbosity": "low", @@ -125,6 +126,7 @@ You can also define custom models that extend built-in ones and can optionally u }, "gpt-5-low": { "id": "gpt-5", + "name": "MyGPT5 (Low Reasoning)", "options": { "reasoningEffort": "low", "textVerbosity": "low", From 7dd8ea58c22005d430d4ea7e18f3f693477adc5b Mon Sep 17 00:00:00 2001 From: shamil2 <42864151+shamil2@users.noreply.github.com> Date: Sat, 20 Dec 2025 19:04:35 +0100 Subject: [PATCH 022/112] =?UTF-8?q?feat:=20add=20Catppuccin=20Frapp=C3=A9?= =?UTF-8?q?=20theme=20(#5821)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shamil2 --- .../src/cli/cmd/tui/context/theme.tsx | 2 + .../tui/context/theme/catppuccin-frappe.json | 233 ++++++++++++++++++ 2 files changed, 235 insertions(+) create mode 100644 packages/opencode/src/cli/cmd/tui/context/theme/catppuccin-frappe.json diff --git a/packages/opencode/src/cli/cmd/tui/context/theme.tsx b/packages/opencode/src/cli/cmd/tui/context/theme.tsx index cbe836b1c..a17b13533 100644 --- a/packages/opencode/src/cli/cmd/tui/context/theme.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/theme.tsx @@ -6,6 +6,7 @@ import { createSimpleContext } from "./helper" import aura from "./theme/aura.json" with { type: "json" } import ayu from "./theme/ayu.json" with { type: "json" } import catppuccin from "./theme/catppuccin.json" with { type: "json" } +import catppuccinFrappe from "./theme/catppuccin-frappe.json" with { type: "json" } import catppuccinMacchiato from "./theme/catppuccin-macchiato.json" with { type: "json" } import cobalt2 from "./theme/cobalt2.json" with { type: "json" } import cursor from "./theme/cursor.json" with { type: "json" } @@ -137,6 +138,7 @@ export const DEFAULT_THEMES: Record = { aura, ayu, catppuccin, + ["catppuccin-frappe"]: catppuccinFrappe, ["catppuccin-macchiato"]: catppuccinMacchiato, cobalt2, cursor, diff --git a/packages/opencode/src/cli/cmd/tui/context/theme/catppuccin-frappe.json b/packages/opencode/src/cli/cmd/tui/context/theme/catppuccin-frappe.json new file mode 100644 index 000000000..79e56ee9a --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/context/theme/catppuccin-frappe.json @@ -0,0 +1,233 @@ +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "frappeRosewater": "#f2d5cf", + "frappeFlamingo": "#eebebe", + "frappePink": "#f4b8e4", + "frappeMauve": "#ca9ee6", + "frappeRed": "#e78284", + "frappeMaroon": "#ea999c", + "frappePeach": "#ef9f76", + "frappeYellow": "#e5c890", + "frappeGreen": "#a6d189", + "frappeTeal": "#81c8be", + "frappeSky": "#99d1db", + "frappeSapphire": "#85c1dc", + "frappeBlue": "#8da4e2", + "frappeLavender": "#babbf1", + "frappeText": "#c6d0f5", + "frappeSubtext1": "#b5bfe2", + "frappeSubtext0": "#a5adce", + "frappeOverlay2": "#949cb8", + "frappeOverlay1": "#838ba7", + "frappeOverlay0": "#737994", + "frappeSurface2": "#626880", + "frappeSurface1": "#51576d", + "frappeSurface0": "#414559", + "frappeBase": "#303446", + "frappeMantle": "#292c3c", + "frappeCrust": "#232634" + }, + "theme": { + "primary": { + "dark": "frappeBlue", + "light": "frappeBlue" + }, + "secondary": { + "dark": "frappeMauve", + "light": "frappeMauve" + }, + "accent": { + "dark": "frappePink", + "light": "frappePink" + }, + "error": { + "dark": "frappeRed", + "light": "frappeRed" + }, + "warning": { + "dark": "frappeYellow", + "light": "frappeYellow" + }, + "success": { + "dark": "frappeGreen", + "light": "frappeGreen" + }, + "info": { + "dark": "frappeTeal", + "light": "frappeTeal" + }, + "text": { + "dark": "frappeText", + "light": "frappeText" + }, + "textMuted": { + "dark": "frappeSubtext1", + "light": "frappeSubtext1" + }, + "background": { + "dark": "frappeBase", + "light": "frappeBase" + }, + "backgroundPanel": { + "dark": "frappeMantle", + "light": "frappeMantle" + }, + "backgroundElement": { + "dark": "frappeCrust", + "light": "frappeCrust" + }, + "border": { + "dark": "frappeSurface0", + "light": "frappeSurface0" + }, + "borderActive": { + "dark": "frappeSurface1", + "light": "frappeSurface1" + }, + "borderSubtle": { + "dark": "frappeSurface2", + "light": "frappeSurface2" + }, + "diffAdded": { + "dark": "frappeGreen", + "light": "frappeGreen" + }, + "diffRemoved": { + "dark": "frappeRed", + "light": "frappeRed" + }, + "diffContext": { + "dark": "frappeOverlay2", + "light": "frappeOverlay2" + }, + "diffHunkHeader": { + "dark": "frappePeach", + "light": "frappePeach" + }, + "diffHighlightAdded": { + "dark": "frappeGreen", + "light": "frappeGreen" + }, + "diffHighlightRemoved": { + "dark": "frappeRed", + "light": "frappeRed" + }, + "diffAddedBg": { + "dark": "#29342b", + "light": "#29342b" + }, + "diffRemovedBg": { + "dark": "#3a2a31", + "light": "#3a2a31" + }, + "diffContextBg": { + "dark": "frappeMantle", + "light": "frappeMantle" + }, + "diffLineNumber": { + "dark": "frappeSurface1", + "light": "frappeSurface1" + }, + "diffAddedLineNumberBg": { + "dark": "#223025", + "light": "#223025" + }, + "diffRemovedLineNumberBg": { + "dark": "#2f242b", + "light": "#2f242b" + }, + "markdownText": { + "dark": "frappeText", + "light": "frappeText" + }, + "markdownHeading": { + "dark": "frappeMauve", + "light": "frappeMauve" + }, + "markdownLink": { + "dark": "frappeBlue", + "light": "frappeBlue" + }, + "markdownLinkText": { + "dark": "frappeSky", + "light": "frappeSky" + }, + "markdownCode": { + "dark": "frappeGreen", + "light": "frappeGreen" + }, + "markdownBlockQuote": { + "dark": "frappeYellow", + "light": "frappeYellow" + }, + "markdownEmph": { + "dark": "frappeYellow", + "light": "frappeYellow" + }, + "markdownStrong": { + "dark": "frappePeach", + "light": "frappePeach" + }, + "markdownHorizontalRule": { + "dark": "frappeSubtext0", + "light": "frappeSubtext0" + }, + "markdownListItem": { + "dark": "frappeBlue", + "light": "frappeBlue" + }, + "markdownListEnumeration": { + "dark": "frappeSky", + "light": "frappeSky" + }, + "markdownImage": { + "dark": "frappeBlue", + "light": "frappeBlue" + }, + "markdownImageText": { + "dark": "frappeSky", + "light": "frappeSky" + }, + "markdownCodeBlock": { + "dark": "frappeText", + "light": "frappeText" + }, + "syntaxComment": { + "dark": "frappeOverlay2", + "light": "frappeOverlay2" + }, + "syntaxKeyword": { + "dark": "frappeMauve", + "light": "frappeMauve" + }, + "syntaxFunction": { + "dark": "frappeBlue", + "light": "frappeBlue" + }, + "syntaxVariable": { + "dark": "frappeRed", + "light": "frappeRed" + }, + "syntaxString": { + "dark": "frappeGreen", + "light": "frappeGreen" + }, + "syntaxNumber": { + "dark": "frappePeach", + "light": "frappePeach" + }, + "syntaxType": { + "dark": "frappeYellow", + "light": "frappeYellow" + }, + "syntaxOperator": { + "dark": "frappeSky", + "light": "frappeSky" + }, + "syntaxPunctuation": { + "dark": "frappeText", + "light": "frappeText" + } + } +} From ad6a5e6157ea728d3d2cb29297d6bbb5f79dc6bc Mon Sep 17 00:00:00 2001 From: Ryan Vogel Date: Sat, 20 Dec 2025 13:05:06 -0500 Subject: [PATCH 023/112] feat(docs): adding .md to docs pages shows raw markdown (#5823) --- packages/web/src/pages/[...slug].md.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 packages/web/src/pages/[...slug].md.ts diff --git a/packages/web/src/pages/[...slug].md.ts b/packages/web/src/pages/[...slug].md.ts new file mode 100644 index 000000000..51c63b5a6 --- /dev/null +++ b/packages/web/src/pages/[...slug].md.ts @@ -0,0 +1,18 @@ +import type { APIRoute } from "astro" +import { getCollection } from "astro:content" + +export const GET: APIRoute = async ({ params }) => { + const slug = params.slug || "index" + const docs = await getCollection("docs") + const doc = docs.find((d) => d.id === slug) + + if (!doc) { + return new Response("Not found", { status: 404 }) + } + + return new Response(doc.body, { + headers: { + "Content-Type": "text/plain; charset=utf-8", + }, + }) +} From 9caaae6a185957b4dc58d4eadf86d8af8a8fdbd5 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Sat, 20 Dec 2025 13:47:28 -0600 Subject: [PATCH 024/112] tweak: better error message if no primary agents are enabled --- packages/opencode/src/cli/error.ts | 3 ++- packages/opencode/src/config/config.ts | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/error.ts b/packages/opencode/src/cli/error.ts index 07a53d293..54ced0d7a 100644 --- a/packages/opencode/src/cli/error.ts +++ b/packages/opencode/src/cli/error.ts @@ -32,7 +32,8 @@ export function FormatError(input: unknown) { } if (Config.InvalidError.isInstance(input)) return [ - `Config file at ${input.data.path} is invalid` + (input.data.message ? `: ${input.data.message}` : ""), + `Configuration is invalid${input.data.path && input.data.path !== "config" ? ` at ${input.data.path}` : ""}` + + (input.data.message ? `: ${input.data.message}` : ""), ...(input.data.issues?.map((issue) => "↳ " + issue.message + " " + issue.path.join(".")) ?? []), ].join("\n") diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 031bdd31b..1158d67f4 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -141,6 +141,17 @@ export namespace Config { if (!result.keybinds) result.keybinds = Info.shape.keybinds.parse({}) + // Only validate if user has configured agents - if none configured, built-in agents will be used + if (Object.keys(result.agent).length > 0) { + const primaryAgents = Object.values(result.agent).filter((a) => a.mode !== "subagent" && !a.hidden && !a.disable) + if (primaryAgents.length === 0) { + throw new InvalidError({ + path: "config", + message: "No primary agents are available. Please configure at least one agent with mode 'primary' or 'all'.", + }) + } + } + return { config: result, directories, From 6c40bfe04322c14350c9bd3447174986800a57d7 Mon Sep 17 00:00:00 2001 From: Ryan Vogel Date: Sat, 20 Dec 2025 14:51:13 -0500 Subject: [PATCH 025/112] docs: clarify model ID format for OpenCode provider (#5854) --- packages/web/src/content/docs/agents.mdx | 2 ++ packages/web/src/content/docs/models.mdx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/web/src/content/docs/agents.mdx b/packages/web/src/content/docs/agents.mdx index e9d4490a1..6c1b15239 100644 --- a/packages/web/src/content/docs/agents.mdx +++ b/packages/web/src/content/docs/agents.mdx @@ -331,6 +331,8 @@ If you don’t specify a model, primary agents use the [model globally configure } ``` +The model ID in your OpenCode config uses the format `provider/model-id`. For example, if you're using [OpenCode Zen](/docs/zen), you would use `opencode/gpt-5.1-codex` for GPT 5.1 Codex. + --- ### Tools diff --git a/packages/web/src/content/docs/models.mdx b/packages/web/src/content/docs/models.mdx index 002f3f558..2077b8e0b 100644 --- a/packages/web/src/content/docs/models.mdx +++ b/packages/web/src/content/docs/models.mdx @@ -60,7 +60,7 @@ OpenCode config. } ``` -Here the full ID is `provider_id/model_id`. +Here the full ID is `provider_id/model_id`. For example, if you're using [OpenCode Zen](/docs/zen), you would use `opencode/gpt-5.1-codex` for GPT 5.1 Codex. If you've configured a [custom provider](/docs/providers#custom), the `provider_id` is key from the `provider` part of your config, and the `model_id` is the key from `provider.models`. From c81506b28d78c944da72bad33899bb0ef00ff816 Mon Sep 17 00:00:00 2001 From: YuY801103 Date: Sun, 21 Dec 2025 05:51:42 +0800 Subject: [PATCH 026/112] docs: add Traditional Chinese (Taiwan) README translation (#5861) Co-authored-by: Yu --- README.zh-TW.md | 115 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 README.zh-TW.md diff --git a/README.zh-TW.md b/README.zh-TW.md new file mode 100644 index 000000000..d3cbb263c --- /dev/null +++ b/README.zh-TW.md @@ -0,0 +1,115 @@ +

+ + + + + OpenCode logo + + +

+

開源的 AI Coding Agent。

+

+ Discord + npm + Build status +

+ +[![OpenCode Terminal UI](packages/web/src/assets/lander/screenshot.png)](https://opencode.ai) + +--- + +### 安裝 + +```bash +# 直接安裝 (YOLO) +curl -fsSL https://opencode.ai/install | bash + +# 套件管理員 +npm i -g opencode-ai@latest # 也可使用 bun/pnpm/yarn +scoop bucket add extras; scoop install extras/opencode # Windows +choco install opencode # Windows +brew install opencode # macOS 與 Linux +paru -S opencode-bin # Arch Linux +mise use -g github:sst/opencode # 任何作業系統 +nix run nixpkgs#opencode # 或使用 github:sst/opencode 以取得最新開發分支 +``` + +> [!TIP] +> 安裝前請先移除 0.1.x 以前的舊版本。 + +### 桌面應用程式 (BETA) + +OpenCode 也提供桌面版應用程式。您可以直接從 [發佈頁面 (releases page)](https://github.com/sst/opencode/releases) 或 [opencode.ai/download](https://opencode.ai/download) 下載。 + +| 平台 | 下載連結 | +| --------------------- | ------------------------------------- | +| macOS (Apple Silicon) | `opencode-desktop-darwin-aarch64.dmg` | +| macOS (Intel) | `opencode-desktop-darwin-x64.dmg` | +| Windows | `opencode-desktop-windows-x64.exe` | +| Linux | `.deb`, `.rpm`, 或 AppImage | + +```bash +# macOS (Homebrew Cask) +brew install --cask opencode-desktop +``` + +#### 安裝目錄 + +安裝腳本會依據以下優先順序決定安裝路徑: + +1. `$OPENCODE_INSTALL_DIR` - 自定義安裝目錄 +2. `$XDG_BIN_DIR` - 符合 XDG 基礎目錄規範的路徑 +3. `$HOME/bin` - 標準使用者執行檔目錄 (若存在或可建立) +4. `$HOME/.opencode/bin` - 預設備用路徑 + +```bash +# 範例 +OPENCODE_INSTALL_DIR=/usr/local/bin curl -fsSL https://opencode.ai/install | bash +XDG_BIN_DIR=$HOME/.local/bin curl -fsSL https://opencode.ai/install | bash +``` + +### Agents + +OpenCode 內建了兩種 Agent,您可以使用 `Tab` 鍵快速切換。 + +- **build** - 預設模式,具備完整權限的 Agent,適用於開發工作。 +- **plan** - 唯讀模式,適用於程式碼分析與探索。 + - 預設禁止修改檔案。 + - 執行 bash 指令前會詢問權限。 + - 非常適合用來探索陌生的程式碼庫或規劃變更。 + +此外,OpenCode 還包含一個 **general** 子 Agent,用於處理複雜搜尋與多步驟任務。此 Agent 供系統內部使用,亦可透過在訊息中輸入 `@general` 來呼叫。 + +了解更多關於 [Agents](https://opencode.ai/docs/agents) 的資訊。 + +### 線上文件 + +關於如何設定 OpenCode 的詳細資訊,請參閱我們的 [**官方文件**](https://opencode.ai/docs)。 + +### 參與貢獻 + +如果您有興趣參與 OpenCode 的開發,請在提交 Pull Request 前先閱讀我們的 [貢獻指南 (Contributing Docs)](./CONTRIBUTING.md)。 + +### 基於 OpenCode 進行開發 + +如果您正在開發與 OpenCode 相關的專案,並在名稱中使用了 "opencode"(例如 "opencode-dashboard" 或 "opencode-mobile"),請在您的 README 中加入聲明,說明該專案並非由 OpenCode 團隊開發,且與我們沒有任何隸屬關係。 + +### 常見問題 (FAQ) + +#### 這跟 Claude Code 有什麼不同? + +在功能面上與 Claude Code 非常相似。以下是關鍵差異: + +- 100% 開源。 +- 不綁定特定的服務提供商。雖然我們推薦使用透過 [OpenCode Zen](https://opencode.ai/zen) 提供的模型,但 OpenCode 也可搭配 Claude, OpenAI, Google 甚至本地模型使用。隨著模型不斷演進,彼此間的差距會縮小且價格會下降,因此具備「不限廠商 (provider-agnostic)」的特性至關重要。 +- 內建 LSP (語言伺服器協定) 支援。 +- 專注於終端機介面 (TUI)。OpenCode 由 Neovim 愛好者與 [terminal.shop](https://terminal.shop) 的創作者打造;我們將不斷挑戰終端機介面的極限。 +- 客戶端/伺服器架構 (Client/Server Architecture)。這讓 OpenCode 能夠在您的電腦上運行的同時,由行動裝置進行遠端操控。這意味著 TUI 前端只是眾多可能的客戶端之一。 + +#### 另一個同名的 Repo 是什麼? + +另一個名稱相近的儲存庫與本專案無關。您可以點此[閱讀背後的故事](https://x.com/thdxr/status/1933561254481666466)。 + +--- + +**加入我們的社群** [Discord](https://discord.gg/opencode) | [X.com](https://x.com/opencode) From 182630e0d7d49d8c9842781f08b19388346d8e5c Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Sat, 20 Dec 2025 19:52:12 -0600 Subject: [PATCH 027/112] feat(desktop): new layout --- packages/desktop/src/context/layout.tsx | 27 +- packages/desktop/src/pages/session.tsx | 470 ++++++++++-------------- 2 files changed, 205 insertions(+), 292 deletions(-) diff --git a/packages/desktop/src/context/layout.tsx b/packages/desktop/src/context/layout.tsx index 0d3de5683..8bfc8aa21 100644 --- a/packages/desktop/src/context/layout.tsx +++ b/packages/desktop/src/context/layout.tsx @@ -46,8 +46,8 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( opened: false, height: 280, }, - review: { - state: "pane" as "pane" | "tab", + session: { + width: 600, }, sessionTabs: {} as Record, }), @@ -156,13 +156,14 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( setStore("terminal", "height", height) }, }, - review: { - state: createMemo(() => store.review?.state ?? "closed"), - pane() { - setStore("review", "state", "pane") - }, - tab() { - setStore("review", "state", "tab") + session: { + width: createMemo(() => store.session?.width ?? 600), + resize(width: number) { + if (!store.session) { + setStore("session", { width }) + } else { + setStore("session", "width", width) + } }, }, tabs(sessionKey: string) { @@ -186,14 +187,6 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( } }, async open(tab: string) { - if (tab === "chat") { - if (!store.sessionTabs[sessionKey]) { - setStore("sessionTabs", sessionKey, { all: [], active: undefined }) - } else { - setStore("sessionTabs", sessionKey, "active", undefined) - } - return - } const current = store.sessionTabs[sessionKey] ?? { all: [] } if (tab !== "review") { if (!current.all.includes(tab)) { diff --git a/packages/desktop/src/pages/session.tsx b/packages/desktop/src/pages/session.tsx index 6e993ff8f..796b5b0c7 100644 --- a/packages/desktop/src/pages/session.tsx +++ b/packages/desktop/src/pages/session.tsx @@ -22,7 +22,6 @@ import { IconButton } from "@opencode-ai/ui/icon-button" import { Icon } from "@opencode-ai/ui/icon" import { Tooltip } from "@opencode-ai/ui/tooltip" import { DiffChanges } from "@opencode-ai/ui/diff-changes" -import { ProgressCircle } from "@opencode-ai/ui/progress-circle" import { ResizeHandle } from "@opencode-ai/ui/resize-handle" import { Tabs } from "@opencode-ai/ui/tabs" import { useCodeComponent } from "@opencode-ai/ui/context/code" @@ -50,7 +49,7 @@ import { DialogSelectFile } from "@/components/dialog-select-file" import { DialogSelectModel } from "@/components/dialog-select-model" import { useCommand } from "@/context/command" import { useNavigate, useParams } from "@solidjs/router" -import { AssistantMessage, UserMessage } from "@opencode-ai/sdk/v2" +import { UserMessage } from "@opencode-ai/sdk/v2" import { useSDK } from "@/context/sdk" import { usePrompt } from "@/context/prompt" import { extractPromptFromParts } from "@/utils/prompt" @@ -118,27 +117,8 @@ export default function Page() { setActiveMessage(msgs[targetIndex]) } - const last = createMemo( - () => messages().findLast((x) => x.role === "assistant" && x.tokens.output > 0) as AssistantMessage, - ) - const model = createMemo(() => - last() ? sync.data.provider.all.find((x) => x.id === last().providerID)?.models[last().modelID] : undefined, - ) const diffs = createMemo(() => (params.id ? (sync.data.session_diff[params.id] ?? []) : [])) - const tokens = createMemo(() => { - if (!last()) return - const t = last().tokens - return t.input + t.output + t.reasoning + t.cache.read + t.cache.write - }) - - const context = createMemo(() => { - const total = tokens() - const limit = model()?.limit.context - if (!total || !limit) return 0 - return Math.round((total / limit) * 100) - }) - const [store, setStore] = createStore({ clickTimer: undefined as number | undefined, activeDraggable: undefined as string | undefined, @@ -551,273 +531,213 @@ export default function Page() { ) } - const wide = createMemo(() => layout.review.state() === "tab" || !diffs().length) + const showTabs = createMemo(() => diffs().length > 0 || tabs().all().length > 0) return (
-
- + {/* Session pane - always visible */} +
- - - -
- - -
-
Session
- - -
{context() ?? 0}%
-
-
-
- - - - - } - > -
- - - -
-
Review
- -
- {info()?.summary?.files ?? 0} -
-
-
-
-
-
- - - {(tab) => } - - -
- - dialog.show(() => )} +
+ + +
+ + + setStore("stepsExpanded", (x) => !x)} + onUserInteracted={() => setStore("userInteracted", true)} + classes={{ + root: "pb-20 flex-1 min-w-0", + content: "pb-20", + container: + "w-full " + + (!showTabs() + ? "max-w-200 mx-auto px-6" + : visibleUserMessages().length > 1 + ? "pr-6 pl-18" + : "px-6"), + }} /> - +
- -
- -
-
- - -
- - - setStore("stepsExpanded", (x) => !x)} - onUserInteracted={() => setStore("userInteracted", true)} - classes={{ - root: "pb-20 flex-1 min-w-0", - content: "pb-20", - container: - "w-full " + - (wide() - ? "max-w-200 mx-auto px-6" - : visibleUserMessages().length > 1 - ? "pr-6 pl-18" - : "px-6"), - }} - /> - + + +
+
New session
+
+ +
+ {getDirectory(sync.data.path.directory)} + {getFilename(sync.data.path.directory)} +
+
+ + {(project) => ( +
+ +
+ Last modified  + + {DateTime.fromMillis(project().time.updated ?? project().time.created).toRelative()} + +
- - -
-
New session
-
- -
- {getDirectory(sync.data.path.directory)} - {getFilename(sync.data.path.directory)} + )} + +
+ + +
+
+
+ { + inputRef = el + }} + /> +
+
+ + + +
+ + {/* Tabs pane - visible when there are diffs or file tabs */} + +
+ + + + +
+ + + +
+ + + +
+
Review
+ +
+ {info()?.summary?.files ?? 0} +
+
- - {(project) => ( -
- -
- Last modified  - - {DateTime.fromMillis(project().time.updated ?? project().time.created).toRelative()} - -
-
- )} -
-
- - -
-
- { - inputRef = el + + + + + {(tab) => } + + +
+ + dialog.show(() => )} + /> + +
+ +
+ + +
+
-
-
- -
- - { - layout.review.tab() - tabs().setActive("review") - }} - /> - - } - /> -
-
-
- - - -
- -
-
-
- - {(tab) => { - const [file] = createResource( - () => tab, - async (tab) => { - if (tab.startsWith("file://")) { - return local.file.node(tab.replace("file://", "")) - } - return undefined - }, - ) - return ( - - - - {(f) => ( - - )} - - - ) - }} - - - - - {(draggedFile) => { - const [file] = createResource( - () => draggedFile(), - async (tab) => { - if (tab.startsWith("file://")) { - return local.file.node(tab.replace("file://", "")) - } - return undefined - }, - ) - return ( -
- {(f) => } -
- ) - }} -
-
- - -
- { - inputRef = el - }} - /> + + + {(tab) => { + const [file] = createResource( + () => tab, + async (tab) => { + if (tab.startsWith("file://")) { + return local.file.node(tab.replace("file://", "")) + } + return undefined + }, + ) + return ( + + + + {(f) => ( + + )} + + + + ) + }} + + + + + {(draggedFile) => { + const [file] = createResource( + () => draggedFile(), + async (tab) => { + if (tab.startsWith("file://")) { + return local.file.node(tab.replace("file://", "")) + } + return undefined + }, + ) + return ( +
+ {(f) => } +
+ ) + }} +
+
+
From b5d7d3dec1a390514c068eb95f5b58b9c9149db7 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Sat, 20 Dec 2025 20:02:40 -0600 Subject: [PATCH 028/112] fix(desktop): layout --- packages/desktop/src/pages/session.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/desktop/src/pages/session.tsx b/packages/desktop/src/pages/session.tsx index 796b5b0c7..508fbc9c2 100644 --- a/packages/desktop/src/pages/session.tsx +++ b/packages/desktop/src/pages/session.tsx @@ -538,7 +538,7 @@ export default function Page() {
{/* Session pane - always visible */}
@@ -601,7 +601,12 @@ export default function Page() {
-
+
{ inputRef = el From f9cef22a531e70013f7c8a649a9ae6ae3e515bed Mon Sep 17 00:00:00 2001 From: opencode Date: Sun, 21 Dec 2025 02:06:25 +0000 Subject: [PATCH 029/112] release: v1.0.181 --- bun.lock | 30 +++++++++++++------------- 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 | 4 ++-- packages/sdk/js/package.json | 4 ++-- packages/slack/package.json | 2 +- packages/tauri/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, 39 insertions(+), 39 deletions(-) diff --git a/bun.lock b/bun.lock index 089de5002..047970137 100644 --- a/bun.lock +++ b/bun.lock @@ -20,7 +20,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.0.180", + "version": "1.0.181", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -48,7 +48,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.180", + "version": "1.0.181", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -75,7 +75,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.180", + "version": "1.0.181", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -99,7 +99,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.180", + "version": "1.0.181", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -123,7 +123,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.180", + "version": "1.0.181", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -171,7 +171,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.0.180", + "version": "1.0.181", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -200,7 +200,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.180", + "version": "1.0.181", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -216,7 +216,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.180", + "version": "1.0.181", "bin": { "opencode": "./bin/opencode", }, @@ -308,7 +308,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.180", + "version": "1.0.181", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -328,7 +328,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.180", + "version": "1.0.181", "devDependencies": { "@hey-api/openapi-ts": "0.88.1", "@tsconfig/node22": "catalog:", @@ -339,7 +339,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.180", + "version": "1.0.181", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -352,7 +352,7 @@ }, "packages/tauri": { "name": "@opencode-ai/tauri", - "version": "1.0.180", + "version": "1.0.181", "dependencies": { "@opencode-ai/desktop": "workspace:*", "@solid-primitives/storage": "catalog:", @@ -379,7 +379,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.180", + "version": "1.0.181", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -414,7 +414,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.0.180", + "version": "1.0.181", "dependencies": { "zod": "catalog:", }, @@ -425,7 +425,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.180", + "version": "1.0.181", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 4e8d3fd59..4405438f8 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.0.180", + "version": "1.0.181", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 4418597d6..cf3879125 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.0.180", + "version": "1.0.181", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 250e2cdab..343a07d46 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.180", + "version": "1.0.181", "$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 1f18ce314..6259d72f9 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.180", + "version": "1.0.181", "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 c1cf191d4..f982a8ea1 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.180", + "version": "1.0.181", "description": "", "type": "module", "exports": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index acb03ed8e..497cd6ba6 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.0.180", + "version": "1.0.181", "private": true, "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index 446839565..dbcff25c5 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.0.180" +version = "1.0.181" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/sst/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.180/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.181/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.180/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.181/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.180/opencode-linux-arm64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.181/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.180/opencode-linux-x64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.181/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.180/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.181/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index b18a0f5f4..162b71409 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.180", + "version": "1.0.181", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 90427b7f8..01ce44729 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.180", + "version": "1.0.181", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 647bcb563..f131648e2 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.0.180", + "version": "1.0.181", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} +} \ No newline at end of file diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 665499a6e..52712ebfd 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.0.180", + "version": "1.0.181", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -29,4 +29,4 @@ "publishConfig": { "directory": "dist" } -} +} \ No newline at end of file diff --git a/packages/slack/package.json b/packages/slack/package.json index 7964da49b..b3a626933 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.180", + "version": "1.0.181", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/tauri/package.json b/packages/tauri/package.json index 537c3f3d5..ec2bc72cd 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/tauri", "private": true, - "version": "1.0.180", + "version": "1.0.181", "type": "module", "scripts": { "typecheck": "tsgo -b", diff --git a/packages/ui/package.json b/packages/ui/package.json index 2f42e536d..8a758b6fe 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.180", + "version": "1.0.181", "type": "module", "exports": { "./*": "./src/components/*.tsx", diff --git a/packages/util/package.json b/packages/util/package.json index 19b21e7a0..dc4ee807e 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.0.180", + "version": "1.0.181", "private": true, "type": "module", "exports": { diff --git a/packages/web/package.json b/packages/web/package.json index 160b27817..f9f9e0875 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.180", + "version": "1.0.181", "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 b51f976c8..345c7a9aa 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.0.180", + "version": "1.0.181", "publisher": "sst-dev", "repository": { "type": "git", From 3d822e5f795d0c5bbb20bef15c232154cf101779 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Sat, 20 Dec 2025 21:04:37 -0600 Subject: [PATCH 030/112] fix: regression where config would error despite valid agents --- packages/opencode/src/config/config.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 1158d67f4..031bdd31b 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -141,17 +141,6 @@ export namespace Config { if (!result.keybinds) result.keybinds = Info.shape.keybinds.parse({}) - // Only validate if user has configured agents - if none configured, built-in agents will be used - if (Object.keys(result.agent).length > 0) { - const primaryAgents = Object.values(result.agent).filter((a) => a.mode !== "subagent" && !a.hidden && !a.disable) - if (primaryAgents.length === 0) { - throw new InvalidError({ - path: "config", - message: "No primary agents are available. Please configure at least one agent with mode 'primary' or 'all'.", - }) - } - } - return { config: result, directories, From 0b046d6cf09ba65d0efa20cf20e061c306142c1b Mon Sep 17 00:00:00 2001 From: opencode Date: Sun, 21 Dec 2025 03:07:26 +0000 Subject: [PATCH 031/112] release: v1.0.182 --- bun.lock | 30 +++++++++++++------------- 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/tauri/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 047970137..8027d29f0 100644 --- a/bun.lock +++ b/bun.lock @@ -20,7 +20,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.0.181", + "version": "1.0.182", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -48,7 +48,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.181", + "version": "1.0.182", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -75,7 +75,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.181", + "version": "1.0.182", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -99,7 +99,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.181", + "version": "1.0.182", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -123,7 +123,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.181", + "version": "1.0.182", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -171,7 +171,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.0.181", + "version": "1.0.182", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -200,7 +200,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.181", + "version": "1.0.182", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -216,7 +216,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.181", + "version": "1.0.182", "bin": { "opencode": "./bin/opencode", }, @@ -308,7 +308,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.181", + "version": "1.0.182", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -328,7 +328,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.181", + "version": "1.0.182", "devDependencies": { "@hey-api/openapi-ts": "0.88.1", "@tsconfig/node22": "catalog:", @@ -339,7 +339,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.181", + "version": "1.0.182", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -352,7 +352,7 @@ }, "packages/tauri": { "name": "@opencode-ai/tauri", - "version": "1.0.181", + "version": "1.0.182", "dependencies": { "@opencode-ai/desktop": "workspace:*", "@solid-primitives/storage": "catalog:", @@ -379,7 +379,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.181", + "version": "1.0.182", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -414,7 +414,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.0.181", + "version": "1.0.182", "dependencies": { "zod": "catalog:", }, @@ -425,7 +425,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.181", + "version": "1.0.182", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 4405438f8..e13b96f38 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.0.181", + "version": "1.0.182", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index cf3879125..6da120dc9 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.0.181", + "version": "1.0.182", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 343a07d46..7ae216136 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.181", + "version": "1.0.182", "$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 6259d72f9..830400591 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.181", + "version": "1.0.182", "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 f982a8ea1..a41ed60c3 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.181", + "version": "1.0.182", "description": "", "type": "module", "exports": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index 497cd6ba6..54ce9e17f 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.0.181", + "version": "1.0.182", "private": true, "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index dbcff25c5..8e7f26f1e 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.0.181" +version = "1.0.182" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/sst/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.181/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.182/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.181/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.182/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.181/opencode-linux-arm64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.182/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.181/opencode-linux-x64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.182/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.181/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.182/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index 162b71409..6f0fa372c 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.181", + "version": "1.0.182", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 01ce44729..11bc4b0cb 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.181", + "version": "1.0.182", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index f131648e2..3385d68f5 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.0.181", + "version": "1.0.182", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 52712ebfd..a4ef941e5 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.0.181", + "version": "1.0.182", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/slack/package.json b/packages/slack/package.json index b3a626933..b44f1505c 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.181", + "version": "1.0.182", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/tauri/package.json b/packages/tauri/package.json index ec2bc72cd..34a013a51 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/tauri", "private": true, - "version": "1.0.181", + "version": "1.0.182", "type": "module", "scripts": { "typecheck": "tsgo -b", diff --git a/packages/ui/package.json b/packages/ui/package.json index 8a758b6fe..df5031fb4 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.181", + "version": "1.0.182", "type": "module", "exports": { "./*": "./src/components/*.tsx", diff --git a/packages/util/package.json b/packages/util/package.json index dc4ee807e..5d796ef52 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.0.181", + "version": "1.0.182", "private": true, "type": "module", "exports": { diff --git a/packages/web/package.json b/packages/web/package.json index f9f9e0875..d22646849 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.181", + "version": "1.0.182", "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 345c7a9aa..200d6ae8e 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.0.181", + "version": "1.0.182", "publisher": "sst-dev", "repository": { "type": "git", From cfaac9f2e12acdfcf95459f450452d049d514513 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sun, 21 Dec 2025 03:05:21 +0000 Subject: [PATCH 032/112] chore: generate --- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 3385d68f5..a4753726d 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} \ No newline at end of file +} diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index a4ef941e5..f23970060 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -29,4 +29,4 @@ "publishConfig": { "directory": "dist" } -} \ No newline at end of file +} From d3922f0965a17491dc7fdf24af5b3ac0c9a72510 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Sat, 20 Dec 2025 19:36:22 -0800 Subject: [PATCH 033/112] core: add verification that at least 1 primary agent is enabled, add regression tests (#5881) --- packages/opencode/src/agent/agent.ts | 8 + packages/opencode/test/agent/agent.test.ts | 146 +++++++++++++++++++ packages/opencode/test/config/config.test.ts | 32 ++++ 3 files changed, 186 insertions(+) create mode 100644 packages/opencode/test/agent/agent.test.ts diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 26f241fab..90c8594cd 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -262,6 +262,14 @@ export namespace Agent { } } + const hasPrimaryAgents = Object.values(result).filter((a) => a.mode !== "subagent" && !a.hidden).length > 0 + if (!hasPrimaryAgents) { + throw new Config.InvalidError({ + path: "config", + message: "No primary agents are available. Please configure at least one agent with mode 'primary' or 'all'.", + }) + } + return result }) diff --git a/packages/opencode/test/agent/agent.test.ts b/packages/opencode/test/agent/agent.test.ts new file mode 100644 index 000000000..222bf8367 --- /dev/null +++ b/packages/opencode/test/agent/agent.test.ts @@ -0,0 +1,146 @@ +import { test, expect } from "bun:test" +import path from "path" +import fs from "fs/promises" +import { tmpdir } from "../fixture/fixture" +import { Instance } from "../../src/project/instance" +import { Agent } from "../../src/agent/agent" + +test("loads built-in agents when no custom agents configured", async () => { + await using tmp = await tmpdir() + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const agents = await Agent.list() + const names = agents.map((a) => a.name) + expect(names).toContain("build") + expect(names).toContain("plan") + }, + }) +}) + +test("custom subagent works alongside built-in primary agents", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + const opencodeDir = path.join(dir, ".opencode") + await fs.mkdir(opencodeDir, { recursive: true }) + const agentDir = path.join(opencodeDir, "agent") + await fs.mkdir(agentDir, { recursive: true }) + + await Bun.write( + path.join(agentDir, "helper.md"), + `--- +model: test/model +mode: subagent +--- +Helper subagent prompt`, + ) + }, + }) + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const agents = await Agent.list() + const helper = agents.find((a) => a.name === "helper") + expect(helper).toBeDefined() + expect(helper?.mode).toBe("subagent") + + // Built-in primary agents should still exist + const build = agents.find((a) => a.name === "build") + expect(build).toBeDefined() + expect(build?.mode).toBe("primary") + }, + }) +}) + +test("throws error when all primary agents are disabled", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + await Bun.write( + path.join(dir, "opencode.json"), + JSON.stringify({ + $schema: "https://opencode.ai/config.json", + agent: { + build: { disable: true }, + plan: { disable: true }, + }, + }), + ) + }, + }) + await Instance.provide({ + directory: tmp.path, + fn: async () => { + try { + await Agent.list() + expect(true).toBe(false) // should not reach here + } catch (e: any) { + expect(e.data?.message).toContain("No primary agents are available") + } + }, + }) +}) + +test("does not throw when at least one primary agent remains", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + await Bun.write( + path.join(dir, "opencode.json"), + JSON.stringify({ + $schema: "https://opencode.ai/config.json", + agent: { + build: { disable: true }, + }, + }), + ) + }, + }) + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const agents = await Agent.list() + const plan = agents.find((a) => a.name === "plan") + expect(plan).toBeDefined() + expect(plan?.mode).toBe("primary") + }, + }) +}) + +test("custom primary agent satisfies requirement when built-ins disabled", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + const opencodeDir = path.join(dir, ".opencode") + await fs.mkdir(opencodeDir, { recursive: true }) + const agentDir = path.join(opencodeDir, "agent") + await fs.mkdir(agentDir, { recursive: true }) + + await Bun.write( + path.join(agentDir, "custom.md"), + `--- +model: test/model +mode: primary +--- +Custom primary agent`, + ) + + await Bun.write( + path.join(dir, "opencode.json"), + JSON.stringify({ + $schema: "https://opencode.ai/config.json", + agent: { + build: { disable: true }, + plan: { disable: true }, + }, + }), + ) + }, + }) + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const agents = await Agent.list() + const custom = agents.find((a) => a.name === "custom") + expect(custom).toBeDefined() + expect(custom?.mode).toBe("primary") + }, + }) +}) diff --git a/packages/opencode/test/config/config.test.ts b/packages/opencode/test/config/config.test.ts index 2ff8c01cd..6f43cab61 100644 --- a/packages/opencode/test/config/config.test.ts +++ b/packages/opencode/test/config/config.test.ts @@ -450,6 +450,38 @@ test("merges plugin arrays from global and local configs", async () => { }) }) +test("does not error when only custom agent is a subagent", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + const opencodeDir = path.join(dir, ".opencode") + await fs.mkdir(opencodeDir, { recursive: true }) + const agentDir = path.join(opencodeDir, "agent") + await fs.mkdir(agentDir, { recursive: true }) + + await Bun.write( + path.join(agentDir, "helper.md"), + `--- +model: test/model +mode: subagent +--- +Helper subagent prompt`, + ) + }, + }) + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const config = await Config.get() + expect(config.agent?.["helper"]).toEqual({ + name: "helper", + model: "test/model", + mode: "subagent", + prompt: "Helper subagent prompt", + }) + }, + }) +}) + test("deduplicates duplicate plugins from global and local configs", async () => { await using tmp = await tmpdir({ init: async (dir) => { From 6dc4e5ac9325c669bf7c0d22f7550d9447955eb1 Mon Sep 17 00:00:00 2001 From: Christopher Tso Date: Sun, 21 Dec 2025 17:09:58 +1100 Subject: [PATCH 034/112] Make CLI build script Windows-friendly (#5835) --- packages/opencode/package.json | 2 +- packages/opencode/script/build.ts | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 11bc4b0cb..2592553e7 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -7,7 +7,7 @@ "scripts": { "typecheck": "tsgo --noEmit", "test": "bun test", - "build": "./script/build.ts", + "build": "bun run script/build.ts", "dev": "bun run --conditions=browser ./src/index.ts", "random": "echo 'Random script updated at $(date)' && echo 'Change queued successfully' && echo 'Another change made' && echo 'Yet another change' && echo 'One more change' && echo 'Final change' && echo 'Another final change' && echo 'Yet another final change'", "clean": "echo 'Cleaning up...' && rm -rf node_modules dist", diff --git a/packages/opencode/script/build.ts b/packages/opencode/script/build.ts index a85fde9e2..f51cb2924 100755 --- a/packages/opencode/script/build.ts +++ b/packages/opencode/script/build.ts @@ -16,6 +16,7 @@ import pkg from "../package.json" import { Script } from "@opencode-ai/script" const singleFlag = process.argv.includes("--single") +const baselineFlag = process.argv.includes("--baseline") const skipInstall = process.argv.includes("--skip-install") const allTargets: { @@ -78,7 +79,19 @@ const allTargets: { ] const targets = singleFlag - ? allTargets.filter((item) => item.os === process.platform && item.arch === process.arch) + ? allTargets.filter((item) => { + if (item.os !== process.platform || item.arch !== process.arch) { + return false + } + + // When building for the current platform, prefer a single native binary by default. + // Baseline binaries require additional Bun artifacts and can be flaky to download. + if (item.avx2 === false) { + return baselineFlag + } + + return true + }) : allTargets await $`rm -rf dist` From 8c895570c6b2eef81c824c6207c9f2ac5e7cc82b Mon Sep 17 00:00:00 2001 From: Github Action Date: Sun, 21 Dec 2025 06:11:08 +0000 Subject: [PATCH 035/112] Update Nix flake.lock and hashes --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 127262668..e1c4419dc 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1766025857, - "narHash": "sha256-Lav5jJazCW4mdg1iHcROpuXqmM94BWJvabLFWaJVJp0=", + "lastModified": 1766125104, + "narHash": "sha256-l/YGrEpLromL4viUo5GmFH3K5M1j0Mb9O+LiaeCPWEM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "def3da69945bbe338c373fddad5a1bb49cf199ce", + "rev": "7d853e518814cca2a657b72eeba67ae20ebf7059", "type": "github" }, "original": { From 1bce898ca72d275f3b4314e9b78d40f8a24d5f52 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Sun, 21 Dec 2025 04:01:55 -0600 Subject: [PATCH 036/112] fix(desktop): file loading errors --- packages/desktop/src/context/local.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/desktop/src/context/local.tsx b/packages/desktop/src/context/local.tsx index f56973835..69807a2f4 100644 --- a/packages/desktop/src/context/local.tsx +++ b/packages/desktop/src/context/local.tsx @@ -360,7 +360,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const init = async (path: string) => { const relativePath = relative(path) if (!store.node[relativePath]) await fetch(path) - if (store.node[relativePath].loaded) return + if (store.node[relativePath]?.loaded) return return load(relativePath) } @@ -380,7 +380,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ context.addActive() if (options?.pinned) setStore("node", path, "pinned", true) if (options?.view && store.node[relativePath].view === undefined) setStore("node", path, "view", options.view) - if (store.node[relativePath].loaded) return + if (store.node[relativePath]?.loaded) return return load(relativePath) } From 184643f0db48fe35dfbb32f5234bd8d28691c234 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Sun, 21 Dec 2025 04:06:10 -0600 Subject: [PATCH 037/112] fix(desktop): non-latin file paths failed --- packages/util/src/encode.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/util/src/encode.ts b/packages/util/src/encode.ts index cc40fbe9d..fc1f783bf 100644 --- a/packages/util/src/encode.ts +++ b/packages/util/src/encode.ts @@ -1,9 +1,13 @@ export function base64Encode(value: string) { - return btoa(value).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "") + const bytes = new TextEncoder().encode(value) + const binary = Array.from(bytes, (b) => String.fromCharCode(b)).join("") + return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "") } export function base64Decode(value: string) { - return atob(value.replace(/-/g, "+").replace(/_/g, "/")) + const binary = atob(value.replace(/-/g, "+").replace(/_/g, "/")) + const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0)) + return new TextDecoder().decode(bytes) } export async function hash(content: string, algorithm = "SHA-256"): Promise { From bf663905579d198d63ff1641112ec4f682cee09a Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Sun, 21 Dec 2025 04:11:09 -0600 Subject: [PATCH 038/112] fix(desktop): better error reporting --- packages/desktop/src/pages/error.tsx | 30 +++++++++++++++++++++++----- packages/desktop/vite.config.ts | 1 + 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/desktop/src/pages/error.tsx b/packages/desktop/src/pages/error.tsx index 352b9f3e8..c7330c298 100644 --- a/packages/desktop/src/pages/error.tsx +++ b/packages/desktop/src/pages/error.tsx @@ -62,12 +62,32 @@ function formatInitError(error: InitError): string { } } -function formatError(error: unknown): string { +function formatErrorChain(error: unknown, depth = 0): string { if (!error) return "Unknown error" - if (isInitError(error)) return formatInitError(error) - if (error instanceof Error) return `${error.name}: ${error.message}\n\n${error.stack}` - if (typeof error === "string") return error - return JSON.stringify(error, null, 2) + + const indent = depth > 0 ? `\n${"─".repeat(40)}\nCaused by:\n` : "" + + if (isInitError(error)) { + return indent + formatInitError(error) + } + + if (error instanceof Error) { + const parts = [indent + `${error.name}: ${error.message}`] + if (error.stack) { + parts.push(error.stack) + } + if (error.cause) { + parts.push(formatErrorChain(error.cause, depth + 1)) + } + return parts.join("\n\n") + } + + if (typeof error === "string") return indent + error + return indent + JSON.stringify(error, null, 2) +} + +function formatError(error: unknown): string { + return formatErrorChain(error, 0) } interface ErrorPageProps { diff --git a/packages/desktop/vite.config.ts b/packages/desktop/vite.config.ts index a388884cd..57071a894 100644 --- a/packages/desktop/vite.config.ts +++ b/packages/desktop/vite.config.ts @@ -10,5 +10,6 @@ export default defineConfig({ }, build: { target: "esnext", + sourcemap: true, }, }) From 9d48fd4bbdd74770bf4d8a59a476b1bbc0b9d817 Mon Sep 17 00:00:00 2001 From: opencode Date: Sun, 21 Dec 2025 10:14:41 +0000 Subject: [PATCH 039/112] release: v1.0.183 --- bun.lock | 30 +++++++++++++------------- 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 | 4 ++-- packages/sdk/js/package.json | 4 ++-- packages/slack/package.json | 2 +- packages/tauri/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, 39 insertions(+), 39 deletions(-) diff --git a/bun.lock b/bun.lock index 8027d29f0..0a3252e41 100644 --- a/bun.lock +++ b/bun.lock @@ -20,7 +20,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.0.182", + "version": "1.0.183", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -48,7 +48,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.182", + "version": "1.0.183", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -75,7 +75,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.182", + "version": "1.0.183", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -99,7 +99,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.182", + "version": "1.0.183", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -123,7 +123,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.182", + "version": "1.0.183", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -171,7 +171,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.0.182", + "version": "1.0.183", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -200,7 +200,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.182", + "version": "1.0.183", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -216,7 +216,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.182", + "version": "1.0.183", "bin": { "opencode": "./bin/opencode", }, @@ -308,7 +308,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.182", + "version": "1.0.183", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -328,7 +328,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.182", + "version": "1.0.183", "devDependencies": { "@hey-api/openapi-ts": "0.88.1", "@tsconfig/node22": "catalog:", @@ -339,7 +339,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.182", + "version": "1.0.183", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -352,7 +352,7 @@ }, "packages/tauri": { "name": "@opencode-ai/tauri", - "version": "1.0.182", + "version": "1.0.183", "dependencies": { "@opencode-ai/desktop": "workspace:*", "@solid-primitives/storage": "catalog:", @@ -379,7 +379,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.182", + "version": "1.0.183", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -414,7 +414,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.0.182", + "version": "1.0.183", "dependencies": { "zod": "catalog:", }, @@ -425,7 +425,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.182", + "version": "1.0.183", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index e13b96f38..515aff903 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.0.182", + "version": "1.0.183", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 6da120dc9..3eadd2e4e 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.0.182", + "version": "1.0.183", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 7ae216136..c14a107ff 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.182", + "version": "1.0.183", "$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 830400591..095dd6f25 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.182", + "version": "1.0.183", "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 a41ed60c3..d70f13add 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.182", + "version": "1.0.183", "description": "", "type": "module", "exports": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index 54ce9e17f..bad614e41 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.0.182", + "version": "1.0.183", "private": true, "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index 8e7f26f1e..dfd7bdffe 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.0.182" +version = "1.0.183" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/sst/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.182/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.183/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.182/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.183/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.182/opencode-linux-arm64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.183/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.182/opencode-linux-x64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.183/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.182/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.183/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index 6f0fa372c..06a5a51ad 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.182", + "version": "1.0.183", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 2592553e7..321a466ee 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.182", + "version": "1.0.183", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index a4753726d..7a6f61fd9 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.0.182", + "version": "1.0.183", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} +} \ No newline at end of file diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index f23970060..78f5c8806 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.0.182", + "version": "1.0.183", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -29,4 +29,4 @@ "publishConfig": { "directory": "dist" } -} +} \ No newline at end of file diff --git a/packages/slack/package.json b/packages/slack/package.json index b44f1505c..128413bfe 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.182", + "version": "1.0.183", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/tauri/package.json b/packages/tauri/package.json index 34a013a51..4098150ae 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/tauri", "private": true, - "version": "1.0.182", + "version": "1.0.183", "type": "module", "scripts": { "typecheck": "tsgo -b", diff --git a/packages/ui/package.json b/packages/ui/package.json index df5031fb4..863206b13 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.182", + "version": "1.0.183", "type": "module", "exports": { "./*": "./src/components/*.tsx", diff --git a/packages/util/package.json b/packages/util/package.json index 5d796ef52..95863c577 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.0.182", + "version": "1.0.183", "private": true, "type": "module", "exports": { diff --git a/packages/web/package.json b/packages/web/package.json index d22646849..cc623c1f5 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.182", + "version": "1.0.183", "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 200d6ae8e..8f1047a1d 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.0.182", + "version": "1.0.183", "publisher": "sst-dev", "repository": { "type": "git", From 5072331f0444f0ce67a8266b6687144171582c08 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Sun, 21 Dec 2025 04:35:09 -0600 Subject: [PATCH 040/112] fix(desktop): incorrect state dir on macos --- packages/tauri/src-tauri/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/tauri/src-tauri/src/lib.rs b/packages/tauri/src-tauri/src/lib.rs index ffefbabf6..3c08841ab 100644 --- a/packages/tauri/src-tauri/src/lib.rs +++ b/packages/tauri/src-tauri/src/lib.rs @@ -6,7 +6,7 @@ use std::{ sync::{Arc, Mutex}, time::{Duration, Instant}, }; -use tauri::{AppHandle, LogicalSize, Manager, RunEvent, WebviewUrl, WebviewWindow}; +use tauri::{AppHandle, LogicalSize, Manager, RunEvent, WebviewUrl, WebviewWindow, path::BaseDirectory}; use tauri_plugin_clipboard_manager::ClipboardExt; use tauri_plugin_dialog::{DialogExt, MessageDialogButtons, MessageDialogResult}; use tauri_plugin_shell::process::{CommandChild, CommandEvent}; @@ -97,6 +97,11 @@ fn spawn_sidecar(app: &AppHandle, port: u32) -> CommandChild { let log_state = app.state::(); let log_state_clone = log_state.inner().clone(); + let state_dir = app + .path() + .resolve("", BaseDirectory::AppLocalData) + .expect("Failed to resolve app local data dir"); + #[cfg(target_os = "windows")] let (mut rx, child) = app .shell() @@ -104,6 +109,7 @@ fn spawn_sidecar(app: &AppHandle, port: u32) -> CommandChild { .unwrap() .env("OPENCODE_EXPERIMENTAL_ICON_DISCOVERY", "true") .env("OPENCODE_CLIENT", "desktop") + .env("XDG_STATE_HOME", &state_dir) .args(["serve", &format!("--port={port}")]) .spawn() .expect("Failed to spawn opencode"); @@ -120,6 +126,7 @@ fn spawn_sidecar(app: &AppHandle, port: u32) -> CommandChild { .command(&shell) .env("OPENCODE_EXPERIMENTAL_ICON_DISCOVERY", "true") .env("OPENCODE_CLIENT", "desktop") + .env("XDG_STATE_HOME", &state_dir) .args([ "-il", "-c", From 36bb02ae4559e2bf372c1125843a81ec8b2d9ed0 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sun, 21 Dec 2025 10:36:43 +0000 Subject: [PATCH 041/112] chore: generate --- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 7a6f61fd9..d7aec1eb4 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} \ No newline at end of file +} diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 78f5c8806..bb5699a53 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -29,4 +29,4 @@ "publishConfig": { "directory": "dist" } -} \ No newline at end of file +} From 8865e524cb9831f7c0bf995e1b67159a949ef4de Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Sun, 21 Dec 2025 04:39:46 -0600 Subject: [PATCH 042/112] fix(desktop): allow text selection --- packages/tauri/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tauri/index.html b/packages/tauri/index.html index 8de2d21d0..faeb1a1fd 100644 --- a/packages/tauri/index.html +++ b/packages/tauri/index.html @@ -14,7 +14,7 @@ - + ` + // Inject the script right after the opening tag + const modifiedHtml = html.replace("", `${portScript}`) + return c.html(modifiedHtml) + } + + return response }), ) @@ -2607,14 +2622,9 @@ export namespace Server { idleTimeout: 0, fetch: App().fetch, websocket: websocket, - } as const - if (opts.port === 0) { - try { - return Bun.serve({ ...args, port: 4096 }) - } catch { - // port 4096 not available, fall through to use port 0 - } - } - return Bun.serve({ ...args, port: opts.port }) + }) + // Store the actual port for injection into frontend HTML + serverPort = server.port ?? opts.port + return server } } From dbaac790397bb7e4c3f7def6078b40015e013516 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Mon, 22 Dec 2025 06:02:16 -0600 Subject: [PATCH 095/112] fix: server --- packages/opencode/src/server/server.ts | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 69bd5e3be..3a480228e 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -53,9 +53,6 @@ globalThis.AI_SDK_LOG_WARNINGS = false export namespace Server { const log = Log.create({ service: "server" }) - // Port that the server is running on, used to inject into frontend HTML - let serverPort: number = 4096 - export const Event = { Connected: BusEvent.define("server.connected", z.object({})), Disposed: BusEvent.define("global.disposed", z.object({})), @@ -2616,15 +2613,24 @@ export namespace Server { return result } + let serverPort: number = 4096 + export function listen(opts: { port: number; hostname: string }) { const args = { hostname: opts.hostname, idleTimeout: 0, fetch: App().fetch, websocket: websocket, - }) - // Store the actual port for injection into frontend HTML - serverPort = server.port ?? opts.port - return server + } as const + if (opts.port === 0) { + try { + serverPort = 4096 + return Bun.serve({ ...args, port: 4096 }) + } catch { + // port 4096 not available, fall through to use port 0 + } + } + serverPort = opts.port + return Bun.serve({ ...args, port: opts.port }) } } From a97631f7693c532ebed0da66a947fb4951e22632 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Mon, 22 Dec 2025 12:05:15 +0000 Subject: [PATCH 096/112] ignore: update download stats 2025-12-22 --- STATS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/STATS.md b/STATS.md index eb0f43364..7f59be1aa 100644 --- a/STATS.md +++ b/STATS.md @@ -177,3 +177,4 @@ | 2025-12-19 | 1,203,485 (+24,827) | 1,129,698 (+16,280) | 2,333,183 (+41,107) | | 2025-12-20 | 1,223,000 (+19,515) | 1,146,258 (+16,560) | 2,369,258 (+36,075) | | 2025-12-21 | 1,242,675 (+19,675) | 1,158,909 (+12,651) | 2,401,584 (+32,326) | +| 2025-12-22 | 1,262,522 (+19,847) | 1,169,121 (+10,212) | 2,431,643 (+30,059) | From 240ad31edd412ca370c5e54dbf4abd5d6eca5c67 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Mon, 22 Dec 2025 06:04:56 -0600 Subject: [PATCH 097/112] Revert "fix: server" This reverts commit dbaac790397bb7e4c3f7def6078b40015e013516. --- packages/opencode/src/server/server.ts | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 3a480228e..69bd5e3be 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -53,6 +53,9 @@ globalThis.AI_SDK_LOG_WARNINGS = false export namespace Server { const log = Log.create({ service: "server" }) + // Port that the server is running on, used to inject into frontend HTML + let serverPort: number = 4096 + export const Event = { Connected: BusEvent.define("server.connected", z.object({})), Disposed: BusEvent.define("global.disposed", z.object({})), @@ -2613,24 +2616,15 @@ export namespace Server { return result } - let serverPort: number = 4096 - export function listen(opts: { port: number; hostname: string }) { const args = { hostname: opts.hostname, idleTimeout: 0, fetch: App().fetch, websocket: websocket, - } as const - if (opts.port === 0) { - try { - serverPort = 4096 - return Bun.serve({ ...args, port: 4096 }) - } catch { - // port 4096 not available, fall through to use port 0 - } - } - serverPort = opts.port - return Bun.serve({ ...args, port: opts.port }) + }) + // Store the actual port for injection into frontend HTML + serverPort = server.port ?? opts.port + return server } } From 2c16b9fa61b8d8c333c9fb1a1ab51f1089f69079 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Mon, 22 Dec 2025 06:05:10 -0600 Subject: [PATCH 098/112] Revert "server: ensure frontend has correct port for PTY websocket connections (#5898)" This reverts commit a05915ddc8f34d592c05ac6a4f4e8d932a9a0964. --- packages/desktop/src/app.tsx | 2 +- packages/opencode/src/server/server.ts | 34 +++++++++----------------- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/packages/desktop/src/app.tsx b/packages/desktop/src/app.tsx index e5607fd33..2ed529bbc 100644 --- a/packages/desktop/src/app.tsx +++ b/packages/desktop/src/app.tsx @@ -35,7 +35,7 @@ const url = new URLSearchParams(document.location.search).get("url") || (location.hostname.includes("opencode.ai") || location.hostname.includes("localhost") ? `http://${host}:${port}` - : window.location.origin) + : "/") export function App() { return ( diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 69bd5e3be..e92c46225 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -6,6 +6,7 @@ import { describeRoute, generateSpecs, validator, resolver, openAPIRouteHandler import { Hono } from "hono" import { cors } from "hono/cors" import { stream, streamSSE } from "hono/streaming" +import { proxy } from "hono/proxy" import { Session } from "../session" import z from "zod" import { Provider } from "../provider/provider" @@ -53,9 +54,6 @@ globalThis.AI_SDK_LOG_WARNINGS = false export namespace Server { const log = Log.create({ service: "server" }) - // Port that the server is running on, used to inject into frontend HTML - let serverPort: number = 4096 - export const Event = { Connected: BusEvent.define("server.connected", z.object({})), Disposed: BusEvent.define("global.disposed", z.object({})), @@ -2580,25 +2578,12 @@ export namespace Server { }, ) .all("/*", async (c) => { - const response = await fetch(`https://desktop.opencode.ai${c.req.path}`, { - method: c.req.method, + return proxy(`https://desktop.opencode.ai${c.req.path}`, { + ...c.req, headers: { host: "desktop.opencode.ai", }, }) - - const contentType = response.headers.get("content-type") || "" - - // If this is an HTML response, inject the server port - if (contentType.includes("text/html")) { - const html = await response.text() - const portScript = `` - // Inject the script right after the opening tag - const modifiedHtml = html.replace("", `${portScript}`) - return c.html(modifiedHtml) - } - - return response }), ) @@ -2622,9 +2607,14 @@ export namespace Server { idleTimeout: 0, fetch: App().fetch, websocket: websocket, - }) - // Store the actual port for injection into frontend HTML - serverPort = server.port ?? opts.port - return server + } as const + if (opts.port === 0) { + try { + return Bun.serve({ ...args, port: 4096 }) + } catch { + // port 4096 not available, fall through to use port 0 + } + } + return Bun.serve({ ...args, port: opts.port }) } } From c6e9a5c800f7b65f5e7138628443248bed88ecd2 Mon Sep 17 00:00:00 2001 From: opencode Date: Mon, 22 Dec 2025 12:14:06 +0000 Subject: [PATCH 099/112] release: v1.0.186 --- bun.lock | 30 +++++++++++++------------- 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 | 4 ++-- packages/sdk/js/package.json | 4 ++-- packages/slack/package.json | 2 +- packages/tauri/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, 39 insertions(+), 39 deletions(-) diff --git a/bun.lock b/bun.lock index aca0296f4..706347b59 100644 --- a/bun.lock +++ b/bun.lock @@ -22,7 +22,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.0.185", + "version": "1.0.186", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -50,7 +50,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.185", + "version": "1.0.186", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -77,7 +77,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.185", + "version": "1.0.186", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -101,7 +101,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.185", + "version": "1.0.186", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -125,7 +125,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.185", + "version": "1.0.186", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -173,7 +173,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.0.185", + "version": "1.0.186", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -202,7 +202,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.185", + "version": "1.0.186", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -218,7 +218,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.185", + "version": "1.0.186", "bin": { "opencode": "./bin/opencode", }, @@ -310,7 +310,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.185", + "version": "1.0.186", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -330,7 +330,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.185", + "version": "1.0.186", "devDependencies": { "@hey-api/openapi-ts": "0.88.1", "@tsconfig/node22": "catalog:", @@ -341,7 +341,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.185", + "version": "1.0.186", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -354,7 +354,7 @@ }, "packages/tauri": { "name": "@opencode-ai/tauri", - "version": "1.0.185", + "version": "1.0.186", "dependencies": { "@opencode-ai/desktop": "workspace:*", "@solid-primitives/storage": "catalog:", @@ -381,7 +381,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.185", + "version": "1.0.186", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -416,7 +416,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.0.185", + "version": "1.0.186", "dependencies": { "zod": "catalog:", }, @@ -427,7 +427,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.185", + "version": "1.0.186", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 61eb151f8..2fe98264a 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.0.185", + "version": "1.0.186", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 0cf83ecd2..e1971f3ef 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.0.185", + "version": "1.0.186", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 1a12d6b06..8c9daf340 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.185", + "version": "1.0.186", "$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 2f04a292e..2ce541a3b 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.185", + "version": "1.0.186", "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 ef776b72f..5f38ac60d 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.185", + "version": "1.0.186", "description": "", "type": "module", "exports": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index 72848ffb9..602788abb 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.0.185", + "version": "1.0.186", "private": true, "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index 8475c3788..8d0141d7b 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.0.185" +version = "1.0.186" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/sst/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.185/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.186/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.185/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.186/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.185/opencode-linux-arm64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.186/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.185/opencode-linux-x64.tar.gz" +archive = "https://github.com/sst/opencode/releases/download/v1.0.186/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.185/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.186/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index a8fd285eb..593499d28 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.185", + "version": "1.0.186", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index b9f8891a0..dfba43513 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.185", + "version": "1.0.186", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 0b1ba7886..fd3fd9f51 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.0.185", + "version": "1.0.186", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} +} \ No newline at end of file diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 2ad892d9a..1751488b1 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.0.185", + "version": "1.0.186", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -29,4 +29,4 @@ "publishConfig": { "directory": "dist" } -} +} \ No newline at end of file diff --git a/packages/slack/package.json b/packages/slack/package.json index b9259ae62..1d85ced4e 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.185", + "version": "1.0.186", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/tauri/package.json b/packages/tauri/package.json index f198e87f5..ff068c65a 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/tauri", "private": true, - "version": "1.0.185", + "version": "1.0.186", "type": "module", "scripts": { "typecheck": "tsgo -b", diff --git a/packages/ui/package.json b/packages/ui/package.json index ab5a8d575..f1fd5b9d8 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.185", + "version": "1.0.186", "type": "module", "exports": { "./*": "./src/components/*.tsx", diff --git a/packages/util/package.json b/packages/util/package.json index cfd59f974..f2fb03145 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.0.185", + "version": "1.0.186", "private": true, "type": "module", "exports": { diff --git a/packages/web/package.json b/packages/web/package.json index e4393f630..9b2609dec 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.185", + "version": "1.0.186", "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 9a3bc2af5..be3139886 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.0.185", + "version": "1.0.186", "publisher": "sst-dev", "repository": { "type": "git", From 60db171b44193041348bfc00623c7a56e645a0d4 Mon Sep 17 00:00:00 2001 From: Buck Evan Date: Mon, 22 Dec 2025 08:37:43 -0600 Subject: [PATCH 100/112] fix(read): narrow .env file blocking to not block .envrc (#5654) Co-authored-by: Claude --- packages/opencode/src/tool/read.ts | 8 +++-- packages/opencode/test/tool/read.test.ts | 42 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 packages/opencode/test/tool/read.test.ts diff --git a/packages/opencode/src/tool/read.ts b/packages/opencode/src/tool/read.ts index 27426ad24..fd81c4864 100644 --- a/packages/opencode/src/tool/read.ts +++ b/packages/opencode/src/tool/read.ts @@ -60,10 +60,12 @@ export const ReadTool = Tool.define("read", { } const block = iife(() => { - const whitelist = [".env.sample", ".example"] + const basename = path.basename(filepath) + const whitelist = [".env.sample", ".env.example", ".example", ".env.template"] - if (whitelist.some((w) => filepath.endsWith(w))) return false - if (filepath.includes(".env")) return true + if (whitelist.some((w) => basename.endsWith(w))) return false + // Block .env, .env.local, .env.production, etc. but not .envrc + if (/^\.env(\.|$)/.test(basename)) return true return false }) diff --git a/packages/opencode/test/tool/read.test.ts b/packages/opencode/test/tool/read.test.ts new file mode 100644 index 000000000..47a7aee2a --- /dev/null +++ b/packages/opencode/test/tool/read.test.ts @@ -0,0 +1,42 @@ +import { describe, expect, test } from "bun:test" +import path from "path" +import { ReadTool } from "../../src/tool/read" +import { Instance } from "../../src/project/instance" +import { tmpdir } from "../fixture/fixture" + +const ctx = { + sessionID: "test", + messageID: "", + callID: "", + agent: "build", + abort: AbortSignal.any([]), + metadata: () => {}, +} + +describe("tool.read env file blocking", () => { + test.each([ + [".env", true], + [".env.local", true], + [".env.production", true], + [".env.sample", false], + [".env.example", false], + [".envrc", false], + ["environment.ts", false], + ])("%s blocked=%s", async (filename, blocked) => { + await using tmp = await tmpdir({ + init: (dir) => Bun.write(path.join(dir, filename), "content"), + }) + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const read = await ReadTool.init() + const promise = read.execute({ filePath: path.join(tmp.path, filename) }, ctx) + if (blocked) { + await expect(promise).rejects.toThrow("blocked") + } else { + expect((await promise).output).toContain("content") + } + }, + }) + }) +}) From dab2e54df846e6867df188437010f056afb0c1e3 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Mon, 22 Dec 2025 14:38:20 +0000 Subject: [PATCH 101/112] chore: generate --- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/package.json b/packages/plugin/package.json index fd3fd9f51..9da158f1d 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} \ No newline at end of file +} diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 1751488b1..81498a60f 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -29,4 +29,4 @@ "publishConfig": { "directory": "dist" } -} \ No newline at end of file +} From 33c0b125cb2c915a50311246cc1179271763b0b8 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Mon, 22 Dec 2025 10:45:51 -0500 Subject: [PATCH 102/112] fix url for web --- packages/desktop/src/app.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/desktop/src/app.tsx b/packages/desktop/src/app.tsx index 2ed529bbc..9d000b8ff 100644 --- a/packages/desktop/src/app.tsx +++ b/packages/desktop/src/app.tsx @@ -21,6 +21,7 @@ import Home from "@/pages/home" import DirectoryLayout from "@/pages/directory-layout" import Session from "@/pages/session" import { ErrorPage } from "./pages/error" +import { iife } from "@opencode-ai/util/iife" declare global { interface Window { @@ -28,14 +29,17 @@ declare global { } } -const host = import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "127.0.0.1" -const port = window.__OPENCODE__?.port ?? import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096" +const url = iife(() => { + const param = new URLSearchParams(document.location.search).get("url") + if (param) return param -const url = - new URLSearchParams(document.location.search).get("url") || - (location.hostname.includes("opencode.ai") || location.hostname.includes("localhost") - ? `http://${host}:${port}` - : "/") + if (location.hostname.includes("opencode.ai")) return "http://localhost:4096" + if (window.__OPENCODE__) return `http://127.0.0.1:${window.__OPENCODE__.port}` + if (import.meta.env.VITE_OPENCODE_SERVER) + return `http://${import.meta.env.VITE_OPENCODE_SERVER_HOST}:${import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"}` + + return "/" +}) export function App() { return ( From 8e01f6cc135c7db73f8474c884fbff34b60bdd5c Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Mon, 22 Dec 2025 09:51:17 -0600 Subject: [PATCH 103/112] fix(desktop): diff readability (colors) --- packages/ui/src/pierre/index.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/packages/ui/src/pierre/index.ts b/packages/ui/src/pierre/index.ts index f83fc82a2..824d96b11 100644 --- a/packages/ui/src/pierre/index.ts +++ b/packages/ui/src/pierre/index.ts @@ -10,6 +10,31 @@ export type DiffProps = FileDiffOptions & { } const unsafeCSS = ` +[data-diffs] { + --diffs-bg: light-dark(var(--diffs-light-bg), var(--diffs-dark-bg)); + --diffs-bg-buffer: var(--diffs-bg-buffer-override, light-dark( color-mix(in lab, var(--diffs-bg) 92%, var(--diffs-mixer)), color-mix(in lab, var(--diffs-bg) 92%, var(--diffs-mixer)))); + --diffs-bg-hover: var(--diffs-bg-hover-override, light-dark( color-mix(in lab, var(--diffs-bg) 97%, var(--diffs-mixer)), color-mix(in lab, var(--diffs-bg) 91%, var(--diffs-mixer)))); + --diffs-bg-context: var(--diffs-bg-context-override, light-dark( color-mix(in lab, var(--diffs-bg) 98.5%, var(--diffs-mixer)), color-mix(in lab, var(--diffs-bg) 92.5%, var(--diffs-mixer)))); + --diffs-bg-separator: var(--diffs-bg-separator-override, light-dark( color-mix(in lab, var(--diffs-bg) 96%, var(--diffs-mixer)), color-mix(in lab, var(--diffs-bg) 85%, var(--diffs-mixer)))); + --diffs-fg: light-dark(var(--diffs-light), var(--diffs-dark)); + --diffs-fg-number: var(--diffs-fg-number-override, light-dark(color-mix(in lab, var(--diffs-fg) 65%, var(--diffs-bg)), color-mix(in lab, var(--diffs-fg) 65%, var(--diffs-bg)))); + --diffs-deletion-base: var(--diffs-deletion-color-override, light-dark(var(--diffs-light-deletion-color, var(--diffs-deletion-color, rgb(255, 0, 0))), var(--diffs-dark-deletion-color, var(--diffs-deletion-color, rgb(255, 0, 0))))); + --diffs-addition-base: var(--diffs-addition-color-override, light-dark(var(--diffs-light-addition-color, var(--diffs-addition-color, rgb(0, 255, 0))), var(--diffs-dark-addition-color, var(--diffs-addition-color, rgb(0, 255, 0))))); + --diffs-modified-base: var(--diffs-modified-color-override, light-dark(var(--diffs-light-modified-color, var(--diffs-modified-color, rgb(0, 0, 255))), var(--diffs-dark-modified-color, var(--diffs-modified-color, rgb(0, 0, 255))))); + --diffs-bg-deletion: var(--diffs-bg-deletion-override, light-dark( color-mix(in lab, var(--diffs-bg) 98%, var(--diffs-deletion-base)), color-mix(in lab, var(--diffs-bg) 92%, var(--diffs-deletion-base)))); + --diffs-bg-deletion-number: var(--diffs-bg-deletion-number-override, light-dark( color-mix(in lab, var(--diffs-bg) 91%, var(--diffs-deletion-base)), color-mix(in lab, var(--diffs-bg) 85%, var(--diffs-deletion-base)))); + --diffs-bg-deletion-hover: var(--diffs-bg-deletion-hover-override, light-dark( color-mix(in lab, var(--diffs-bg) 80%, var(--diffs-deletion-base)), color-mix(in lab, var(--diffs-bg) 75%, var(--diffs-deletion-base)))); + --diffs-bg-deletion-emphasis: var(--diffs-bg-deletion-emphasis-override, light-dark(rgb(from var(--diffs-deletion-base) r g b / 0.7), rgb(from var(--diffs-deletion-base) r g b / 0.1))); + --diffs-bg-addition: var(--diffs-bg-addition-override, light-dark( color-mix(in lab, var(--diffs-bg) 98%, var(--diffs-addition-base)), color-mix(in lab, var(--diffs-bg) 92%, var(--diffs-addition-base)))); + --diffs-bg-addition-number: var(--diffs-bg-addition-number-override, light-dark( color-mix(in lab, var(--diffs-bg) 91%, var(--diffs-addition-base)), color-mix(in lab, var(--diffs-bg) 85%, var(--diffs-addition-base)))); + --diffs-bg-addition-hover: var(--diffs-bg-addition-hover-override, light-dark( color-mix(in lab, var(--diffs-bg) 80%, var(--diffs-addition-base)), color-mix(in lab, var(--diffs-bg) 70%, var(--diffs-addition-base)))); + --diffs-bg-addition-emphasis: var(--diffs-bg-addition-emphasis-override, light-dark(rgb(from var(--diffs-addition-base) r g b / 0.07), rgb(from var(--diffs-addition-base) r g b / 0.1))); + --diffs-selection-base: var(--diffs-modified-base); + --diffs-selection-number-fg: light-dark( color-mix(in lab, var(--diffs-selection-base) 65%, var(--diffs-mixer)), color-mix(in lab, var(--diffs-selection-base) 75%, var(--diffs-mixer))); + --diffs-bg-selection: var(--diffs-bg-selection-override, light-dark( color-mix(in lab, var(--diffs-bg) 82%, var(--diffs-selection-base)), color-mix(in lab, var(--diffs-bg) 75%, var(--diffs-selection-base)))); + --diffs-bg-selection-number: var(--diffs-bg-selection-number-override, light-dark( color-mix(in lab, var(--diffs-bg) 75%, var(--diffs-selection-base)), color-mix(in lab, var(--diffs-bg) 60%, var(--diffs-selection-base)))); +} + [data-diffs-header], [data-diffs] { [data-separator-wrapper] { From 753abbe164e2be8a84eb424d56444380f59f6b92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lek=C3=AB=20Dobruna?= Date: Mon, 22 Dec 2025 16:56:32 +0100 Subject: [PATCH 104/112] fix: duplicate words in dialog options (#5944) --- .../opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx | 2 +- .../opencode/src/cli/cmd/tui/routes/session/dialog-subagent.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx index 86317d62a..ff17b5567 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx @@ -54,7 +54,7 @@ export function DialogMessage(props: { { title: "Copy", value: "message.copy", - description: "copy message text to clipboard", + description: "message text to clipboard", onSelect: async (dialog) => { const msg = message() if (!msg) return diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-subagent.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-subagent.tsx index a9446b20d..c5ef70ef0 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-subagent.tsx @@ -11,7 +11,7 @@ export function DialogSubagent(props: { sessionID: string }) { { title: "Open", value: "subagent.view", - description: "open the subagent's session", + description: "the subagent's session", onSelect: (dialog) => { route.navigate({ type: "session", From 29c99ed4abfce2f1fef06dc55be0b575436e028d Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Mon, 22 Dec 2025 09:55:38 -0600 Subject: [PATCH 105/112] ci: limit to opencode repo --- .github/workflows/docs-update.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs-update.yml b/.github/workflows/docs-update.yml index bdb3e43b8..aa48c14ad 100644 --- a/.github/workflows/docs-update.yml +++ b/.github/workflows/docs-update.yml @@ -8,7 +8,8 @@ on: jobs: update-docs: - runs-on: ubuntu-latest + if: github.repository == 'sst/opencode' + runs-on: blacksmith-4vcpu-ubuntu-2404 permissions: id-token: write contents: write @@ -19,6 +20,9 @@ jobs: with: fetch-depth: 0 # Fetch full history to access commits + - name: Setup Bun + uses: ./.github/actions/setup-bun + - name: Get recent commits id: commits run: | From 4a32fa6f0231f581d7f6dfcf3bede4286874df65 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Mon, 22 Dec 2025 10:13:50 -0600 Subject: [PATCH 106/112] fix(share): expanded state and responsiveness --- .../enterprise/src/routes/share/[shareID].tsx | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/packages/enterprise/src/routes/share/[shareID].tsx b/packages/enterprise/src/routes/share/[shareID].tsx index a8b2c7f24..471104d79 100644 --- a/packages/enterprise/src/routes/share/[shareID].tsx +++ b/packages/enterprise/src/routes/share/[shareID].tsx @@ -212,6 +212,7 @@ export default function () { {iife(() => { const [store, setStore] = createStore({ messageId: undefined as string | undefined, + expandedSteps: {} as Record, }) const messages = createMemo(() => data().sessionID @@ -253,20 +254,22 @@ export default function () { const title = () => (
-
-
+
+
v{info().version}
-
- -
{model()?.name ?? modelID()}
-
-
- {DateTime.fromMillis(info().time.created).toFormat("dd MMM yyyy, HH:mm")} +
+
+ +
{model()?.name ?? modelID()}
+
+
+ {DateTime.fromMillis(info().time.created).toFormat("dd MMM yyyy, HH:mm")} +
{info().title}
@@ -282,6 +285,8 @@ export default function () { setStore("expandedSteps", message.id, (v) => !v)} classes={{ root: "min-w-0 w-full relative", content: @@ -359,6 +364,13 @@ export default function () { { + const id = store.messageId ?? firstUserMessage()!.id! + setStore("expandedSteps", id, (v) => !v) + }} classes={{ root: "grow", content: "flex flex-col justify-between", From 0545c5da2d02c14249c7a6fce04b85e237e6fd00 Mon Sep 17 00:00:00 2001 From: Daniel Polito Date: Mon, 22 Dec 2025 13:59:02 -0300 Subject: [PATCH 107/112] GitHub pull request event (#5335) --- packages/opencode/src/cli/cmd/github.ts | 101 ++++++++++++++++-------- 1 file changed, 67 insertions(+), 34 deletions(-) diff --git a/packages/opencode/src/cli/cmd/github.ts b/packages/opencode/src/cli/cmd/github.ts index 7234cb12f..607fc7caf 100644 --- a/packages/opencode/src/cli/cmd/github.ts +++ b/packages/opencode/src/cli/cmd/github.ts @@ -7,7 +7,7 @@ import { graphql } from "@octokit/graphql" import * as core from "@actions/core" import * as github from "@actions/github" import type { Context } from "@actions/github/lib/context" -import type { IssueCommentEvent, PullRequestReviewCommentEvent } from "@octokit/webhooks-types" +import type { IssueCommentEvent, PullRequestReviewCommentEvent, PullRequestEvent } from "@octokit/webhooks-types" import { UI } from "../ui" import { cmd } from "./cmd" import { ModelsDev } from "../../provider/models" @@ -127,7 +127,7 @@ type IssueQueryResponse = { const AGENT_USERNAME = "opencode-agent[bot]" const AGENT_REACTION = "eyes" const WORKFLOW_FILE = ".github/workflows/opencode.yml" -const SUPPORTED_EVENTS = ["issue_comment", "pull_request_review_comment", "schedule"] as const +const SUPPORTED_EVENTS = ["issue_comment", "pull_request_review_comment", "schedule", "pull_request"] as const // Parses GitHub remote URLs in various formats: // - https://github.com/owner/repo.git @@ -392,6 +392,7 @@ export const GithubRunCommand = cmd({ core.setFailed(`Unsupported event type: ${context.eventName}`) process.exit(1) } + const isCommentEvent = ["issue_comment", "pull_request_review_comment"].includes(context.eventName) const isScheduleEvent = context.eventName === "schedule" const { providerID, modelID } = normalizeModel() @@ -400,17 +401,17 @@ export const GithubRunCommand = cmd({ const oidcBaseUrl = normalizeOidcBaseUrl() const { owner, repo } = context.repo // For schedule events, payload has no issue/comment data - const payload = isScheduleEvent - ? undefined - : (context.payload as IssueCommentEvent | PullRequestReviewCommentEvent) + const payload = isCommentEvent + ? (context.payload as IssueCommentEvent | PullRequestReviewCommentEvent) + : undefined const issueEvent = payload && isIssueCommentEvent(payload) ? payload : undefined const actor = isScheduleEvent ? undefined : context.actor const issueId = isScheduleEvent ? undefined - : context.eventName === "pull_request_review_comment" - ? (payload as PullRequestReviewCommentEvent).pull_request.number - : (payload as IssueCommentEvent).issue.number + : context.eventName === "issue_comment" + ? (payload as IssueCommentEvent).issue.number + : (payload as PullRequestEvent | PullRequestReviewCommentEvent).pull_request.number const runUrl = `/${owner}/${repo}/actions/runs/${runId}` const shareBaseUrl = isMock ? "https://dev.opencode.ai" : "https://opencode.ai" @@ -424,11 +425,11 @@ export const GithubRunCommand = cmd({ type PromptFiles = Awaited>["promptFiles"] const triggerCommentId = payload?.comment.id const useGithubToken = normalizeUseGithubToken() - const commentType = isScheduleEvent - ? undefined - : context.eventName === "pull_request_review_comment" + const commentType = isCommentEvent + ? context.eventName === "pull_request_review_comment" ? "pr_review" : "issue" + : undefined try { if (useGithubToken) { @@ -455,7 +456,7 @@ export const GithubRunCommand = cmd({ // Skip permission check for schedule events (no actor to check) if (!isScheduleEvent) { await assertPermissions() - await addReaction(commentType!) + await addReaction(commentType) } // Setup opencode session @@ -494,7 +495,10 @@ export const GithubRunCommand = cmd({ } else { console.log("Response:", response) } - } else if (context.eventName === "pull_request_review_comment" || issueEvent?.issue.pull_request) { + } else if ( + ["pull_request", "pull_request_review_comment"].includes(context.eventName) || + issueEvent?.issue.pull_request + ) { const prData = await fetchPR() // Local PR if (prData.headRepository.nameWithOwner === prData.baseRepository.nameWithOwner) { @@ -509,7 +513,7 @@ export const GithubRunCommand = cmd({ } const hasShared = prData.comments.nodes.some((c) => c.body.includes(`${shareBaseUrl}/s/${shareId}`)) await createComment(`${response}${footer({ image: !hasShared })}`) - await removeReaction(commentType!) + await removeReaction(commentType) } // Fork PR else { @@ -524,7 +528,7 @@ export const GithubRunCommand = cmd({ } const hasShared = prData.comments.nodes.some((c) => c.body.includes(`${shareBaseUrl}/s/${shareId}`)) await createComment(`${response}${footer({ image: !hasShared })}`) - await removeReaction(commentType!) + await removeReaction(commentType) } } // Issue @@ -545,10 +549,10 @@ export const GithubRunCommand = cmd({ `${response}\n\nCloses #${issueId}${footer({ image: true })}`, ) await createComment(`Created PR #${pr}${footer({ image: true })}`) - await removeReaction(commentType!) + await removeReaction(commentType) } else { await createComment(`${response}${footer({ image: true })}`) - await removeReaction(commentType!) + await removeReaction(commentType) } } } catch (e: any) { @@ -562,7 +566,7 @@ export const GithubRunCommand = cmd({ } if (!isScheduleEvent) { await createComment(`${msg}${footer()}`) - await removeReaction(commentType!) + await removeReaction(commentType) } core.setFailed(msg) // Also output the clean error message for the action to capture @@ -657,6 +661,9 @@ export const GithubRunCommand = cmd({ .map((m) => m.trim().toLowerCase()) .filter(Boolean) let prompt = (() => { + if (!isCommentEvent) { + return "Review this pull request" + } const body = payload!.comment.body.trim() const bodyLower = body.toLowerCase() if (mentions.some((m) => bodyLower === m)) { @@ -1030,30 +1037,57 @@ Co-authored-by: ${actor} <${actor}@users.noreply.github.com>"` if (!["admin", "write"].includes(permission)) throw new Error(`User ${actor} does not have write permissions`) } - async function addReaction(commentType: "issue" | "pr_review") { + async function addReaction(commentType?: "issue" | "pr_review") { // Only called for non-schedule events, so triggerCommentId is defined console.log("Adding reaction...") - if (commentType === "pr_review") { - return await octoRest.rest.reactions.createForPullRequestReviewComment({ + if (triggerCommentId) { + if (commentType === "pr_review") { + return await octoRest.rest.reactions.createForPullRequestReviewComment({ + owner, + repo, + comment_id: triggerCommentId!, + content: AGENT_REACTION, + }) + } + return await octoRest.rest.reactions.createForIssueComment({ owner, repo, comment_id: triggerCommentId!, content: AGENT_REACTION, }) } - return await octoRest.rest.reactions.createForIssueComment({ + return await octoRest.rest.reactions.createForIssue({ owner, repo, - comment_id: triggerCommentId!, + issue_number: issueId!, content: AGENT_REACTION, }) } - async function removeReaction(commentType: "issue" | "pr_review") { + async function removeReaction(commentType?: "issue" | "pr_review") { // Only called for non-schedule events, so triggerCommentId is defined console.log("Removing reaction...") - if (commentType === "pr_review") { - const reactions = await octoRest.rest.reactions.listForPullRequestReviewComment({ + if (triggerCommentId) { + if (commentType === "pr_review") { + const reactions = await octoRest.rest.reactions.listForPullRequestReviewComment({ + owner, + repo, + comment_id: triggerCommentId!, + content: AGENT_REACTION, + }) + + const eyesReaction = reactions.data.find((r) => r.user?.login === AGENT_USERNAME) + if (!eyesReaction) return + + return await octoRest.rest.reactions.deleteForPullRequestComment({ + owner, + repo, + comment_id: triggerCommentId!, + reaction_id: eyesReaction.id, + }) + } + + const reactions = await octoRest.rest.reactions.listForIssueComment({ owner, repo, comment_id: triggerCommentId!, @@ -1063,29 +1097,28 @@ Co-authored-by: ${actor} <${actor}@users.noreply.github.com>"` const eyesReaction = reactions.data.find((r) => r.user?.login === AGENT_USERNAME) if (!eyesReaction) return - await octoRest.rest.reactions.deleteForPullRequestComment({ + return await octoRest.rest.reactions.deleteForIssueComment({ owner, repo, comment_id: triggerCommentId!, reaction_id: eyesReaction.id, }) - return } - const reactions = await octoRest.rest.reactions.listForIssueComment({ + const reactions = await octoRest.rest.reactions.listForIssue({ owner, repo, - comment_id: triggerCommentId!, + issue_number: issueId!, content: AGENT_REACTION, }) const eyesReaction = reactions.data.find((r) => r.user?.login === AGENT_USERNAME) if (!eyesReaction) return - await octoRest.rest.reactions.deleteForIssueComment({ + await octoRest.rest.reactions.deleteForIssue({ owner, repo, - comment_id: triggerCommentId!, + issue_number: issueId!, reaction_id: eyesReaction.id, }) } @@ -1178,7 +1211,7 @@ query($owner: String!, $repo: String!, $number: Int!) { const comments = (issue.comments?.nodes || []) .filter((c) => { const id = parseInt(c.databaseId) - return id !== payload!.comment.id + return id !== triggerCommentId }) .map((c) => ` - ${c.author.login} at ${c.createdAt}: ${c.body}`) @@ -1306,7 +1339,7 @@ query($owner: String!, $repo: String!, $number: Int!) { const comments = (pr.comments?.nodes || []) .filter((c) => { const id = parseInt(c.databaseId) - return id !== payload!.comment.id + return id !== triggerCommentId }) .map((c) => `- ${c.author.login} at ${c.createdAt}: ${c.body}`) From 3f0afd7cf6438c37213d16c178d082a0146bb693 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Mon, 22 Dec 2025 11:00:32 -0600 Subject: [PATCH 108/112] ci: tweak docs prompt --- .github/workflows/docs-update.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs-update.yml b/.github/workflows/docs-update.yml index aa48c14ad..559e74176 100644 --- a/.github/workflows/docs-update.yml +++ b/.github/workflows/docs-update.yml @@ -66,4 +66,5 @@ jobs: 4. If you are creating a new documentation file be sure to update packages/web/astro.config.mjs too. Focus on user-facing features and API changes. Skip internal refactors, bug fixes, and test updates unless they affect user-facing behavior. - All doc related commits should start with "docs:" prefix. + Don't feel the need to document every little thing. It is perfectly okay to make 0 changes at all. + Try to keep documentation only for large features or changes that already have a good spot to be documented. From af214d35cb24fe20d4f967f07b639c7de39c830c Mon Sep 17 00:00:00 2001 From: Will Marella <162729147+will-marella@users.noreply.github.com> Date: Mon, 22 Dec 2025 12:06:00 -0500 Subject: [PATCH 109/112] Add keybindable commands to navigate between user messages (#5078) Co-authored-by: Will@Cambridge Co-authored-by: Will@Cambridge --- .../src/cli/cmd/tui/routes/session/index.tsx | 62 +++++++++++++++++++ packages/opencode/src/config/config.ts | 2 + packages/sdk/js/src/gen/types.gen.ts | 8 +++ packages/web/src/content/docs/keybinds.mdx | 2 + 4 files changed, 74 insertions(+) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index 4ad4dc0ca..3b1c58966 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -201,6 +201,52 @@ export function Session() { let prompt: PromptRef const keybind = useKeybind() + // Helper: Find next visible message boundary in direction + const findNextVisibleMessage = (direction: "next" | "prev"): string | null => { + const children = scroll.getChildren() + const messagesList = messages() + const scrollTop = scroll.y + + // Get visible messages sorted by position, filtering for valid non-synthetic, non-ignored content + const visibleMessages = children + .filter((c) => { + if (!c.id) return false + const message = messagesList.find((m) => m.id === c.id) + if (!message) return false + + // Check if message has valid non-synthetic, non-ignored text parts + const parts = sync.data.part[message.id] + if (!parts || !Array.isArray(parts)) return false + + return parts.some((part) => part && part.type === "text" && !part.synthetic && !part.ignored) + }) + .sort((a, b) => a.y - b.y) + + if (visibleMessages.length === 0) return null + + if (direction === "next") { + // Find first message below current position + return visibleMessages.find((c) => c.y > scrollTop + 10)?.id ?? null + } + // Find last message above current position + return [...visibleMessages].reverse().find((c) => c.y < scrollTop - 10)?.id ?? null + } + + // Helper: Scroll to message in direction or fallback to page scroll + const scrollToMessage = (direction: "next" | "prev", dialog: ReturnType) => { + const targetID = findNextVisibleMessage(direction) + + if (!targetID) { + scroll.scrollBy(direction === "next" ? scroll.height : -scroll.height) + dialog.clear() + return + } + + const child = scroll.getChildren().find((c) => c.id === targetID) + if (child) scroll.scrollBy(child.y - scroll.y - 1) + dialog.clear() + } + useKeyboard((evt) => { if (dialog.stack.length > 0) return @@ -634,6 +680,22 @@ export function Session() { } }, }, + { + title: "Next message", + value: "session.message.next", + keybind: "messages_next", + category: "Session", + disabled: true, + onSelect: (dialog) => scrollToMessage("next", dialog), + }, + { + title: "Previous message", + value: "session.message.previous", + keybind: "messages_previous", + category: "Session", + disabled: true, + onSelect: (dialog) => scrollToMessage("prev", dialog), + }, { title: "Copy last assistant message", value: "messages.copy", diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 031bdd31b..daf81f434 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -456,6 +456,8 @@ export namespace Config { .describe("Scroll messages down by half page"), messages_first: z.string().optional().default("ctrl+g,home").describe("Navigate to first message"), messages_last: z.string().optional().default("ctrl+alt+g,end").describe("Navigate to last message"), + messages_next: z.string().optional().default("none").describe("Navigate to next message"), + messages_previous: z.string().optional().default("none").describe("Navigate to previous message"), messages_last_user: z.string().optional().default("none").describe("Navigate to last user message"), messages_copy: z.string().optional().default("y").describe("Copy message"), messages_undo: z.string().optional().default("u").describe("Undo message"), diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts index 964112d81..06993d3f9 100644 --- a/packages/sdk/js/src/gen/types.gen.ts +++ b/packages/sdk/js/src/gen/types.gen.ts @@ -858,6 +858,14 @@ export type KeybindsConfig = { * Navigate to last message */ messages_last?: string + /** + * Navigate to next message + */ + messages_next?: string + /** + * Navigate to previous message + */ + messages_previous?: string /** * Navigate to last user message */ diff --git a/packages/web/src/content/docs/keybinds.mdx b/packages/web/src/content/docs/keybinds.mdx index 35610af51..b7e370825 100644 --- a/packages/web/src/content/docs/keybinds.mdx +++ b/packages/web/src/content/docs/keybinds.mdx @@ -32,6 +32,8 @@ OpenCode has a list of keybinds that you can customize through the OpenCode conf "messages_half_page_down": "ctrl+alt+d", "messages_first": "ctrl+g,home", "messages_last": "ctrl+alt+g,end", + "messages_next": "none", + "messages_previous": "none", "messages_copy": "y", "messages_undo": "u", "messages_redo": "r", From 90f232d7f15a8bf09ebeed24297ceb5f4ea4dbad Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Mon, 22 Dec 2025 17:06:35 +0000 Subject: [PATCH 110/112] chore: generate --- packages/sdk/js/src/v2/gen/types.gen.ts | 8 ++++++++ packages/sdk/openapi.json | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index f7c0e88a5..e3249848c 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -890,6 +890,14 @@ export type KeybindsConfig = { * Navigate to last message */ messages_last?: string + /** + * Navigate to next message + */ + messages_next?: string + /** + * Navigate to previous message + */ + messages_previous?: string /** * Navigate to last user message */ diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index 12699ee2b..a1576668a 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -7308,6 +7308,16 @@ "default": "ctrl+alt+g,end", "type": "string" }, + "messages_next": { + "description": "Navigate to next message", + "default": "none", + "type": "string" + }, + "messages_previous": { + "description": "Navigate to previous message", + "default": "none", + "type": "string" + }, "messages_last_user": { "description": "Navigate to last user message", "default": "none", From 291b65977c0de428f86886acd05f79c46051be90 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Mon, 22 Dec 2025 11:27:23 -0600 Subject: [PATCH 111/112] chore(desktop): auto scroll utility --- packages/desktop/src/pages/session.tsx | 94 ++---------- packages/ui/src/components/message-part.tsx | 11 +- .../src/components/session-message-rail.css | 2 +- packages/ui/src/components/session-turn.tsx | 125 ++-------------- packages/ui/src/hooks/create-auto-scroll.tsx | 135 ++++++++++++++++++ packages/ui/src/hooks/index.ts | 1 + 6 files changed, 170 insertions(+), 198 deletions(-) create mode 100644 packages/ui/src/hooks/create-auto-scroll.tsx diff --git a/packages/desktop/src/pages/session.tsx b/packages/desktop/src/pages/session.tsx index 1f38da3c7..b6f5ccca1 100644 --- a/packages/desktop/src/pages/session.tsx +++ b/packages/desktop/src/pages/session.tsx @@ -12,7 +12,7 @@ import { createRenderEffect, batch, } from "solid-js" -import { createResizeObserver } from "@solid-primitives/resize-observer" + import { Dynamic } from "solid-js/web" import { useLocal, type LocalFile } from "@/context/local" import { createStore } from "solid-js/store" @@ -27,6 +27,7 @@ import { ResizeHandle } from "@opencode-ai/ui/resize-handle" import { Tabs } from "@opencode-ai/ui/tabs" import { useCodeComponent } from "@opencode-ai/ui/context/code" import { SessionTurn } from "@opencode-ai/ui/session-turn" +import { createAutoScroll } from "@opencode-ai/ui/hooks" import { SessionMessageRail } from "@opencode-ai/ui/session-message-rail" import { SessionReview } from "@opencode-ai/ui/session-review" import { @@ -93,13 +94,6 @@ export default function Page() { userInteracted: false, stepsExpanded: true, mobileStepsExpanded: {} as Record, - mobileLastScrollTop: 0, - mobileLastScrollHeight: 0, - mobileAutoScrolled: false, - mobileUserScrolled: false, - mobileContentRef: undefined as HTMLDivElement | undefined, - mobileLastContentWidth: 0, - mobileReflowing: false, messageId: undefined as string | undefined, }) @@ -541,90 +535,20 @@ export default function Page() { const showTabs = createMemo(() => diffs().length > 0 || tabs().all().length > 0) - let mobileScrollRef: HTMLDivElement | undefined const mobileWorking = createMemo(() => status().type !== "idle") - - function handleMobileScroll() { - if (!mobileScrollRef || store.mobileAutoScrolled) return - - const scrollTop = mobileScrollRef.scrollTop - const scrollHeight = mobileScrollRef.scrollHeight - - if (store.mobileReflowing) { - batch(() => { - setStore("mobileLastScrollTop", scrollTop) - setStore("mobileLastScrollHeight", scrollHeight) - }) - return - } - - const scrolledUp = scrollTop < store.mobileLastScrollTop - 50 - if (scrolledUp && mobileWorking()) { - setStore("mobileUserScrolled", true) - setStore("userInteracted", true) - } - - batch(() => { - setStore("mobileLastScrollTop", scrollTop) - setStore("mobileLastScrollHeight", scrollHeight) - }) - } - - function handleMobileInteraction() { - if (mobileWorking()) { - setStore("mobileUserScrolled", true) - setStore("userInteracted", true) - } - } - - function scrollMobileToBottom() { - if (!mobileScrollRef || store.mobileUserScrolled || !mobileWorking()) return - setStore("mobileAutoScrolled", true) - requestAnimationFrame(() => { - mobileScrollRef?.scrollTo({ top: mobileScrollRef.scrollHeight, behavior: "smooth" }) - requestAnimationFrame(() => { - batch(() => { - setStore("mobileLastScrollTop", mobileScrollRef?.scrollTop ?? 0) - setStore("mobileLastScrollHeight", mobileScrollRef?.scrollHeight ?? 0) - setStore("mobileAutoScrolled", false) - }) - }) - }) - } - - createEffect(() => { - if (!mobileWorking()) setStore("mobileUserScrolled", false) + const mobileAutoScroll = createAutoScroll({ + working: mobileWorking, + onUserInteracted: () => setStore("userInteracted", true), }) - createResizeObserver( - () => store.mobileContentRef, - ({ width }) => { - const widthChanged = Math.abs(width - store.mobileLastContentWidth) > 5 - if (widthChanged && store.mobileLastContentWidth > 0) { - setStore("mobileReflowing", true) - requestAnimationFrame(() => { - requestAnimationFrame(() => { - setStore("mobileReflowing", false) - if (mobileWorking() && !store.mobileUserScrolled) { - scrollMobileToBottom() - } - }) - }) - } else if (!store.mobileReflowing) { - scrollMobileToBottom() - } - setStore("mobileLastContentWidth", width) - }, - ) - const MobileTurns = () => (
-
setStore("mobileContentRef", el)} class="flex flex-col gap-45 items-start justify-start mt-4"> +
{(message) => ( tool: string output?: string + status?: string hideDetails?: boolean defaultOpen?: boolean } @@ -398,6 +400,7 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) { tool={part.tool} metadata={metadata} output={part.state.status === "completed" ? part.state.output : undefined} + status={part.state.status} hideDetails={props.hideDetails} defaultOpen={props.defaultOpen} /> @@ -561,6 +564,10 @@ ToolRegistry.register({ const summary = () => (props.metadata.summary ?? []) as { id: string; tool: string; state: { status: string; title?: string } }[] + const autoScroll = createAutoScroll({ + working: () => true, + }) + return ( -
-
+
+
{(item) => { const info = getToolInfo(item.tool) diff --git a/packages/ui/src/components/session-message-rail.css b/packages/ui/src/components/session-message-rail.css index dc2352c22..5729e4920 100644 --- a/packages/ui/src/components/session-message-rail.css +++ b/packages/ui/src/components/session-message-rail.css @@ -17,7 +17,7 @@ display: none; } -@container (min-width: 72rem) { +@container (min-width: 88rem) { [data-slot="session-message-rail-compact"] { display: none; } diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx index 71e6689f6..e49e70864 100644 --- a/packages/ui/src/components/session-turn.tsx +++ b/packages/ui/src/components/session-turn.tsx @@ -3,7 +3,7 @@ import { useData } from "../context" import { useDiffComponent } from "../context/diff" import { getDirectory, getFilename } from "@opencode-ai/util/path" import { checksum } from "@opencode-ai/util/encode" -import { batch, createEffect, createMemo, For, Match, onCleanup, ParentProps, Show, Switch } from "solid-js" +import { createEffect, createMemo, For, Match, onCleanup, ParentProps, Show, Switch } from "solid-js" import { createResizeObserver } from "@solid-primitives/resize-observer" import { DiffChanges } from "./diff-changes" import { Typewriter } from "./typewriter" @@ -19,6 +19,7 @@ import { Button } from "./button" import { Spinner } from "./spinner" import { createStore } from "solid-js/store" import { DateTime, DurationUnit, Interval } from "luxon" +import { createAutoScroll } from "../hooks" function computeStatusFromPart(part: PartType | undefined): string | undefined { if (!part) return undefined @@ -233,17 +234,14 @@ export function SessionTurn( }) } - let scrollRef: HTMLDivElement | undefined + const autoScroll = createAutoScroll({ + working, + onUserInteracted: props.onUserInteracted, + }) + const [store, setStore] = createStore({ - contentRef: undefined as HTMLDivElement | undefined, stickyTitleRef: undefined as HTMLDivElement | undefined, stickyTriggerRef: undefined as HTMLDivElement | undefined, - lastScrollTop: 0, - lastScrollHeight: 0, - lastContainerWidth: 0, - autoScrolled: false, - userScrolled: false, - reflowing: false, stickyHeaderHeight: 0, retrySeconds: 0, status: rawStatus(), @@ -265,104 +263,6 @@ export function SessionTurn( onCleanup(() => clearInterval(timer)) }) - function handleScroll() { - if (!scrollRef || store.autoScrolled) return - - const scrollTop = scrollRef.scrollTop - const scrollHeight = scrollRef.scrollHeight - - if (store.reflowing) { - batch(() => { - setStore("lastScrollTop", scrollTop) - setStore("lastScrollHeight", scrollHeight) - }) - return - } - - const scrollHeightChanged = Math.abs(scrollHeight - store.lastScrollHeight) > 10 - const scrollTopDelta = scrollTop - store.lastScrollTop - - if (scrollHeightChanged && scrollTopDelta < 0) { - const heightRatio = store.lastScrollHeight > 0 ? scrollHeight / store.lastScrollHeight : 1 - const expectedScrollTop = store.lastScrollTop * heightRatio - if (Math.abs(scrollTop - expectedScrollTop) < 100) { - batch(() => { - setStore("lastScrollTop", scrollTop) - setStore("lastScrollHeight", scrollHeight) - }) - return - } - } - - const reset = scrollTop <= 0 && store.lastScrollTop > 0 && working() && !store.userScrolled - if (reset) { - batch(() => { - setStore("lastScrollTop", scrollTop) - setStore("lastScrollHeight", scrollHeight) - }) - requestAnimationFrame(scrollToBottom) - return - } - - const scrolledUp = scrollTop < store.lastScrollTop - 50 && !scrollHeightChanged - if (scrolledUp && working()) { - setStore("userScrolled", true) - props.onUserInteracted?.() - } - - batch(() => { - setStore("lastScrollTop", scrollTop) - setStore("lastScrollHeight", scrollHeight) - }) - } - - function handleInteraction() { - if (working()) { - setStore("userScrolled", true) - props.onUserInteracted?.() - } - } - - function scrollToBottom() { - if (!scrollRef || store.userScrolled || !working()) return - setStore("autoScrolled", true) - requestAnimationFrame(() => { - scrollRef?.scrollTo({ top: scrollRef.scrollHeight, behavior: "smooth" }) - requestAnimationFrame(() => { - batch(() => { - setStore("lastScrollTop", scrollRef?.scrollTop ?? 0) - setStore("lastScrollHeight", scrollRef?.scrollHeight ?? 0) - setStore("autoScrolled", false) - }) - }) - }) - } - - createResizeObserver( - () => store.contentRef, - ({ width }) => { - const widthChanged = Math.abs(width - store.lastContainerWidth) > 5 - if (widthChanged && store.lastContainerWidth > 0) { - setStore("reflowing", true) - requestAnimationFrame(() => { - requestAnimationFrame(() => { - setStore("reflowing", false) - if (working() && !store.userScrolled) { - scrollToBottom() - } - }) - }) - } else if (!store.reflowing) { - scrollToBottom() - } - setStore("lastContainerWidth", width) - }, - ) - - createEffect(() => { - if (!working()) setStore("userScrolled", false) - }) - createResizeObserver( () => store.stickyTitleRef, ({ height }) => { @@ -412,12 +312,17 @@ export function SessionTurn( return (
-
-
+
+
{(msg) => (
setStore("contentRef", el)} + ref={autoScroll.contentRef} data-message={msg().id} data-slot="session-turn-message-container" class={props.classes?.container} diff --git a/packages/ui/src/hooks/create-auto-scroll.tsx b/packages/ui/src/hooks/create-auto-scroll.tsx new file mode 100644 index 000000000..d201fe36b --- /dev/null +++ b/packages/ui/src/hooks/create-auto-scroll.tsx @@ -0,0 +1,135 @@ +import { batch, createEffect } from "solid-js" +import { createStore } from "solid-js/store" +import { createResizeObserver } from "@solid-primitives/resize-observer" + +export interface AutoScrollOptions { + working: () => boolean + onUserInteracted?: () => void +} + +export function createAutoScroll(options: AutoScrollOptions) { + let scrollRef: HTMLElement | undefined + const [store, setStore] = createStore({ + contentRef: undefined as HTMLElement | undefined, + lastScrollTop: 0, + lastScrollHeight: 0, + lastContentWidth: 0, + autoScrolled: false, + userScrolled: false, + reflowing: false, + }) + + function scrollToBottom() { + if (!scrollRef || store.userScrolled || !options.working()) return + setStore("autoScrolled", true) + requestAnimationFrame(() => { + scrollRef?.scrollTo({ top: scrollRef.scrollHeight, behavior: "smooth" }) + requestAnimationFrame(() => { + batch(() => { + setStore("lastScrollTop", scrollRef?.scrollTop ?? 0) + setStore("lastScrollHeight", scrollRef?.scrollHeight ?? 0) + setStore("autoScrolled", false) + }) + }) + }) + } + + function handleScroll() { + if (!scrollRef || store.autoScrolled) return + + const scrollTop = scrollRef.scrollTop + const scrollHeight = scrollRef.scrollHeight + + if (store.reflowing) { + batch(() => { + setStore("lastScrollTop", scrollTop) + setStore("lastScrollHeight", scrollHeight) + }) + return + } + + const scrollHeightChanged = Math.abs(scrollHeight - store.lastScrollHeight) > 10 + const scrollTopDelta = scrollTop - store.lastScrollTop + + // Handle reflow-caused scroll position changes + if (scrollHeightChanged && scrollTopDelta < 0) { + const heightRatio = store.lastScrollHeight > 0 ? scrollHeight / store.lastScrollHeight : 1 + const expectedScrollTop = store.lastScrollTop * heightRatio + if (Math.abs(scrollTop - expectedScrollTop) < 100) { + batch(() => { + setStore("lastScrollTop", scrollTop) + setStore("lastScrollHeight", scrollHeight) + }) + return + } + } + + // Handle reset to top while working + const reset = scrollTop <= 0 && store.lastScrollTop > 0 && options.working() && !store.userScrolled + if (reset) { + batch(() => { + setStore("lastScrollTop", scrollTop) + setStore("lastScrollHeight", scrollHeight) + }) + requestAnimationFrame(scrollToBottom) + return + } + + // Detect intentional scroll up + const scrolledUp = scrollTop < store.lastScrollTop - 50 && !scrollHeightChanged + if (scrolledUp && options.working()) { + setStore("userScrolled", true) + options.onUserInteracted?.() + } + + batch(() => { + setStore("lastScrollTop", scrollTop) + setStore("lastScrollHeight", scrollHeight) + }) + } + + function handleInteraction() { + if (options.working()) { + setStore("userScrolled", true) + options.onUserInteracted?.() + } + } + + // Reset userScrolled when work completes + createEffect(() => { + if (!options.working()) setStore("userScrolled", false) + }) + + // Handle content resize + createResizeObserver( + () => store.contentRef, + ({ width }) => { + const widthChanged = Math.abs(width - store.lastContentWidth) > 5 + if (widthChanged && store.lastContentWidth > 0) { + setStore("reflowing", true) + requestAnimationFrame(() => { + requestAnimationFrame(() => { + setStore("reflowing", false) + if (options.working() && !store.userScrolled) { + scrollToBottom() + } + }) + }) + } else if (!store.reflowing) { + scrollToBottom() + } + setStore("lastContentWidth", width) + }, + ) + + return { + scrollRef: (el: HTMLElement | undefined) => { + scrollRef = el + }, + contentRef: (el: HTMLElement | undefined) => setStore("contentRef", el), + handleScroll, + handleInteraction, + scrollToBottom, + userScrolled: () => store.userScrolled, + } +} diff --git a/packages/ui/src/hooks/index.ts b/packages/ui/src/hooks/index.ts index 7eef78091..1c90a2e49 100644 --- a/packages/ui/src/hooks/index.ts +++ b/packages/ui/src/hooks/index.ts @@ -1 +1,2 @@ export * from "./use-filtered-list" +export * from "./create-auto-scroll" From 6baee0791f48bcf32eef1e199d0cadca57772b9b Mon Sep 17 00:00:00 2001 From: Daniel Polito Date: Mon, 22 Dec 2025 14:53:58 -0300 Subject: [PATCH 112/112] docs: Github Auto Pull Request Docs (#5974) --- packages/web/src/content/docs/github.mdx | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/packages/web/src/content/docs/github.mdx b/packages/web/src/content/docs/github.mdx index bd792f92f..25c3ce927 100644 --- a/packages/web/src/content/docs/github.mdx +++ b/packages/web/src/content/docs/github.mdx @@ -109,6 +109,7 @@ OpenCode can be triggered by the following GitHub events: | `issue_comment` | Comment on an issue or PR | Mention `/opencode` or `/oc` in your comment. OpenCode reads the issue/PR context and can create branches, open PRs, or reply with explanations. | | `pull_request_review_comment` | Comment on specific code lines in a PR | Mention `/opencode` or `/oc` while reviewing code. OpenCode receives file path, line numbers, and diff context for precise responses. | | `schedule` | Cron-based schedule | Run OpenCode on a schedule using the `prompt` input. Useful for automated code reviews, reports, or maintenance tasks. OpenCode can create issues or PRs as needed. | +| `pull_request` | PR opened or updated | Automatically trigger OpenCode when PRs are opened, synchronized, or reopened. Useful for automated reviews without needing to leave a comment. | ### Schedule Example @@ -150,6 +151,43 @@ For scheduled events, the `prompt` input is **required** since there's no commen --- +### Pull Request Example + +Automatically review PRs when they are opened or updated: + +```yaml title=".github/workflows/opencode-review.yml" +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v4 + - uses: sst/opencode/github@latest + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + model: anthropic/claude-sonnet-4-20250514 + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements +``` + +For `pull_request` events, if no `prompt` is provided, OpenCode defaults to reviewing the pull request. + +--- + ## Custom prompts Override the default prompt to customize OpenCode's behavior for your workflow.