From 9b57db30d12d9ad3d961f5d51970be8459eaa783 Mon Sep 17 00:00:00 2001 From: seilk <88271769+seilk@users.noreply.github.com> Date: Fri, 16 Jan 2026 07:00:36 +0900 Subject: [PATCH 01/99] feat: add litellmProxy provider option for explicit LiteLLM compatibility (#8658) Co-authored-by: Mark Henderson Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> --- packages/opencode/src/session/llm.ts | 36 +++++++- packages/opencode/src/session/message-v2.ts | 11 +++ packages/opencode/test/session/llm.test.ts | 90 +++++++++++++++++++ .../opencode/test/session/message-v2.test.ts | 90 +++++++++++++++++++ 4 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 packages/opencode/test/session/llm.test.ts diff --git a/packages/opencode/src/session/llm.ts b/packages/opencode/src/session/llm.ts index 5b6178bc01b..d36af37f7d1 100644 --- a/packages/opencode/src/session/llm.ts +++ b/packages/opencode/src/session/llm.ts @@ -10,6 +10,8 @@ import { type Tool, type ToolSet, extractReasoningMiddleware, + tool, + jsonSchema, } from "ai" import { clone, mergeDeep, pipe } from "remeda" import { ProviderTransform } from "@/provider/transform" @@ -140,6 +142,26 @@ export namespace LLM { const tools = await resolveTools(input) + // LiteLLM and some Anthropic proxies require the tools parameter to be present + // when message history contains tool calls, even if no tools are being used. + // Add a dummy tool that is never called to satisfy this validation. + // This is enabled for: + // 1. Providers with "litellm" in their ID or API ID (auto-detected) + // 2. Providers with explicit "litellmProxy: true" option (opt-in for custom gateways) + const isLiteLLMProxy = + provider.options?.["litellmProxy"] === true || + input.model.providerID.toLowerCase().includes("litellm") || + input.model.api.id.toLowerCase().includes("litellm") + + if (isLiteLLMProxy && Object.keys(tools).length === 0 && hasToolCalls(input.messages)) { + tools["_noop"] = tool({ + description: + "Placeholder for LiteLLM/Anthropic proxy compatibility - required when message history contains tool calls but no active tools are needed", + inputSchema: jsonSchema({ type: "object", properties: {} }), + execute: async () => ({ output: "", title: "", metadata: {} }), + }) + } + return streamText({ onError(error) { l.error("stream error", { @@ -171,7 +193,7 @@ export namespace LLM { topP: params.topP, topK: params.topK, providerOptions: ProviderTransform.providerOptions(input.model, params.options), - activeTools: Object.keys(tools).filter((x) => x !== "invalid"), + activeTools: Object.keys(tools).filter((x) => x !== "invalid" && x !== "_noop"), tools, maxOutputTokens, abortSignal: input.abort, @@ -238,4 +260,16 @@ export namespace LLM { } return input.tools } + + // Check if messages contain any tool-call content + // Used to determine if a dummy tool should be added for LiteLLM proxy compatibility + export function hasToolCalls(messages: ModelMessage[]): boolean { + for (const msg of messages) { + if (!Array.isArray(msg.content)) continue + for (const part of msg.content) { + if (part.type === "tool-call" || part.type === "tool-result") return true + } + } + return false + } } diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index c1d4015f6d3..7a55599fd55 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -533,6 +533,17 @@ export namespace MessageV2 { errorText: part.state.error, callProviderMetadata: part.metadata, }) + // Handle pending/running tool calls to prevent dangling tool_use blocks + // Anthropic/Claude APIs require every tool_use to have a corresponding tool_result + if (part.state.status === "pending" || part.state.status === "running") + assistantMessage.parts.push({ + type: ("tool-" + part.tool) as `tool-${string}`, + state: "output-error", + toolCallId: part.callID, + input: part.state.input, + errorText: "[Tool execution was interrupted]", + callProviderMetadata: part.metadata, + }) } if (part.type === "reasoning") { assistantMessage.parts.push({ diff --git a/packages/opencode/test/session/llm.test.ts b/packages/opencode/test/session/llm.test.ts new file mode 100644 index 00000000000..779cbc48f7d --- /dev/null +++ b/packages/opencode/test/session/llm.test.ts @@ -0,0 +1,90 @@ +import { describe, expect, test } from "bun:test" +import { LLM } from "../../src/session/llm" +import type { ModelMessage } from "ai" + +describe("session.llm.hasToolCalls", () => { + test("returns false for empty messages array", () => { + expect(LLM.hasToolCalls([])).toBe(false) + }) + + test("returns false for messages with only text content", () => { + const messages: ModelMessage[] = [ + { + role: "user", + content: [{ type: "text", text: "Hello" }], + }, + { + role: "assistant", + content: [{ type: "text", text: "Hi there" }], + }, + ] + expect(LLM.hasToolCalls(messages)).toBe(false) + }) + + test("returns true when messages contain tool-call", () => { + const messages = [ + { + role: "user", + content: [{ type: "text", text: "Run a command" }], + }, + { + role: "assistant", + content: [ + { + type: "tool-call", + toolCallId: "call-123", + toolName: "bash", + }, + ], + }, + ] as ModelMessage[] + expect(LLM.hasToolCalls(messages)).toBe(true) + }) + + test("returns true when messages contain tool-result", () => { + const messages = [ + { + role: "tool", + content: [ + { + type: "tool-result", + toolCallId: "call-123", + toolName: "bash", + }, + ], + }, + ] as ModelMessage[] + expect(LLM.hasToolCalls(messages)).toBe(true) + }) + + test("returns false for messages with string content", () => { + const messages: ModelMessage[] = [ + { + role: "user", + content: "Hello world", + }, + { + role: "assistant", + content: "Hi there", + }, + ] + expect(LLM.hasToolCalls(messages)).toBe(false) + }) + + test("returns true when tool-call is mixed with text content", () => { + const messages = [ + { + role: "assistant", + content: [ + { type: "text", text: "Let me run that command" }, + { + type: "tool-call", + toolCallId: "call-456", + toolName: "read", + }, + ], + }, + ] as ModelMessage[] + expect(LLM.hasToolCalls(messages)).toBe(true) + }) +}) diff --git a/packages/opencode/test/session/message-v2.test.ts b/packages/opencode/test/session/message-v2.test.ts index 071da270c9c..f069f6ba68a 100644 --- a/packages/opencode/test/session/message-v2.test.ts +++ b/packages/opencode/test/session/message-v2.test.ts @@ -569,4 +569,94 @@ describe("session.message-v2.toModelMessage", () => { expect(MessageV2.toModelMessage(input)).toStrictEqual([]) }) + + test("converts pending/running tool calls to error results to prevent dangling tool_use", () => { + const userID = "m-user" + const assistantID = "m-assistant" + + const input: MessageV2.WithParts[] = [ + { + info: userInfo(userID), + parts: [ + { + ...basePart(userID, "u1"), + type: "text", + text: "run tool", + }, + ] as MessageV2.Part[], + }, + { + info: assistantInfo(assistantID, userID), + parts: [ + { + ...basePart(assistantID, "a1"), + type: "tool", + callID: "call-pending", + tool: "bash", + state: { + status: "pending", + input: { cmd: "ls" }, + raw: "", + }, + }, + { + ...basePart(assistantID, "a2"), + type: "tool", + callID: "call-running", + tool: "read", + state: { + status: "running", + input: { path: "/tmp" }, + time: { start: 0 }, + }, + }, + ] as MessageV2.Part[], + }, + ] + + const result = MessageV2.toModelMessage(input) + + expect(result).toStrictEqual([ + { + role: "user", + content: [{ type: "text", text: "run tool" }], + }, + { + role: "assistant", + content: [ + { + type: "tool-call", + toolCallId: "call-pending", + toolName: "bash", + input: { cmd: "ls" }, + providerExecuted: undefined, + }, + { + type: "tool-call", + toolCallId: "call-running", + toolName: "read", + input: { path: "/tmp" }, + providerExecuted: undefined, + }, + ], + }, + { + role: "tool", + content: [ + { + type: "tool-result", + toolCallId: "call-pending", + toolName: "bash", + output: { type: "error-text", value: "[Tool execution was interrupted]" }, + }, + { + type: "tool-result", + toolCallId: "call-running", + toolName: "read", + output: { type: "error-text", value: "[Tool execution was interrupted]" }, + }, + ], + }, + ]) + }) }) From 83ed1adcbd41e903fd640bcacfbbc314f9c2af5e Mon Sep 17 00:00:00 2001 From: "outside.observer" Date: Fri, 16 Jan 2026 01:02:29 +0300 Subject: [PATCH 02/99] feat: add Carbonfox theme (#8723) --- .../src/cli/cmd/tui/context/theme.tsx | 2 + .../cli/cmd/tui/context/theme/carbonfox.json | 248 ++++++++++++++++++ packages/ui/src/theme/default-themes.ts | 3 + packages/ui/src/theme/themes/carbonfox.json | 122 +++++++++ 4 files changed, 375 insertions(+) create mode 100644 packages/opencode/src/cli/cmd/tui/context/theme/carbonfox.json create mode 100644 packages/ui/src/theme/themes/carbonfox.json diff --git a/packages/opencode/src/cli/cmd/tui/context/theme.tsx b/packages/opencode/src/cli/cmd/tui/context/theme.tsx index 127be0dfc09..7cde1b9648e 100644 --- a/packages/opencode/src/cli/cmd/tui/context/theme.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/theme.tsx @@ -35,6 +35,7 @@ import tokyonight from "./theme/tokyonight.json" with { type: "json" } import vercel from "./theme/vercel.json" with { type: "json" } import vesper from "./theme/vesper.json" with { type: "json" } import zenburn from "./theme/zenburn.json" with { type: "json" } +import carbonfox from "./theme/carbonfox.json" with { type: "json" } import { useKV } from "./kv" import { useRenderer } from "@opentui/solid" import { createStore, produce } from "solid-js/store" @@ -170,6 +171,7 @@ export const DEFAULT_THEMES: Record = { vesper, vercel, zenburn, + carbonfox, } function resolveTheme(theme: ThemeJson, mode: "dark" | "light") { diff --git a/packages/opencode/src/cli/cmd/tui/context/theme/carbonfox.json b/packages/opencode/src/cli/cmd/tui/context/theme/carbonfox.json new file mode 100644 index 00000000000..b91de1fea9f --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/context/theme/carbonfox.json @@ -0,0 +1,248 @@ +{ + "$schema": "https://opencode.ai/theme.json", + "defs": { + "bg0": "#0d0d0d", + "bg1": "#161616", + "bg1a": "#1a1a1a", + "bg2": "#1e1e1e", + "bg3": "#262626", + "bg4": "#303030", + "fg0": "#ffffff", + "fg1": "#f2f4f8", + "fg2": "#a9afbc", + "fg3": "#7d848f", + "lbg0": "#ffffff", + "lbg1": "#f4f4f4", + "lbg2": "#e8e8e8", + "lbg3": "#dcdcdc", + "lfg0": "#000000", + "lfg1": "#161616", + "lfg2": "#525252", + "lfg3": "#6f6f6f", + "red": "#ee5396", + "green": "#25be6a", + "yellow": "#08bdba", + "blue": "#78a9ff", + "magenta": "#be95ff", + "cyan": "#33b1ff", + "white": "#dfdfe0", + "orange": "#3ddbd9", + "pink": "#ff7eb6", + "blueBright": "#8cb6ff", + "cyanBright": "#52c7ff", + "greenBright": "#46c880", + "redLight": "#9f1853", + "greenLight": "#198038", + "yellowLight": "#007d79", + "blueLight": "#0043ce", + "magentaLight": "#6929c4", + "cyanLight": "#0072c3", + "warning": "#f1c21b", + "diffGreen": "#50fa7b", + "diffRed": "#ff6b6b", + "diffGreenBg": "#0f2418", + "diffRedBg": "#2a1216" + }, + "theme": { + "primary": { + "dark": "cyan", + "light": "blueLight" + }, + "secondary": { + "dark": "blue", + "light": "blueLight" + }, + "accent": { + "dark": "pink", + "light": "redLight" + }, + "error": { + "dark": "red", + "light": "redLight" + }, + "warning": { + "dark": "warning", + "light": "yellowLight" + }, + "success": { + "dark": "green", + "light": "greenLight" + }, + "info": { + "dark": "blue", + "light": "blueLight" + }, + "text": { + "dark": "fg1", + "light": "lfg1" + }, + "textMuted": { + "dark": "fg3", + "light": "lfg3" + }, + "background": { + "dark": "bg1", + "light": "lbg0" + }, + "backgroundPanel": { + "dark": "bg1a", + "light": "lbg1" + }, + "backgroundElement": { + "dark": "bg2", + "light": "lbg1" + }, + "border": { + "dark": "bg4", + "light": "lbg3" + }, + "borderActive": { + "dark": "cyan", + "light": "blueLight" + }, + "borderSubtle": { + "dark": "bg3", + "light": "lbg2" + }, + "diffAdded": { + "dark": "diffGreen", + "light": "greenLight" + }, + "diffRemoved": { + "dark": "diffRed", + "light": "redLight" + }, + "diffContext": { + "dark": "fg3", + "light": "lfg3" + }, + "diffHunkHeader": { + "dark": "blue", + "light": "blueLight" + }, + "diffHighlightAdded": { + "dark": "#7dffaa", + "light": "greenLight" + }, + "diffHighlightRemoved": { + "dark": "#ff9999", + "light": "redLight" + }, + "diffAddedBg": { + "dark": "diffGreenBg", + "light": "#defbe6" + }, + "diffRemovedBg": { + "dark": "diffRedBg", + "light": "#fff1f1" + }, + "diffContextBg": { + "dark": "bg1", + "light": "lbg1" + }, + "diffLineNumber": { + "dark": "fg3", + "light": "lfg3" + }, + "diffAddedLineNumberBg": { + "dark": "diffGreenBg", + "light": "#defbe6" + }, + "diffRemovedLineNumberBg": { + "dark": "diffRedBg", + "light": "#fff1f1" + }, + "markdownText": { + "dark": "fg1", + "light": "lfg1" + }, + "markdownHeading": { + "dark": "blueBright", + "light": "blueLight" + }, + "markdownLink": { + "dark": "blue", + "light": "blueLight" + }, + "markdownLinkText": { + "dark": "cyan", + "light": "cyanLight" + }, + "markdownCode": { + "dark": "green", + "light": "greenLight" + }, + "markdownBlockQuote": { + "dark": "fg3", + "light": "lfg3" + }, + "markdownEmph": { + "dark": "magenta", + "light": "magentaLight" + }, + "markdownStrong": { + "dark": "fg0", + "light": "lfg0" + }, + "markdownHorizontalRule": { + "dark": "bg4", + "light": "lbg3" + }, + "markdownListItem": { + "dark": "cyan", + "light": "cyanLight" + }, + "markdownListEnumeration": { + "dark": "cyan", + "light": "cyanLight" + }, + "markdownImage": { + "dark": "blue", + "light": "blueLight" + }, + "markdownImageText": { + "dark": "cyan", + "light": "cyanLight" + }, + "markdownCodeBlock": { + "dark": "fg2", + "light": "lfg2" + }, + "syntaxComment": { + "dark": "fg3", + "light": "lfg3" + }, + "syntaxKeyword": { + "dark": "magenta", + "light": "magentaLight" + }, + "syntaxFunction": { + "dark": "blueBright", + "light": "blueLight" + }, + "syntaxVariable": { + "dark": "white", + "light": "lfg1" + }, + "syntaxString": { + "dark": "green", + "light": "greenLight" + }, + "syntaxNumber": { + "dark": "orange", + "light": "yellowLight" + }, + "syntaxType": { + "dark": "yellow", + "light": "yellowLight" + }, + "syntaxOperator": { + "dark": "fg2", + "light": "lfg2" + }, + "syntaxPunctuation": { + "dark": "fg2", + "light": "lfg1" + } + } +} diff --git a/packages/ui/src/theme/default-themes.ts b/packages/ui/src/theme/default-themes.ts index 54c96251cf3..e90892a8e7e 100644 --- a/packages/ui/src/theme/default-themes.ts +++ b/packages/ui/src/theme/default-themes.ts @@ -11,6 +11,7 @@ import oneDarkProThemeJson from "./themes/onedarkpro.json" import shadesOfPurpleThemeJson from "./themes/shadesofpurple.json" import nightowlThemeJson from "./themes/nightowl.json" import vesperThemeJson from "./themes/vesper.json" +import carbonfoxThemeJson from "./themes/carbonfox.json" export const oc1Theme = oc1ThemeJson as DesktopTheme export const tokyonightTheme = tokyoThemeJson as DesktopTheme @@ -24,6 +25,7 @@ export const oneDarkProTheme = oneDarkProThemeJson as DesktopTheme export const shadesOfPurpleTheme = shadesOfPurpleThemeJson as DesktopTheme export const nightowlTheme = nightowlThemeJson as DesktopTheme export const vesperTheme = vesperThemeJson as DesktopTheme +export const carbonfoxTheme = carbonfoxThemeJson as DesktopTheme export const DEFAULT_THEMES: Record = { "oc-1": oc1Theme, @@ -38,4 +40,5 @@ export const DEFAULT_THEMES: Record = { shadesofpurple: shadesOfPurpleTheme, nightowl: nightowlTheme, vesper: vesperTheme, + carbonfox: carbonfoxTheme, } diff --git a/packages/ui/src/theme/themes/carbonfox.json b/packages/ui/src/theme/themes/carbonfox.json new file mode 100644 index 00000000000..e2fa20d8034 --- /dev/null +++ b/packages/ui/src/theme/themes/carbonfox.json @@ -0,0 +1,122 @@ +{ + "$schema": "https://opencode.ai/desktop-theme.json", + "name": "Carbonfox", + "id": "carbonfox", + "light": { + "seeds": { + "neutral": "#8e8e8e", + "primary": "#0072c3", + "success": "#198038", + "warning": "#f1c21b", + "error": "#da1e28", + "info": "#0043ce", + "interactive": "#0f62fe", + "diffAdd": "#198038", + "diffDelete": "#da1e28" + }, + "overrides": { + "background-base": "#ffffff", + "background-weak": "#f4f4f4", + "background-strong": "#e8e8e8", + "background-stronger": "#dcdcdc", + "surface-raised-strong": "#ffffff", + "surface-raised-stronger": "#ffffff", + "surface-float-base": "#161616", + "surface-float-base-hover": "#262626", + "text-base": "#161616", + "text-weak": "#525252", + "text-strong": "#000000", + "syntax-string": "#198038", + "syntax-primitive": "#da1e28", + "syntax-property": "#0043ce", + "syntax-type": "#007d79", + "syntax-constant": "#6929c4", + "syntax-keyword": "#525252", + "syntax-info": "#0043ce", + "markdown-heading": "#0043ce", + "markdown-text": "#161616", + "markdown-link": "#0043ce", + "markdown-link-text": "#0072c3", + "markdown-code": "#198038", + "markdown-block-quote": "#525252", + "markdown-emph": "#6929c4", + "markdown-strong": "#161616", + "markdown-horizontal-rule": "#c6c6c6", + "markdown-list-item": "#0072c3", + "markdown-list-enumeration": "#0072c3", + "markdown-image": "#0043ce", + "markdown-image-text": "#0072c3", + "markdown-code-block": "#393939" + } + }, + "dark": { + "seeds": { + "neutral": "#393939", + "primary": "#33b1ff", + "success": "#42be65", + "warning": "#f1c21b", + "error": "#ff8389", + "info": "#78a9ff", + "interactive": "#4589ff", + "diffAdd": "#42be65", + "diffDelete": "#ff8389" + }, + "overrides": { + "background-base": "#161616", + "background-weak": "#262626", + "background-strong": "#0d0d0d", + "background-stronger": "#000000", + "surface-raised-base": "#1c1c1c", + "surface-raised-base-hover": "#262626", + "surface-raised-strong": "#262626", + "surface-raised-strong-hover": "#303030", + "surface-raised-stronger": "#303030", + "surface-raised-stronger-hover": "#393939", + "surface-raised-stronger-non-alpha": "#303030", + "surface-float-base": "#0d0d0d", + "surface-float-base-hover": "#1a1a1a", + "surface-inset-base": "#0d0d0d", + "surface-inset-strong": "#000000", + "surface-base": "#1e1e1e", + "surface-base-hover": "#262626", + "surface-diff-add-base": "#0e3a22", + "surface-diff-delete-base": "#4d1a1f", + "input-base": "#262626", + "input-hover": "#303030", + "button-secondary-base": "#393939", + "button-secondary-hover": "#4c4c4c", + "border-weak-base": "#393939", + "border-weak-hover": "#4c4c4c", + "border-base": "#525252", + "border-hover": "#636363", + "border-strong-base": "#6f6f6f", + "text-base": "#f2f4f8", + "text-weak": "#8d8d8d", + "text-weaker": "#6f6f6f", + "text-strong": "#ffffff", + "icon-base": "#8d8d8d", + "icon-weak-base": "#6f6f6f", + "syntax-string": "#42be65", + "syntax-primitive": "#ff8389", + "syntax-property": "#78a9ff", + "syntax-type": "#08bdba", + "syntax-constant": "#be95ff", + "syntax-keyword": "#8d8d8d", + "syntax-info": "#78a9ff", + "markdown-heading": "#82cfff", + "markdown-text": "#f2f4f8", + "markdown-link": "#78a9ff", + "markdown-link-text": "#33b1ff", + "markdown-code": "#42be65", + "markdown-block-quote": "#8d8d8d", + "markdown-emph": "#be95ff", + "markdown-strong": "#ffffff", + "markdown-horizontal-rule": "#393939", + "markdown-list-item": "#33b1ff", + "markdown-list-enumeration": "#33b1ff", + "markdown-image": "#78a9ff", + "markdown-image-text": "#33b1ff", + "markdown-code-block": "#c6c6c6" + } + } +} From b9b5d42bd8fc1e7a4285897fde3d33bd402be6fe Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Thu, 15 Jan 2026 22:03:17 +0000 Subject: [PATCH 03/99] chore: generate --- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 3384f02725d..d479f6d343e 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -25,4 +25,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 f64489effca..ec9391a49ff 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -30,4 +30,4 @@ "publishConfig": { "directory": "dist" } -} \ No newline at end of file +} From f4086ac4596a6a22cc9c5b0f82f81c0068b9d470 Mon Sep 17 00:00:00 2001 From: Jeong Juahn Date: Fri, 16 Jan 2026 07:04:01 +0900 Subject: [PATCH 04/99] fix:subagent reasoningEffort not being applied (#8646) Co-authored-by: Bot --- packages/opencode/src/tool/task.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts index 170d4448088..96e3d36b831 100644 --- a/packages/opencode/src/tool/task.ts +++ b/packages/opencode/src/tool/task.ts @@ -150,6 +150,7 @@ export const TaskTool = Tool.define("task", async (ctx) => { providerID: model.providerID, }, agent: agent.name, + options: agent.options, tools: { todowrite: false, todoread: false, From 9d8d0e97eca59f626f67b1ec1b9bdcaf05f717dd Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Thu, 15 Jan 2026 16:06:35 -0600 Subject: [PATCH 05/99] Revert "fix:subagent reasoningEffort not being applied (#8646)" This reverts commit f4086ac4596a6a22cc9c5b0f82f81c0068b9d470. --- packages/opencode/src/tool/task.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts index 96e3d36b831..170d4448088 100644 --- a/packages/opencode/src/tool/task.ts +++ b/packages/opencode/src/tool/task.ts @@ -150,7 +150,6 @@ export const TaskTool = Tool.define("task", async (ctx) => { providerID: model.providerID, }, agent: agent.name, - options: agent.options, tools: { todowrite: false, todoread: false, From 306fc05c0096efde6b01c86f87757644150528bd Mon Sep 17 00:00:00 2001 From: David Hill Date: Thu, 15 Jan 2026 21:55:55 +0000 Subject: [PATCH 06/99] fix: project avatar border radius --- packages/app/src/pages/layout.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index 2a36a99f25e..30a45722be4 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -821,13 +821,13 @@ export default function Layout(props: ParentProps) { const opencode = "4b0ea68d7af9a6031a7ffda7ad66e0cb83315750" return ( -
-
+
+
0 && props.notify ? { "-webkit-mask-image": mask, "mask-image": mask } @@ -982,7 +982,7 @@ export default function Layout(props: ParentProps) { + + + {(session) => } @@ -1200,6 +1215,7 @@ export default function Layout(props: ParentProps) { .filter((session) => !session.parentID) .toSorted(sortSessions), ) + const loading = createMemo(() => workspaceStore.status !== "complete" && sessions().length === 0) const hasMore = createMemo(() => workspaceStore.sessionTotal > workspaceStore.session.length) const loadMore = async () => { setWorkspaceStore("limit", (limit) => limit + 5) @@ -1214,6 +1230,9 @@ export default function Layout(props: ParentProps) { class="size-full flex flex-col py-2 overflow-y-auto no-scrollbar" >