From bacf705ee5dc9826e0eff0451c8ea8607777ab66 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Thu, 11 Dec 2025 17:07:22 -0600 Subject: [PATCH 001/856] wip --- packages/opencode/src/provider/transform.ts | 33 +++++++++++++++++++++ packages/opencode/src/session/message-v2.ts | 4 +++ 2 files changed, 37 insertions(+) diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index c0ee452365f..c2a92e888f8 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -3,6 +3,7 @@ import { unique } from "remeda" import type { JSONSchema } from "zod/v4/core" import type { Provider } from "./provider" import type { ModelsDev } from "./models" +import type { MessageV2 } from "@/session/message-v2" type Modality = NonNullable["input"][number] @@ -210,6 +211,38 @@ export namespace ProviderTransform { return undefined } + export function thinking(model: Provider.Model, thinking: MessageV2.Thinking) { + if (!model.capabilities.reasoning) return undefined + + switch (model.api.npm) { + case "@openrouter/ai-sdk-provider": + return { + reasoning: { effort: thinking.effort }, + } + case "@ai-sdk/openai-compatible": + const result: Record = { + reasoningEffort: thinking.effort, + } + + if (model.providerID === "baseten") { + result["chat_template_args"] = { enable_thinking: true } + } + + return result + + case "@ai-sdk/openai": + return { + reasoningEffort: thinking.effort, + reasoningSummary: "auto", + include: ["reasoning.encrypted_content"], + } + + case "@ai-sdk/anthropic": + // TODO: map to thinking budgets + return {} + } + } + export function options( model: Provider.Model, sessionID: string, diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index 1f4fffaa66b..c13f1203dde 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -286,6 +286,9 @@ export namespace MessageV2 { sessionID: z.string(), }) + export const Thinking = z.object({ effort: z.enum(["low", "medium", "high"]) }) + export type Thinking = z.infer + export const User = Base.extend({ role: z.literal("user"), time: z.object({ @@ -305,6 +308,7 @@ export namespace MessageV2 { }), system: z.string().optional(), tools: z.record(z.string(), z.boolean()).optional(), + thinking: Thinking.optional(), }).meta({ ref: "UserMessage", }) From 86f9c3acce9e685a1d0b51b9d926f237800f559f Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Thu, 11 Dec 2025 23:08:04 +0000 Subject: [PATCH 002/856] chore: format code --- packages/sdk/js/src/v2/gen/types.gen.ts | 3 +++ packages/sdk/openapi.json | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index f8890d9fb70..e99bac66222 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -90,6 +90,9 @@ export type UserMessage = { tools?: { [key: string]: boolean } + thinking?: { + effort: "low" | "medium" | "high" + } } export type ProviderAuthError = { diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index 7c7c216f5d2..2c657ebc0e5 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -5023,6 +5023,16 @@ "additionalProperties": { "type": "boolean" } + }, + "thinking": { + "type": "object", + "properties": { + "effort": { + "type": "string", + "enum": ["low", "medium", "high"] + } + }, + "required": ["effort"] } }, "required": ["id", "sessionID", "role", "time", "agent", "model"] From c316ef35d9c32d8fa08c499a8393eefd350b8b99 Mon Sep 17 00:00:00 2001 From: David Hill Date: Fri, 12 Dec 2025 09:43:41 +0000 Subject: [PATCH 003/856] fix: make the logo on the home screen non-selectable --- packages/opencode/src/cli/cmd/tui/component/logo.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/logo.tsx b/packages/opencode/src/cli/cmd/tui/component/logo.tsx index 4f512159651..d1be06a7f25 100644 --- a/packages/opencode/src/cli/cmd/tui/component/logo.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/logo.tsx @@ -1,4 +1,3 @@ -import { Installation } from "@/installation" import { TextAttributes } from "@opentui/core" import { For } from "solid-js" import { useTheme } from "@tui/context/theme" @@ -14,8 +13,10 @@ export function Logo() { {(line, index) => ( - {line} - + + {line} + + {LOGO_RIGHT[index()]} From 41319a288582a37e076722c954423f8d2c340290 Mon Sep 17 00:00:00 2001 From: David Hill Date: Fri, 12 Dec 2025 09:44:04 +0000 Subject: [PATCH 004/856] wip: desktop sidebar icon updates --- packages/desktop/src/pages/layout.tsx | 4 ++-- packages/ui/src/components/icon.tsx | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx index 70764292fe7..b997296fa23 100644 --- a/packages/desktop/src/pages/layout.tsx +++ b/packages/desktop/src/pages/layout.tsx @@ -501,7 +501,7 @@ export default function Layout(props: ParentProps) { @@ -196,14 +248,7 @@ export default function Layout(props: ParentProps) { data-selected={props.project.worktree === currentDirectory()} onClick={() => navigateToProject(props.project.worktree)} > -
- -
+ @@ -211,35 +256,30 @@ export default function Layout(props: ParentProps) { } const SortableProject = (props: { project: Project & { expanded: boolean } }): JSX.Element => { + const notification = useNotification() const sortable = createSortable(props.project.worktree) const [projectStore] = globalSync.child(props.project.worktree) const slug = createMemo(() => base64Encode(props.project.worktree)) const name = createMemo(() => getFilename(props.project.worktree)) + const [expanded, setExpanded] = createSignal(true) return ( // @ts-ignore
- + diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx index ad398803089..0dbd7a6500f 100644 --- a/packages/ui/src/components/icon.tsx +++ b/packages/ui/src/components/icon.tsx @@ -4,6 +4,7 @@ const icons = { "align-right": ``, "arrow-up": ``, "arrow-left": ``, + archive: ``, "bubble-5": ``, "bullet-list": ``, "check-small": ``, From 3d751c0da13c46e04b8886b08506eae608b4fb81 Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Fri, 12 Dec 2025 23:37:17 +0800 Subject: [PATCH 028/856] tauri: add basic custom titlebar (#5438) --- bun.lock | 3 + nix/hashes.json | 2 +- packages/desktop/index.html | 4 +- packages/desktop/src/pages/layout.tsx | 4 +- packages/tauri/index.html | 4 +- packages/tauri/package.json | 1 + packages/tauri/src-tauri/Cargo.lock | 84 +++++++++++++++++++ packages/tauri/src-tauri/Cargo.toml | 1 + .../tauri/src-tauri/capabilities/default.json | 3 +- packages/tauri/src-tauri/src/lib.rs | 6 +- packages/tauri/src/index.tsx | 4 + 11 files changed, 107 insertions(+), 9 deletions(-) diff --git a/bun.lock b/bun.lock index d9cdd91d9e4..9d5819b153d 100644 --- a/bun.lock +++ b/bun.lock @@ -356,6 +356,7 @@ "@tauri-apps/api": "^2", "@tauri-apps/plugin-dialog": "~2", "@tauri-apps/plugin-opener": "^2", + "@tauri-apps/plugin-os": "~2", "@tauri-apps/plugin-process": "~2", "@tauri-apps/plugin-shell": "~2", "@tauri-apps/plugin-store": "~2", @@ -1663,6 +1664,8 @@ "@tauri-apps/plugin-opener": ["@tauri-apps/plugin-opener@2.5.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-ei/yRRoCklWHImwpCcDK3VhNXx+QXM9793aQ64YxpqVF0BDuuIlXhZgiAkc15wnPVav+IbkYhmDJIv5R326Mew=="], + "@tauri-apps/plugin-os": ["@tauri-apps/plugin-os@2.3.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-n+nXWeuSeF9wcEsSPmRnBEGrRgOy6jjkSU+UVCOV8YUGKb2erhDOxis7IqRXiRVHhY8XMKks00BJ0OAdkpf6+A=="], + "@tauri-apps/plugin-process": ["@tauri-apps/plugin-process@2.3.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-nCa4fGVaDL/B9ai03VyPOjfAHRHSBz5v6F/ObsB73r/dA3MHHhZtldaDMIc0V/pnUw9ehzr2iEG+XkSEyC0JJA=="], "@tauri-apps/plugin-shell": ["@tauri-apps/plugin-shell@2.3.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-Xod+pRcFxmOWFWEnqH5yZcA7qwAMuaaDkMR1Sply+F8VfBj++CGnj2xf5UoialmjZ2Cvd8qrvSCbU+7GgNVsKQ=="], diff --git a/nix/hashes.json b/nix/hashes.json index 14ea1d55daa..b640219471d 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,3 +1,3 @@ { - "nodeModules": "sha256-JiPLmRyjpwiAJSDO6Sah/cMdncMicqQqGrBVOAVHMWA=" + "nodeModules": "sha256-3CG0wAMQp2E6ghPUXbYaYifJorp9b1WvCtHD+o8Nhck=" } diff --git a/packages/desktop/index.html b/packages/desktop/index.html index b9d3e535120..9803517a07e 100644 --- a/packages/desktop/index.html +++ b/packages/desktop/index.html @@ -14,7 +14,7 @@ - + -
+
diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx index c34904e119e..d2700683572 100644 --- a/packages/desktop/src/pages/layout.tsx +++ b/packages/desktop/src/pages/layout.tsx @@ -426,7 +426,7 @@ export default function Layout(props: ParentProps) { } return ( -
+ -
+
- + -
+
diff --git a/packages/tauri/package.json b/packages/tauri/package.json index 7e0f670b483..d712f15f4af 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -16,6 +16,7 @@ "@tauri-apps/api": "^2", "@tauri-apps/plugin-dialog": "~2", "@tauri-apps/plugin-opener": "^2", + "@tauri-apps/plugin-os": "~2", "@tauri-apps/plugin-process": "~2", "@tauri-apps/plugin-shell": "~2", "@tauri-apps/plugin-store": "~2", diff --git a/packages/tauri/src-tauri/Cargo.lock b/packages/tauri/src-tauri/Cargo.lock index b42329d7509..42a7dae81d3 100644 --- a/packages/tauri/src-tauri/Cargo.lock +++ b/packages/tauri/src-tauri/Cargo.lock @@ -1256,6 +1256,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix", + "windows-link 0.2.1", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -2309,6 +2319,16 @@ dependencies = [ "objc2-foundation 0.3.2", ] +[[package]] +name = "objc2-core-location" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" +dependencies = [ + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + [[package]] name = "objc2-core-text" version = "0.3.2" @@ -2440,6 +2460,7 @@ checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ "bitflags 2.10.0", "objc2 0.6.3", + "objc2-core-foundation", "objc2-foundation 0.3.2", ] @@ -2461,8 +2482,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ "bitflags 2.10.0", + "block2 0.6.2", "objc2 0.6.3", + "objc2-cloud-kit", + "objc2-core-data", "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-location", + "objc2-core-text", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" +dependencies = [ + "objc2 0.6.3", "objc2-foundation 0.3.2", ] @@ -2511,6 +2551,7 @@ dependencies = [ "tauri-build", "tauri-plugin-dialog", "tauri-plugin-opener", + "tauri-plugin-os", "tauri-plugin-process", "tauri-plugin-shell", "tauri-plugin-store", @@ -2535,6 +2576,22 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "os_info" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c39b5918402d564846d5aba164c09a66cc88d232179dfd3e3c619a25a268392" +dependencies = [ + "android_system_properties", + "log", + "nix", + "objc2 0.6.3", + "objc2-foundation 0.3.2", + "objc2-ui-kit", + "serde", + "windows-sys 0.61.2", +] + [[package]] name = "os_pipe" version = "1.2.3" @@ -3872,6 +3929,15 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -4146,6 +4212,24 @@ dependencies = [ "zbus", ] +[[package]] +name = "tauri-plugin-os" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f08346c8deb39e96f86973da0e2d76cbb933d7ac9b750f6dc4daf955a6f997" +dependencies = [ + "gethostname", + "log", + "os_info", + "serde", + "serde_json", + "serialize-to-javascript", + "sys-locale", + "tauri", + "tauri-plugin", + "thiserror 2.0.17", +] + [[package]] name = "tauri-plugin-process" version = "2.3.1" diff --git a/packages/tauri/src-tauri/Cargo.toml b/packages/tauri/src-tauri/Cargo.toml index f72e5f428d2..a39c2201111 100644 --- a/packages/tauri/src-tauri/Cargo.toml +++ b/packages/tauri/src-tauri/Cargo.toml @@ -31,3 +31,4 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = "1.48.0" listeners = "0.3" +tauri-plugin-os = "2" diff --git a/packages/tauri/src-tauri/capabilities/default.json b/packages/tauri/src-tauri/capabilities/default.json index 320586de4c4..91af8cbdcee 100644 --- a/packages/tauri/src-tauri/capabilities/default.json +++ b/packages/tauri/src-tauri/capabilities/default.json @@ -13,6 +13,7 @@ "dialog:default", "process:default", "store:default", - "window-state:default" + "window-state:default", + "os:default" ] } diff --git a/packages/tauri/src-tauri/src/lib.rs b/packages/tauri/src-tauri/src/lib.rs index eb712235ecd..fea3addb545 100644 --- a/packages/tauri/src-tauri/src/lib.rs +++ b/packages/tauri/src-tauri/src/lib.rs @@ -4,7 +4,9 @@ use std::{ sync::{Arc, Mutex}, time::{Duration, Instant}, }; -use tauri::{AppHandle, LogicalSize, Manager, Monitor, RunEvent, WebviewUrl, WebviewWindow}; +use tauri::{ + AppHandle, LogicalSize, Manager, Monitor, RunEvent, TitleBarStyle, WebviewUrl, WebviewWindow, +}; use tauri_plugin_dialog::{DialogExt, MessageDialogButtons, MessageDialogResult}; use tauri_plugin_shell::process::{CommandChild, CommandEvent}; use tauri_plugin_shell::ShellExt; @@ -107,6 +109,7 @@ pub fn run() { let updater_enabled = option_env!("TAURI_SIGNING_PRIVATE_KEY").is_some(); let mut builder = tauri::Builder::default() + .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_window_state::Builder::new().build()) .plugin(tauri_plugin_store::Builder::new().build()) .plugin(tauri_plugin_dialog::init()) @@ -180,6 +183,7 @@ pub fn run() { .inner_size(size.width as f64, size.height as f64) .decorations(true) .zoom_hotkeys_enabled(true) + .title_bar_style(TitleBarStyle::Overlay) .initialization_script(format!( r#" window.__OPENCODE__ ??= {{}}; diff --git a/packages/tauri/src/index.tsx b/packages/tauri/src/index.tsx index c72805fe648..84ba73c0727 100644 --- a/packages/tauri/src/index.tsx +++ b/packages/tauri/src/index.tsx @@ -5,6 +5,7 @@ import { runUpdater } from "./updater" import { onMount } from "solid-js" import { open, save } from "@tauri-apps/plugin-dialog" import { open as shellOpen } from "@tauri-apps/plugin-shell" +import { type as ostype } from "@tauri-apps/plugin-os" const root = document.getElementById("root") if (import.meta.env.DEV && !(root instanceof HTMLElement)) { @@ -54,6 +55,9 @@ render(() => { return ( + {ostype() === "macos" && ( +
+ )} ) From c4c36ea54b3cff9b694c2027292b5cda50591e85 Mon Sep 17 00:00:00 2001 From: xu0o0 Date: Sat, 13 Dec 2025 00:43:18 +0800 Subject: [PATCH 029/856] acp: fix internal error on `/compact` (#5424) --- packages/opencode/src/acp/agent.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/opencode/src/acp/agent.ts b/packages/opencode/src/acp/agent.ts index a1e45e1d21e..d20c971ebc5 100644 --- a/packages/opencode/src/acp/agent.ts +++ b/packages/opencode/src/acp/agent.ts @@ -914,6 +914,8 @@ export namespace ACP { { sessionID, directory, + providerID: model.providerID, + modelID: model.modelID, }, { throwOnError: true }, ) From 03be72bb2b6ac8635845157d95ab999bd984bb02 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Fri, 12 Dec 2025 10:45:02 -0600 Subject: [PATCH 030/856] chore: cleanup --- packages/desktop/src/components/header.tsx | 113 +++++++++++++++++++ packages/desktop/src/context/global-sync.tsx | 62 +++++----- packages/desktop/src/pages/layout.tsx | 101 ++--------------- 3 files changed, 154 insertions(+), 122 deletions(-) create mode 100644 packages/desktop/src/components/header.tsx diff --git a/packages/desktop/src/components/header.tsx b/packages/desktop/src/components/header.tsx new file mode 100644 index 00000000000..cc4d018166b --- /dev/null +++ b/packages/desktop/src/components/header.tsx @@ -0,0 +1,113 @@ +import { useGlobalSync } from "@/context/global-sync" +import { useLayout } from "@/context/layout" +import { Session } from "@opencode-ai/sdk/v2/client" +import { Button } from "@opencode-ai/ui/button" +import { Icon } from "@opencode-ai/ui/icon" +import { Mark } from "@opencode-ai/ui/logo" +import { Select } from "@opencode-ai/ui/select" +import { Tooltip } from "@opencode-ai/ui/tooltip" +import { base64Decode } from "@opencode-ai/util/encode" +import { getFilename } from "@opencode-ai/util/path" +import { A, useParams } from "@solidjs/router" +import { createMemo, Show } from "solid-js" + +export function Header(props: { + navigateToProject: (directory: string) => void + navigateToSession: (session: Session | undefined) => void +}) { + const globalSync = useGlobalSync() + const layout = useLayout() + const params = useParams() + const currentDirectory = createMemo(() => base64Decode(params.dir ?? "")) + const store = createMemo(() => globalSync.child(currentDirectory())[0]) + const sessions = createMemo(() => store().session ?? []) + const currentSession = createMemo(() => sessions().find((s) => s.id === params.id)) + + return ( +
+ + + +
+ 0}> +
+
+ +
/
+ project.worktree)} - current={currentDirectory()} - label={(x) => getFilename(x)} - onSelect={(x) => (x ? navigateToProject(x) : undefined)} - class="text-14-regular text-text-base" - variant="ghost" - > - {/* @ts-ignore */} - {(i) => ( -
- -
{getFilename(i)}
-
- )} - -
/
-