From b19fd14f800c8a062d2c6f1766702a1e9a2c4cfe Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Wed, 12 Nov 2025 10:40:48 -0600 Subject: [PATCH 001/262] ignore: make issue button send opencode version too --- packages/opencode/src/cli/cmd/tui/app.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 377d497d7..ce509415a 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -488,6 +488,8 @@ function ErrorComponent(props: { error: Error; reset: () => void; onExit: () => ) } + issueURL.searchParams.set("opencode-version", Installation.VERSION) + const copyIssueURL = () => { Clipboard.copy(issueURL.toString()).then(() => { setCopied(true) From fd9d2db7554d0697df97200e804206335303ad1e Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Wed, 12 Nov 2025 10:52:20 -0600 Subject: [PATCH 002/262] ci: update zed sync --- script/sync-zed.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/script/sync-zed.ts b/script/sync-zed.ts index 8c9090303..2e4684b6b 100755 --- a/script/sync-zed.ts +++ b/script/sync-zed.ts @@ -7,7 +7,6 @@ import { join } from "path" const FORK_REPO = "sst/zed-extensions" const UPSTREAM_REPO = "zed-industries/extensions" const EXTENSION_NAME = "opencode" -const OPENCODE_REPO = "sst/opencode" async function main() { const version = process.argv[2] @@ -40,8 +39,8 @@ async function main() { process.chdir(workDir) // Configure git identity - await $`git config user.name "github-actions[bot]"` - await $`git config user.email "github-actions[bot]@users.noreply.github.com"` + await $`git config user.name "Dax"` + await $`git config user.email "mail@thdxr.com"` // Sync fork with upstream console.log(`🔄 Syncing fork with upstream...`) From c857cff585b8eee5d4ec993eed74847f2df1492e Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 12 Nov 2025 12:17:54 -0600 Subject: [PATCH 003/262] fix(desktop): double listing dir --- packages/desktop/src/components/prompt-input.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/desktop/src/components/prompt-input.tsx b/packages/desktop/src/components/prompt-input.tsx index c48572d76..b2022cf30 100644 --- a/packages/desktop/src/components/prompt-input.tsx +++ b/packages/desktop/src/components/prompt-input.tsx @@ -366,7 +366,9 @@ export const PromptInput: Component = (props) => { {getDirectory(i)} - {getFilename(i)} + + {getFilename(i)} +
From c8bda598f55bd0d104c979866605b5cc61d1250a Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 12 Nov 2025 20:41:44 +0200 Subject: [PATCH 004/262] fix: correct cache cost for OpenRouter and other OpenAI-compatible providers (#4256) --- packages/opencode/src/session/index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index d0bdfb9e1..dff23c24d 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -378,8 +378,14 @@ export namespace Session { metadata: z.custom().optional(), }), (input) => { + const cachedInputTokens = input.usage.cachedInputTokens ?? 0 + const excludesCachedTokens = !!(input.metadata?.["anthropic"] || input.metadata?.["bedrock"]) + const adjustedInputTokens = excludesCachedTokens + ? (input.usage.inputTokens ?? 0) + : (input.usage.inputTokens ?? 0) - cachedInputTokens + const tokens = { - input: input.usage.inputTokens ?? 0, + input: adjustedInputTokens, output: input.usage.outputTokens ?? 0, reasoning: input.usage?.reasoningTokens ?? 0, cache: { @@ -387,7 +393,7 @@ export namespace Session { // @ts-expect-error input.metadata?.["bedrock"]?.["usage"]?.["cacheWriteInputTokens"] ?? 0) as number, - read: input.usage.cachedInputTokens ?? 0, + read: cachedInputTokens, }, } return { From a96bf8e62d8aac9bb43f88c1ca4c8cfb257e677b Mon Sep 17 00:00:00 2001 From: Elias <55650958+eliasto@users.noreply.github.com> Date: Wed, 12 Nov 2025 14:28:35 -0500 Subject: [PATCH 005/262] docs: OVHcloud AI Endpoints provider (#4257) --- packages/web/src/content/docs/providers.mdx | 36 +++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/packages/web/src/content/docs/providers.mdx b/packages/web/src/content/docs/providers.mdx index a3ebda0e6..e8d913a70 100644 --- a/packages/web/src/content/docs/providers.mdx +++ b/packages/web/src/content/docs/providers.mdx @@ -783,6 +783,42 @@ OpenCode Zen is a list of tested and verified models provided by the OpenCode te --- +### OVHcloud AI Endpoints + +1. Head over to the [OVHcloud panel](https://ovh.com/manager). Navigate to the `Public Cloud` section, `AI & Machine Learning` > `AI Endpoints` and in `API Keys` tab, click **Create a new API key**. + +2. Run `opencode auth login` and select **OVHcloud AI Endpoints**. + + ```bash + $ opencode auth login + + ┌ Add credential + │ + ◆ Select provider + │ ● OVHcloud AI Endpoints + │ ... + └ + ``` + +3. Enter your OVHcloud AI Endpoints API key. + + ```bash + $ opencode auth login + + ┌ Add credential + │ + ◇ Select provider + │ OVHcloud AI Endpoints + │ + ◇ Enter your API key + │ _ + └ + ``` + +4. Run the `/models` command to select a model like _gpt-oss-120b_. + +--- + ### Together AI 1. Head over to the [Together AI console](https://api.together.ai), create an account, and click **Add Key**. From 8addaa7e084f8bb9a838610b311aa1110dada659 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Wed, 12 Nov 2025 13:55:13 -0600 Subject: [PATCH 006/262] fix: custom model name merging --- packages/opencode/src/provider/provider.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index e30576bf7..f8e6d0f75 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -12,6 +12,7 @@ import { Auth } from "../auth" import { Instance } from "../project/instance" import { Global } from "../global" import { Flag } from "../flag/flag" +import { iife } from "@/util/iife" export namespace Provider { const log = Log.create({ service: "provider" }) @@ -290,9 +291,14 @@ export namespace Provider { for (const [modelID, model] of Object.entries(provider.models ?? {})) { const existing = parsed.models[model.id ?? modelID] + const name = iife(() => { + if (model.name) return model.name + if (model.id && model.id !== modelID) return modelID + return existing?.name ?? modelID + }) const parsedModel: ModelsDev.Model = { id: modelID, - name: model.name ?? existing?.name ?? modelID, + name, release_date: model.release_date ?? existing?.release_date, attachment: model.attachment ?? existing?.attachment ?? false, reasoning: model.reasoning ?? existing?.reasoning ?? false, From b63b6d04c6add179f4a8d764ed6e811298aafa11 Mon Sep 17 00:00:00 2001 From: Melih Mucuk Date: Wed, 12 Nov 2025 21:59:35 +0200 Subject: [PATCH 007/262] Fix usage & billing for custom model aliases and cached/reasoning tokens (#4222) Co-authored-by: Melih Mucuk Co-authored-by: Aiden Cline --- packages/opencode/src/session/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index dff23c24d..b920ca23c 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -402,6 +402,9 @@ export namespace Session { .add(new Decimal(tokens.output).mul(input.model.cost?.output ?? 0).div(1_000_000)) .add(new Decimal(tokens.cache.read).mul(input.model.cost?.cache_read ?? 0).div(1_000_000)) .add(new Decimal(tokens.cache.write).mul(input.model.cost?.cache_write ?? 0).div(1_000_000)) + // TODO: update models.dev to have better pricing model, for now: + // charge reasoning tokens at the same rate as output tokens + .add(new Decimal(tokens.reasoning).mul(input.model.cost?.output ?? 0).div(1_000_000)) .toNumber(), tokens, } From 90f05eb9c23ddd37a4337e22429741f87dc725cd Mon Sep 17 00:00:00 2001 From: phantomreactor Date: Thu, 13 Nov 2025 02:40:23 +0530 Subject: [PATCH 008/262] paste images in wsl using ctrl+v (#4123) Co-authored-by: GitHub Action --- .../src/cli/cmd/tui/util/clipboard.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/util/clipboard.ts b/packages/opencode/src/cli/cmd/tui/util/clipboard.ts index aac172141..c62630e0c 100644 --- a/packages/opencode/src/cli/cmd/tui/util/clipboard.ts +++ b/packages/opencode/src/cli/cmd/tui/util/clipboard.ts @@ -1,5 +1,5 @@ import { $ } from "bun" -import { platform } from "os" +import { platform, release } from "os" import clipboardy from "clipboardy" import { lazy } from "../../../../util/lazy.js" import { tmpdir } from "os" @@ -29,6 +29,18 @@ export namespace Clipboard { } } + if (os === "win32" || release().includes("WSL")) { + const script = + "Add-Type -AssemblyName System.Windows.Forms; $img = [System.Windows.Forms.Clipboard]::GetImage(); if ($img) { $ms = New-Object System.IO.MemoryStream; $img.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png); [System.Convert]::ToBase64String($ms.ToArray()) }" + const base64 = await $`powershell.exe -command "${script}"`.nothrow().text() + if (base64) { + const imageBuffer = Buffer.from(base64.trim(), "base64") + if (imageBuffer.length > 0) { + return { data: imageBuffer.toString("base64"), mime: "image/png" } + } + } + } + if (os === "linux") { const wayland = await $`wl-paste -t image/png`.nothrow().arrayBuffer() if (wayland && wayland.byteLength > 0) { @@ -40,18 +52,6 @@ export namespace Clipboard { } } - if (os === "win32") { - const script = - "Add-Type -AssemblyName System.Windows.Forms; $img = [System.Windows.Forms.Clipboard]::GetImage(); if ($img) { $ms = New-Object System.IO.MemoryStream; $img.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png); [System.Convert]::ToBase64String($ms.ToArray()) }" - const base64 = await $`powershell -command "${script}"`.nothrow().text() - if (base64) { - const imageBuffer = Buffer.from(base64.trim(), "base64") - if (imageBuffer.length > 0) { - return { data: imageBuffer.toString("base64"), mime: "image/png" } - } - } - } - const text = await clipboardy.read().catch(() => {}) if (text) { return { data: text, mime: "text/plain" } From 4ab4baf3a4a5f11e88462480e600053b1bd953ed Mon Sep 17 00:00:00 2001 From: OpeOginni <107570612+OpeOginni@users.noreply.github.com> Date: Wed, 12 Nov 2025 23:15:17 +0100 Subject: [PATCH 009/262] feat(sidebar): add expandable sections for sidebar (#4132) Co-authored-by: GitHub Action --- .../cli/cmd/tui/routes/session/sidebar.tsx | 209 ++++++++++-------- 1 file changed, 117 insertions(+), 92 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx index 8374f701c..ee83a3afc 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx @@ -1,5 +1,5 @@ import { useSync } from "@tui/context/sync" -import { createMemo, For, Show, Switch, Match } from "solid-js" +import { createMemo, For, Show, Switch, Match, createSignal } from "solid-js" import { useTheme } from "../../context/theme" import { Locale } from "@/util/locale" import path from "path" @@ -13,6 +13,11 @@ export function Sidebar(props: { sessionID: string }) { const todo = createMemo(() => sync.data.todo[props.sessionID] ?? []) const messages = createMemo(() => sync.data.message[props.sessionID] ?? []) + const [mcpExpanded, setMcpExpanded] = createSignal(true) + const [diffExpanded, setDiffExpanded] = createSignal(true) + const [todoExpanded, setTodoExpanded] = createSignal(true) + const [lspExpanded, setLspExpanded] = createSignal(true) + const cost = createMemo(() => { const total = messages().reduce((sum, x) => sum + (x.role === "assistant" ? x.cost : 0), 0) return new Intl.NumberFormat("en-US", { @@ -55,110 +60,130 @@ export function Sidebar(props: { sessionID: string }) { 0}> - - MCP - - - {([key, item]) => ( - - - • - - - {key}{" "} - - - Connected - {(val) => {val().error}} - Disabled in configuration - - - - - )} - + setMcpExpanded(!mcpExpanded())}> + {mcpExpanded() ? "▼" : "▶"} + + MCP + + + + + {([key, item]) => ( + + + • + + + {key}{" "} + + + Connected + {(val) => {val().error}} + Disabled in configuration + + + + + )} + + 0}> - - LSP - - - {(item) => ( - - - • - - - {item.id} {item.root} - - - )} - + setLspExpanded(!lspExpanded())}> + {lspExpanded() ? "▼" : "▶"} + + LSP + + + + + {(item) => ( + + + • + + + {item.id} {item.root} + + + )} + + 0}> - - Todo - - - {(todo) => ( - - [{todo.status === "completed" ? "✓" : " "}] {todo.content} - - )} - + setTodoExpanded(!todoExpanded())}> + {todoExpanded() ? "▼" : "▶"} + + Todo + + + + + {(todo) => ( + + [{todo.status === "completed" ? "✓" : " "}] {todo.content} + + )} + + 0}> - - Modified Files - - - {(item) => { - const file = createMemo(() => { - const splits = item.file.split(path.sep).filter(Boolean) - const last = splits.at(-1)! - const rest = splits.slice(0, -1).join(path.sep) - return Locale.truncateMiddle(rest, 30 - last.length) + "/" + last - }) - return ( - - - {file()} - - - - +{item.additions} - - - -{item.deletions} - + setDiffExpanded(!diffExpanded())}> + {diffExpanded() ? "▼" : "▶"} + + Modified Files + + + + + {(item) => { + const file = createMemo(() => { + const splits = item.file.split(path.sep).filter(Boolean) + const last = splits.at(-1)! + const rest = splits.slice(0, -1).join(path.sep) + return Locale.truncateMiddle(rest, 30 - last.length) + "/" + last + }) + return ( + + + {file()} + + + + +{item.additions} + + + -{item.deletions} + + - - ) - }} - + ) + }} + + From 6d36dbf9de5ea75035c7dca41fcfda5e69a6fd05 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Wed, 12 Nov 2025 14:16:07 -0800 Subject: [PATCH 010/262] fix: github action dirty check (#4262) --- packages/opencode/src/cli/cmd/github.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/opencode/src/cli/cmd/github.ts b/packages/opencode/src/cli/cmd/github.ts index cd3ceb94b..34d47ee5c 100644 --- a/packages/opencode/src/cli/cmd/github.ts +++ b/packages/opencode/src/cli/cmd/github.ts @@ -439,9 +439,10 @@ export const GithubRunCommand = cmd({ // Local PR if (prData.headRepository.nameWithOwner === prData.baseRepository.nameWithOwner) { await checkoutLocalBranch(prData) + const head = (await $`git rev-parse HEAD`).stdout.toString().trim() const dataPrompt = buildPromptDataForPR(prData) const response = await chat(`${userPrompt}\n\n${dataPrompt}`, promptFiles) - if (await branchIsDirty()) { + if (await branchIsDirty(head)) { const summary = await summarize(response) await pushToLocalBranch(summary) } @@ -451,9 +452,10 @@ export const GithubRunCommand = cmd({ // Fork PR else { await checkoutForkBranch(prData) + const head = (await $`git rev-parse HEAD`).stdout.toString().trim() const dataPrompt = buildPromptDataForPR(prData) const response = await chat(`${userPrompt}\n\n${dataPrompt}`, promptFiles) - if (await branchIsDirty()) { + if (await branchIsDirty(head)) { const summary = await summarize(response) await pushToForkBranch(summary, prData) } @@ -464,10 +466,11 @@ export const GithubRunCommand = cmd({ // Issue else { const branch = await checkoutNewBranch() + const head = (await $`git rev-parse HEAD`).stdout.toString().trim() const issueData = await fetchIssue() const dataPrompt = buildPromptDataForIssue(issueData) const response = await chat(`${userPrompt}\n\n${dataPrompt}`, promptFiles) - if (await branchIsDirty()) { + if (await branchIsDirty(head)) { const summary = await summarize(response) await pushToNewBranch(summary, branch) const pr = await createPR( @@ -832,10 +835,13 @@ Co-authored-by: ${actor} <${actor}@users.noreply.github.com>"` await $`git push fork HEAD:${remoteBranch}` } - async function branchIsDirty() { + async function branchIsDirty(originalHead: string) { console.log("Checking if branch is dirty...") const ret = await $`git status --porcelain` - return ret.stdout.toString().trim().length > 0 + const status = ret.stdout.toString().trim() + if (status.length > 0) return true + const head = await $`git rev-parse HEAD` + return head.stdout.toString().trim() !== originalHead } async function assertPermissions() { From 288bc88e40ef69f0c018aa653a04cbb868f7a95b Mon Sep 17 00:00:00 2001 From: Luke Parker <10430890+Hona@users.noreply.github.com> Date: Thu, 13 Nov 2025 09:47:39 +1000 Subject: [PATCH 011/262] fix: Tool calling on windows (#4234) --- packages/opencode/src/storage/storage.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/storage/storage.ts b/packages/opencode/src/storage/storage.ts index cff7211cc..5d4f63943 100644 --- a/packages/opencode/src/storage/storage.ts +++ b/packages/opencode/src/storage/storage.ts @@ -170,7 +170,8 @@ export namespace Storage { const target = path.join(dir, ...key) + ".json" return withErrorHandling(async () => { using _ = await Lock.read(target) - return Bun.file(target).json() as Promise + const result = await Bun.file(target).json() + return result as T }) } @@ -178,7 +179,7 @@ export namespace Storage { const dir = await state().then((x) => x.dir) const target = path.join(dir, ...key) + ".json" return withErrorHandling(async () => { - using _ = await Lock.write("storage") + using _ = await Lock.write(target) const content = await Bun.file(target).json() fn(content) await Bun.write(target, JSON.stringify(content, null, 2)) @@ -190,7 +191,7 @@ export namespace Storage { const dir = await state().then((x) => x.dir) const target = path.join(dir, ...key) + ".json" return withErrorHandling(async () => { - using _ = await Lock.write("storage") + using _ = await Lock.write(target) await Bun.write(target, JSON.stringify(content, null, 2)) }) } From a7774115c504132393dfebc34f9c15c6a2880ad6 Mon Sep 17 00:00:00 2001 From: opencode Date: Thu, 13 Nov 2025 00:13:18 +0000 Subject: [PATCH 012/262] release: v1.0.62 --- bun.lock | 22 +++++++++++----------- 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/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/ui/package.json | 2 +- packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- 15 files changed, 32 insertions(+), 32 deletions(-) diff --git a/bun.lock b/bun.lock index 3f9916ccd..bfb957616 100644 --- a/bun.lock +++ b/bun.lock @@ -40,7 +40,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.61", + "version": "1.0.62", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -67,7 +67,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.61", + "version": "1.0.62", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -91,7 +91,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.61", + "version": "1.0.62", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -115,7 +115,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.61", + "version": "1.0.62", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -155,7 +155,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.61", + "version": "1.0.62", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "22.0.0", @@ -171,7 +171,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.61", + "version": "1.0.62", "bin": { "opencode": "./bin/opencode", }, @@ -249,7 +249,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.61", + "version": "1.0.62", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -269,7 +269,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.61", + "version": "1.0.62", "devDependencies": { "@hey-api/openapi-ts": "0.81.0", "@tsconfig/node22": "catalog:", @@ -280,7 +280,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.61", + "version": "1.0.62", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -293,7 +293,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.61", + "version": "1.0.62", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -323,7 +323,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.61", + "version": "1.0.62", "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 876875272..781d2cb69 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -7,7 +7,7 @@ "dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev", "build": "./script/generate-sitemap.ts && vinxi build && ../../opencode/script/schema.ts ./.output/public/config.json", "start": "vinxi start", - "version": "1.0.61" + "version": "1.0.62" }, "dependencies": { "@ibm/plex": "6.4.1", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 781f9f5ab..7aa268679 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.61", + "version": "1.0.62", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 097dbd6d3..69ee0c0b8 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.61", + "version": "1.0.62", "$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 9e3aefe5a..178c9cd4d 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.61", + "version": "1.0.62", "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 143b023fe..74b9707ea 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.61", + "version": "1.0.62", "description": "", "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index b0c66eb41..220780709 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "opencode" name = "OpenCode" description = "The AI coding agent built for the terminal" -version = "1.0.61" +version = "1.0.62" 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.61/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.62/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.61/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.62/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.61/opencode-linux-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.62/opencode-linux-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.61/opencode-linux-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.62/opencode-linux-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.61/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.62/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index 5a680fa7b..dbe47b50d 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.61", + "version": "1.0.62", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 0c033c5b1..76dcffb84 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.61", + "version": "1.0.62", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index a9be085b9..3d46c470d 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.61", + "version": "1.0.62", "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 25de57553..ef9a50679 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.61", + "version": "1.0.62", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -26,4 +26,4 @@ "publishConfig": { "directory": "dist" } -} +} \ No newline at end of file diff --git a/packages/slack/package.json b/packages/slack/package.json index f14ddc485..e240199a5 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.61", + "version": "1.0.62", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/ui/package.json b/packages/ui/package.json index 348d75b7d..42f5a6afb 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.61", + "version": "1.0.62", "type": "module", "exports": { ".": "./src/components/index.ts", diff --git a/packages/web/package.json b/packages/web/package.json index caea252e6..5ea8830e9 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.61", + "version": "1.0.62", "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 cbb3080bd..a7c59cc9d 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.61", + "version": "1.0.62", "publisher": "sst-dev", "repository": { "type": "git", From 767038afc3db38356fdd04ce6434a22f594d8256 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Wed, 12 Nov 2025 18:52:39 -0600 Subject: [PATCH 013/262] ci: update zed sync --- script/sync-zed.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script/sync-zed.ts b/script/sync-zed.ts index 2e4684b6b..752655447 100755 --- a/script/sync-zed.ts +++ b/script/sync-zed.ts @@ -39,8 +39,8 @@ async function main() { process.chdir(workDir) // Configure git identity - await $`git config user.name "Dax"` - await $`git config user.email "mail@thdxr.com"` + await $`git config user.name "Dax Raad"` + await $`git config user.email "d@ironbay.co"` // Sync fork with upstream console.log(`🔄 Syncing fork with upstream...`) From b981f0a205ea77bab5eaf3add492b6d47c4ecfc8 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Thu, 13 Nov 2025 00:53:22 +0000 Subject: [PATCH 014/262] chore: format code --- 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 3d46c470d..3ecd6c95b 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 ef9a50679..4758dba1a 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -26,4 +26,4 @@ "publishConfig": { "directory": "dist" } -} \ No newline at end of file +} From 09fa84ccfc134c0fdede815e33868c9fbe256ad8 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Wed, 12 Nov 2025 19:03:37 -0600 Subject: [PATCH 015/262] fix: dirty check --- packages/opencode/src/cli/cmd/github.ts | 51 ++++++++++++++++--------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/packages/opencode/src/cli/cmd/github.ts b/packages/opencode/src/cli/cmd/github.ts index 34d47ee5c..1f60e81e9 100644 --- a/packages/opencode/src/cli/cmd/github.ts +++ b/packages/opencode/src/cli/cmd/github.ts @@ -442,9 +442,10 @@ export const GithubRunCommand = cmd({ const head = (await $`git rev-parse HEAD`).stdout.toString().trim() const dataPrompt = buildPromptDataForPR(prData) const response = await chat(`${userPrompt}\n\n${dataPrompt}`, promptFiles) - if (await branchIsDirty(head)) { + const { dirty, uncommittedChanges } = await branchIsDirty(head) + if (dirty) { const summary = await summarize(response) - await pushToLocalBranch(summary) + await pushToLocalBranch(summary, uncommittedChanges) } const hasShared = prData.comments.nodes.some((c) => c.body.includes(`${shareBaseUrl}/s/${shareId}`)) await updateComment(`${response}${footer({ image: !hasShared })}`) @@ -455,9 +456,10 @@ export const GithubRunCommand = cmd({ const head = (await $`git rev-parse HEAD`).stdout.toString().trim() const dataPrompt = buildPromptDataForPR(prData) const response = await chat(`${userPrompt}\n\n${dataPrompt}`, promptFiles) - if (await branchIsDirty(head)) { + const { dirty, uncommittedChanges } = await branchIsDirty(head) + if (dirty) { const summary = await summarize(response) - await pushToForkBranch(summary, prData) + await pushToForkBranch(summary, prData, uncommittedChanges) } const hasShared = prData.comments.nodes.some((c) => c.body.includes(`${shareBaseUrl}/s/${shareId}`)) await updateComment(`${response}${footer({ image: !hasShared })}`) @@ -470,9 +472,10 @@ export const GithubRunCommand = cmd({ const issueData = await fetchIssue() const dataPrompt = buildPromptDataForIssue(issueData) const response = await chat(`${userPrompt}\n\n${dataPrompt}`, promptFiles) - if (await branchIsDirty(head)) { + const { dirty, uncommittedChanges } = await branchIsDirty(head) + if (dirty) { const summary = await summarize(response) - await pushToNewBranch(summary, branch) + await pushToNewBranch(summary, branch, uncommittedChanges) const pr = await createPR( repoData.data.default_branch, branch, @@ -805,33 +808,39 @@ export const GithubRunCommand = cmd({ return `opencode/${type}${issueId}-${timestamp}` } - async function pushToNewBranch(summary: string, branch: string) { + async function pushToNewBranch(summary: string, branch: string, commit: boolean) { console.log("Pushing to new branch...") - await $`git add .` - await $`git commit -m "${summary} + if (commit) { + await $`git add .` + await $`git commit -m "${summary} Co-authored-by: ${actor} <${actor}@users.noreply.github.com>"` + } await $`git push -u origin ${branch}` } - async function pushToLocalBranch(summary: string) { + async function pushToLocalBranch(summary: string, commit: boolean) { console.log("Pushing to local branch...") - await $`git add .` - await $`git commit -m "${summary} + if (commit) { + await $`git add .` + await $`git commit -m "${summary} Co-authored-by: ${actor} <${actor}@users.noreply.github.com>"` + } await $`git push` } - async function pushToForkBranch(summary: string, pr: GitHubPullRequest) { + async function pushToForkBranch(summary: string, pr: GitHubPullRequest, commit: boolean) { console.log("Pushing to fork branch...") const remoteBranch = pr.headRefName - await $`git add .` - await $`git commit -m "${summary} + if (commit) { + await $`git add .` + await $`git commit -m "${summary} Co-authored-by: ${actor} <${actor}@users.noreply.github.com>"` + } await $`git push fork HEAD:${remoteBranch}` } @@ -839,9 +848,17 @@ Co-authored-by: ${actor} <${actor}@users.noreply.github.com>"` console.log("Checking if branch is dirty...") const ret = await $`git status --porcelain` const status = ret.stdout.toString().trim() - if (status.length > 0) return true + if (status.length > 0) { + return { + dirty: true, + uncommittedChanges: true, + } + } const head = await $`git rev-parse HEAD` - return head.stdout.toString().trim() !== originalHead + return { + dirty: head.stdout.toString().trim() !== originalHead, + uncommittedChanges: false, + } } async function assertPermissions() { From 43a8d1b1ae31155a65deb04fab3db4e145b24732 Mon Sep 17 00:00:00 2001 From: Luke Parker <10430890+Hona@users.noreply.github.com> Date: Thu, 13 Nov 2025 13:57:44 +1000 Subject: [PATCH 016/262] fix: Enable Windows builds and fix bun+pnpm install on Windows (#4273) --- packages/opencode/script/build.ts | 8 +-- packages/opencode/script/postinstall.mjs | 89 +++++++++++++++++++----- 2 files changed, 74 insertions(+), 23 deletions(-) diff --git a/packages/opencode/script/build.ts b/packages/opencode/script/build.ts index 97631d907..2aaaaa2f5 100755 --- a/packages/opencode/script/build.ts +++ b/packages/opencode/script/build.ts @@ -66,11 +66,11 @@ const allTargets: { avx2: false, }, { - os: "windows", + os: "win32", arch: "x64", }, { - os: "windows", + os: "win32", arch: "x64", avx2: false, }, @@ -115,7 +115,7 @@ for (const item of targets) { entrypoints: ["./src/index.ts", parserWorker, workerPath], define: { OPENCODE_VERSION: `'${Script.version}'`, - OTUI_TREE_SITTER_WORKER_PATH: "/$bunfs/root/" + path.relative(dir, parserWorker), + OTUI_TREE_SITTER_WORKER_PATH: "/$bunfs/root/" + path.relative(dir, parserWorker).replaceAll("\\", "/"), OPENCODE_WORKER_PATH: workerPath, OPENCODE_CHANNEL: `'${Script.channel}'`, }, @@ -127,7 +127,7 @@ for (const item of targets) { { name, version: Script.version, - os: [item.os === "windows" ? "win32" : item.os], + os: [item.os], cpu: [item.arch], }, null, diff --git a/packages/opencode/script/postinstall.mjs b/packages/opencode/script/postinstall.mjs index b875d158f..89e670754 100644 --- a/packages/opencode/script/postinstall.mjs +++ b/packages/opencode/script/postinstall.mjs @@ -20,7 +20,7 @@ function detectPlatformAndArch() { platform = "linux" break case "win32": - platform = "windows" + platform = "win32" break default: platform = os.platform() @@ -50,24 +50,65 @@ function detectPlatformAndArch() { function findBinary() { const { platform, arch } = detectPlatformAndArch() const packageName = `opencode-${platform}-${arch}` - const binary = platform === "windows" ? "opencode.exe" : "opencode" + const binaryName = platform === "win32" ? "opencode.exe" : "opencode" try { // Use require.resolve to find the package const packageJsonPath = require.resolve(`${packageName}/package.json`) const packageDir = path.dirname(packageJsonPath) - const binaryPath = path.join(packageDir, "bin", binary) + const binaryPath = path.join(packageDir, "bin", binaryName) if (!fs.existsSync(binaryPath)) { throw new Error(`Binary not found at ${binaryPath}`) } - return binaryPath + return { binaryPath, binaryName } } catch (error) { throw new Error(`Could not find package ${packageName}: ${error.message}`) } } +function prepareBinDirectory(binaryName) { + const binDir = path.join(__dirname, "bin") + const targetPath = path.join(binDir, binaryName) + + // Ensure bin directory exists + if (!fs.existsSync(binDir)) { + fs.mkdirSync(binDir, { recursive: true }) + } + + // Remove existing binary/symlink if it exists + if (fs.existsSync(targetPath)) { + fs.unlinkSync(targetPath) + } + + return { binDir, targetPath } +} + +function copyBinary(sourcePath, binaryName) { + const { targetPath } = prepareBinDirectory(binaryName) + + fs.copyFileSync(sourcePath, targetPath) + console.log(`opencode binary installed: ${targetPath}`) + + // Verify the file exists after operation + if (!fs.existsSync(targetPath)) { + throw new Error(`Failed to copy binary to ${targetPath}`) + } +} + +function symlinkBinary(sourcePath, binaryName) { + const { targetPath } = prepareBinDirectory(binaryName) + + fs.symlinkSync(sourcePath, targetPath) + console.log(`opencode binary symlinked: ${targetPath} -> ${sourcePath}`) + + // Verify the file exists after operation + if (!fs.existsSync(targetPath)) { + throw new Error(`Failed to symlink binary to ${targetPath}`) + } +} + async function regenerateWindowsCmdWrappers() { console.log("Windows + npm detected: Forcing npm to rebuild bin links") @@ -102,27 +143,37 @@ async function main() { if (os.platform() === "win32") { // NPM eg format - npm/11.4.2 node/v24.4.1 win32 x64 // Bun eg format - bun/1.2.19 npm/? node/v24.3.0 win32 x64 - if (process.env.npm_config_user_agent.startsWith("npm")) { + // pnpm eg format - pnpm/8.10.0 npm/? node/v20.10.0 win32 x64 + const userAgent = process.env.npm_config_user_agent || "" + + if (userAgent.startsWith("npm")) { await regenerateWindowsCmdWrappers() - } else { - console.log("Windows detected but not npm, skipping postinstall") + return } + + if (userAgent.startsWith("bun")) { + console.log("Windows + bun detected: Setting up binary") + const { binaryPath, binaryName } = findBinary() + copyBinary(binaryPath, binaryName) + return + } + + if (userAgent.startsWith("pnpm")) { + console.log("Windows + pnpm detected: Setting up binary") + const { binaryPath, binaryName } = findBinary() + copyBinary(binaryPath, binaryName) + return + } + + // Unknown package manager on Windows + console.log("Windows detected but unknown package manager, skipping postinstall") return } - const binaryPath = findBinary() - const binScript = path.join(__dirname, "bin", "opencode") - - // Remove existing bin script if it exists - if (fs.existsSync(binScript)) { - fs.unlinkSync(binScript) - } - - // Create symlink to the actual binary - fs.symlinkSync(binaryPath, binScript) - console.log(`opencode binary symlinked: ${binScript} -> ${binaryPath}`) + const { binaryPath, binaryName } = findBinary() + symlinkBinary(binaryPath, binaryName) } catch (error) { - console.error("Failed to create opencode binary symlink:", error.message) + console.error("Failed to setup opencode binary:", error.message) process.exit(1) } } From f80a3fea31e2bcf549ed5655e2a8eb7a781e03f6 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Wed, 12 Nov 2025 22:05:07 -0600 Subject: [PATCH 017/262] fixes --- packages/opencode/script/build.ts | 6 +++--- packages/opencode/script/postinstall.mjs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/opencode/script/build.ts b/packages/opencode/script/build.ts index 2aaaaa2f5..6731bea0b 100755 --- a/packages/opencode/script/build.ts +++ b/packages/opencode/script/build.ts @@ -66,11 +66,11 @@ const allTargets: { avx2: false, }, { - os: "win32", + os: "windows", arch: "x64", }, { - os: "win32", + os: "windows", arch: "x64", avx2: false, }, @@ -127,7 +127,7 @@ for (const item of targets) { { name, version: Script.version, - os: [item.os], + os: [item.os === "windows" ? "win32" : item.os], cpu: [item.arch], }, null, diff --git a/packages/opencode/script/postinstall.mjs b/packages/opencode/script/postinstall.mjs index 89e670754..23a665175 100644 --- a/packages/opencode/script/postinstall.mjs +++ b/packages/opencode/script/postinstall.mjs @@ -20,7 +20,7 @@ function detectPlatformAndArch() { platform = "linux" break case "win32": - platform = "win32" + platform = "windows" break default: platform = os.platform() @@ -50,7 +50,7 @@ function detectPlatformAndArch() { function findBinary() { const { platform, arch } = detectPlatformAndArch() const packageName = `opencode-${platform}-${arch}` - const binaryName = platform === "win32" ? "opencode.exe" : "opencode" + const binaryName = platform === "windows" ? "opencode.exe" : "opencode" try { // Use require.resolve to find the package From ec3579d7cb9a47d5416f8b02b0e2f3e2e7503c89 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Thu, 13 Nov 2025 12:04:32 +0000 Subject: [PATCH 018/262] ignore: update download stats 2025-11-13 --- STATS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/STATS.md b/STATS.md index 3f8da4f21..0bb9d011e 100644 --- a/STATS.md +++ b/STATS.md @@ -138,3 +138,4 @@ | 2025-11-10 | 722,288 (+8,826) | 668,225 (+7,766) | 1,390,513 (+16,592) | | 2025-11-11 | 729,769 (+7,481) | 677,501 (+9,276) | 1,407,270 (+16,757) | | 2025-11-12 | 740,180 (+10,411) | 686,454 (+8,953) | 1,426,634 (+19,364) | +| 2025-11-13 | 749,905 (+9,725) | 696,157 (+9,703) | 1,446,062 (+19,428) | From 609ab069a99d6832c03c5b7b0b88c14b240ba4f8 Mon Sep 17 00:00:00 2001 From: "Tommy D. Rossi" Date: Thu, 13 Nov 2025 17:02:10 +0100 Subject: [PATCH 019/262] Add scroll acceleration support to TUI (#4289) --- .../src/cli/cmd/tui/routes/session/index.tsx | 31 ++++++++++++++++++- packages/opencode/src/config/config.ts | 8 ++++- packages/sdk/js/src/gen/types.gen.ts | 9 ++++++ packages/web/src/content/docs/config.mdx | 10 +++++- packages/web/src/content/docs/tui.mdx | 8 +++-- 5 files changed, 61 insertions(+), 5 deletions(-) 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 4c3dd96ff..e3d199ee4 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -17,7 +17,14 @@ import { useRoute, useRouteData } from "@tui/context/route" import { useSync } from "@tui/context/sync" import { SplitBorder } from "@tui/component/border" import { useTheme } from "@tui/context/theme" -import { BoxRenderable, ScrollBoxRenderable, TextAttributes, addDefaultParsers } from "@opentui/core" +import { + BoxRenderable, + ScrollBoxRenderable, + TextAttributes, + addDefaultParsers, + MacOSScrollAccel, + type ScrollAcceleration, +} from "@opentui/core" import { Prompt, type PromptRef } from "@tui/component/prompt" import type { AssistantMessage, Part, ToolPart, UserMessage, TextPart, ReasoningPart } from "@opencode-ai/sdk" import { useLocal } from "@tui/context/local" @@ -62,6 +69,16 @@ import { LSP } from "@/lsp/index.ts" addDefaultParsers(parsers.parsers) +class CustomSpeedScroll implements ScrollAcceleration { + constructor(private speed: number) {} + + tick(_now?: number): number { + return this.speed + } + + reset(): void {} +} + const context = createContext<{ width: number conceal: () => boolean @@ -95,6 +112,17 @@ export function Session() { const sidebarVisible = createMemo(() => sidebar() === "show" || (sidebar() === "auto" && wide())) const contentWidth = createMemo(() => dimensions().width - (sidebarVisible() ? 42 : 0) - 4) + const scrollAcceleration = createMemo(() => { + const tui = sync.data.config.tui + if (tui?.scroll_acceleration?.enabled) { + return new MacOSScrollAccel() + } + if (tui?.scroll_speed) { + return new CustomSpeedScroll(tui.scroll_speed) + } + return undefined + }) + createEffect(async () => { await sync.session .sync(route.sessionID) @@ -684,6 +712,7 @@ export function Session() { stickyScroll={true} stickyStart="bottom" flexGrow={1} + scrollAcceleration={scrollAcceleration()} > {(message, index) => ( diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index e6bed238f..3ca8c25de 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -437,7 +437,13 @@ export namespace Config { }) export const TUI = z.object({ - scroll_speed: z.number().min(1).optional().default(2).describe("TUI scroll speed"), + scroll_speed: z.number().min(1).optional().default(1).describe("TUI scroll speed"), + scroll_acceleration: z + .object({ + enabled: z.boolean().describe("Enable scroll acceleration"), + }) + .optional() + .describe("Scroll acceleration settings"), }) export const Layout = z.enum(["auto", "stretch"]).meta({ diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts index 3e64fc9a0..1d90fe106 100644 --- a/packages/sdk/js/src/gen/types.gen.ts +++ b/packages/sdk/js/src/gen/types.gen.ts @@ -301,6 +301,15 @@ export type Config = { * TUI scroll speed */ scroll_speed?: number + /** + * Scroll acceleration settings + */ + scroll_acceleration?: { + /** + * Enable scroll acceleration + */ + enabled: boolean + } } /** * Command configuration, see https://opencode.ai/docs/commands diff --git a/packages/web/src/content/docs/config.mdx b/packages/web/src/content/docs/config.mdx index c02edd2ff..a27acc779 100644 --- a/packages/web/src/content/docs/config.mdx +++ b/packages/web/src/content/docs/config.mdx @@ -93,11 +93,19 @@ You can configure TUI-specific settings through the `tui` option. { "$schema": "https://opencode.ai/config.json", "tui": { - "scroll_speed": 3 + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } } } ``` +Available options: + +- `scroll_acceleration.enabled` - Enable macOS-style scroll acceleration. **Takes precedence over `scroll_speed`.** +- `scroll_speed` - Custom scroll speed multiplier (default: `1`, minimum: `1`). Ignored if `scroll_acceleration.enabled` is `true`. + [Learn more about using the TUI here](/docs/tui). --- diff --git a/packages/web/src/content/docs/tui.mdx b/packages/web/src/content/docs/tui.mdx index 4dd7608be..f50409c41 100644 --- a/packages/web/src/content/docs/tui.mdx +++ b/packages/web/src/content/docs/tui.mdx @@ -336,11 +336,15 @@ You can customize TUI behavior through your OpenCode config file. { "$schema": "https://opencode.ai/config.json", "tui": { - "scroll_speed": 3 + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + } } } ``` ### Options -- `scroll_speed` - Controls how fast the TUI scrolls when using scroll commands (default: `2`, minimum: `1`) +- `scroll_acceleration` - Enable macOS-style scroll acceleration for smooth, natural scrolling. When enabled, scroll speed increases with rapid scrolling gestures and stays precise for slower movements. **This setting takes precedence over `scroll_speed` and overrides it when enabled.** +- `scroll_speed` - Controls how fast the TUI scrolls when using scroll commands (default: `1`, minimum: `1`). **Note: This is ignored if `scroll_acceleration.enabled` is set to `true`.** From 73443585e5e939522d306c601056dcdf609d67c3 Mon Sep 17 00:00:00 2001 From: Luke Parker <10430890+Hona@users.noreply.github.com> Date: Fri, 14 Nov 2025 02:38:57 +1000 Subject: [PATCH 020/262] fix: resolve bun/pnpm global install failures on Windows (#4275) Co-authored-by: Aiden Cline --- packages/opencode/script/build.ts | 9 +-- packages/opencode/script/postinstall.mjs | 70 +----------------------- packages/opencode/script/publish.ts | 31 ++++++++++- 3 files changed, 36 insertions(+), 74 deletions(-) diff --git a/packages/opencode/script/build.ts b/packages/opencode/script/build.ts index 6731bea0b..502baed02 100755 --- a/packages/opencode/script/build.ts +++ b/packages/opencode/script/build.ts @@ -66,11 +66,11 @@ const allTargets: { avx2: false, }, { - os: "windows", + os: "win32", arch: "x64", }, { - os: "windows", + os: "win32", arch: "x64", avx2: false, }, @@ -88,7 +88,8 @@ await $`bun install --os="*" --cpu="*" @parcel/watcher@${pkg.dependencies["@parc for (const item of targets) { const name = [ pkg.name, - item.os, + // changing to win32 flags npm for some reason + item.os === "win32" ? "windows" : item.os, item.arch, item.avx2 === false ? "baseline" : undefined, item.abi === undefined ? undefined : item.abi, @@ -127,7 +128,7 @@ for (const item of targets) { { name, version: Script.version, - os: [item.os === "windows" ? "win32" : item.os], + os: [item.os], cpu: [item.arch], }, null, diff --git a/packages/opencode/script/postinstall.mjs b/packages/opencode/script/postinstall.mjs index 23a665175..78f022c9f 100644 --- a/packages/opencode/script/postinstall.mjs +++ b/packages/opencode/script/postinstall.mjs @@ -85,18 +85,6 @@ function prepareBinDirectory(binaryName) { return { binDir, targetPath } } -function copyBinary(sourcePath, binaryName) { - const { targetPath } = prepareBinDirectory(binaryName) - - fs.copyFileSync(sourcePath, targetPath) - console.log(`opencode binary installed: ${targetPath}`) - - // Verify the file exists after operation - if (!fs.existsSync(targetPath)) { - throw new Error(`Failed to copy binary to ${targetPath}`) - } -} - function symlinkBinary(sourcePath, binaryName) { const { targetPath } = prepareBinDirectory(binaryName) @@ -109,64 +97,12 @@ function symlinkBinary(sourcePath, binaryName) { } } -async function regenerateWindowsCmdWrappers() { - console.log("Windows + npm detected: Forcing npm to rebuild bin links") - - try { - const { execSync } = require("child_process") - const pkgPath = path.join(__dirname, "..") - - // npm_config_global is string | undefined - // if it exists, the value is true - const isGlobal = process.env.npm_config_global === "true" || pkgPath.includes(path.join("npm", "node_modules")) - - // The npm rebuild command does 2 things - Execute lifecycle scripts and rebuild bin links - // We want to skip lifecycle scripts to avoid infinite loops, so we use --ignore-scripts - const cmd = `npm rebuild opencode-ai --ignore-scripts${isGlobal ? " -g" : ""}` - const opts = { - stdio: "inherit", - shell: true, - ...(isGlobal ? {} : { cwd: path.join(pkgPath, "..", "..") }), // For local, run from project root - } - - console.log(`Running: ${cmd}`) - execSync(cmd, opts) - console.log("Successfully rebuilt npm bin links") - } catch (error) { - console.error("Error rebuilding npm links:", error.message) - console.error("npm rebuild failed. You may need to manually run: npm rebuild opencode-ai --ignore-scripts") - } -} - async function main() { try { if (os.platform() === "win32") { - // NPM eg format - npm/11.4.2 node/v24.4.1 win32 x64 - // Bun eg format - bun/1.2.19 npm/? node/v24.3.0 win32 x64 - // pnpm eg format - pnpm/8.10.0 npm/? node/v20.10.0 win32 x64 - const userAgent = process.env.npm_config_user_agent || "" - - if (userAgent.startsWith("npm")) { - await regenerateWindowsCmdWrappers() - return - } - - if (userAgent.startsWith("bun")) { - console.log("Windows + bun detected: Setting up binary") - const { binaryPath, binaryName } = findBinary() - copyBinary(binaryPath, binaryName) - return - } - - if (userAgent.startsWith("pnpm")) { - console.log("Windows + pnpm detected: Setting up binary") - const { binaryPath, binaryName } = findBinary() - copyBinary(binaryPath, binaryName) - return - } - - // Unknown package manager on Windows - console.log("Windows detected but unknown package manager, skipping postinstall") + // On Windows, the .exe is already included in the package and bin field points to it + // No postinstall setup needed + console.log("Windows detected: binary setup not needed (using packaged .exe)") return } diff --git a/packages/opencode/script/publish.ts b/packages/opencode/script/publish.ts index 3e989cc6a..ac2fce56b 100755 --- a/packages/opencode/script/publish.ts +++ b/packages/opencode/script/publish.ts @@ -2,8 +2,10 @@ import { $ } from "bun" import pkg from "../package.json" import { Script } from "@opencode-ai/script" +import { fileURLToPath } from "url" +import fs from "fs" -const dir = new URL("..", import.meta.url).pathname +const dir = fileURLToPath(new URL("..", import.meta.url)) process.chdir(dir) const { binaries } = await import("./build.ts") @@ -15,14 +17,29 @@ const { binaries } = await import("./build.ts") await $`mkdir -p ./dist/${pkg.name}` await $`cp -r ./bin ./dist/${pkg.name}/bin` + +// Copy Windows .exe if any Windows binaries were built +let hasWindowsBinary = false +for (const binaryName of Object.keys(binaries)) { + if (binaryName.includes("win32")) { + const winBinaryPath = `./dist/${binaryName}/bin/opencode.exe` + if (fs.existsSync(winBinaryPath)) { + await $`cp ${winBinaryPath} ./dist/${pkg.name}/bin/opencode.exe` + hasWindowsBinary = true + break + } + } +} + await $`cp ./script/preinstall.mjs ./dist/${pkg.name}/preinstall.mjs` await $`cp ./script/postinstall.mjs ./dist/${pkg.name}/postinstall.mjs` + await Bun.file(`./dist/${pkg.name}/package.json`).write( JSON.stringify( { name: pkg.name + "-ai", bin: { - [pkg.name]: `./bin/${pkg.name}`, + [pkg.name]: hasWindowsBinary ? `./bin/${pkg.name}.exe` : `./bin/${pkg.name}`, }, scripts: { preinstall: "bun ./preinstall.mjs || node ./preinstall.mjs", @@ -36,7 +53,15 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write( ), ) for (const [name] of Object.entries(binaries)) { - await $`cd dist/${name} && chmod 777 -R . && bun publish --access public --tag ${Script.channel}` + try { + process.chdir(`./dist/${name}`) + if (process.platform !== "win32") { + await $`chmod 755 -R .` + } + await $`bun publish --access public --tag ${Script.channel}` + } finally { + process.chdir(dir) + } } await $`cd ./dist/${pkg.name} && bun publish --access public --tag ${Script.channel}` From ff462dfd7a7319c59e6600aae9c553a59762e739 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Thu, 13 Nov 2025 10:22:07 -0800 Subject: [PATCH 021/262] fix: windows install (#4293) Co-authored-by: GitHub Action --- .github/workflows/snapshot.yml | 2 +- packages/opencode/bin/opencode | 139 ++++++++++++++---------- packages/opencode/bin/opencode.cmd | 58 ---------- packages/opencode/script/preinstall.mjs | 44 -------- packages/opencode/script/publish.ts | 19 +--- 5 files changed, 83 insertions(+), 179 deletions(-) delete mode 100644 packages/opencode/bin/opencode.cmd delete mode 100644 packages/opencode/script/preinstall.mjs diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 402c014fd..ab2f9c0f2 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -4,7 +4,7 @@ on: push: branches: - dev - - opentui + - windows - v0 concurrency: ${{ github.workflow }}-${{ github.ref }} diff --git a/packages/opencode/bin/opencode b/packages/opencode/bin/opencode index 8f75eb189..e35cc0094 100755 --- a/packages/opencode/bin/opencode +++ b/packages/opencode/bin/opencode @@ -1,61 +1,84 @@ -#!/bin/sh -set -e +#!/usr/bin/env node -if [ -n "$OPENCODE_BIN_PATH" ]; then - resolved="$OPENCODE_BIN_PATH" -else - # Get the real path of this script, resolving any symlinks - script_path="$0" - while [ -L "$script_path" ]; do - link_target="$(readlink "$script_path")" - case "$link_target" in - /*) script_path="$link_target" ;; - *) script_path="$(dirname "$script_path")/$link_target" ;; - esac - done - script_dir="$(dirname "$script_path")" - script_dir="$(cd "$script_dir" && pwd)" - - # Map platform names - case "$(uname -s)" in - Darwin) platform="darwin" ;; - Linux) platform="linux" ;; - MINGW*|CYGWIN*|MSYS*) platform="win32" ;; - *) platform="$(uname -s | tr '[:upper:]' '[:lower:]')" ;; - esac - - # Map architecture names - case "$(uname -m)" in - x86_64|amd64) arch="x64" ;; - aarch64) arch="arm64" ;; - armv7l) arch="arm" ;; - *) arch="$(uname -m)" ;; - esac - - name="opencode-${platform}-${arch}" - binary="opencode" - [ "$platform" = "win32" ] && binary="opencode.exe" - - # Search for the binary starting from real script location - resolved="" - current_dir="$script_dir" - while [ "$current_dir" != "/" ]; do - candidate="$current_dir/node_modules/$name/bin/$binary" - if [ -f "$candidate" ]; then - resolved="$candidate" - break - fi - current_dir="$(dirname "$current_dir")" - done - - if [ -z "$resolved" ]; then - printf "It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the \"%s\" package\n" "$name" >&2 - exit 1 - fi -fi +const childProcess = require("child_process") +const fs = require("fs") +const path = require("path") +const os = require("os") -# Handle SIGINT gracefully -trap '' INT +function run(target) { + const result = childProcess.spawnSync(target, process.argv.slice(2), { + stdio: "inherit", + }) + if (result.error) { + console.error(result.error.message) + process.exit(1) + } + const code = typeof result.status === "number" ? result.status : 0 + process.exit(code) +} -# Execute the binary with all arguments -exec "$resolved" "$@" +const envPath = process.env.OPENCODE_BIN_PATH +if (envPath) { + run(envPath) +} + +const scriptPath = fs.realpathSync(__filename) +const scriptDir = path.dirname(scriptPath) + +const platformMap = { + darwin: "darwin", + linux: "linux", + win32: "windows", +} +const archMap = { + x64: "x64", + arm64: "arm64", + arm: "arm", +} + +let platform = platformMap[os.platform()] +if (!platform) { + platform = os.platform() +} +let arch = archMap[os.arch()] +if (!arch) { + arch = os.arch() +} +const base = "opencode-" + platform + "-" + arch +const binary = platform === "windows" ? "opencode.exe" : "opencode" + +function findBinary(startDir) { + let current = startDir + for (;;) { + const modules = path.join(current, "node_modules") + if (fs.existsSync(modules)) { + const entries = fs.readdirSync(modules) + for (const entry of entries) { + if (!entry.startsWith(base)) { + continue + } + const candidate = path.join(modules, entry, "bin", binary) + if (fs.existsSync(candidate)) { + return candidate + } + } + } + const parent = path.dirname(current) + if (parent === current) { + return + } + current = parent + } +} + +const resolved = findBinary(scriptDir) +if (!resolved) { + console.error( + 'It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the "' + + base + + '" package', + ) + process.exit(1) +} + +run(resolved) diff --git a/packages/opencode/bin/opencode.cmd b/packages/opencode/bin/opencode.cmd deleted file mode 100644 index 775bfe688..000000000 --- a/packages/opencode/bin/opencode.cmd +++ /dev/null @@ -1,58 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -if defined OPENCODE_BIN_PATH ( - set "resolved=%OPENCODE_BIN_PATH%" - goto :execute -) - -rem Get the directory of this script -set "script_dir=%~dp0" -set "script_dir=%script_dir:~0,-1%" - -rem Detect platform and architecture -set "platform=windows" - -rem Detect architecture -if "%PROCESSOR_ARCHITECTURE%"=="AMD64" ( - set "arch=x64" -) else if "%PROCESSOR_ARCHITECTURE%"=="ARM64" ( - set "arch=arm64" -) else if "%PROCESSOR_ARCHITECTURE%"=="x86" ( - set "arch=x86" -) else ( - set "arch=x64" -) - -set "name=opencode-!platform!-!arch!" -set "binary=opencode.exe" - -rem Search for the binary starting from script location -set "resolved=" -set "current_dir=%script_dir%" - -:search_loop -set "candidate=%current_dir%\node_modules\%name%\bin\%binary%" -if exist "%candidate%" ( - set "resolved=%candidate%" - goto :execute -) - -rem Move up one directory -for %%i in ("%current_dir%") do set "parent_dir=%%~dpi" -set "parent_dir=%parent_dir:~0,-1%" - -rem Check if we've reached the root -if "%current_dir%"=="%parent_dir%" goto :not_found -set "current_dir=%parent_dir%" -goto :search_loop - -:not_found -echo It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the "%name%" package >&2 -exit /b 1 - -:execute -rem Execute the binary with all arguments in the same console window -rem Use start /b /wait to ensure it runs in the current shell context for all shells -start /b /wait "" "%resolved%" %* -exit /b %ERRORLEVEL% diff --git a/packages/opencode/script/preinstall.mjs b/packages/opencode/script/preinstall.mjs deleted file mode 100644 index dfe46d9e7..000000000 --- a/packages/opencode/script/preinstall.mjs +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env node - -import fs from "fs" -import path from "path" -import os from "os" -import { fileURLToPath } from "url" - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -function main() { - if (os.platform() !== "win32") { - console.log("Non-Windows platform detected, skipping preinstall") - return - } - - console.log("Windows detected: Modifying package.json bin entry") - - // Read package.json - const packageJsonPath = path.join(__dirname, "package.json") - const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")) - - // Modify bin to point to .cmd file on Windows - packageJson.bin = { - opencode: "./bin/opencode.cmd", - } - - // Write it back - fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)) - console.log("Updated package.json bin to use opencode.cmd") - - // Now you can also remove the Unix script if you want - const unixScript = path.join(__dirname, "bin", "opencode") - if (fs.existsSync(unixScript)) { - console.log("Removing Unix shell script") - fs.unlinkSync(unixScript) - } -} - -try { - main() -} catch (error) { - console.error("Preinstall script error:", error.message) - process.exit(0) -} diff --git a/packages/opencode/script/publish.ts b/packages/opencode/script/publish.ts index ac2fce56b..d5afe56fb 100755 --- a/packages/opencode/script/publish.ts +++ b/packages/opencode/script/publish.ts @@ -3,7 +3,6 @@ import { $ } from "bun" import pkg from "../package.json" import { Script } from "@opencode-ai/script" import { fileURLToPath } from "url" -import fs from "fs" const dir = fileURLToPath(new URL("..", import.meta.url)) process.chdir(dir) @@ -17,21 +16,6 @@ const { binaries } = await import("./build.ts") await $`mkdir -p ./dist/${pkg.name}` await $`cp -r ./bin ./dist/${pkg.name}/bin` - -// Copy Windows .exe if any Windows binaries were built -let hasWindowsBinary = false -for (const binaryName of Object.keys(binaries)) { - if (binaryName.includes("win32")) { - const winBinaryPath = `./dist/${binaryName}/bin/opencode.exe` - if (fs.existsSync(winBinaryPath)) { - await $`cp ${winBinaryPath} ./dist/${pkg.name}/bin/opencode.exe` - hasWindowsBinary = true - break - } - } -} - -await $`cp ./script/preinstall.mjs ./dist/${pkg.name}/preinstall.mjs` await $`cp ./script/postinstall.mjs ./dist/${pkg.name}/postinstall.mjs` await Bun.file(`./dist/${pkg.name}/package.json`).write( @@ -39,10 +23,9 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write( { name: pkg.name + "-ai", bin: { - [pkg.name]: hasWindowsBinary ? `./bin/${pkg.name}.exe` : `./bin/${pkg.name}`, + [pkg.name]: `./bin/${pkg.name}`, }, scripts: { - preinstall: "bun ./preinstall.mjs || node ./preinstall.mjs", postinstall: "bun ./postinstall.mjs || node ./postinstall.mjs", }, version: Script.version, From a673e3650d8f1d2fdebc4c6490280f43b4459e68 Mon Sep 17 00:00:00 2001 From: opencode Date: Thu, 13 Nov 2025 19:00:14 +0000 Subject: [PATCH 022/262] release: v1.0.63 --- bun.lock | 22 +++++++++++----------- 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/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/ui/package.json | 2 +- packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- 15 files changed, 32 insertions(+), 32 deletions(-) diff --git a/bun.lock b/bun.lock index bfb957616..7e4935244 100644 --- a/bun.lock +++ b/bun.lock @@ -40,7 +40,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.62", + "version": "1.0.63", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -67,7 +67,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.62", + "version": "1.0.63", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -91,7 +91,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.62", + "version": "1.0.63", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -115,7 +115,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.62", + "version": "1.0.63", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -155,7 +155,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.62", + "version": "1.0.63", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "22.0.0", @@ -171,7 +171,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.62", + "version": "1.0.63", "bin": { "opencode": "./bin/opencode", }, @@ -249,7 +249,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.62", + "version": "1.0.63", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -269,7 +269,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.62", + "version": "1.0.63", "devDependencies": { "@hey-api/openapi-ts": "0.81.0", "@tsconfig/node22": "catalog:", @@ -280,7 +280,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.62", + "version": "1.0.63", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -293,7 +293,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.62", + "version": "1.0.63", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -323,7 +323,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.62", + "version": "1.0.63", "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 781d2cb69..97b9a9bdb 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -7,7 +7,7 @@ "dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev", "build": "./script/generate-sitemap.ts && vinxi build && ../../opencode/script/schema.ts ./.output/public/config.json", "start": "vinxi start", - "version": "1.0.62" + "version": "1.0.63" }, "dependencies": { "@ibm/plex": "6.4.1", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 7aa268679..cf5fcb94a 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.62", + "version": "1.0.63", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 69ee0c0b8..38642512a 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.62", + "version": "1.0.63", "$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 178c9cd4d..f0add1044 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.62", + "version": "1.0.63", "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 74b9707ea..fceff45d5 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.62", + "version": "1.0.63", "description": "", "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index 220780709..db6b40bae 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "opencode" name = "OpenCode" description = "The AI coding agent built for the terminal" -version = "1.0.62" +version = "1.0.63" 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.62/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.63/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.62/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.63/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.62/opencode-linux-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.63/opencode-linux-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.62/opencode-linux-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.63/opencode-linux-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.62/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.63/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index dbe47b50d..16088e63a 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.62", + "version": "1.0.63", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 76dcffb84..dfe5e725b 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.62", + "version": "1.0.63", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 3ecd6c95b..ef647bae7 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.62", + "version": "1.0.63", "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 4758dba1a..0ba382830 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.62", + "version": "1.0.63", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -26,4 +26,4 @@ "publishConfig": { "directory": "dist" } -} +} \ No newline at end of file diff --git a/packages/slack/package.json b/packages/slack/package.json index e240199a5..afa383f5a 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.62", + "version": "1.0.63", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/ui/package.json b/packages/ui/package.json index 42f5a6afb..2e1978244 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.62", + "version": "1.0.63", "type": "module", "exports": { ".": "./src/components/index.ts", diff --git a/packages/web/package.json b/packages/web/package.json index 5ea8830e9..92d322291 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.62", + "version": "1.0.63", "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 a7c59cc9d..931c80dbe 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.62", + "version": "1.0.63", "publisher": "sst-dev", "repository": { "type": "git", From e225294dd4bd1c7c263e69c2f62ef1886c16db56 Mon Sep 17 00:00:00 2001 From: Valerio Di Maggio <48596273+val-2@users.noreply.github.com> Date: Thu, 13 Nov 2025 20:41:56 +0100 Subject: [PATCH 023/262] Fix: unreadable texts in light mode (#4301) --- .../opencode/src/cli/cmd/tui/routes/session/index.tsx | 8 ++++---- packages/opencode/src/cli/cmd/tui/ui/toast.tsx | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) 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 e3d199ee4..500038f35 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -1253,7 +1253,7 @@ ToolRegistry.register({ {(value) => {value}} - + @@ -1463,16 +1463,16 @@ ToolRegistry.register({ - + - + - + diff --git a/packages/opencode/src/cli/cmd/tui/ui/toast.tsx b/packages/opencode/src/cli/cmd/tui/ui/toast.tsx index 24d630c73..7e9684170 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/toast.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/toast.tsx @@ -31,11 +31,11 @@ export function Toast() { customBorderChars={SplitBorder.customBorderChars} > - + {current().title} - {current().message} + {current().message} )} From 829d86840ab793511cd98ad629014b6a08c8c369 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Thu, 13 Nov 2025 19:42:31 +0000 Subject: [PATCH 024/262] chore: format code --- 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 ef647bae7..41fef23b6 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 0ba382830..ff3b9170c 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -26,4 +26,4 @@ "publishConfig": { "directory": "dist" } -} \ No newline at end of file +} From 779a27693a9d37ae212c27af353414ff4de07ea4 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Thu, 13 Nov 2025 14:25:47 -0600 Subject: [PATCH 025/262] fix: opencode run timeout --- packages/desktop/src/context/sdk.tsx | 5 ----- packages/opencode/src/cli/cmd/tui/context/sdk.tsx | 5 ----- packages/sdk/js/src/client.ts | 11 +++++++++++ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/desktop/src/context/sdk.tsx b/packages/desktop/src/context/sdk.tsx index 7ffa30494..8d0cace65 100644 --- a/packages/desktop/src/context/sdk.tsx +++ b/packages/desktop/src/context/sdk.tsx @@ -10,11 +10,6 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({ const sdk = createOpencodeClient({ baseUrl: props.url, signal: abort.signal, - fetch: (req) => { - // @ts-ignore - req.timeout = false - return fetch(req) - }, }) const emitter = createGlobalEmitter<{ diff --git a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx index 655c68022..8b7564eb5 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx @@ -10,11 +10,6 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({ const sdk = createOpencodeClient({ baseUrl: props.url, signal: abort.signal, - fetch: (req) => { - // @ts-ignore - req.timeout = false - return fetch(req) - }, }) const emitter = createGlobalEmitter<{ diff --git a/packages/sdk/js/src/client.ts b/packages/sdk/js/src/client.ts index 29b9de906..ac9aa1519 100644 --- a/packages/sdk/js/src/client.ts +++ b/packages/sdk/js/src/client.ts @@ -6,6 +6,17 @@ import { type Config } from "./gen/client/types.gen.js" import { OpencodeClient } from "./gen/sdk.gen.js" export function createOpencodeClient(config?: Config) { + if (!config?.fetch) { + config = { + ...config, + fetch: (req) => { + // @ts-ignore + req.timeout = false + return fetch(req) + }, + } + } + const client = createClient(config) return new OpencodeClient({ client }) } From a8836c5615f620321cc7aa2670767e0c9586d27b Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 13 Nov 2025 14:47:25 -0600 Subject: [PATCH 026/262] wip(desktop): layout improvements --- packages/desktop/index.html | 14 +- .../desktop/src/components/prompt-input.tsx | 12 +- .../desktop/src/components/session-review.tsx | 104 ++++ .../components/sticky-accordion-header.tsx | 17 + packages/desktop/src/context/local.tsx | 11 +- packages/desktop/src/pages/session.tsx | 252 +++----- packages/ui/script/colors.txt | 35 +- packages/ui/script/tailwind.ts | 2 +- packages/ui/src/components/accordion.css | 29 +- packages/ui/src/components/accordion.tsx | 11 +- packages/ui/src/components/button.css | 2 +- packages/ui/src/components/card.css | 2 +- packages/ui/src/components/checkbox.css | 2 +- packages/ui/src/components/collapsible.css | 2 +- packages/ui/src/components/dialog.css | 2 +- packages/ui/src/components/icon-button.css | 2 +- packages/ui/src/components/icon.tsx | 1 + packages/ui/src/components/list.css | 2 +- packages/ui/src/components/select-dialog.css | 4 +- packages/ui/src/components/select.css | 4 +- packages/ui/src/components/tabs.css | 48 +- packages/ui/src/components/tabs.tsx | 31 +- packages/ui/src/components/tooltip.css | 2 +- packages/ui/src/styles/colors.css | 48 ++ packages/ui/src/styles/tailwind/colors.css | 16 +- packages/ui/src/styles/theme.css | 541 ++++++++++++++++-- packages/ui/src/styles/utilities.css | 2 +- 27 files changed, 881 insertions(+), 317 deletions(-) create mode 100644 packages/desktop/src/components/session-review.tsx create mode 100644 packages/desktop/src/components/sticky-accordion-header.tsx diff --git a/packages/desktop/index.html b/packages/desktop/index.html index e88b49ac8..961ae814a 100644 --- a/packages/desktop/index.html +++ b/packages/desktop/index.html @@ -8,14 +8,12 @@ OpenCode - - - - - - - - +
diff --git a/packages/desktop/src/components/prompt-input.tsx b/packages/desktop/src/components/prompt-input.tsx index b2022cf30..2ae5f87fc 100644 --- a/packages/desktop/src/components/prompt-input.tsx +++ b/packages/desktop/src/components/prompt-input.tsx @@ -347,7 +347,7 @@ export const PromptInput: Component = (props) => {
0} fallback={
No matching files
}> @@ -382,7 +382,7 @@ export const PromptInput: Component = (props) => { onSubmit={handleSubmit} classList={{ "bg-surface-raised-stronger-non-alpha border border-border-strong-base": true, - "rounded-2xl overflow-clip focus-within:border-transparent focus-within:shadow-xs-border-select": true, + "rounded-md overflow-clip focus-within:border-transparent focus-within:shadow-xs-border-select": true, [props.class ?? ""]: !!props.class, }} > @@ -396,17 +396,17 @@ export const PromptInput: Component = (props) => { onInput={handleInput} onKeyDown={handleKeyDown} classList={{ - "w-full p-3 text-14-regular text-text-strong focus:outline-none whitespace-pre-wrap": true, + "w-full px-5 py-3 text-14-regular text-text-strong focus:outline-none whitespace-pre-wrap": true, "[&>[data-type=file]]:text-icon-info-active": true, }} /> -
+
Plan and build anything
-
+