From 1ba5535460403be437066c536d6afbd672ccea51 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Wed, 15 Oct 2025 12:04:51 +0000 Subject: [PATCH 01/10] ignore: update download stats 2025-10-15 --- STATS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/STATS.md b/STATS.md index 7b3831a43..aa6156ccc 100644 --- a/STATS.md +++ b/STATS.md @@ -108,3 +108,4 @@ | 2025-10-11 | 488,427 (+4,053) | 414,699 (+8,684) | 903,126 (+12,737) | | 2025-10-12 | 492,125 (+3,698) | 418,745 (+4,046) | 910,870 (+7,744) | | 2025-10-14 | 505,130 (+13,005) | 429,286 (+10,541) | 934,416 (+23,546) | +| 2025-10-15 | 512,717 (+7,587) | 439,290 (+10,004) | 952,007 (+17,591) | From 92bc78a2d3ecda25535dc7772d5092557e0c0e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Haris=20Gu=C5=A1i=C4=87?= Date: Wed, 15 Oct 2025 17:53:09 +0200 Subject: [PATCH 02/10] Improve http error codes (#3186) --- packages/opencode/src/server/server.ts | 66 ++++++++++++++++++++---- packages/opencode/src/storage/storage.ts | 49 ++++++++++++++---- 2 files changed, 94 insertions(+), 21 deletions(-) diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index ded9f0e21..c33e6deb4 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -33,6 +33,8 @@ import { lazy } from "../util/lazy" import { Todo } from "../session/todo" import { InstanceBootstrap } from "../project/bootstrap" import { MCP } from "../mcp" +import { Storage } from "../storage/storage" +import type { ContentfulStatusCode } from "hono/utils/http-status" const ERRORS = { 400: { @@ -42,17 +44,33 @@ const ERRORS = { schema: resolver( z .object({ - data: z.record(z.string(), z.any()), + data: z.any().nullable(), + errors: z.array(z.record(z.string(), z.any())), + success: z.literal(false), }) .meta({ - ref: "Error", + ref: "BadRequestError", }), ), }, }, }, + 404: { + description: "Not found", + content: { + "application/json": { + schema: resolver( + Storage.NotFoundError.Schema + ) + }, + }, + }, } as const +function errors(...codes: number[]) { + return Object.fromEntries(codes.map((code) => [code, ERRORS[code as keyof typeof ERRORS]])) +} + export namespace Server { const log = Log.create({ service: "server" }) @@ -68,13 +86,18 @@ export namespace Server { error: err, }) if (err instanceof NamedError) { - return c.json(err.toObject(), { - status: 400, - }) + let status: ContentfulStatusCode + if (err instanceof Storage.NotFoundError) + status = 404 + else if (err instanceof Provider.ModelNotFoundError) + status = 400 + else + status = 500 + return c.json(err.toObject(), { status }) } const message = err instanceof Error && err.stack ? err.stack : err.toString() return c.json(new NamedError.Unknown({ message }).toObject(), { - status: 400, + status: 500, }) }) .use(async (c, next) => { @@ -153,7 +176,7 @@ export namespace Server { }, }, }, - ...ERRORS, + ...errors(400), }, }), validator("json", Config.Info), @@ -177,7 +200,7 @@ export namespace Server { }, }, }, - ...ERRORS, + ...errors(400), }, }), async (c) => { @@ -210,7 +233,7 @@ export namespace Server { }, }, }, - ...ERRORS, + ...errors(400), }, }), validator( @@ -305,6 +328,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -333,6 +357,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -361,6 +386,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -381,7 +407,7 @@ export namespace Server { description: "Create a new session", operationId: "session.create", responses: { - ...ERRORS, + ...errors(400), 200: { description: "Successfully created session", content: { @@ -413,6 +439,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -440,6 +467,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -481,6 +509,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -541,6 +570,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -567,6 +597,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -596,6 +627,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -625,6 +657,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -661,6 +694,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -693,6 +727,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -727,6 +762,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -762,6 +798,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -792,6 +829,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -822,6 +860,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -852,6 +891,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -879,6 +919,7 @@ export namespace Server { }, }, }, + ...errors(400, 404), }, }), validator( @@ -1132,6 +1173,7 @@ export namespace Server { }, }, }, + ...errors(400), }, }), validator( @@ -1223,6 +1265,7 @@ export namespace Server { }, }, }, + ...errors(400), }, }), validator( @@ -1355,6 +1398,7 @@ export namespace Server { }, }, }, + ...errors(400), }, }), validator( @@ -1406,7 +1450,7 @@ export namespace Server { }, }, }, - ...ERRORS, + ...errors(400), }, }), validator( diff --git a/packages/opencode/src/storage/storage.ts b/packages/opencode/src/storage/storage.ts index 546d123c6..e54fcd446 100644 --- a/packages/opencode/src/storage/storage.ts +++ b/packages/opencode/src/storage/storage.ts @@ -5,12 +5,21 @@ import { Global } from "../global" import { lazy } from "../util/lazy" import { Lock } from "../util/lock" import { $ } from "bun" +import { NamedError } from "@/util/error" +import z from "zod" export namespace Storage { const log = Log.create({ service: "storage" }) type Migration = (dir: string) => Promise + export const NotFoundError = NamedError.create( + "NotFoundError", + z.object({ + message: z.string(), + }), + ) + const MIGRATIONS: Migration[] = [ async (dir) => { const project = path.resolve(dir, "../project") @@ -131,31 +140,51 @@ export namespace Storage { export async function remove(key: string[]) { const dir = await state().then((x) => x.dir) const target = path.join(dir, ...key) + ".json" - await fs.unlink(target).catch(() => {}) + return withErrorHandling(async () => { + await fs.unlink(target).catch(() => {}) + }) } export async function read(key: string[]) { const dir = await state().then((x) => x.dir) const target = path.join(dir, ...key) + ".json" - using _ = await Lock.read(target) - return Bun.file(target).json() as Promise + return withErrorHandling(async () => { + using _ = await Lock.read(target) + return Bun.file(target).json() as Promise + }) } export async function update(key: string[], fn: (draft: T) => void) { const dir = await state().then((x) => x.dir) const target = path.join(dir, ...key) + ".json" - using _ = await Lock.write("storage") - const content = await Bun.file(target).json() - fn(content) - await Bun.write(target, JSON.stringify(content, null, 2)) - return content as T + return withErrorHandling(async () => { + using _ = await Lock.write("storage") + const content = await Bun.file(target).json() + fn(content) + await Bun.write(target, JSON.stringify(content, null, 2)) + return content as T + }) } export async function write(key: string[], content: T) { const dir = await state().then((x) => x.dir) const target = path.join(dir, ...key) + ".json" - using _ = await Lock.write("storage") - await Bun.write(target, JSON.stringify(content, null, 2)) + return withErrorHandling(async () => { + using _ = await Lock.write("storage") + await Bun.write(target, JSON.stringify(content, null, 2)) + }) + } + + async function withErrorHandling(body: () => Promise) { + return body().catch((e) => { + if (!(e instanceof Error)) + throw e + const errnoException = e as NodeJS.ErrnoException + if (errnoException.code === "ENOENT") { + throw new NotFoundError({ message: `Resource not found: ${errnoException.path}` }) + } + throw e + }) } const glob = new Bun.Glob("**/*") From e29d1d339ce5022f5b573d6e112a00dd1b870559 Mon Sep 17 00:00:00 2001 From: Matt Gillard Date: Thu, 16 Oct 2025 03:09:22 +1100 Subject: [PATCH 03/10] updated bedrock provider for the new Australian sonnet 4.5 cross region inference (#3050) Co-authored-by: Matt Gillard --- packages/opencode/src/provider/provider.ts | 37 ++++++++++++---------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index 77440413c..37a0efdcb 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -120,12 +120,17 @@ export namespace Provider { break } case "ap": { - const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "nova-pro"].some((m) => - modelID.includes(m), - ) - if (modelRequiresPrefix) { - regionPrefix = "apac" - modelID = `${regionPrefix}.${modelID}` + const isAustraliaRegion = ["ap-southeast-2", "ap-southeast-4"].includes(region) + if (isAustraliaRegion && modelID.startsWith("anthropic.claude-sonnet-4-5")) { + modelID = `au.${modelID}` + } else { + const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "nova-pro"].some((m) => + modelID.includes(m), + ) + if (modelRequiresPrefix) { + regionPrefix = "apac" + modelID = `${regionPrefix}.${modelID}` + } } break } @@ -265,17 +270,17 @@ export namespace Provider { cost: !model.cost && !existing?.cost ? { - input: 0, - output: 0, - cache_read: 0, - cache_write: 0, - } + input: 0, + output: 0, + cache_read: 0, + cache_write: 0, + } : { - cache_read: 0, - cache_write: 0, - ...existing?.cost, - ...model.cost, - }, + cache_read: 0, + cache_write: 0, + ...existing?.cost, + ...model.cost, + }, options: { ...existing?.options, ...model.options, From 2267ce251162d5c84c3988da07f80a9d781cde65 Mon Sep 17 00:00:00 2001 From: Frank Date: Wed, 15 Oct 2025 13:52:59 -0400 Subject: [PATCH 04/10] zen: support haiku 4.5 --- .../routes/workspace/[id]/model-section.tsx | 2 +- packages/web/src/content/docs/zen.mdx | 24 ++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/console/app/src/routes/workspace/[id]/model-section.tsx b/packages/console/app/src/routes/workspace/[id]/model-section.tsx index be3cffc47..0a6086036 100644 --- a/packages/console/app/src/routes/workspace/[id]/model-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/model-section.tsx @@ -22,7 +22,7 @@ const getModelsInfo = query(async (workspaceID: string) => { return withActor(async () => { return { all: Object.entries(ZenModel.list()) - .filter(([id, _model]) => !["claude-3-5-haiku", "qwen3-max"].includes(id)) + .filter(([id, _model]) => !["claude-3-5-haiku"].includes(id)) .filter(([id, _model]) => !id.startsWith("an-")) .sort(([_idA, modelA], [_idB, modelB]) => modelA.name.localeCompare(modelB.name)) .map(([id, model]) => ({ id, name: model.name })), diff --git a/packages/web/src/content/docs/zen.mdx b/packages/web/src/content/docs/zen.mdx index f1c2b3338..464bbfd52 100644 --- a/packages/web/src/content/docs/zen.mdx +++ b/packages/web/src/content/docs/zen.mdx @@ -62,17 +62,18 @@ You are charged per request and you can add credits to your account. You can also access our models through the following API endpoints. -| Model | Model ID | Endpoint | AI SDK Package | -| ---------------- | ---------------- | --------------------------------------------- | --------------------------- | -| GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | -| GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | -| Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Haiku 3.5 | claude-3-5-haiku | `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` | -| Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Grok Code Fast 1 | grok-code | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Model | Model ID | Endpoint | AI SDK Package | +| ----------------- | ----------------- | --------------------------------------------- | --------------------------- | +| GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Haiku 3.5 | claude-3-5-haiku | `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` | +| Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Grok Code Fast 1 | grok-code | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | The [model id](/docs/config/#models) in your OpenCode config uses the format `opencode/`. For example, for GPT 5 Codex, you would @@ -94,6 +95,7 @@ We support a pay-as-you-go model. Below are the prices **per 1M tokens**. | Claude Sonnet 4.5 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | +| Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | | Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | | GPT 5 | $1.25 | $10.00 | $0.125 | - | From b2ff4be4c6990bbad2576a13c13dba83245c89e0 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Wed, 15 Oct 2025 13:00:26 -0500 Subject: [PATCH 05/10] fix: Text content blocks must contain non-whitespace text (#3194) --- packages/opencode/src/session/message-v2.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index 8dc059ca1..81b4158db 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -513,6 +513,8 @@ export namespace MessageV2 { } if (msg.info.role === "assistant") { + const hasEmptyTextPart = msg.parts.some((part) => part.type === "text" && part.text.trim() === "") + if (hasEmptyTextPart) continue result.push({ id: msg.info.id, role: "assistant", From 278ffb9a4e7f99c7546ec8150b195d6e49476f3a Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Wed, 15 Oct 2025 13:01:54 -0500 Subject: [PATCH 06/10] fix: spawns hanging (#3192) --- packages/opencode/src/tool/bash.ts | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/opencode/src/tool/bash.ts b/packages/opencode/src/tool/bash.ts index d4e8ce85a..af1610d56 100644 --- a/packages/opencode/src/tool/bash.ts +++ b/packages/opencode/src/tool/bash.ts @@ -145,14 +145,26 @@ export const BashTool = Tool.define("bash", { }) } - const process = spawn(params.command, { + const proc = spawn(params.command, { shell: true, cwd: Instance.directory, signal: ctx.abort, stdio: ["ignore", "pipe", "pipe"], timeout, + detached: process.platform !== "win32", }) + if (!ctx.abort.aborted) { + ctx.abort.addEventListener("abort", () => { + if (!proc.pid) return + if (process.platform === "win32") { + proc.kill() + return + } + process.kill(-proc.pid) + }) + } + let output = "" // Initialize metadata with empty output @@ -163,7 +175,7 @@ export const BashTool = Tool.define("bash", { }, }) - process.stdout?.on("data", (chunk) => { + proc.stdout?.on("data", (chunk) => { output += chunk.toString() ctx.metadata({ metadata: { @@ -173,7 +185,7 @@ export const BashTool = Tool.define("bash", { }) }) - process.stderr?.on("data", (chunk) => { + proc.stderr?.on("data", (chunk) => { output += chunk.toString() ctx.metadata({ metadata: { @@ -184,7 +196,7 @@ export const BashTool = Tool.define("bash", { }) await new Promise((resolve) => { - process.on("close", () => { + proc.on("close", () => { resolve() }) }) @@ -192,7 +204,7 @@ export const BashTool = Tool.define("bash", { ctx.metadata({ metadata: { output: output, - exit: process.exitCode, + exit: proc.exitCode, description: params.description, }, }) @@ -202,7 +214,7 @@ export const BashTool = Tool.define("bash", { output += "\n\n(Output was truncated due to length limit)" } - if (process.signalCode === "SIGTERM" && params.timeout) { + if (proc.signalCode === "SIGTERM" && params.timeout) { output += `\n\n(Command timed out after ${timeout} ms)` } @@ -210,7 +222,7 @@ export const BashTool = Tool.define("bash", { title: params.command, metadata: { output, - exit: process.exitCode, + exit: proc.exitCode, description: params.description, }, output, From ca534a36e590b4aba9f0feb00b9ee3362ce7ef0a Mon Sep 17 00:00:00 2001 From: Fabian Kukuck <7205627+fkukuck@users.noreply.github.com> Date: Wed, 15 Oct 2025 20:44:16 +0200 Subject: [PATCH 07/10] feat: make compact feature use streaming API (#3079) Co-authored-by: fku Co-authored-by: Aiden Cline --- packages/opencode/src/session/compaction.ts | 62 ++++++++++++++------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/packages/opencode/src/session/compaction.ts b/packages/opencode/src/session/compaction.ts index 78f8d4a34..f9c5f3633 100644 --- a/packages/opencode/src/session/compaction.ts +++ b/packages/opencode/src/session/compaction.ts @@ -1,4 +1,4 @@ -import { generateText, type ModelMessage } from "ai" +import { streamText, type ModelMessage } from "ai" import { Session } from "." import { Identifier } from "../id/id" import { Instance } from "../project/instance" @@ -122,7 +122,19 @@ export namespace SessionCompaction { created: Date.now(), }, })) as MessageV2.Assistant - const generated = await generateText({ + const part = (await Session.updatePart({ + type: "text", + sessionID: input.sessionID, + messageID: msg.id, + id: Identifier.ascending("part"), + text: "", + time: { + start: Date.now(), + }, + })) as MessageV2.TextPart + + let summaryText = "" + const stream = streamText({ maxRetries: 10, model: model.language, providerOptions: { @@ -147,23 +159,35 @@ export namespace SessionCompaction { }, ], }) - const usage = Session.getUsage({ model: model.info, usage: generated.usage, metadata: generated.providerMetadata }) - msg.cost += usage.cost - msg.tokens = usage.tokens - msg.summary = true - msg.time.completed = Date.now() - await Session.updateMessage(msg) - const part = await Session.updatePart({ - type: "text", - sessionID: input.sessionID, - messageID: msg.id, - id: Identifier.ascending("part"), - text: generated.text, - time: { - start: Date.now(), - end: Date.now(), - }, - }) + + for await (const value of stream.fullStream) { + switch (value.type) { + case "text-delta": + summaryText += value.text + await Session.updatePart({ + ...part, + text: summaryText, + }) + break + case "text-end": + part.text = summaryText + await Session.updatePart({ + ...part, + }) + break + case "finish": { + const usage = Session.getUsage({ model: model.info, usage: value.totalUsage, metadata: undefined }) + msg.cost += usage.cost + msg.tokens = usage.tokens + msg.summary = true + msg.time.completed = Date.now() + await Session.updateMessage(msg) + part.time!.end = Date.now() + await Session.updatePart(part) + break + } + } + } Bus.publish(Event.Compacted, { sessionID: input.sessionID, From d3caa55c108367e84da269f784406baf63474f38 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Wed, 15 Oct 2025 15:20:14 -0500 Subject: [PATCH 08/10] Revert "fix: spawns hanging (#3192)" This reverts commit 278ffb9a4e7f99c7546ec8150b195d6e49476f3a. --- packages/opencode/src/tool/bash.ts | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/packages/opencode/src/tool/bash.ts b/packages/opencode/src/tool/bash.ts index af1610d56..d4e8ce85a 100644 --- a/packages/opencode/src/tool/bash.ts +++ b/packages/opencode/src/tool/bash.ts @@ -145,26 +145,14 @@ export const BashTool = Tool.define("bash", { }) } - const proc = spawn(params.command, { + const process = spawn(params.command, { shell: true, cwd: Instance.directory, signal: ctx.abort, stdio: ["ignore", "pipe", "pipe"], timeout, - detached: process.platform !== "win32", }) - if (!ctx.abort.aborted) { - ctx.abort.addEventListener("abort", () => { - if (!proc.pid) return - if (process.platform === "win32") { - proc.kill() - return - } - process.kill(-proc.pid) - }) - } - let output = "" // Initialize metadata with empty output @@ -175,7 +163,7 @@ export const BashTool = Tool.define("bash", { }, }) - proc.stdout?.on("data", (chunk) => { + process.stdout?.on("data", (chunk) => { output += chunk.toString() ctx.metadata({ metadata: { @@ -185,7 +173,7 @@ export const BashTool = Tool.define("bash", { }) }) - proc.stderr?.on("data", (chunk) => { + process.stderr?.on("data", (chunk) => { output += chunk.toString() ctx.metadata({ metadata: { @@ -196,7 +184,7 @@ export const BashTool = Tool.define("bash", { }) await new Promise((resolve) => { - proc.on("close", () => { + process.on("close", () => { resolve() }) }) @@ -204,7 +192,7 @@ export const BashTool = Tool.define("bash", { ctx.metadata({ metadata: { output: output, - exit: proc.exitCode, + exit: process.exitCode, description: params.description, }, }) @@ -214,7 +202,7 @@ export const BashTool = Tool.define("bash", { output += "\n\n(Output was truncated due to length limit)" } - if (proc.signalCode === "SIGTERM" && params.timeout) { + if (process.signalCode === "SIGTERM" && params.timeout) { output += `\n\n(Command timed out after ${timeout} ms)` } @@ -222,7 +210,7 @@ export const BashTool = Tool.define("bash", { title: params.command, metadata: { output, - exit: proc.exitCode, + exit: process.exitCode, description: params.description, }, output, From 2d2d4641cbcea97af33ceca4d091a92f379a70c9 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Wed, 15 Oct 2025 16:06:11 -0500 Subject: [PATCH 09/10] ignore: update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a29d1032..aa2be8aef 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Take a look at the git history to see what kind of PRs we end up merging. To run OpenCode locally you need. -- Bun +- Bun 1.3 or higher - Golang 1.24.x And run. From 790fe72f39cc9b608ff3a790df822f1d3240eca1 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Wed, 15 Oct 2025 19:48:57 -0400 Subject: [PATCH 10/10] sync --- packages/opencode/src/session/todo.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/session/todo.ts b/packages/opencode/src/session/todo.ts index 4f4268540..d0b454f75 100644 --- a/packages/opencode/src/session/todo.ts +++ b/packages/opencode/src/session/todo.ts @@ -29,6 +29,8 @@ export namespace Todo { } export async function get(sessionID: string) { - return Storage.read(["todo", sessionID]) ?? [] + return Storage.read(["todo", sessionID]) + .then((x) => x || []) + .catch(() => []) } }