From 3aaf29b69344917f3dfee8a9ca35fb24b74f2b9b Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Wed, 18 Feb 2026 15:41:20 +0000 Subject: [PATCH 01/88] chore: update nix node_modules hashes --- nix/hashes.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/hashes.json b/nix/hashes.json index 3fa1455fc0..07a3bb69ed 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,8 +1,8 @@ { "nodeModules": { - "x86_64-linux": "sha256-C3WIEER2XgzO85wk2sp3BzQ6dknW026zslD8nKZjo2U=", - "aarch64-linux": "sha256-+tTJHZMZ/+8fAjI/1fUTuca8J2MZfB+5vhBoZ7jgqcE=", - "aarch64-darwin": "sha256-vS82puFGBBToxyIBa8Zi0KLKdJYr64T6HZL2rL32mH8=", - "x86_64-darwin": "sha256-Tr8JMTCxV6WVt3dXV7iq3PNCm2Cn+RXAbU9+o7pKKV0=" + "x86_64-linux": "sha256-BqHdoRCZt6DJStmbUkMbKWU4MLl6+Y3xNx81oI6mSLk=", + "aarch64-linux": "sha256-YIDQCSkVTvfGtJ6Ymc65gRX1HyI/uTwjK3rs8EPp39Y=", + "aarch64-darwin": "sha256-TYwPqlMq90S8R8ldPJ9qLMLRvOfQUwbV2ow9A28c3Yc=", + "x86_64-darwin": "sha256-KdsMP04/vQ9x1WGY8tdsnjUPqMIjmU9c2GxN4l+6XJo=" } } From 4a5823562ca2f2ee0255aa815228e9973b6efb28 Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Thu, 19 Feb 2026 00:03:08 +0800 Subject: [PATCH 02/88] desktop: fix isLocal --- packages/app/src/context/server.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/app/src/context/server.tsx b/packages/app/src/context/server.tsx index 182f7507f8..adc7bfcc11 100644 --- a/packages/app/src/context/server.tsx +++ b/packages/app/src/context/server.tsx @@ -187,10 +187,13 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( const origin = createMemo(() => projectsKey(state.active)) const projectsList = createMemo(() => store.projects[origin()] ?? []) - const isLocal = createMemo(() => origin() === "local") const current: Accessor = createMemo( () => allServers().find((s) => ServerConnection.key(s) === state.active) ?? allServers()[0], ) + const isLocal = createMemo(() => { + const c = current() + return c?.type === "sidecar" && c.variant === "base" + }) return { ready: isReady, From f8904e3972fba3d9fc3b08fa2531da8fca378dd1 Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Thu, 19 Feb 2026 00:05:50 +0800 Subject: [PATCH 03/88] desktop: handle sidecar key in projectsKey --- packages/app/src/context/server.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/app/src/context/server.tsx b/packages/app/src/context/server.tsx index adc7bfcc11..336f8aa98c 100644 --- a/packages/app/src/context/server.tsx +++ b/packages/app/src/context/server.tsx @@ -21,11 +21,12 @@ export function serverDisplayName(conn?: ServerConnection.Any) { return conn.http.url.replace(/^https?:\/\//, "").replace(/\/+$/, "") } -function projectsKey(url: string) { - if (!url) return "" - const host = url.replace(/^https?:\/\//, "").split(":")[0] +function projectsKey(key: ServerConnection.Key) { + if (!key) return "" + if (key === "sidecar") return "local" + const host = key.replace(/^https?:\/\//, "").split(":")[0] if (host === "localhost" || host === "127.0.0.1") return "local" - return url + return key } export namespace ServerConnection { From d27dbfe062b18f832acf958357e175ed18ab98d9 Mon Sep 17 00:00:00 2001 From: Mike Harris Date: Wed, 18 Feb 2026 11:56:37 -0500 Subject: [PATCH 04/88] fix(cli): session list --max-count not honored, shows too few sessions (#14162) --- packages/opencode/src/cli/cmd/session.ts | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/packages/opencode/src/cli/cmd/session.ts b/packages/opencode/src/cli/cmd/session.ts index 1803f84952..8239b0bcb3 100644 --- a/packages/opencode/src/cli/cmd/session.ts +++ b/packages/opencode/src/cli/cmd/session.ts @@ -85,26 +85,17 @@ export const SessionListCommand = cmd({ }, handler: async (args) => { await bootstrap(process.cwd(), async () => { - const sessions = [] - for await (const session of Session.list()) { - if (!session.parentID) { - sessions.push(session) - } - } + const sessions = [...Session.list({ roots: true, limit: args.maxCount })] - sessions.sort((a, b) => b.time.updated - a.time.updated) - - const limitedSessions = args.maxCount ? sessions.slice(0, args.maxCount) : sessions - - if (limitedSessions.length === 0) { + if (sessions.length === 0) { return } let output: string if (args.format === "json") { - output = formatSessionJSON(limitedSessions) + output = formatSessionJSON(sessions) } else { - output = formatSessionTable(limitedSessions) + output = formatSessionTable(sessions) } const shouldPaginate = process.stdout.isTTY && !args.maxCount && args.format === "table" From 83b7d8e04cd4e4d343f2006278ade0caa82173d2 Mon Sep 17 00:00:00 2001 From: Vladimir Glafirov Date: Wed, 18 Feb 2026 17:58:38 +0100 Subject: [PATCH 05/88] feat: GitLab Duo - bump gitlab-ai-provider to 3.6.0 (adds Sonnet 4.6) (#14115) --- bun.lock | 4 ++-- packages/opencode/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bun.lock b/bun.lock index b2bd70b8e2..c7be0f25bb 100644 --- a/bun.lock +++ b/bun.lock @@ -289,7 +289,7 @@ "@ai-sdk/vercel": "1.0.33", "@ai-sdk/xai": "2.0.51", "@clack/prompts": "1.0.0-alpha.1", - "@gitlab/gitlab-ai-provider": "3.5.1", + "@gitlab/gitlab-ai-provider": "3.6.0", "@gitlab/opencode-gitlab-auth": "1.3.3", "@hono/standard-validator": "0.1.5", "@hono/zod-validator": "catalog:", @@ -992,7 +992,7 @@ "@fontsource/inter": ["@fontsource/inter@5.2.8", "", {}, "sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg=="], - "@gitlab/gitlab-ai-provider": ["@gitlab/gitlab-ai-provider@3.5.1", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.0", "@anycable/core": "^0.9.2", "graphql-request": "^6.1.0", "isomorphic-ws": "^5.0.0", "openai": "^6.16.0", "socket.io-client": "^4.8.1", "vscode-jsonrpc": "^8.2.1", "zod": "^3.25.76" }, "peerDependencies": { "@ai-sdk/provider": ">=2.0.0", "@ai-sdk/provider-utils": ">=3.0.0" } }, "sha512-I8+EGdUeKmGJSjAdFobHtqpxM9Fm00w0j7NJbtln/D/XQ1SKEGoZIuqJko4v0pV2mkhGUIs7qezljH/2kbXovA=="], + "@gitlab/gitlab-ai-provider": ["@gitlab/gitlab-ai-provider@3.6.0", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.0", "@anycable/core": "^0.9.2", "graphql-request": "^6.1.0", "isomorphic-ws": "^5.0.0", "openai": "^6.16.0", "socket.io-client": "^4.8.1", "vscode-jsonrpc": "^8.2.1", "zod": "^3.25.76" }, "peerDependencies": { "@ai-sdk/provider": ">=2.0.0", "@ai-sdk/provider-utils": ">=3.0.0" } }, "sha512-8LmcIQ86xkMtC7L4P1/QYVEC+yKMTRerfPeniaaQGalnzXKtX6iMHLjLPOL9Rxp55lOXi6ed0WrFuJzZx+fNRg=="], "@gitlab/opencode-gitlab-auth": ["@gitlab/opencode-gitlab-auth@1.3.3", "", { "dependencies": { "@fastify/rate-limit": "^10.2.0", "@opencode-ai/plugin": "*", "fastify": "^5.2.0", "open": "^10.0.0" } }, "sha512-FT+KsCmAJjtqWr1YAq0MywGgL9kaLQ4apmsoowAXrPqHtoYf2i/nY10/A+L06kNj22EATeEDRpbB1NWXMto/SA=="], diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 6e1288b28d..dc9bfdaac8 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -75,7 +75,7 @@ "@ai-sdk/vercel": "1.0.33", "@ai-sdk/xai": "2.0.51", "@clack/prompts": "1.0.0-alpha.1", - "@gitlab/gitlab-ai-provider": "3.5.1", + "@gitlab/gitlab-ai-provider": "3.6.0", "@gitlab/opencode-gitlab-auth": "1.3.3", "@hono/standard-validator": "0.1.5", "@hono/zod-validator": "catalog:", From fc1addb8f4830e71c268fb0609fa6489cd55e2b2 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Wed, 18 Feb 2026 11:01:59 -0600 Subject: [PATCH 06/88] ignore: tweak contributing md (#14168) --- CONTRIBUTING.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4bec009ef4..2ae3fc6f2f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,6 +24,11 @@ If you are unsure if a PR would be accepted, feel free to ask a maintainer or lo Want to take on an issue? Leave a comment and a maintainer may assign it to you unless it is something we are already working on. +## Adding New Providers + +New providers shouldn't require many if ANY code changes, but if you want to add support for a new provider first make a PR to: +https://github.com/anomalyco/models.dev + ## Developing OpenCode - Requirements: Bun 1.3+ From 38572b81753aa56b7d87a9e46cdb04293bbc6956 Mon Sep 17 00:00:00 2001 From: Alexander Abramov Date: Wed, 18 Feb 2026 20:02:29 +0300 Subject: [PATCH 07/88] feat: add Julia language server support (#14129) Co-authored-by: Alexander Abramov --- packages/opencode/src/lsp/language.ts | 1 + packages/opencode/src/lsp/server.ts | 18 ++++++++++++++++++ packages/web/src/content/docs/lsp.mdx | 1 + 3 files changed, 20 insertions(+) diff --git a/packages/opencode/src/lsp/language.ts b/packages/opencode/src/lsp/language.ts index 430b10caa2..58f4c8488b 100644 --- a/packages/opencode/src/lsp/language.ts +++ b/packages/opencode/src/lsp/language.ts @@ -44,6 +44,7 @@ export const LANGUAGE_EXTENSIONS: Record = { ".htm": "html", ".ini": "ini", ".java": "java", + ".jl": "julia", ".js": "javascript", ".kt": "kotlin", ".kts": "kotlin", diff --git a/packages/opencode/src/lsp/server.ts b/packages/opencode/src/lsp/server.ts index b0755b8b56..0200be2260 100644 --- a/packages/opencode/src/lsp/server.ts +++ b/packages/opencode/src/lsp/server.ts @@ -2043,4 +2043,22 @@ export namespace LSPServer { } }, } + + export const JuliaLS: Info = { + id: "julials", + extensions: [".jl"], + root: NearestRoot(["Project.toml", "Manifest.toml", "*.jl"]), + async spawn(root) { + const julia = Bun.which("julia") + if (!julia) { + log.info("julia not found, please install julia first (https://julialang.org/downloads/)") + return + } + return { + process: spawn(julia, ["--startup-file=no", "--history-file=no", "-e", "using LanguageServer; runserver()"], { + cwd: root, + }), + } + }, + } } diff --git a/packages/web/src/content/docs/lsp.mdx b/packages/web/src/content/docs/lsp.mdx index 339761a9b3..f242f4c5e4 100644 --- a/packages/web/src/content/docs/lsp.mdx +++ b/packages/web/src/content/docs/lsp.mdx @@ -27,6 +27,7 @@ OpenCode comes with several built-in LSP servers for popular languages: | gopls | .go | `go` command available | | hls | .hs, .lhs | `haskell-language-server-wrapper` command available | | jdtls | .java | `Java SDK (version 21+)` installed | +| julials | .jl | `julia` and `LanguageServer.jl` installed | | kotlin-ls | .kt, .kts | Auto-installs for Kotlin projects | | lua-ls | .lua | Auto-installs for Lua projects | | nixd | .nix | `nixd` command available | From 37b24f4870dc35f369e4827b89b0159c12daf4df Mon Sep 17 00:00:00 2001 From: Dax Date: Wed, 18 Feb 2026 12:03:24 -0500 Subject: [PATCH 08/88] refactor: migrate index.ts from Bun.file() to Filesystem module (#14160) --- packages/opencode/src/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts index 39e77782f5..6551565886 100644 --- a/packages/opencode/src/index.ts +++ b/packages/opencode/src/index.ts @@ -13,6 +13,7 @@ import { Installation } from "./installation" import { NamedError } from "@opencode-ai/util/error" import { FormatError } from "./cli/error" import { ServeCommand } from "./cli/cmd/serve" +import { Filesystem } from "./util/filesystem" import { DebugCommand } from "./cli/cmd/debug" import { StatsCommand } from "./cli/cmd/stats" import { McpCommand } from "./cli/cmd/mcp" @@ -81,7 +82,7 @@ const cli = yargs(hideBin(process.argv)) }) const marker = path.join(Global.Path.data, "opencode.db") - if (!(await Bun.file(marker).exists())) { + if (!(await Filesystem.exists(marker))) { const tty = process.stderr.isTTY process.stderr.write("Performing one time database migration, may take a few minutes..." + EOL) const width = 36 From 91a3ee642d72b95367f745134c381c129552fbc9 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Wed, 18 Feb 2026 17:08:31 +0000 Subject: [PATCH 09/88] chore: update nix node_modules hashes --- nix/hashes.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/hashes.json b/nix/hashes.json index 07a3bb69ed..c3510c39f6 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,8 +1,8 @@ { "nodeModules": { - "x86_64-linux": "sha256-BqHdoRCZt6DJStmbUkMbKWU4MLl6+Y3xNx81oI6mSLk=", - "aarch64-linux": "sha256-YIDQCSkVTvfGtJ6Ymc65gRX1HyI/uTwjK3rs8EPp39Y=", - "aarch64-darwin": "sha256-TYwPqlMq90S8R8ldPJ9qLMLRvOfQUwbV2ow9A28c3Yc=", - "x86_64-darwin": "sha256-KdsMP04/vQ9x1WGY8tdsnjUPqMIjmU9c2GxN4l+6XJo=" + "x86_64-linux": "sha256-5sXHoHbRdXbqM/zRJZiXt26sm/yyyZN/4OOHUtdofhk=", + "aarch64-linux": "sha256-JCMm5X7e27BBV4wyaknCMM4CBt4Lr72SSvaGxEeNsJE=", + "aarch64-darwin": "sha256-DBQJURlTPqFt0OYUHSvZZ4H0NUf020aic4zNX5CXzDc=", + "x86_64-darwin": "sha256-t2luVxqCcRSgq/WNWkm4ZpKXO22n2RnAWP6msoTOr+A=" } } From 3d189b42a3bdd98675a972524389399d229d96a3 Mon Sep 17 00:00:00 2001 From: Dax Date: Wed, 18 Feb 2026 12:10:42 -0500 Subject: [PATCH 10/88] refactor: migrate file/ripgrep.ts from Bun.file()/Bun.write() to Filesystem module (#14159) --- packages/opencode/src/cli/cmd/mcp.ts | 11 ++-- packages/opencode/src/config/config.ts | 76 ++++++++++++-------------- packages/opencode/src/file/ripgrep.ts | 12 ++-- 3 files changed, 46 insertions(+), 53 deletions(-) diff --git a/packages/opencode/src/cli/cmd/mcp.ts b/packages/opencode/src/cli/cmd/mcp.ts index 95719215e3..c45b9e55d0 100644 --- a/packages/opencode/src/cli/cmd/mcp.ts +++ b/packages/opencode/src/cli/cmd/mcp.ts @@ -13,6 +13,7 @@ import { Installation } from "../../installation" import path from "path" import { Global } from "../../global" import { modify, applyEdits } from "jsonc-parser" +import { Filesystem } from "../../util/filesystem" import { Bus } from "../../bus" function getAuthStatusIcon(status: MCP.AuthStatus): string { @@ -388,7 +389,7 @@ async function resolveConfigPath(baseDir: string, global = false) { } for (const candidate of candidates) { - if (await Bun.file(candidate).exists()) { + if (await Filesystem.exists(candidate)) { return candidate } } @@ -398,11 +399,9 @@ async function resolveConfigPath(baseDir: string, global = false) { } async function addMcpToConfig(name: string, mcpConfig: Config.Mcp, configPath: string) { - const file = Bun.file(configPath) - let text = "{}" - if (await file.exists()) { - text = await file.text() + if (await Filesystem.exists(configPath)) { + text = await Filesystem.readText(configPath) } // Use jsonc-parser to modify while preserving comments @@ -411,7 +410,7 @@ async function addMcpToConfig(name: string, mcpConfig: Config.Mcp, configPath: s }) const result = applyEdits(text, edits) - await Bun.write(configPath, result) + await Filesystem.write(configPath, result) return configPath } diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 261731b8b0..dfdcb0343e 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -255,19 +255,20 @@ export namespace Config { const pkg = path.join(dir, "package.json") const targetVersion = Installation.isLocal() ? "*" : Installation.VERSION - const json = await Bun.file(pkg) - .json() - .catch(() => ({})) + const json = await Filesystem.readJson<{ dependencies?: Record }>(pkg).catch(() => ({ + dependencies: {}, + })) json.dependencies = { ...json.dependencies, "@opencode-ai/plugin": targetVersion, } - await Bun.write(pkg, JSON.stringify(json, null, 2)) + await Filesystem.writeJson(pkg, json) await new Promise((resolve) => setTimeout(resolve, 3000)) const gitignore = path.join(dir, ".gitignore") - const hasGitIgnore = await Bun.file(gitignore).exists() - if (!hasGitIgnore) await Bun.write(gitignore, ["node_modules", "package.json", "bun.lock", ".gitignore"].join("\n")) + const hasGitIgnore = await Filesystem.exists(gitignore) + if (!hasGitIgnore) + await Filesystem.write(gitignore, ["node_modules", "package.json", "bun.lock", ".gitignore"].join("\n")) // Install any additional dependencies defined in the package.json // This allows local plugins and custom tools to use external packages @@ -303,11 +304,10 @@ export namespace Config { if (!existsSync(nodeModules)) return true const pkg = path.join(dir, "package.json") - const pkgFile = Bun.file(pkg) - const pkgExists = await pkgFile.exists() + const pkgExists = await Filesystem.exists(pkg) if (!pkgExists) return true - const parsed = await pkgFile.json().catch(() => null) + const parsed = await Filesystem.readJson<{ dependencies?: Record }>(pkg).catch(() => null) const dependencies = parsed?.dependencies ?? {} const depVersion = dependencies["@opencode-ai/plugin"] if (!depVersion) return true @@ -1220,7 +1220,7 @@ export namespace Config { if (provider && model) result.model = `${provider}/${model}` result["$schema"] = "https://opencode.ai/config.json" result = mergeDeep(result, rest) - await Bun.write(path.join(Global.Path.config, "config.json"), JSON.stringify(result, null, 2)) + await Filesystem.writeJson(path.join(Global.Path.config, "config.json"), result) await fs.unlink(legacy) }) .catch(() => {}) @@ -1231,12 +1231,10 @@ export namespace Config { async function loadFile(filepath: string): Promise { log.info("loading", { path: filepath }) - let text = await Bun.file(filepath) - .text() - .catch((err) => { - if (err.code === "ENOENT") return - throw new JsonError({ path: filepath }, { cause: err }) - }) + let text = await Filesystem.readText(filepath).catch((err: any) => { + if (err.code === "ENOENT") return + throw new JsonError({ path: filepath }, { cause: err }) + }) if (!text) return {} return load(text, filepath) } @@ -1263,21 +1261,19 @@ export namespace Config { } const resolvedPath = path.isAbsolute(filePath) ? filePath : path.resolve(configDir, filePath) const fileContent = ( - await Bun.file(resolvedPath) - .text() - .catch((error) => { - const errMsg = `bad file reference: "${match}"` - if (error.code === "ENOENT") { - throw new InvalidError( - { - path: configFilepath, - message: errMsg + ` ${resolvedPath} does not exist`, - }, - { cause: error }, - ) - } - throw new InvalidError({ path: configFilepath, message: errMsg }, { cause: error }) - }) + await Filesystem.readText(resolvedPath).catch((error: any) => { + const errMsg = `bad file reference: "${match}"` + if (error.code === "ENOENT") { + throw new InvalidError( + { + path: configFilepath, + message: errMsg + ` ${resolvedPath} does not exist`, + }, + { cause: error }, + ) + } + throw new InvalidError({ path: configFilepath, message: errMsg }, { cause: error }) + }) ).trim() // escape newlines/quotes, strip outer quotes text = text.replace(match, () => JSON.stringify(fileContent).slice(1, -1)) @@ -1314,7 +1310,7 @@ export namespace Config { parsed.data.$schema = "https://opencode.ai/config.json" // Write the $schema to the original text to preserve variables like {env:VAR} const updated = original.replace(/^\s*\{/, '{\n "$schema": "https://opencode.ai/config.json",') - await Bun.write(configFilepath, updated).catch(() => {}) + await Filesystem.write(configFilepath, updated).catch(() => {}) } const data = parsed.data if (data.plugin) { @@ -1370,7 +1366,7 @@ export namespace Config { export async function update(config: Info) { const filepath = path.join(Instance.directory, "config.json") const existing = await loadFile(filepath) - await Bun.write(filepath, JSON.stringify(mergeDeep(existing, config), null, 2)) + await Filesystem.writeJson(filepath, mergeDeep(existing, config)) await Instance.dispose() } @@ -1441,24 +1437,22 @@ export namespace Config { export async function updateGlobal(config: Info) { const filepath = globalConfigFile() - const before = await Bun.file(filepath) - .text() - .catch((err) => { - if (err.code === "ENOENT") return "{}" - throw new JsonError({ path: filepath }, { cause: err }) - }) + const before = await Filesystem.readText(filepath).catch((err: any) => { + if (err.code === "ENOENT") return "{}" + throw new JsonError({ path: filepath }, { cause: err }) + }) const next = await (async () => { if (!filepath.endsWith(".jsonc")) { const existing = parseConfig(before, filepath) const merged = mergeDeep(existing, config) - await Bun.write(filepath, JSON.stringify(merged, null, 2)) + await Filesystem.writeJson(filepath, merged) return merged } const updated = patchJsonc(before, config) const merged = parseConfig(updated, filepath) - await Bun.write(filepath, updated) + await Filesystem.write(filepath, updated) return merged })() diff --git a/packages/opencode/src/file/ripgrep.ts b/packages/opencode/src/file/ripgrep.ts index 58f9af7cdb..ca1eadae8e 100644 --- a/packages/opencode/src/file/ripgrep.ts +++ b/packages/opencode/src/file/ripgrep.ts @@ -6,6 +6,7 @@ import z from "zod" import { NamedError } from "@opencode-ai/util/error" import { lazy } from "../util/lazy" import { $ } from "bun" +import { Filesystem } from "../util/filesystem" import { ZipReader, BlobReader, BlobWriter } from "@zip.js/zip.js" import { Log } from "@/util/log" @@ -131,8 +132,7 @@ export namespace Ripgrep { } const filepath = path.join(Global.Path.bin, "rg" + (process.platform === "win32" ? ".exe" : "")) - const file = Bun.file(filepath) - if (!(await file.exists())) { + if (!(await Filesystem.exists(filepath))) { const platformKey = `${process.arch}-${process.platform}` as keyof typeof PLATFORM const config = PLATFORM[platformKey] if (!config) throw new UnsupportedPlatformError({ platform: platformKey }) @@ -144,9 +144,9 @@ export namespace Ripgrep { const response = await fetch(url) if (!response.ok) throw new DownloadFailedError({ url, status: response.status }) - const buffer = await response.arrayBuffer() + const arrayBuffer = await response.arrayBuffer() const archivePath = path.join(Global.Path.bin, filename) - await Bun.write(archivePath, buffer) + await Filesystem.write(archivePath, Buffer.from(arrayBuffer)) if (config.extension === "tar.gz") { const args = ["tar", "-xzf", archivePath, "--strip-components=1"] @@ -166,7 +166,7 @@ export namespace Ripgrep { }) } if (config.extension === "zip") { - const zipFileReader = new ZipReader(new BlobReader(new Blob([await Bun.file(archivePath).arrayBuffer()]))) + const zipFileReader = new ZipReader(new BlobReader(new Blob([arrayBuffer]))) const entries = await zipFileReader.getEntries() let rgEntry: any for (const entry of entries) { @@ -190,7 +190,7 @@ export namespace Ripgrep { stderr: "Failed to extract rg.exe from zip archive", }) } - await Bun.write(filepath, await rgBlob.arrayBuffer()) + await Filesystem.write(filepath, Buffer.from(await rgBlob.arrayBuffer())) await zipFileReader.close() } await fs.unlink(archivePath) From a5c15a23e4b352b21c4e0fe8056c302436564107 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Wed, 18 Feb 2026 12:21:25 -0500 Subject: [PATCH 11/88] core: allow readJson to be called without explicit type parameter Added default type parameter 'any' to readJson so users can call it without specifying a type when they don't need strict typing. This reduces boilerplate for quick JSON reads where type safety isn't required. --- packages/opencode/src/util/filesystem.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/util/filesystem.ts b/packages/opencode/src/util/filesystem.ts index 5c63af0303..d2f22be520 100644 --- a/packages/opencode/src/util/filesystem.ts +++ b/packages/opencode/src/util/filesystem.ts @@ -30,7 +30,7 @@ export namespace Filesystem { return readFile(p, "utf-8") } - export async function readJson(p: string): Promise { + export async function readJson(p: string): Promise { return JSON.parse(await readFile(p, "utf-8")) } From 472d01fbaf8e5aa46048062d3dd8f7acb1fc2c49 Mon Sep 17 00:00:00 2001 From: Dax Date: Wed, 18 Feb 2026 12:22:46 -0500 Subject: [PATCH 12/88] refactor: migrate cli/cmd/run.ts from Bun.file() to Filesystem/stat modules (#14155) --- packages/opencode/src/cli/cmd/github.ts | 3 ++- packages/opencode/src/cli/cmd/run.ts | 12 +++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/packages/opencode/src/cli/cmd/github.ts b/packages/opencode/src/cli/cmd/github.ts index 7f9a03d948..c44b7f6a20 100644 --- a/packages/opencode/src/cli/cmd/github.ts +++ b/packages/opencode/src/cli/cmd/github.ts @@ -1,5 +1,6 @@ import path from "path" import { exec } from "child_process" +import { Filesystem } from "../../util/filesystem" import * as prompts from "@clack/prompts" import { map, pipe, sortBy, values } from "remeda" import { Octokit } from "@octokit/rest" @@ -360,7 +361,7 @@ export const GithubInstallCommand = cmd({ ? "" : `\n env:${providers[provider].env.map((e) => `\n ${e}: \${{ secrets.${e} }}`).join("")}` - await Bun.write( + await Filesystem.write( path.join(app.root, WORKFLOW_FILE), `name: opencode diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index 55cf9a2a0a..bf63eabf81 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -6,6 +6,7 @@ import { cmd } from "./cmd" import { Flag } from "../../flag/flag" import { bootstrap } from "../bootstrap" import { EOL } from "os" +import { Filesystem } from "../../util/filesystem" import { createOpencodeClient, type Message, type OpencodeClient, type ToolPart } from "@opencode-ai/sdk/v2" import { Server } from "../../server/server" import { Provider } from "../../provider/provider" @@ -315,19 +316,12 @@ export const RunCommand = cmd({ for (const filePath of list) { const resolvedPath = path.resolve(process.cwd(), filePath) - const file = Bun.file(resolvedPath) - const stats = await file.stat().catch(() => {}) - if (!stats) { - UI.error(`File not found: ${filePath}`) - process.exit(1) - } - if (!(await file.exists())) { + if (!(await Filesystem.exists(resolvedPath))) { UI.error(`File not found: ${filePath}`) process.exit(1) } - const stat = await file.stat() - const mime = stat.isDirectory() ? "application/x-directory" : "text/plain" + const mime = (await Filesystem.isDir(resolvedPath)) ? "application/x-directory" : "text/plain" files.push({ type: "file", From b714bb21d232d9c9fbb7fb1915c752d7ff4f150d Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Wed, 18 Feb 2026 12:23:06 -0500 Subject: [PATCH 13/88] ci: switch to standard GitHub cache action for Bun dependencies --- .github/actions/setup-bun/action.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/actions/setup-bun/action.yml b/.github/actions/setup-bun/action.yml index 8cf87c5d8e..20d53e81e8 100644 --- a/.github/actions/setup-bun/action.yml +++ b/.github/actions/setup-bun/action.yml @@ -3,12 +3,13 @@ description: "Setup Bun with caching and install dependencies" runs: using: "composite" steps: - - name: Mount Bun Cache - if: ${{ runner.os == 'Linux' }} - uses: useblacksmith/stickydisk@v1 + - name: Cache Bun dependencies + uses: actions/cache@v4 with: - key: ${{ github.repository }}-bun-cache-${{ runner.os }} - path: ~/.bun + path: ~/.bun/install/cache + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} + restore-keys: | + ${{ runner.os }}-bun- - name: Setup Bun uses: oven-sh/setup-bun@v2 From a500eaa2d425978ad97b3e034404adcaab171411 Mon Sep 17 00:00:00 2001 From: Dax Date: Wed, 18 Feb 2026 12:31:35 -0500 Subject: [PATCH 14/88] refactor: migrate format/formatter.ts from Bun.file() to Filesystem module (#14153) --- packages/opencode/src/format/formatter.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/opencode/src/format/formatter.ts b/packages/opencode/src/format/formatter.ts index 694c23d558..47b2d6a12d 100644 --- a/packages/opencode/src/format/formatter.ts +++ b/packages/opencode/src/format/formatter.ts @@ -67,7 +67,10 @@ export const prettier: Info = { async enabled() { const items = await Filesystem.findUp("package.json", Instance.directory, Instance.worktree) for (const item of items) { - const json = await Bun.file(item).json() + const json = await Filesystem.readJson<{ + dependencies?: Record + devDependencies?: Record + }>(item) if (json.dependencies?.prettier) return true if (json.devDependencies?.prettier) return true } @@ -86,7 +89,10 @@ export const oxfmt: Info = { if (!Flag.OPENCODE_EXPERIMENTAL_OXFMT) return false const items = await Filesystem.findUp("package.json", Instance.directory, Instance.worktree) for (const item of items) { - const json = await Bun.file(item).json() + const json = await Filesystem.readJson<{ + dependencies?: Record + devDependencies?: Record + }>(item) if (json.dependencies?.oxfmt) return true if (json.devDependencies?.oxfmt) return true } @@ -179,7 +185,7 @@ export const ruff: Info = { const found = await Filesystem.findUp(config, Instance.directory, Instance.worktree) if (found.length > 0) { if (config === "pyproject.toml") { - const content = await Bun.file(found[0]).text() + const content = await Filesystem.readText(found[0]) if (content.includes("[tool.ruff]")) return true } else { return true @@ -190,7 +196,7 @@ export const ruff: Info = { for (const dep of deps) { const found = await Filesystem.findUp(dep, Instance.directory, Instance.worktree) if (found.length > 0) { - const content = await Bun.file(found[0]).text() + const content = await Filesystem.readText(found[0]) if (content.includes("ruff")) return true } } @@ -348,7 +354,10 @@ export const pint: Info = { async enabled() { const items = await Filesystem.findUp("composer.json", Instance.directory, Instance.worktree) for (const item of items) { - const json = await Bun.file(item).json() + const json = await Filesystem.readJson<{ + require?: Record + "require-dev"?: Record + }>(item) if (json.require?.["laravel/pint"]) return true if (json["require-dev"]?.["laravel/pint"]) return true } From ef155f3766868d3148efa8925e432b974edf0353 Mon Sep 17 00:00:00 2001 From: Dax Date: Wed, 18 Feb 2026 12:33:20 -0500 Subject: [PATCH 16/88] refactor: migrate file/index.ts from Bun.file() to Filesystem module (#14152) --- packages/opencode/src/file/index.ts | 43 ++++++++++++----------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/packages/opencode/src/file/index.ts b/packages/opencode/src/file/index.ts index 32465015e9..bfe120f134 100644 --- a/packages/opencode/src/file/index.ts +++ b/packages/opencode/src/file/index.ts @@ -1,7 +1,6 @@ import { BusEvent } from "@/bus/bus-event" import z from "zod" import { $ } from "bun" -import type { BunFile } from "bun" import { formatPatch, structuredPatch } from "diff" import path from "path" import fs from "fs" @@ -241,8 +240,8 @@ export namespace File { return mimeType.startsWith("image/") } - async function shouldEncode(file: BunFile): Promise { - const type = file.type?.toLowerCase() + async function shouldEncode(mimeType: string): Promise { + const type = mimeType.toLowerCase() log.info("shouldEncode", { type }) if (!type) return false @@ -385,7 +384,7 @@ export namespace File { const untrackedFiles = untrackedOutput.trim().split("\n") for (const filepath of untrackedFiles) { try { - const content = await Bun.file(path.join(Instance.directory, filepath)).text() + const content = await Filesystem.readText(path.join(Instance.directory, filepath)) const lines = content.split("\n").length changedFiles.push({ path: filepath, @@ -437,10 +436,9 @@ export namespace File { // Fast path: check extension before any filesystem operations if (isImageByExtension(file)) { - const bunFile = Bun.file(full) - if (await bunFile.exists()) { - const buffer = await bunFile.arrayBuffer().catch(() => new ArrayBuffer(0)) - const content = Buffer.from(buffer).toString("base64") + if (await Filesystem.exists(full)) { + const buffer = await Filesystem.readBytes(full).catch(() => Buffer.from([])) + const content = buffer.toString("base64") const mimeType = getImageMimeType(file) return { type: "text", content, mimeType, encoding: "base64" } } @@ -451,29 +449,24 @@ export namespace File { return { type: "binary", content: "" } } - const bunFile = Bun.file(full) - - if (!(await bunFile.exists())) { + if (!(await Filesystem.exists(full))) { return { type: "text", content: "" } } - const encode = await shouldEncode(bunFile) - const mimeType = bunFile.type || "application/octet-stream" + const mimeType = Filesystem.mimeType(full) + const encode = await shouldEncode(mimeType) if (encode && !isImage(mimeType)) { return { type: "binary", content: "", mimeType } } if (encode) { - const buffer = await bunFile.arrayBuffer().catch(() => new ArrayBuffer(0)) - const content = Buffer.from(buffer).toString("base64") + const buffer = await Filesystem.readBytes(full).catch(() => Buffer.from([])) + const content = buffer.toString("base64") return { type: "text", content, mimeType, encoding: "base64" } } - const content = await bunFile - .text() - .catch(() => "") - .then((x) => x.trim()) + const content = (await Filesystem.readText(full).catch(() => "")).trim() if (project.vcs === "git") { let diff = await $`git diff ${file}`.cwd(Instance.directory).quiet().nothrow().text() @@ -497,13 +490,13 @@ export namespace File { let ignored = (_: string) => false if (project.vcs === "git") { const ig = ignore() - const gitignore = Bun.file(path.join(Instance.worktree, ".gitignore")) - if (await gitignore.exists()) { - ig.add(await gitignore.text()) + const gitignorePath = path.join(Instance.worktree, ".gitignore") + if (await Filesystem.exists(gitignorePath)) { + ig.add(await Filesystem.readText(gitignorePath)) } - const ignoreFile = Bun.file(path.join(Instance.worktree, ".ignore")) - if (await ignoreFile.exists()) { - ig.add(await ignoreFile.text()) + const ignorePath = path.join(Instance.worktree, ".ignore") + if (await Filesystem.exists(ignorePath)) { + ig.add(await Filesystem.readText(ignorePath)) } ignored = ig.ignores.bind(ig) } From 8f4a72c57a28009a576f65ee713c1241fc3df35f Mon Sep 17 00:00:00 2001 From: Dax Date: Wed, 18 Feb 2026 12:35:32 -0500 Subject: [PATCH 17/88] refactor: migrate config/markdown.ts from Bun.file() to Filesystem module (#14151) --- packages/opencode/src/cli/cmd/uninstall.ts | 9 ++++----- packages/opencode/src/config/markdown.ts | 3 ++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/opencode/src/cli/cmd/uninstall.ts b/packages/opencode/src/cli/cmd/uninstall.ts index 704d3572bb..3d8e7e3f75 100644 --- a/packages/opencode/src/cli/cmd/uninstall.ts +++ b/packages/opencode/src/cli/cmd/uninstall.ts @@ -7,6 +7,7 @@ import { $ } from "bun" import fs from "fs/promises" import path from "path" import os from "os" +import { Filesystem } from "../../util/filesystem" interface UninstallArgs { keepConfig: boolean @@ -267,9 +268,7 @@ async function getShellConfigFile(): Promise { .catch(() => false) if (!exists) continue - const content = await Bun.file(file) - .text() - .catch(() => "") + const content = await Filesystem.readText(file).catch(() => "") if (content.includes("# opencode") || content.includes(".opencode/bin")) { return file } @@ -279,7 +278,7 @@ async function getShellConfigFile(): Promise { } async function cleanShellConfig(file: string) { - const content = await Bun.file(file).text() + const content = await Filesystem.readText(file) const lines = content.split("\n") const filtered: string[] = [] @@ -315,7 +314,7 @@ async function cleanShellConfig(file: string) { } const output = filtered.join("\n") + "\n" - await Bun.write(file, output) + await Filesystem.write(file, output) } async function getDirectorySize(dir: string): Promise { diff --git a/packages/opencode/src/config/markdown.ts b/packages/opencode/src/config/markdown.ts index 4cd17746c5..5b4ccf0477 100644 --- a/packages/opencode/src/config/markdown.ts +++ b/packages/opencode/src/config/markdown.ts @@ -1,6 +1,7 @@ import { NamedError } from "@opencode-ai/util/error" import matter from "gray-matter" import { z } from "zod" +import { Filesystem } from "../util/filesystem" export namespace ConfigMarkdown { export const FILE_REGEX = /(? Date: Wed, 18 Feb 2026 12:38:30 -0500 Subject: [PATCH 19/88] refactor: migrate src/bun/index.ts from Bun.file()/Bun.write() to Filesystem module (#14147) --- packages/opencode/src/bun/index.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/opencode/src/bun/index.ts b/packages/opencode/src/bun/index.ts index bdb7cff78e..79aaae2bcc 100644 --- a/packages/opencode/src/bun/index.ts +++ b/packages/opencode/src/bun/index.ts @@ -66,14 +66,14 @@ export namespace BunProc { using _ = await Lock.write("bun-install") const mod = path.join(Global.Path.cache, "node_modules", pkg) - const pkgjson = Bun.file(path.join(Global.Path.cache, "package.json")) - const parsed = await pkgjson.json().catch(async () => { - const result = { dependencies: {} } - await Bun.write(pkgjson.name!, JSON.stringify(result, null, 2)) + const pkgjsonPath = path.join(Global.Path.cache, "package.json") + const parsed = await Filesystem.readJson<{ dependencies: Record }>(pkgjsonPath).catch(async () => { + const result = { dependencies: {} as Record } + await Filesystem.writeJson(pkgjsonPath, result) return result }) - const dependencies = parsed.dependencies ?? {} - if (!parsed.dependencies) parsed.dependencies = dependencies + if (!parsed.dependencies) parsed.dependencies = {} as Record + const dependencies = parsed.dependencies const modExists = await Filesystem.exists(mod) const cachedVersion = dependencies[pkg] @@ -123,15 +123,16 @@ export namespace BunProc { // This ensures subsequent starts use the cached version until explicitly updated let resolvedVersion = version if (version === "latest") { - const installedPkgJson = Bun.file(path.join(mod, "package.json")) - const installedPkg = await installedPkgJson.json().catch(() => null) + const installedPkg = await Filesystem.readJson<{ version?: string }>(path.join(mod, "package.json")).catch( + () => null, + ) if (installedPkg?.version) { resolvedVersion = installedPkg.version } } parsed.dependencies[pkg] = resolvedVersion - await Bun.write(pkgjson.name!, JSON.stringify(parsed, null, 2)) + await Filesystem.writeJson(pkgjsonPath, parsed) return mod } } From eb3f337695638234c28b06cdaa8515ac48443e56 Mon Sep 17 00:00:00 2001 From: Dax Date: Wed, 18 Feb 2026 12:38:44 -0500 Subject: [PATCH 20/88] refactor: migrate clipboard.ts from Bun.file() to Filesystem module (#14148) --- packages/opencode/src/cli/cmd/tui/util/clipboard.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/util/clipboard.ts b/packages/opencode/src/cli/cmd/tui/util/clipboard.ts index 4be6787346..7d1aad3a86 100644 --- a/packages/opencode/src/cli/cmd/tui/util/clipboard.ts +++ b/packages/opencode/src/cli/cmd/tui/util/clipboard.ts @@ -4,6 +4,7 @@ import clipboardy from "clipboardy" import { lazy } from "../../../../util/lazy.js" import { tmpdir } from "os" import path from "path" +import { Filesystem } from "../../../../util/filesystem" /** * Writes text to clipboard via OSC 52 escape sequence. @@ -34,9 +35,8 @@ export namespace Clipboard { await $`osascript -e 'set imageData to the clipboard as "PNGf"' -e 'set fileRef to open for access POSIX file "${tmpfile}" with write permission' -e 'set eof fileRef to 0' -e 'write imageData to fileRef' -e 'close access fileRef'` .nothrow() .quiet() - const file = Bun.file(tmpfile) - const buffer = await file.arrayBuffer() - return { data: Buffer.from(buffer).toString("base64"), mime: "image/png" } + const buffer = await Filesystem.readBytes(tmpfile) + return { data: buffer.toString("base64"), mime: "image/png" } } catch { } finally { await $`rm -f "${tmpfile}"`.nothrow().quiet() From 5638b782c56e00bceeb029066811a0712c68e2ec Mon Sep 17 00:00:00 2001 From: Dax Date: Wed, 18 Feb 2026 12:44:33 -0500 Subject: [PATCH 21/88] refactor: migrate editor.ts from Bun.file()/Bun.write() to Filesystem module (#14149) --- packages/opencode/src/cli/cmd/tui/util/editor.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/util/editor.ts b/packages/opencode/src/cli/cmd/tui/util/editor.ts index f98e24b069..cb7c691bbd 100644 --- a/packages/opencode/src/cli/cmd/tui/util/editor.ts +++ b/packages/opencode/src/cli/cmd/tui/util/editor.ts @@ -3,6 +3,7 @@ import { rm } from "node:fs/promises" import { tmpdir } from "node:os" import { join } from "node:path" import { CliRenderer } from "@opentui/core" +import { Filesystem } from "@/util/filesystem" export namespace Editor { export async function open(opts: { value: string; renderer: CliRenderer }): Promise { @@ -12,7 +13,7 @@ export namespace Editor { const filepath = join(tmpdir(), `${Date.now()}.md`) await using _ = defer(async () => rm(filepath, { force: true })) - await Bun.write(filepath, opts.value) + await Filesystem.write(filepath, opts.value) opts.renderer.suspend() opts.renderer.currentRenderBuffer.clear() const parts = editor.split(" ") @@ -23,7 +24,7 @@ export namespace Editor { stderr: "inherit", }) await proc.exited - const content = await Bun.file(filepath).text() + const content = await Filesystem.readText(filepath) opts.renderer.currentRenderBuffer.clear() opts.renderer.resume() opts.renderer.requestRender() From d447b7694afc0080b78e7052b9de4c5a1a5f9eaf Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Wed, 18 Feb 2026 12:45:27 -0500 Subject: [PATCH 22/88] fix(github): emit PROMPT_TOO_LARGE error on context overflow (#14166) --- packages/opencode/src/cli/cmd/github.ts | 39 +++++++++++++++---- .../opencode/test/cli/github-action.test.ts | 38 +++++++++++++++++- 2 files changed, 68 insertions(+), 9 deletions(-) diff --git a/packages/opencode/src/cli/cmd/github.ts b/packages/opencode/src/cli/cmd/github.ts index c44b7f6a20..fd1a2f7e58 100644 --- a/packages/opencode/src/cli/cmd/github.ts +++ b/packages/opencode/src/cli/cmd/github.ts @@ -174,6 +174,18 @@ export function extractResponseText(parts: MessageV2.Part[]): string | null { throw new Error("Failed to parse response: no parts returned") } +/** + * Formats a PROMPT_TOO_LARGE error message with details about files in the prompt. + * Content is base64 encoded, so we calculate original size by multiplying by 0.75. + */ +export function formatPromptTooLargeError(files: { filename: string; content: string }[]): string { + const fileDetails = + files.length > 0 + ? `\n\nFiles in prompt:\n${files.map((f) => ` - ${f.filename} (${((f.content.length * 0.75) / 1024).toFixed(0)} KB)`).join("\n")}` + : "" + return `PROMPT_TOO_LARGE: The prompt exceeds the model's context limit.${fileDetails}` +} + export const GithubCommand = cmd({ command: "github", describe: "manage GitHub agent", @@ -803,6 +815,7 @@ export const GithubRunCommand = cmd({ replacement, }) } + return { userPrompt: prompt, promptFiles: imgData } } @@ -910,10 +923,15 @@ export const GithubRunCommand = cmd({ // result should always be assistant just satisfying type checker if (result.info.role === "assistant" && result.info.error) { - console.error("Agent error:", result.info.error) - throw new Error( - `${result.info.error.name}: ${"message" in result.info.error ? result.info.error.message : ""}`, - ) + const err = result.info.error + console.error("Agent error:", err) + + if (err.name === "ContextOverflowError") { + throw new Error(formatPromptTooLargeError(files)) + } + + const errorMsg = err.data?.message || "" + throw new Error(`${err.name}: ${errorMsg}`) } const text = extractResponseText(result.parts) @@ -939,10 +957,15 @@ export const GithubRunCommand = cmd({ }) if (summary.info.role === "assistant" && summary.info.error) { - console.error("Summary agent error:", summary.info.error) - throw new Error( - `${summary.info.error.name}: ${"message" in summary.info.error ? summary.info.error.message : ""}`, - ) + const err = summary.info.error + console.error("Summary agent error:", err) + + if (err.name === "ContextOverflowError") { + throw new Error(formatPromptTooLargeError(files)) + } + + const errorMsg = err.data?.message || "" + throw new Error(`${err.name}: ${errorMsg}`) } const summaryText = extractResponseText(summary.parts) diff --git a/packages/opencode/test/cli/github-action.test.ts b/packages/opencode/test/cli/github-action.test.ts index 773d9eb6a4..cd64bb59ec 100644 --- a/packages/opencode/test/cli/github-action.test.ts +++ b/packages/opencode/test/cli/github-action.test.ts @@ -1,5 +1,5 @@ import { test, expect, describe } from "bun:test" -import { extractResponseText } from "../../src/cli/cmd/github" +import { extractResponseText, formatPromptTooLargeError } from "../../src/cli/cmd/github" import type { MessageV2 } from "../../src/session/message-v2" // Helper to create minimal valid parts @@ -159,3 +159,39 @@ describe("extractResponseText", () => { expect(extractResponseText(parts)).toBe("Here's what I found") }) }) + +describe("formatPromptTooLargeError", () => { + test("formats error without files", () => { + const result = formatPromptTooLargeError([]) + expect(result).toBe("PROMPT_TOO_LARGE: The prompt exceeds the model's context limit.") + }) + + test("formats error with files (base64 content)", () => { + // Base64 is ~33% larger than original, so we multiply by 0.75 to get original size + // 400 KB base64 = 300 KB original, 200 KB base64 = 150 KB original + const files = [ + { filename: "screenshot.png", content: "a".repeat(400 * 1024) }, + { filename: "diagram.png", content: "b".repeat(200 * 1024) }, + ] + const result = formatPromptTooLargeError(files) + + expect(result).toStartWith("PROMPT_TOO_LARGE: The prompt exceeds the model's context limit.") + expect(result).toInclude("Files in prompt:") + expect(result).toInclude("screenshot.png (300 KB)") + expect(result).toInclude("diagram.png (150 KB)") + }) + + test("lists all files when multiple present", () => { + // Base64 sizes: 4KB -> 3KB, 8KB -> 6KB, 12KB -> 9KB + const files = [ + { filename: "img1.png", content: "x".repeat(4 * 1024) }, + { filename: "img2.jpg", content: "y".repeat(8 * 1024) }, + { filename: "img3.gif", content: "z".repeat(12 * 1024) }, + ] + const result = formatPromptTooLargeError(files) + + expect(result).toInclude("img1.png (3 KB)") + expect(result).toInclude("img2.jpg (6 KB)") + expect(result).toInclude("img3.gif (9 KB)") + }) +}) From 3f60a6c2a46dab1622ee4f4c99e4dfad876f3a3c Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 18 Feb 2026 09:56:58 -0600 Subject: [PATCH 23/88] chore: cleanup --- packages/app/src/pages/session.tsx | 68 ++---------------------------- 1 file changed, 3 insertions(+), 65 deletions(-) diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 7d950b3466..cbe5a3acac 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -1,14 +1,10 @@ -import { For, onCleanup, Show, Match, Switch, createMemo, createEffect, on } from "solid-js" +import { onCleanup, Show, Match, Switch, createMemo, createEffect, on } from "solid-js" import { createMediaQuery } from "@solid-primitives/media" import { createResizeObserver } from "@solid-primitives/resize-observer" import { useLocal } from "@/context/local" import { selectionFromLines, useFile, type FileSelection, type SelectedLineRange } from "@/context/file" -import { createStore, produce } from "solid-js/store" -import { IconButton } from "@opencode-ai/ui/icon-button" -import { Button } from "@opencode-ai/ui/button" -import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip" +import { createStore } from "solid-js/store" import { ResizeHandle } from "@opencode-ai/ui/resize-handle" -import { Tabs } from "@opencode-ai/ui/tabs" import { Select } from "@opencode-ai/ui/select" import { createAutoScroll } from "@opencode-ai/ui/hooks" import { Mark } from "@opencode-ai/ui/logo" @@ -17,10 +13,7 @@ import { useSync } from "@/context/sync" import { useTerminal } from "@/context/terminal" import { useLayout } from "@/context/layout" import { checksum, base64Encode } from "@opencode-ai/util/encode" -import { findLast } from "@opencode-ai/util/array" import { useDialog } from "@opencode-ai/ui/context/dialog" -import { DialogSelectFile } from "@/components/dialog-select-file" -import FileTree from "@/components/file-tree" import { useCommand } from "@/context/command" import { useLanguage } from "@/context/language" import { useNavigate, useParams } from "@solidjs/router" @@ -29,19 +22,12 @@ import { useSDK } from "@/context/sdk" import { usePrompt } from "@/context/prompt" import { useComments } from "@/context/comments" import { usePermission } from "@/context/permission" -import { showToast } from "@opencode-ai/ui/toast" import { SessionHeader, NewSessionView } from "@/components/session" import { navMark, navParams } from "@/utils/perf" import { same } from "@/utils/same" import { createOpenReviewFile } from "@/pages/session/helpers" import { createScrollSpy } from "@/pages/session/scroll-spy" -import { createFileTabListSync } from "@/pages/session/file-tab-scroll" -import { - SessionReviewTab, - StickyAddButton, - type DiffStyle, - type SessionReviewTabProps, -} from "@/pages/session/review-tab" +import { SessionReviewTab, type DiffStyle, type SessionReviewTabProps } from "@/pages/session/review-tab" import { TerminalPanel } from "@/pages/session/terminal-panel" import { MessageTimeline } from "@/pages/session/message-timeline" import { useSessionCommands } from "@/pages/session/use-session-commands" @@ -195,16 +181,6 @@ export default function Page() { if (!view().reviewPanel.opened()) view().reviewPanel.open() } - const openTab = (value: string) => { - const next = normalizeTab(value) - tabs().open(next) - - const path = file.pathFromTab(next) - if (!path) return - file.load(path) - openReviewPanel() - } - createEffect(() => { const active = tabs().active() if (!active) return @@ -343,33 +319,6 @@ export default function Page() { scrollToMessage(msgs[targetIndex], "auto") } - const kinds = createMemo(() => { - const merge = (a: "add" | "del" | "mix" | undefined, b: "add" | "del" | "mix") => { - if (!a) return b - if (a === b) return a - return "mix" as const - } - - const normalize = (p: string) => p.replaceAll("\\\\", "/").replace(/\/+$/, "") - - const out = new Map() - for (const diff of diffs()) { - const file = normalize(diff.file) - const kind = diff.status === "added" ? "add" : diff.status === "deleted" ? "del" : "mix" - - out.set(file, kind) - - const parts = file.split("/") - for (const [idx] of parts.slice(0, -1).entries()) { - const dir = parts.slice(0, idx + 1).join("/") - if (!dir) continue - out.set(dir, merge(out.get(dir), kind)) - } - } - return out - }) - const emptyDiffFiles: string[] = [] - const diffFiles = createMemo(() => diffs().map((d) => d.file), emptyDiffFiles, { equals: same }) const diffsReady = createMemo(() => { const id = params.id if (!id) return true @@ -709,11 +658,6 @@ export default function Page() { ), ) - const setFileTreeTabValue = (value: string) => { - if (value !== "changes" && value !== "all") return - setFileTreeTab(value) - } - const reviewDiffId = (path: string) => { const sum = checksum(path) if (!sum) return @@ -809,12 +753,6 @@ export default function Page() { return "empty" }) - const activeFileTab = createMemo(() => { - const active = activeTab() - if (!openedTabs().includes(active)) return - return active - }) - createEffect(() => { if (!layout.ready()) return if (tabs().active()) return From ef14f64f9ee10ee7945a547bde4b13d6dcf2f0bd Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 18 Feb 2026 11:02:41 -0600 Subject: [PATCH 24/88] chore: cleanup --- packages/app/src/context/global-sync.test.ts | 10 -- packages/app/src/context/global-sync.tsx | 31 ---- .../context/global-sync/child-store.test.ts | 2 - .../src/context/global-sync/child-store.ts | 5 - .../src/context/global-sync/session-load.ts | 1 - packages/app/src/context/global-sync/types.ts | 1 - packages/app/src/pages/layout.tsx | 18 --- packages/app/src/pages/session.tsx | 46 ------ .../src/pages/session/message-timeline.tsx | 57 ++++---- packages/app/src/utils/perf.ts | 135 ------------------ 10 files changed, 25 insertions(+), 281 deletions(-) delete mode 100644 packages/app/src/utils/perf.ts diff --git a/packages/app/src/context/global-sync.test.ts b/packages/app/src/context/global-sync.test.ts index 396b412318..7956057fd0 100644 --- a/packages/app/src/context/global-sync.test.ts +++ b/packages/app/src/context/global-sync.test.ts @@ -30,7 +30,6 @@ describe("pickDirectoriesToEvict", () => { describe("loadRootSessionsWithFallback", () => { test("uses limited roots query when supported", async () => { const calls: Array<{ directory: string; roots: true; limit?: number }> = [] - let fallback = 0 const result = await loadRootSessionsWithFallback({ directory: "dir", @@ -39,20 +38,15 @@ describe("loadRootSessionsWithFallback", () => { calls.push(query) return { data: [] } }, - onFallback: () => { - fallback += 1 - }, }) expect(result.data).toEqual([]) expect(result.limited).toBe(true) expect(calls).toEqual([{ directory: "dir", roots: true, limit: 10 }]) - expect(fallback).toBe(0) }) test("falls back to full roots query on limited-query failure", async () => { const calls: Array<{ directory: string; roots: true; limit?: number }> = [] - let fallback = 0 const result = await loadRootSessionsWithFallback({ directory: "dir", @@ -62,9 +56,6 @@ describe("loadRootSessionsWithFallback", () => { if (query.limit) throw new Error("unsupported") return { data: [] } }, - onFallback: () => { - fallback += 1 - }, }) expect(result.data).toEqual([]) @@ -73,7 +64,6 @@ describe("loadRootSessionsWithFallback", () => { { directory: "dir", roots: true, limit: 25 }, { directory: "dir", roots: true }, ]) - expect(fallback).toBe(1) }) }) diff --git a/packages/app/src/context/global-sync.tsx b/packages/app/src/context/global-sync.tsx index 4f3664d8e5..7e242130f1 100644 --- a/packages/app/src/context/global-sync.tsx +++ b/packages/app/src/context/global-sync.tsx @@ -57,14 +57,6 @@ function errorMessage(error: unknown) { return "Unknown error" } -function setDevStats(value: { - activeDirectoryStores: number - evictions: number - loadSessionsFullFetchFallback: number -}) { - ;(globalThis as { __OPENCODE_GLOBAL_SYNC_STATS?: typeof value }).__OPENCODE_GLOBAL_SYNC_STATS = value -} - function createGlobalSync() { const globalSDK = useGlobalSDK() const platform = usePlatform() @@ -72,11 +64,6 @@ function createGlobalSync() { const owner = getOwner() if (!owner) throw new Error("GlobalSync must be created within owner") - const stats = { - evictions: 0, - loadSessionsFallback: 0, - } - const sdkCache = new Map() const booting = new Map>() const sessionLoads = new Map>() @@ -112,15 +99,6 @@ function createGlobalSync() { setGlobalStore("session_todo", sessionID, reconcile(todos, { key: "id" })) } - const updateStats = (activeDirectoryStores: number) => { - if (!import.meta.env.DEV) return - setDevStats({ - activeDirectoryStores, - evictions: stats.evictions, - loadSessionsFullFetchFallback: stats.loadSessionsFallback, - }) - } - const paused = () => untrack(() => globalStore.reload) !== undefined const queue = createRefreshQueue({ @@ -131,11 +109,6 @@ function createGlobalSync() { const children = createChildStoreManager({ owner, - markStats: updateStats, - incrementEvictions: () => { - stats.evictions += 1 - updateStats(Object.keys(children.children).length) - }, isBooting: (directory) => booting.has(directory), isLoadingSessions: (directory) => sessionLoads.has(directory), onBootstrap: (directory) => { @@ -207,10 +180,6 @@ function createGlobalSync() { directory, limit, list: (query) => globalSDK.client.session.list(query), - onFallback: () => { - stats.loadSessionsFallback += 1 - updateStats(Object.keys(children.children).length) - }, }) .then((x) => { const nonArchived = (x.data ?? []) diff --git a/packages/app/src/context/global-sync/child-store.test.ts b/packages/app/src/context/global-sync/child-store.test.ts index 500f0fc70a..cec76ff87e 100644 --- a/packages/app/src/context/global-sync/child-store.test.ts +++ b/packages/app/src/context/global-sync/child-store.test.ts @@ -17,8 +17,6 @@ describe("createChildStoreManager", () => { const manager = createChildStoreManager({ owner, - markStats() {}, - incrementEvictions() {}, isBooting: () => false, isLoadingSessions: () => false, onBootstrap() {}, diff --git a/packages/app/src/context/global-sync/child-store.ts b/packages/app/src/context/global-sync/child-store.ts index af08c3bd43..2fe5b78303 100644 --- a/packages/app/src/context/global-sync/child-store.ts +++ b/packages/app/src/context/global-sync/child-store.ts @@ -17,8 +17,6 @@ import { canDisposeDirectory, pickDirectoriesToEvict } from "./eviction" export function createChildStoreManager(input: { owner: Owner - markStats: (activeDirectoryStores: number) => void - incrementEvictions: () => void isBooting: (directory: string) => boolean isLoadingSessions: (directory: string) => boolean onBootstrap: (directory: string) => void @@ -102,7 +100,6 @@ export function createChildStoreManager(input: { } delete children[directory] input.onDispose(directory) - input.markStats(Object.keys(children).length) return true } @@ -120,7 +117,6 @@ export function createChildStoreManager(input: { if (list.length === 0) return for (const directory of list) { if (!disposeDirectory(directory)) continue - input.incrementEvictions() } } @@ -200,7 +196,6 @@ export function createChildStoreManager(input: { }) runWithOwner(input.owner, init) - input.markStats(Object.keys(children).length) } mark(directory) const childStore = children[directory] diff --git a/packages/app/src/context/global-sync/session-load.ts b/packages/app/src/context/global-sync/session-load.ts index 443aa84502..3693dcb460 100644 --- a/packages/app/src/context/global-sync/session-load.ts +++ b/packages/app/src/context/global-sync/session-load.ts @@ -9,7 +9,6 @@ export async function loadRootSessionsWithFallback(input: RootLoadArgs) { limited: true, } as const } catch { - input.onFallback() const result = await input.list({ directory: input.directory, roots: true }) return { data: result.data, diff --git a/packages/app/src/context/global-sync/types.ts b/packages/app/src/context/global-sync/types.ts index ade0b973a2..c61dc337d8 100644 --- a/packages/app/src/context/global-sync/types.ts +++ b/packages/app/src/context/global-sync/types.ts @@ -119,7 +119,6 @@ export type RootLoadArgs = { directory: string limit: number list: (query: { directory: string; roots: true; limit?: number }) => Promise<{ data?: Session[] }> - onFallback: () => void } export type RootLoadResult = { diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index cecb526171..e280b2f927 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -51,7 +51,6 @@ import { DialogSelectServer } from "@/components/dialog-select-server" import { DialogSettings } from "@/components/dialog-settings" import { useCommand, type CommandOption } from "@/context/command" import { ConstrainDragXAxis } from "@/utils/solid-dnd" -import { navStart } from "@/utils/perf" import { DialogSelectDirectory } from "@/components/dialog-select-directory" import { DialogEditProject } from "@/components/dialog-edit-project" import { Titlebar } from "@/components/titlebar" @@ -826,14 +825,6 @@ export default function Layout(props: ParentProps) { if (next) prefetchSession(next) } - if (import.meta.env.DEV) { - navStart({ - dir: base64Encode(session.directory), - from: params.id, - to: session.id, - trigger: offset > 0 ? "alt+arrowdown" : "alt+arrowup", - }) - } navigateToSession(session) queueMicrotask(() => scrollToSession(session.id, `${session.directory}:${session.id}`)) } @@ -869,15 +860,6 @@ export default function Layout(props: ParentProps) { if (next) prefetchSession(next) } - if (import.meta.env.DEV) { - navStart({ - dir: base64Encode(session.directory), - from: params.id, - to: session.id, - trigger: offset > 0 ? "shift+alt+arrowdown" : "shift+alt+arrowup", - }) - } - navigateToSession(session) queueMicrotask(() => scrollToSession(session.id, `${session.directory}:${session.id}`)) return diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index cbe5a3acac..8a91b6e856 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -23,7 +23,6 @@ import { usePrompt } from "@/context/prompt" import { useComments } from "@/context/comments" import { usePermission } from "@/context/permission" import { SessionHeader, NewSessionView } from "@/components/session" -import { navMark, navParams } from "@/utils/perf" import { same } from "@/utils/same" import { createOpenReviewFile } from "@/pages/session/helpers" import { createScrollSpy } from "@/pages/session/scroll-spy" @@ -109,46 +108,6 @@ export default function Page() { ), ) - if (import.meta.env.DEV) { - createEffect( - on( - () => [params.dir, params.id] as const, - ([dir, id], prev) => { - if (!id) return - navParams({ dir, from: prev?.[1], to: id }) - }, - ), - ) - - createEffect(() => { - const id = params.id - if (!id) return - if (!prompt.ready()) return - navMark({ dir: params.dir, to: id, name: "storage:prompt-ready" }) - }) - - createEffect(() => { - const id = params.id - if (!id) return - if (!terminal.ready()) return - navMark({ dir: params.dir, to: id, name: "storage:terminal-ready" }) - }) - - createEffect(() => { - const id = params.id - if (!id) return - if (!file.ready()) return - navMark({ dir: params.dir, to: id, name: "storage:file-view-ready" }) - }) - - createEffect(() => { - const id = params.id - if (!id) return - if (sync.data.message[id] === undefined) return - navMark({ dir: params.dir, to: id, name: "session:data-ready" }) - }) - } - const isDesktop = createMediaQuery("(min-width: 768px)") const desktopReviewOpen = createMemo(() => isDesktop() && view().reviewPanel.opened()) const desktopFileTreeOpen = createMemo(() => isDesktop() && layout.fileTree.opened()) @@ -1140,11 +1099,6 @@ export default function Page() { anchor={anchor} onRegisterMessage={scrollSpy.register} onUnregisterMessage={scrollSpy.unregister} - onFirstTurnMount={() => { - const id = params.id - if (!id) return - navMark({ dir: params.dir, to: id, name: "session:first-turn-mounted" }) - }} lastUserMessageID={lastUserMessage()?.id} /> diff --git a/packages/app/src/pages/session/message-timeline.tsx b/packages/app/src/pages/session/message-timeline.tsx index b949424085..c65e2600e8 100644 --- a/packages/app/src/pages/session/message-timeline.tsx +++ b/packages/app/src/pages/session/message-timeline.tsx @@ -1,4 +1,4 @@ -import { For, createEffect, createMemo, on, onCleanup, onMount, Show, type JSX } from "solid-js" +import { For, createEffect, createMemo, on, onCleanup, Show, type JSX } from "solid-js" import { createStore, produce } from "solid-js/store" import { useNavigate, useParams } from "@solidjs/router" import { Button } from "@opencode-ai/ui/button" @@ -72,7 +72,6 @@ export function MessageTimeline(props: { anchor: (id: string) => string onRegisterMessage: (el: HTMLDivElement, id: string) => void onUnregisterMessage: (id: string) => void - onFirstTurnMount?: () => void lastUserMessageID?: string }) { let touchGesture: number | undefined @@ -516,37 +515,31 @@ export function MessageTimeline(props: { - {(message) => { - if (import.meta.env.DEV && props.onFirstTurnMount) { - onMount(() => props.onFirstTurnMount?.()) - } - - return ( -
{ - props.onRegisterMessage(el, message.id) - onCleanup(() => props.onUnregisterMessage(message.id)) + {(message) => ( +
{ + props.onRegisterMessage(el, message.id) + onCleanup(() => props.onUnregisterMessage(message.id)) + }} + classList={{ + "min-w-0 w-full max-w-full": true, + "md:max-w-200 2xl:max-w-[1000px]": props.centered, + }} + > + - -
- ) - }} + /> +
+ )}
diff --git a/packages/app/src/utils/perf.ts b/packages/app/src/utils/perf.ts deleted file mode 100644 index 105d02a827..0000000000 --- a/packages/app/src/utils/perf.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { uuid } from "@/utils/uuid" - -type Nav = { - id: string - dir?: string - from?: string - to: string - trigger?: string - start: number - marks: Record - logged: boolean - timer?: ReturnType -} - -const dev = import.meta.env.DEV - -const key = (dir: string | undefined, to: string) => `${dir ?? ""}:${to}` - -const now = () => performance.now() - -const navs = new Map() -const pending = new Map() -const active = new Map() - -const required = [ - "session:params", - "session:data-ready", - "session:first-turn-mounted", - "storage:prompt-ready", - "storage:terminal-ready", - "storage:file-view-ready", -] - -function flush(id: string, reason: "complete" | "timeout") { - if (!dev) return - const nav = navs.get(id) - if (!nav) return - if (nav.logged) return - - nav.logged = true - if (nav.timer) clearTimeout(nav.timer) - - const baseName = nav.marks["navigate:start"] !== undefined ? "navigate:start" : "session:params" - const base = nav.marks[baseName] ?? nav.start - - const ms = Object.fromEntries( - Object.entries(nav.marks) - .slice() - .sort(([a], [b]) => a.localeCompare(b)) - .map(([name, t]) => [name, Math.round((t - base) * 100) / 100]), - ) - - console.log( - "perf.session-nav " + - JSON.stringify({ - type: "perf.session-nav.v0", - id: nav.id, - dir: nav.dir, - from: nav.from, - to: nav.to, - trigger: nav.trigger, - base: baseName, - reason, - ms, - }), - ) - - navs.delete(id) -} - -function maybeFlush(id: string) { - if (!dev) return - const nav = navs.get(id) - if (!nav) return - if (nav.logged) return - if (!required.every((name) => nav.marks[name] !== undefined)) return - flush(id, "complete") -} - -function ensure(id: string, data: Omit) { - const existing = navs.get(id) - if (existing) return existing - - const nav: Nav = { - ...data, - marks: {}, - logged: false, - } - nav.timer = setTimeout(() => flush(id, "timeout"), 5000) - navs.set(id, nav) - return nav -} - -export function navStart(input: { dir?: string; from?: string; to: string; trigger?: string }) { - if (!dev) return - - const id = uuid() - const start = now() - const nav = ensure(id, { ...input, id, start }) - nav.marks["navigate:start"] = start - - pending.set(key(input.dir, input.to), id) - return id -} - -export function navParams(input: { dir?: string; from?: string; to: string }) { - if (!dev) return - - const k = key(input.dir, input.to) - const pendingId = pending.get(k) - if (pendingId) pending.delete(k) - const id = pendingId ?? uuid() - - const start = now() - const nav = ensure(id, { ...input, id, start, trigger: pendingId ? "key" : "route" }) - nav.marks["session:params"] = start - - active.set(k, id) - maybeFlush(id) - return id -} - -export function navMark(input: { dir?: string; to: string; name: string }) { - if (!dev) return - - const id = active.get(key(input.dir, input.to)) - if (!id) return - - const nav = navs.get(id) - if (!nav) return - if (nav.marks[input.name] !== undefined) return - - nav.marks[input.name] = now() - maybeFlush(id) -} From 8408e4702e0d0eebd3a459577be3d50082c3f603 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 18 Feb 2026 11:48:19 -0600 Subject: [PATCH 25/88] chore: cleanup --- packages/app/src/pages/session.tsx | 35 -- .../pages/session/use-session-commands.tsx | 362 ++++++++++-------- 2 files changed, 196 insertions(+), 201 deletions(-) diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 8a91b6e856..1658455640 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -10,18 +10,15 @@ import { createAutoScroll } from "@opencode-ai/ui/hooks" import { Mark } from "@opencode-ai/ui/logo" import { useSync } from "@/context/sync" -import { useTerminal } from "@/context/terminal" import { useLayout } from "@/context/layout" import { checksum, base64Encode } from "@opencode-ai/util/encode" import { useDialog } from "@opencode-ai/ui/context/dialog" -import { useCommand } from "@/context/command" import { useLanguage } from "@/context/language" import { useNavigate, useParams } from "@solidjs/router" import { UserMessage } from "@opencode-ai/sdk/v2" import { useSDK } from "@/context/sdk" import { usePrompt } from "@/context/prompt" import { useComments } from "@/context/comments" -import { usePermission } from "@/context/permission" import { SessionHeader, NewSessionView } from "@/components/session" import { same } from "@/utils/same" import { createOpenReviewFile } from "@/pages/session/helpers" @@ -40,16 +37,13 @@ export default function Page() { const local = useLocal() const file = useFile() const sync = useSync() - const terminal = useTerminal() const dialog = useDialog() - const command = useCommand() const language = useLanguage() const params = useParams() const navigate = useNavigate() const sdk = useSDK() const prompt = usePrompt() const comments = useComments() - const permission = usePermission() const [ui, setUi] = createStore({ pendingMessage: undefined as string | undefined, @@ -285,7 +279,6 @@ export default function Page() { return sync.data.session_diff[id] !== undefined }) - const idle = { type: "idle" as const } let inputRef!: HTMLDivElement let promptDock: HTMLDivElement | undefined let dockHeight = 0 @@ -327,8 +320,6 @@ export default function Page() { ), ) - const status = createMemo(() => sync.data.session_status[params.id ?? ""] ?? idle) - createEffect( on( sessionKey, @@ -361,11 +352,6 @@ export default function Page() { return lines.slice(0, 2).join("\n") } - const addSelectionToContext = (path: string, selection: FileSelection) => { - const preview = selectionPreview(path, selection) - prompt.context.add({ type: "file", path, selection, preview }) - } - const addCommentToContext = (input: { file: string selection: SelectedLineRange @@ -457,29 +443,8 @@ export default function Page() { const focusInput = () => inputRef?.focus() useSessionCommands({ - command, - dialog, - file, - language, - local, - permission, - prompt, - sdk, - sync, - terminal, - layout, - params, - navigate, - tabs, - view, - info, - status, - userMessages, - visibleUserMessages, - showAllFiles, navigateMessageByOffset, setActiveMessage, - addSelectionToContext, focusInput, }) diff --git a/packages/app/src/pages/session/use-session-commands.tsx b/packages/app/src/pages/session/use-session-commands.tsx index 4d68afd66d..461351878b 100644 --- a/packages/app/src/pages/session/use-session-commands.tsx +++ b/packages/app/src/pages/session/use-session-commands.tsx @@ -22,29 +22,8 @@ import { UserMessage } from "@opencode-ai/sdk/v2" import { canAddSelectionContext } from "@/pages/session/session-command-helpers" export type SessionCommandContext = { - command: ReturnType - dialog: ReturnType - file: ReturnType - language: ReturnType - local: ReturnType - permission: ReturnType - prompt: ReturnType - sdk: ReturnType - sync: ReturnType - terminal: ReturnType - layout: ReturnType - params: ReturnType - navigate: ReturnType - tabs: () => ReturnType["tabs"]> - view: () => ReturnType["view"]> - info: () => { revert?: { messageID?: string }; share?: { url?: string } } | undefined - status: () => { type: string } - userMessages: () => UserMessage[] - visibleUserMessages: () => UserMessage[] - showAllFiles: () => void navigateMessageByOffset: (offset: number) => void setActiveMessage: (message: UserMessage | undefined) => void - addSelectionToContext: (path: string, selection: FileSelection) => void focusInput: () => void } @@ -55,45 +34,98 @@ const withCategory = (category: string) => { }) } -export const useSessionCommands = (input: SessionCommandContext) => { - const sessionCommand = withCategory(input.language.t("command.category.session")) - const fileCommand = withCategory(input.language.t("command.category.file")) - const contextCommand = withCategory(input.language.t("command.category.context")) - const viewCommand = withCategory(input.language.t("command.category.view")) - const terminalCommand = withCategory(input.language.t("command.category.terminal")) - const modelCommand = withCategory(input.language.t("command.category.model")) - const mcpCommand = withCategory(input.language.t("command.category.mcp")) - const agentCommand = withCategory(input.language.t("command.category.agent")) - const permissionsCommand = withCategory(input.language.t("command.category.permissions")) +export const useSessionCommands = (actions: SessionCommandContext) => { + const command = useCommand() + const dialog = useDialog() + const file = useFile() + const language = useLanguage() + const local = useLocal() + const permission = usePermission() + const prompt = usePrompt() + const sdk = useSDK() + const sync = useSync() + const terminal = useTerminal() + const layout = useLayout() + const params = useParams() + const navigate = useNavigate() + + const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) + const tabs = createMemo(() => layout.tabs(sessionKey)) + const view = createMemo(() => layout.view(sessionKey)) + const info = createMemo(() => (params.id ? sync.session.get(params.id) : undefined)) + + const idle = { type: "idle" as const } + const status = createMemo(() => sync.data.session_status[params.id ?? ""] ?? idle) + const messages = createMemo(() => (params.id ? (sync.data.message[params.id] ?? []) : [])) + const userMessages = createMemo(() => messages().filter((m) => m.role === "user") as UserMessage[]) + const visibleUserMessages = createMemo(() => { + const revert = info()?.revert?.messageID + if (!revert) return userMessages() + return userMessages().filter((m) => m.id < revert) + }) + + const showAllFiles = () => { + if (layout.fileTree.tab() !== "changes") return + layout.fileTree.setTab("all") + } + + const selectionPreview = (path: string, selection: FileSelection) => { + const content = file.get(path)?.content?.content + if (!content) return undefined + const start = Math.max(1, Math.min(selection.startLine, selection.endLine)) + const end = Math.max(selection.startLine, selection.endLine) + const lines = content.split("\n").slice(start - 1, end) + if (lines.length === 0) return undefined + return lines.slice(0, 2).join("\n") + } + + const addSelectionToContext = (path: string, selection: FileSelection) => { + const preview = selectionPreview(path, selection) + prompt.context.add({ type: "file", path, selection, preview }) + } + + const navigateMessageByOffset = actions.navigateMessageByOffset + const setActiveMessage = actions.setActiveMessage + const focusInput = actions.focusInput + + const sessionCommand = withCategory(language.t("command.category.session")) + const fileCommand = withCategory(language.t("command.category.file")) + const contextCommand = withCategory(language.t("command.category.context")) + const viewCommand = withCategory(language.t("command.category.view")) + const terminalCommand = withCategory(language.t("command.category.terminal")) + const modelCommand = withCategory(language.t("command.category.model")) + const mcpCommand = withCategory(language.t("command.category.mcp")) + const agentCommand = withCategory(language.t("command.category.agent")) + const permissionsCommand = withCategory(language.t("command.category.permissions")) const sessionCommands = createMemo(() => [ sessionCommand({ id: "session.new", - title: input.language.t("command.session.new"), + title: language.t("command.session.new"), keybind: "mod+shift+s", slash: "new", - onSelect: () => input.navigate(`/${input.params.dir}/session`), + onSelect: () => navigate(`/${params.dir}/session`), }), ]) const fileCommands = createMemo(() => [ fileCommand({ id: "file.open", - title: input.language.t("command.file.open"), - description: input.language.t("palette.search.placeholder"), + title: language.t("command.file.open"), + description: language.t("palette.search.placeholder"), keybind: "mod+p", slash: "open", - onSelect: () => input.dialog.show(() => ), + onSelect: () => dialog.show(() => ), }), fileCommand({ id: "tab.close", - title: input.language.t("command.tab.close"), + title: language.t("command.tab.close"), keybind: "mod+w", - disabled: !input.tabs().active(), + disabled: !tabs().active(), onSelect: () => { - const active = input.tabs().active() + const active = tabs().active() if (!active) return - input.tabs().close(active) + tabs().close(active) }, }), ]) @@ -101,30 +133,30 @@ export const useSessionCommands = (input: SessionCommandContext) => { const contextCommands = createMemo(() => [ contextCommand({ id: "context.addSelection", - title: input.language.t("command.context.addSelection"), - description: input.language.t("command.context.addSelection.description"), + title: language.t("command.context.addSelection"), + description: language.t("command.context.addSelection.description"), keybind: "mod+shift+l", disabled: !canAddSelectionContext({ - active: input.tabs().active(), - pathFromTab: input.file.pathFromTab, - selectedLines: input.file.selectedLines, + active: tabs().active(), + pathFromTab: file.pathFromTab, + selectedLines: file.selectedLines, }), onSelect: () => { - const active = input.tabs().active() + const active = tabs().active() if (!active) return - const path = input.file.pathFromTab(active) + const path = file.pathFromTab(active) if (!path) return - const range = input.file.selectedLines(path) as SelectedLineRange | null | undefined + const range = file.selectedLines(path) as SelectedLineRange | null | undefined if (!range) { showToast({ - title: input.language.t("toast.context.noLineSelection.title"), - description: input.language.t("toast.context.noLineSelection.description"), + title: language.t("toast.context.noLineSelection.title"), + description: language.t("toast.context.noLineSelection.description"), }) return } - input.addSelectionToContext(path, selectionFromLines(range)) + addSelectionToContext(path, selectionFromLines(range)) }, }), ]) @@ -132,37 +164,37 @@ export const useSessionCommands = (input: SessionCommandContext) => { const viewCommands = createMemo(() => [ viewCommand({ id: "terminal.toggle", - title: input.language.t("command.terminal.toggle"), + title: language.t("command.terminal.toggle"), keybind: "ctrl+`", slash: "terminal", - onSelect: () => input.view().terminal.toggle(), + onSelect: () => view().terminal.toggle(), }), viewCommand({ id: "review.toggle", - title: input.language.t("command.review.toggle"), + title: language.t("command.review.toggle"), keybind: "mod+shift+r", - onSelect: () => input.view().reviewPanel.toggle(), + onSelect: () => view().reviewPanel.toggle(), }), viewCommand({ id: "fileTree.toggle", - title: input.language.t("command.fileTree.toggle"), + title: language.t("command.fileTree.toggle"), keybind: "mod+\\", - onSelect: () => input.layout.fileTree.toggle(), + onSelect: () => layout.fileTree.toggle(), }), viewCommand({ id: "input.focus", - title: input.language.t("command.input.focus"), + title: language.t("command.input.focus"), keybind: "ctrl+l", - onSelect: () => input.focusInput(), + onSelect: () => focusInput(), }), terminalCommand({ id: "terminal.new", - title: input.language.t("command.terminal.new"), - description: input.language.t("command.terminal.new.description"), + title: language.t("command.terminal.new"), + description: language.t("command.terminal.new.description"), keybind: "ctrl+alt+t", onSelect: () => { - if (input.terminal.all().length > 0) input.terminal.new() - input.view().terminal.open() + if (terminal.all().length > 0) terminal.new() + view().terminal.open() }, }), ]) @@ -170,61 +202,61 @@ export const useSessionCommands = (input: SessionCommandContext) => { const messageCommands = createMemo(() => [ sessionCommand({ id: "message.previous", - title: input.language.t("command.message.previous"), - description: input.language.t("command.message.previous.description"), + title: language.t("command.message.previous"), + description: language.t("command.message.previous.description"), keybind: "mod+arrowup", - disabled: !input.params.id, - onSelect: () => input.navigateMessageByOffset(-1), + disabled: !params.id, + onSelect: () => navigateMessageByOffset(-1), }), sessionCommand({ id: "message.next", - title: input.language.t("command.message.next"), - description: input.language.t("command.message.next.description"), + title: language.t("command.message.next"), + description: language.t("command.message.next.description"), keybind: "mod+arrowdown", - disabled: !input.params.id, - onSelect: () => input.navigateMessageByOffset(1), + disabled: !params.id, + onSelect: () => navigateMessageByOffset(1), }), ]) const agentCommands = createMemo(() => [ modelCommand({ id: "model.choose", - title: input.language.t("command.model.choose"), - description: input.language.t("command.model.choose.description"), + title: language.t("command.model.choose"), + description: language.t("command.model.choose.description"), keybind: "mod+'", slash: "model", - onSelect: () => input.dialog.show(() => ), + onSelect: () => dialog.show(() => ), }), mcpCommand({ id: "mcp.toggle", - title: input.language.t("command.mcp.toggle"), - description: input.language.t("command.mcp.toggle.description"), + title: language.t("command.mcp.toggle"), + description: language.t("command.mcp.toggle.description"), keybind: "mod+;", slash: "mcp", - onSelect: () => input.dialog.show(() => ), + onSelect: () => dialog.show(() => ), }), agentCommand({ id: "agent.cycle", - title: input.language.t("command.agent.cycle"), - description: input.language.t("command.agent.cycle.description"), + title: language.t("command.agent.cycle"), + description: language.t("command.agent.cycle.description"), keybind: "mod+.", slash: "agent", - onSelect: () => input.local.agent.move(1), + onSelect: () => local.agent.move(1), }), agentCommand({ id: "agent.cycle.reverse", - title: input.language.t("command.agent.cycle.reverse"), - description: input.language.t("command.agent.cycle.reverse.description"), + title: language.t("command.agent.cycle.reverse"), + description: language.t("command.agent.cycle.reverse.description"), keybind: "shift+mod+.", - onSelect: () => input.local.agent.move(-1), + onSelect: () => local.agent.move(-1), }), modelCommand({ id: "model.variant.cycle", - title: input.language.t("command.model.variant.cycle"), - description: input.language.t("command.model.variant.cycle.description"), + title: language.t("command.model.variant.cycle"), + description: language.t("command.model.variant.cycle.description"), keybind: "shift+mod+d", onSelect: () => { - input.local.model.variant.cycle() + local.model.variant.cycle() }, }), ]) @@ -233,22 +265,22 @@ export const useSessionCommands = (input: SessionCommandContext) => { permissionsCommand({ id: "permissions.autoaccept", title: - input.params.id && input.permission.isAutoAccepting(input.params.id, input.sdk.directory) - ? input.language.t("command.permissions.autoaccept.disable") - : input.language.t("command.permissions.autoaccept.enable"), + params.id && permission.isAutoAccepting(params.id, sdk.directory) + ? language.t("command.permissions.autoaccept.disable") + : language.t("command.permissions.autoaccept.enable"), keybind: "mod+shift+a", - disabled: !input.params.id || !input.permission.permissionsEnabled(), + disabled: !params.id || !permission.permissionsEnabled(), onSelect: () => { - const sessionID = input.params.id + const sessionID = params.id if (!sessionID) return - input.permission.toggleAutoAccept(sessionID, input.sdk.directory) + permission.toggleAutoAccept(sessionID, sdk.directory) showToast({ - title: input.permission.isAutoAccepting(sessionID, input.sdk.directory) - ? input.language.t("toast.permissions.autoaccept.on.title") - : input.language.t("toast.permissions.autoaccept.off.title"), - description: input.permission.isAutoAccepting(sessionID, input.sdk.directory) - ? input.language.t("toast.permissions.autoaccept.on.description") - : input.language.t("toast.permissions.autoaccept.off.description"), + title: permission.isAutoAccepting(sessionID, sdk.directory) + ? language.t("toast.permissions.autoaccept.on.title") + : language.t("toast.permissions.autoaccept.off.title"), + description: permission.isAutoAccepting(sessionID, sdk.directory) + ? language.t("toast.permissions.autoaccept.on.description") + : language.t("toast.permissions.autoaccept.off.description"), }) }, }), @@ -257,71 +289,71 @@ export const useSessionCommands = (input: SessionCommandContext) => { const sessionActionCommands = createMemo(() => [ sessionCommand({ id: "session.undo", - title: input.language.t("command.session.undo"), - description: input.language.t("command.session.undo.description"), + title: language.t("command.session.undo"), + description: language.t("command.session.undo.description"), slash: "undo", - disabled: !input.params.id || input.visibleUserMessages().length === 0, + disabled: !params.id || visibleUserMessages().length === 0, onSelect: async () => { - const sessionID = input.params.id + const sessionID = params.id if (!sessionID) return - if (input.status()?.type !== "idle") { - await input.sdk.client.session.abort({ sessionID }).catch(() => {}) + if (status()?.type !== "idle") { + await sdk.client.session.abort({ sessionID }).catch(() => {}) } - const revert = input.info()?.revert?.messageID - const message = findLast(input.userMessages(), (x) => !revert || x.id < revert) + const revert = info()?.revert?.messageID + const message = findLast(userMessages(), (x) => !revert || x.id < revert) if (!message) return - await input.sdk.client.session.revert({ sessionID, messageID: message.id }) - const parts = input.sync.data.part[message.id] + await sdk.client.session.revert({ sessionID, messageID: message.id }) + const parts = sync.data.part[message.id] if (parts) { - const restored = extractPromptFromParts(parts, { directory: input.sdk.directory }) - input.prompt.set(restored) + const restored = extractPromptFromParts(parts, { directory: sdk.directory }) + prompt.set(restored) } - const priorMessage = findLast(input.userMessages(), (x) => x.id < message.id) - input.setActiveMessage(priorMessage) + const priorMessage = findLast(userMessages(), (x) => x.id < message.id) + setActiveMessage(priorMessage) }, }), sessionCommand({ id: "session.redo", - title: input.language.t("command.session.redo"), - description: input.language.t("command.session.redo.description"), + title: language.t("command.session.redo"), + description: language.t("command.session.redo.description"), slash: "redo", - disabled: !input.params.id || !input.info()?.revert?.messageID, + disabled: !params.id || !info()?.revert?.messageID, onSelect: async () => { - const sessionID = input.params.id + const sessionID = params.id if (!sessionID) return - const revertMessageID = input.info()?.revert?.messageID + const revertMessageID = info()?.revert?.messageID if (!revertMessageID) return - const nextMessage = input.userMessages().find((x) => x.id > revertMessageID) + const nextMessage = userMessages().find((x) => x.id > revertMessageID) if (!nextMessage) { - await input.sdk.client.session.unrevert({ sessionID }) - input.prompt.reset() - const lastMsg = findLast(input.userMessages(), (x) => x.id >= revertMessageID) - input.setActiveMessage(lastMsg) + await sdk.client.session.unrevert({ sessionID }) + prompt.reset() + const lastMsg = findLast(userMessages(), (x) => x.id >= revertMessageID) + setActiveMessage(lastMsg) return } - await input.sdk.client.session.revert({ sessionID, messageID: nextMessage.id }) - const priorMsg = findLast(input.userMessages(), (x) => x.id < nextMessage.id) - input.setActiveMessage(priorMsg) + await sdk.client.session.revert({ sessionID, messageID: nextMessage.id }) + const priorMsg = findLast(userMessages(), (x) => x.id < nextMessage.id) + setActiveMessage(priorMsg) }, }), sessionCommand({ id: "session.compact", - title: input.language.t("command.session.compact"), - description: input.language.t("command.session.compact.description"), + title: language.t("command.session.compact"), + description: language.t("command.session.compact.description"), slash: "compact", - disabled: !input.params.id || input.visibleUserMessages().length === 0, + disabled: !params.id || visibleUserMessages().length === 0, onSelect: async () => { - const sessionID = input.params.id + const sessionID = params.id if (!sessionID) return - const model = input.local.model.current() + const model = local.model.current() if (!model) { showToast({ - title: input.language.t("toast.model.none.title"), - description: input.language.t("toast.model.none.description"), + title: language.t("toast.model.none.title"), + description: language.t("toast.model.none.description"), }) return } - await input.sdk.client.session.summarize({ + await sdk.client.session.summarize({ sessionID, modelID: model.id, providerID: model.provider.id, @@ -330,29 +362,27 @@ export const useSessionCommands = (input: SessionCommandContext) => { }), sessionCommand({ id: "session.fork", - title: input.language.t("command.session.fork"), - description: input.language.t("command.session.fork.description"), + title: language.t("command.session.fork"), + description: language.t("command.session.fork.description"), slash: "fork", - disabled: !input.params.id || input.visibleUserMessages().length === 0, - onSelect: () => input.dialog.show(() => ), + disabled: !params.id || visibleUserMessages().length === 0, + onSelect: () => dialog.show(() => ), }), ]) const shareCommands = createMemo(() => { - if (input.sync.data.config.share === "disabled") return [] + if (sync.data.config.share === "disabled") return [] return [ sessionCommand({ id: "session.share", - title: input.info()?.share?.url - ? input.language.t("session.share.copy.copyLink") - : input.language.t("command.session.share"), - description: input.info()?.share?.url - ? input.language.t("toast.session.share.success.description") - : input.language.t("command.session.share.description"), + title: info()?.share?.url ? language.t("session.share.copy.copyLink") : language.t("command.session.share"), + description: info()?.share?.url + ? language.t("toast.session.share.success.description") + : language.t("command.session.share.description"), slash: "share", - disabled: !input.params.id, + disabled: !params.id, onSelect: async () => { - if (!input.params.id) return + if (!params.id) return const write = (value: string) => { const body = typeof document === "undefined" ? undefined : document.body @@ -382,7 +412,7 @@ export const useSessionCommands = (input: SessionCommandContext) => { const ok = await write(url) if (!ok) { showToast({ - title: input.language.t("toast.session.share.copyFailed.title"), + title: language.t("toast.session.share.copyFailed.title"), variant: "error", }) return @@ -390,27 +420,27 @@ export const useSessionCommands = (input: SessionCommandContext) => { showToast({ title: existing - ? input.language.t("session.share.copy.copied") - : input.language.t("toast.session.share.success.title"), - description: input.language.t("toast.session.share.success.description"), + ? language.t("session.share.copy.copied") + : language.t("toast.session.share.success.title"), + description: language.t("toast.session.share.success.description"), variant: "success", }) } - const existing = input.info()?.share?.url + const existing = info()?.share?.url if (existing) { await copy(existing, true) return } - const url = await input.sdk.client.session - .share({ sessionID: input.params.id }) + const url = await sdk.client.session + .share({ sessionID: params.id }) .then((res) => res.data?.share?.url) .catch(() => undefined) if (!url) { showToast({ - title: input.language.t("toast.session.share.failed.title"), - description: input.language.t("toast.session.share.failed.description"), + title: language.t("toast.session.share.failed.title"), + description: language.t("toast.session.share.failed.description"), variant: "error", }) return @@ -421,25 +451,25 @@ export const useSessionCommands = (input: SessionCommandContext) => { }), sessionCommand({ id: "session.unshare", - title: input.language.t("command.session.unshare"), - description: input.language.t("command.session.unshare.description"), + title: language.t("command.session.unshare"), + description: language.t("command.session.unshare.description"), slash: "unshare", - disabled: !input.params.id || !input.info()?.share?.url, + disabled: !params.id || !info()?.share?.url, onSelect: async () => { - if (!input.params.id) return - await input.sdk.client.session - .unshare({ sessionID: input.params.id }) + if (!params.id) return + await sdk.client.session + .unshare({ sessionID: params.id }) .then(() => showToast({ - title: input.language.t("toast.session.unshare.success.title"), - description: input.language.t("toast.session.unshare.success.description"), + title: language.t("toast.session.unshare.success.title"), + description: language.t("toast.session.unshare.success.description"), variant: "success", }), ) .catch(() => showToast({ - title: input.language.t("toast.session.unshare.failed.title"), - description: input.language.t("toast.session.unshare.failed.description"), + title: language.t("toast.session.unshare.failed.title"), + description: language.t("toast.session.unshare.failed.description"), variant: "error", }), ) @@ -448,7 +478,7 @@ export const useSessionCommands = (input: SessionCommandContext) => { ] }) - input.command.register("session", () => + command.register("session", () => [ sessionCommands(), fileCommands(), From 72c12d59afca7092dc98842b094305d385cf7863 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 18 Feb 2026 11:55:08 -0600 Subject: [PATCH 26/88] chore: cleanup --- packages/ui/src/i18n/ar.ts | 2 +- packages/ui/src/i18n/br.ts | 2 +- packages/ui/src/i18n/bs.ts | 2 +- packages/ui/src/i18n/da.ts | 2 +- packages/ui/src/i18n/de.ts | 2 +- packages/ui/src/i18n/en.ts | 2 +- packages/ui/src/i18n/es.ts | 2 +- packages/ui/src/i18n/fr.ts | 2 +- packages/ui/src/i18n/ja.ts | 2 +- packages/ui/src/i18n/ko.ts | 2 +- packages/ui/src/i18n/no.ts | 2 +- packages/ui/src/i18n/pl.ts | 2 +- packages/ui/src/i18n/ru.ts | 2 +- packages/ui/src/i18n/th.ts | 2 +- packages/ui/src/i18n/zh.ts | 2 +- packages/ui/src/i18n/zht.ts | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/ui/src/i18n/ar.ts b/packages/ui/src/i18n/ar.ts index e574e9ce03..4d79f3d001 100644 --- a/packages/ui/src/i18n/ar.ts +++ b/packages/ui/src/i18n/ar.ts @@ -33,7 +33,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "تفويض العمل", "ui.sessionTurn.status.planning": "تخطيط الخطوات التالية", - "ui.sessionTurn.status.gatheringContext": "استكشاف...", + "ui.sessionTurn.status.gatheringContext": "استكشاف", "ui.sessionTurn.status.gatheredContext": "تم الاستكشاف", "ui.sessionTurn.status.searchingCodebase": "البحث في قاعدة التعليمات البرمجية", "ui.sessionTurn.status.searchingWeb": "البحث في الويب", diff --git a/packages/ui/src/i18n/br.ts b/packages/ui/src/i18n/br.ts index e985396827..777f1455bd 100644 --- a/packages/ui/src/i18n/br.ts +++ b/packages/ui/src/i18n/br.ts @@ -33,7 +33,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "Delegando trabalho", "ui.sessionTurn.status.planning": "Planejando próximos passos", - "ui.sessionTurn.status.gatheringContext": "Explorando...", + "ui.sessionTurn.status.gatheringContext": "Explorando", "ui.sessionTurn.status.gatheredContext": "Explorado", "ui.sessionTurn.status.searchingCodebase": "Pesquisando no código", "ui.sessionTurn.status.searchingWeb": "Pesquisando na web", diff --git a/packages/ui/src/i18n/bs.ts b/packages/ui/src/i18n/bs.ts index 6726c45d2e..e499647dff 100644 --- a/packages/ui/src/i18n/bs.ts +++ b/packages/ui/src/i18n/bs.ts @@ -37,7 +37,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "Delegiranje posla", "ui.sessionTurn.status.planning": "Planiranje sljedećih koraka", - "ui.sessionTurn.status.gatheringContext": "Istraživanje...", + "ui.sessionTurn.status.gatheringContext": "Istraživanje", "ui.sessionTurn.status.gatheredContext": "Istraženo", "ui.sessionTurn.status.searchingCodebase": "Pretraživanje baze koda", "ui.sessionTurn.status.searchingWeb": "Pretraživanje weba", diff --git a/packages/ui/src/i18n/da.ts b/packages/ui/src/i18n/da.ts index bd7f06a230..546040598f 100644 --- a/packages/ui/src/i18n/da.ts +++ b/packages/ui/src/i18n/da.ts @@ -32,7 +32,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "Delegerer arbejde", "ui.sessionTurn.status.planning": "Planlægger næste trin", - "ui.sessionTurn.status.gatheringContext": "Udforsker...", + "ui.sessionTurn.status.gatheringContext": "Udforsker", "ui.sessionTurn.status.gatheredContext": "Udforsket", "ui.sessionTurn.status.searchingCodebase": "Søger i koden", "ui.sessionTurn.status.searchingWeb": "Søger på nettet", diff --git a/packages/ui/src/i18n/de.ts b/packages/ui/src/i18n/de.ts index a07ff6241a..bf5730f85f 100644 --- a/packages/ui/src/i18n/de.ts +++ b/packages/ui/src/i18n/de.ts @@ -36,7 +36,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "Arbeit delegieren", "ui.sessionTurn.status.planning": "Nächste Schritte planen", - "ui.sessionTurn.status.gatheringContext": "Erkunden...", + "ui.sessionTurn.status.gatheringContext": "Erkunden", "ui.sessionTurn.status.gatheredContext": "Erkundet", "ui.sessionTurn.status.searchingCodebase": "Codebasis durchsuchen", "ui.sessionTurn.status.searchingWeb": "Web durchsuchen", diff --git a/packages/ui/src/i18n/en.ts b/packages/ui/src/i18n/en.ts index a33ff76404..4c9b89c6cf 100644 --- a/packages/ui/src/i18n/en.ts +++ b/packages/ui/src/i18n/en.ts @@ -33,7 +33,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "Delegating work", "ui.sessionTurn.status.planning": "Planning next steps", - "ui.sessionTurn.status.gatheringContext": "Exploring...", + "ui.sessionTurn.status.gatheringContext": "Exploring", "ui.sessionTurn.status.gatheredContext": "Explored", "ui.sessionTurn.status.searchingCodebase": "Searching the codebase", "ui.sessionTurn.status.searchingWeb": "Searching the web", diff --git a/packages/ui/src/i18n/es.ts b/packages/ui/src/i18n/es.ts index dcf8d569dc..2f21b398f1 100644 --- a/packages/ui/src/i18n/es.ts +++ b/packages/ui/src/i18n/es.ts @@ -33,7 +33,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "Delegando trabajo", "ui.sessionTurn.status.planning": "Planificando siguientes pasos", - "ui.sessionTurn.status.gatheringContext": "Explorando...", + "ui.sessionTurn.status.gatheringContext": "Explorando", "ui.sessionTurn.status.gatheredContext": "Explorado", "ui.sessionTurn.status.searchingCodebase": "Buscando en la base de código", "ui.sessionTurn.status.searchingWeb": "Buscando en la web", diff --git a/packages/ui/src/i18n/fr.ts b/packages/ui/src/i18n/fr.ts index c1832e8389..d4ea938684 100644 --- a/packages/ui/src/i18n/fr.ts +++ b/packages/ui/src/i18n/fr.ts @@ -33,7 +33,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "Délégation du travail", "ui.sessionTurn.status.planning": "Planification des prochaines étapes", - "ui.sessionTurn.status.gatheringContext": "Exploration...", + "ui.sessionTurn.status.gatheringContext": "Exploration", "ui.sessionTurn.status.gatheredContext": "Exploré", "ui.sessionTurn.status.searchingCodebase": "Recherche dans la base de code", "ui.sessionTurn.status.searchingWeb": "Recherche sur le web", diff --git a/packages/ui/src/i18n/ja.ts b/packages/ui/src/i18n/ja.ts index 24d8497c13..0a4366ebef 100644 --- a/packages/ui/src/i18n/ja.ts +++ b/packages/ui/src/i18n/ja.ts @@ -32,7 +32,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "作業を委任中", "ui.sessionTurn.status.planning": "次のステップを計画中", - "ui.sessionTurn.status.gatheringContext": "探索中...", + "ui.sessionTurn.status.gatheringContext": "探索中", "ui.sessionTurn.status.gatheredContext": "探索済み", "ui.sessionTurn.status.searchingCodebase": "コードベースを検索中", "ui.sessionTurn.status.searchingWeb": "ウェブを検索中", diff --git a/packages/ui/src/i18n/ko.ts b/packages/ui/src/i18n/ko.ts index 412234c61f..58bd51b991 100644 --- a/packages/ui/src/i18n/ko.ts +++ b/packages/ui/src/i18n/ko.ts @@ -33,7 +33,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "작업 위임 중", "ui.sessionTurn.status.planning": "다음 단계 계획 중", - "ui.sessionTurn.status.gatheringContext": "탐색 중...", + "ui.sessionTurn.status.gatheringContext": "탐색 중", "ui.sessionTurn.status.gatheredContext": "탐색됨", "ui.sessionTurn.status.searchingCodebase": "코드베이스 검색 중", "ui.sessionTurn.status.searchingWeb": "웹 검색 중", diff --git a/packages/ui/src/i18n/no.ts b/packages/ui/src/i18n/no.ts index 434b8228b3..b7e604f9ac 100644 --- a/packages/ui/src/i18n/no.ts +++ b/packages/ui/src/i18n/no.ts @@ -36,7 +36,7 @@ export const dict: Record = { "ui.sessionTurn.status.delegating": "Delegerer arbeid", "ui.sessionTurn.status.planning": "Planlegger neste trinn", - "ui.sessionTurn.status.gatheringContext": "Utforsker...", + "ui.sessionTurn.status.gatheringContext": "Utforsker", "ui.sessionTurn.status.gatheredContext": "Utforsket", "ui.sessionTurn.status.searchingCodebase": "Søker i kodebasen", "ui.sessionTurn.status.searchingWeb": "Søker på nettet", diff --git a/packages/ui/src/i18n/pl.ts b/packages/ui/src/i18n/pl.ts index 5fd3092b7f..fbccb92207 100644 --- a/packages/ui/src/i18n/pl.ts +++ b/packages/ui/src/i18n/pl.ts @@ -32,7 +32,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "Delegowanie pracy", "ui.sessionTurn.status.planning": "Planowanie kolejnych kroków", - "ui.sessionTurn.status.gatheringContext": "Eksplorowanie...", + "ui.sessionTurn.status.gatheringContext": "Eksplorowanie", "ui.sessionTurn.status.gatheredContext": "Wyeksplorowano", "ui.sessionTurn.status.searchingCodebase": "Przeszukiwanie bazy kodu", "ui.sessionTurn.status.searchingWeb": "Przeszukiwanie sieci", diff --git a/packages/ui/src/i18n/ru.ts b/packages/ui/src/i18n/ru.ts index f5bed24d5f..705f2d2109 100644 --- a/packages/ui/src/i18n/ru.ts +++ b/packages/ui/src/i18n/ru.ts @@ -32,7 +32,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "Делегирование работы", "ui.sessionTurn.status.planning": "Планирование следующих шагов", - "ui.sessionTurn.status.gatheringContext": "Исследование...", + "ui.sessionTurn.status.gatheringContext": "Исследование", "ui.sessionTurn.status.gatheredContext": "Исследовано", "ui.sessionTurn.status.searchingCodebase": "Поиск в кодовой базе", "ui.sessionTurn.status.searchingWeb": "Поиск в интернете", diff --git a/packages/ui/src/i18n/th.ts b/packages/ui/src/i18n/th.ts index 2f25641926..cf536e1ff6 100644 --- a/packages/ui/src/i18n/th.ts +++ b/packages/ui/src/i18n/th.ts @@ -34,7 +34,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "มอบหมายงาน", "ui.sessionTurn.status.planning": "วางแผนขั้นตอนถัดไป", - "ui.sessionTurn.status.gatheringContext": "กำลังสำรวจ...", + "ui.sessionTurn.status.gatheringContext": "กำลังสำรวจ", "ui.sessionTurn.status.gatheredContext": "สำรวจแล้ว", "ui.sessionTurn.status.searchingCodebase": "กำลังค้นหาโค้ดเบส", "ui.sessionTurn.status.searchingWeb": "กำลังค้นหาบนเว็บ", diff --git a/packages/ui/src/i18n/zh.ts b/packages/ui/src/i18n/zh.ts index d651d25ab1..5d3d5613da 100644 --- a/packages/ui/src/i18n/zh.ts +++ b/packages/ui/src/i18n/zh.ts @@ -37,7 +37,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "正在委派工作", "ui.sessionTurn.status.planning": "正在规划下一步", - "ui.sessionTurn.status.gatheringContext": "正在探索...", + "ui.sessionTurn.status.gatheringContext": "正在探索", "ui.sessionTurn.status.gatheredContext": "已探索", "ui.sessionTurn.status.searchingCodebase": "正在搜索代码库", "ui.sessionTurn.status.searchingWeb": "正在搜索网页", diff --git a/packages/ui/src/i18n/zht.ts b/packages/ui/src/i18n/zht.ts index d20c2f9b2e..b61349e25d 100644 --- a/packages/ui/src/i18n/zht.ts +++ b/packages/ui/src/i18n/zht.ts @@ -37,7 +37,7 @@ export const dict = { "ui.sessionTurn.status.delegating": "正在委派工作", "ui.sessionTurn.status.planning": "正在規劃下一步", - "ui.sessionTurn.status.gatheringContext": "正在探索...", + "ui.sessionTurn.status.gatheringContext": "正在探索", "ui.sessionTurn.status.gatheredContext": "已探索", "ui.sessionTurn.status.searchingCodebase": "正在搜尋程式碼庫", "ui.sessionTurn.status.searchingWeb": "正在搜尋網頁", From be2e6f1926176dadb5a5cf12d5790189a6a5bb50 Mon Sep 17 00:00:00 2001 From: OpeOginni <107570612+OpeOginni@users.noreply.github.com> Date: Wed, 18 Feb 2026 19:09:09 +0100 Subject: [PATCH 27/88] fix(opencode): update pasteImage to only increment count when the previous attachment is an image too (#14173) --- packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx index cefef208de..4114daf6c6 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -694,7 +694,7 @@ export function Prompt(props: PromptProps) { async function pasteImage(file: { filename?: string; content: string; mime: string }) { const currentOffset = input.visualCursor.offset const extmarkStart = currentOffset - const count = store.prompt.parts.filter((x) => x.type === "file").length + const count = store.prompt.parts.filter((x) => x.type === "file" && x.mime.startsWith("image/")).length const virtualText = `[Image ${count + 1}]` const extmarkEnd = extmarkStart + virtualText.length const textToInsert = virtualText + " " From 8bf06cbcc159a3a3a0711cff67c2e5538793445d Mon Sep 17 00:00:00 2001 From: Dax Date: Wed, 18 Feb 2026 13:25:18 -0500 Subject: [PATCH 28/88] refactor: migrate src/global/index.ts from Bun.file() to Filesystem module (#14146) --- packages/opencode/src/global/index.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/opencode/src/global/index.ts b/packages/opencode/src/global/index.ts index 10b6125a6a..2913ac90fe 100644 --- a/packages/opencode/src/global/index.ts +++ b/packages/opencode/src/global/index.ts @@ -2,6 +2,7 @@ import fs from "fs/promises" import { xdgData, xdgCache, xdgConfig, xdgState } from "xdg-basedir" import path from "path" import os from "os" +import { Filesystem } from "../util/filesystem" const app = "opencode" @@ -35,9 +36,7 @@ await Promise.all([ const CACHE_VERSION = "21" -const version = await Bun.file(path.join(Global.Path.cache, "version")) - .text() - .catch(() => "0") +const version = await Filesystem.readText(path.join(Global.Path.cache, "version")).catch(() => "0") if (version !== CACHE_VERSION) { try { @@ -51,5 +50,5 @@ if (version !== CACHE_VERSION) { ), ) } catch (e) {} - await Bun.file(path.join(Global.Path.cache, "version")).write(CACHE_VERSION) + await Filesystem.write(path.join(Global.Path.cache, "version"), CACHE_VERSION) } From 24a98413223c8309194e1578f491d92874c9aa9f Mon Sep 17 00:00:00 2001 From: Frank Date: Wed, 18 Feb 2026 13:54:23 -0500 Subject: [PATCH 29/88] zen: update sst version --- bun.lock | 108 ++++++++++++++----------- github/sst-env.d.ts | 1 + infra/console.ts | 2 +- package.json | 2 +- packages/app/src/sst-env.d.ts | 2 + packages/app/sst-env.d.ts | 1 + packages/console/app/sst-env.d.ts | 1 + packages/console/core/sst-env.d.ts | 1 + packages/console/function/sst-env.d.ts | 1 + packages/console/mail/sst-env.d.ts | 1 + packages/console/resource/sst-env.d.ts | 1 + packages/desktop/sst-env.d.ts | 1 + packages/enterprise/sst-env.d.ts | 1 + packages/function/sst-env.d.ts | 1 + packages/opencode/sst-env.d.ts | 1 + packages/plugin/sst-env.d.ts | 1 + packages/script/sst-env.d.ts | 1 + packages/sdk/js/sst-env.d.ts | 1 + packages/slack/sst-env.d.ts | 1 + packages/ui/sst-env.d.ts | 1 + packages/util/sst-env.d.ts | 1 + packages/web/sst-env.d.ts | 1 + sdks/vscode/sst-env.d.ts | 1 + sst-env.d.ts | 1 + 24 files changed, 84 insertions(+), 50 deletions(-) diff --git a/bun.lock b/bun.lock index c7be0f25bb..bd340ea6e5 100644 --- a/bun.lock +++ b/bun.lock @@ -18,7 +18,7 @@ "husky": "9.1.7", "prettier": "3.6.2", "semver": "^7.6.0", - "sst": "3.17.23", + "sst": "3.18.10", "turbo": "2.5.6", }, }, @@ -1612,7 +1612,7 @@ "@smithy/config-resolver": ["@smithy/config-resolver@4.4.6", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ=="], - "@smithy/core": ["@smithy/core@3.23.0", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.9", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-stream": "^4.5.12", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-Yq4UPVoQICM9zHnByLmG8632t2M0+yap4T7ANVw482J0W7HW0pOuxwVmeOwzJqX2Q89fkXz0Vybz55Wj2Xzrsg=="], + "@smithy/core": ["@smithy/core@3.23.2", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.9", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-stream": "^4.5.12", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-HaaH4VbGie4t0+9nY3tNBRSxVTr96wzIqexUa6C2qx3MPePAuz7lIxPxYtt1Wc//SPfJLNoZJzfdt0B6ksj2jA=="], "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.8", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw=="], @@ -1642,9 +1642,9 @@ "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.8", "", { "dependencies": { "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A=="], - "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.4.14", "", { "dependencies": { "@smithy/core": "^3.23.0", "@smithy/middleware-serde": "^4.2.9", "@smithy/node-config-provider": "^4.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-middleware": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-FUFNE5KVeaY6U/GL0nzAAHkaCHzXLZcY1EhtQnsAqhD8Du13oPKtMB9/0WK4/LK6a/T5OZ24wPoSShff5iI6Ag=="], + "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.4.16", "", { "dependencies": { "@smithy/core": "^3.23.2", "@smithy/middleware-serde": "^4.2.9", "@smithy/node-config-provider": "^4.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-middleware": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-L5GICFCSsNhbJ5JSKeWFGFy16Q2OhoBizb3X2DrxaJwXSEujVvjG9Jt386dpQn2t7jINglQl0b4K/Su69BdbMA=="], - "@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.31", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/service-error-classification": "^4.2.8", "@smithy/smithy-client": "^4.11.3", "@smithy/types": "^4.12.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-RXBzLpMkIrxBPe4C8OmEOHvS8aH9RUuCOH++Acb5jZDEblxDjyg6un72X9IcbrGTJoiUwmI7hLypNfuDACypbg=="], + "@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.33", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/service-error-classification": "^4.2.8", "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-jLqZOdJhtIL4lnA9hXnAG6GgnJlo1sD3FqsTxm9wSfjviqgWesY/TMBVnT84yr4O0Vfe0jWoXlfFbzsBVph3WA=="], "@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.9", "", { "dependencies": { "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ=="], @@ -1668,7 +1668,7 @@ "@smithy/signature-v4": ["@smithy/signature-v4@5.3.8", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg=="], - "@smithy/smithy-client": ["@smithy/smithy-client@4.11.3", "", { "dependencies": { "@smithy/core": "^3.23.0", "@smithy/middleware-endpoint": "^4.4.14", "@smithy/middleware-stack": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-stream": "^4.5.12", "tslib": "^2.6.2" } }, "sha512-Q7kY5sDau8OoE6Y9zJoRGgje8P4/UY0WzH8R2ok0PDh+iJ+ZnEKowhjEqYafVcubkbYxQVaqwm3iufktzhprGg=="], + "@smithy/smithy-client": ["@smithy/smithy-client@4.11.5", "", { "dependencies": { "@smithy/core": "^3.23.2", "@smithy/middleware-endpoint": "^4.4.16", "@smithy/middleware-stack": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-stream": "^4.5.12", "tslib": "^2.6.2" } }, "sha512-xixwBRqoeP2IUgcAl3U9dvJXc+qJum4lzo3maaJxifsZxKUYLfVfCXvhT4/jD01sRrHg5zjd1cw2Zmjr4/SuKQ=="], "@smithy/types": ["@smithy/types@4.12.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw=="], @@ -1684,9 +1684,9 @@ "@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q=="], - "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.30", "", { "dependencies": { "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.11.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-cMni0uVU27zxOiU8TuC8pQLC1pYeZ/xEMxvchSK/ILwleRd1ugobOcIRr5vXtcRqKd4aBLWlpeBoDPJJ91LQng=="], + "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.32", "", { "dependencies": { "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-092sjYfFMQ/iaPH798LY/OJFBcYu0sSK34Oy9vdixhsU36zlZu8OcYjF3TD4e2ARupyK7xaxPXl+T0VIJTEkkg=="], - "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.33", "", { "dependencies": { "@smithy/config-resolver": "^4.4.6", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.11.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-LEb2aq5F4oZUSzWBG7S53d4UytZSkOEJPXcBq/xbG2/TmK9EW5naUZ8lKu1BEyWMzdHIzEVN16M3k8oxDq+DJA=="], + "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.35", "", { "dependencies": { "@smithy/config-resolver": "^4.4.6", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-miz/ggz87M8VuM29y7jJZMYkn7+IErM5p5UgKIf8OtqVs/h2bXr1Bt3uTsREsI/4nK8a0PQERbAPsVPVNIsG7Q=="], "@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.8", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw=="], @@ -1988,7 +1988,7 @@ "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20251207.1", "", { "os": "win32", "cpu": "x64" }, "sha512-5l51HlXjX7lXwo65DEl1IaCFLjmkMtL6K3NrSEamPNeNTtTQwZRa3pQ9V65dCglnnCQ0M3+VF1RqzC7FU0iDKg=="], - "@typescript/vfs": ["@typescript/vfs@1.6.2", "", { "dependencies": { "debug": "^4.1.1" }, "peerDependencies": { "typescript": "*" } }, "sha512-hoBwJwcbKHmvd2QVebiytN1aELvpk9B74B4L1mFm/XT1Q/VOYAWl2vQ9AWRFtQq8zmz6enTpfTV8WRc4ATjW/g=="], + "@typescript/vfs": ["@typescript/vfs@1.6.4", "", { "dependencies": { "debug": "^4.4.3" }, "peerDependencies": { "typescript": "*" } }, "sha512-PJFXFS4ZJKiJ9Qiuix6Dz/OwEIqHD7Dme1UwZhTK11vR+5dqW2ACbdndWQexBzCx+CPuMe5WBYQWCsFyGlQLlQ=="], "@typespec/ts-http-runtime": ["@typespec/ts-http-runtime@0.3.3", "", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" } }, "sha512-91fp6CAAJSRtH5ja95T1FHSKa8aPW9/Zw6cta81jlZTUw/+Vq8jM/AfF/14h2b71wwR84JUTW/3Y8QPhDAawFA=="], @@ -2054,7 +2054,7 @@ "ai-gateway-provider": ["ai-gateway-provider@2.3.1", "", { "dependencies": { "@ai-sdk/provider": "^2.0.0", "@ai-sdk/provider-utils": "^3.0.19", "ai": "^5.0.116" }, "optionalDependencies": { "@ai-sdk/amazon-bedrock": "^3.0.71", "@ai-sdk/anthropic": "^2.0.56", "@ai-sdk/azure": "^2.0.90", "@ai-sdk/cerebras": "^1.0.33", "@ai-sdk/cohere": "^2.0.21", "@ai-sdk/deepgram": "^1.0.21", "@ai-sdk/deepseek": "^1.0.32", "@ai-sdk/elevenlabs": "^1.0.21", "@ai-sdk/fireworks": "^1.0.30", "@ai-sdk/google": "^2.0.51", "@ai-sdk/google-vertex": "3.0.90", "@ai-sdk/groq": "^2.0.33", "@ai-sdk/mistral": "^2.0.26", "@ai-sdk/openai": "^2.0.88", "@ai-sdk/perplexity": "^2.0.22", "@ai-sdk/xai": "^2.0.42", "@openrouter/ai-sdk-provider": "^1.5.3" }, "peerDependencies": { "@ai-sdk/openai-compatible": "^1.0.29" } }, "sha512-PqI6TVNEDNwr7kOhy7XUGnA8XJB1SpeA9aLqGjr0CyWkKgH+y+ofPm8MZGZ74DOwVejDF+POZq0Qs9jKEKUeYg=="], - "ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], + "ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], "ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="], @@ -2136,11 +2136,11 @@ "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], - "b4a": ["b4a@1.7.4", "", { "peerDependencies": { "react-native-b4a": "*" }, "optionalPeers": ["react-native-b4a"] }, "sha512-u20zJLDaSWpxaZ+zaAkEIB2dZZ1o+DF4T/MRbmsvGp9nletHOyiai19OzX1fF8xUBYsO1bPXxODvcd0978pnug=="], + "b4a": ["b4a@1.7.5", "", { "peerDependencies": { "react-native-b4a": "*" }, "optionalPeers": ["react-native-b4a"] }, "sha512-iEsKNwDh1wiWTps1/hdkNdmBgDlDVZP5U57ZVOlt+dNFqpc/lpPouCIxZw+DYBgc4P9NDfIZMPNR4CHNhzwLIA=="], "babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.12", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig=="], - "babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.40.3", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-5HOwwt0BYiv/zxl7j8Pf2bGL6rDXfV6nUhLs8ygBX+EFJXzBPHM/euj9j/6deMZ6wa52Wb2PBaAV5U/jKwIY1w=="], + "babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.40.5", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-8TFKemVLDYezqqv4mWz+PhRrkryTzivTGu0twyLrOkVZ0P63COx2Y04eVsUjFlwSOXui1z3P3Pn209dokWnirg=="], "babel-plugin-module-resolver": ["babel-plugin-module-resolver@5.0.2", "", { "dependencies": { "find-babel-config": "^2.1.1", "glob": "^9.3.3", "pkg-up": "^3.1.0", "reselect": "^4.1.7", "resolve": "^1.22.8" } }, "sha512-9KtaCazHee2xc0ibfqsDeamwDps6FZNo5S0Q81dUqEuFzVwPhcT4J5jOqIVvgCA3Q/wO9hKYxN/Ds3tIsp5ygg=="], @@ -2216,13 +2216,13 @@ "bun-webgpu": ["bun-webgpu@0.1.4", "", { "dependencies": { "@webgpu/types": "^0.1.60" }, "optionalDependencies": { "bun-webgpu-darwin-arm64": "^0.1.4", "bun-webgpu-darwin-x64": "^0.1.4", "bun-webgpu-linux-x64": "^0.1.4", "bun-webgpu-win32-x64": "^0.1.4" } }, "sha512-Kw+HoXl1PMWJTh9wvh63SSRofTA8vYBFCw0XEP1V1fFdQEDhI8Sgf73sdndE/oDpN/7CMx0Yv/q8FCvO39ROMQ=="], - "bun-webgpu-darwin-arm64": ["bun-webgpu-darwin-arm64@0.1.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-eDgLN9teKTfmvrCqgwwmWNsNszxYs7IZdCqk0S1DCarvMhr4wcajoSBlA/nQA0/owwLduPTS8xxCnQp4/N/gDg=="], + "bun-webgpu-darwin-arm64": ["bun-webgpu-darwin-arm64@0.1.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-qM7W5IaFpWYGPDcNiQ8DOng3noQ97gxpH2MFH1mGsdKwI0T4oy++egSh5Z7s6AQx8WKgc9GzAsTUM4KZkFdacw=="], - "bun-webgpu-darwin-x64": ["bun-webgpu-darwin-x64@0.1.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-X+PjwJUWenUmdQBP8EtdItMyieQ6Nlpn+BH518oaouDiSnWj5+b0Y7DNDZJq7Ezom4EaxmqL/uGYZK3aCQ7CXg=="], + "bun-webgpu-darwin-x64": ["bun-webgpu-darwin-x64@0.1.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-oVoIsme27pcXB68YxnQSAgdNGCa4A3PGWYIBUewOh9VnJaoik4JenGb5Yy+svGE+ETFhQXV9nhHqgMPsDRrO6A=="], - "bun-webgpu-linux-x64": ["bun-webgpu-linux-x64@0.1.4", "", { "os": "linux", "cpu": "x64" }, "sha512-zMLs2YIGB+/jxrYFXaFhVKX/GBt05UTF45lc9srcHc9JXGjEj+12CIo1CHLTAWatXMTqt0Jsu6ukWEoWVT/ayA=="], + "bun-webgpu-linux-x64": ["bun-webgpu-linux-x64@0.1.5", "", { "os": "linux", "cpu": "x64" }, "sha512-+SYt09k+xDEl/GfcU7L1zdNgm7IlvAFKV5Xl/auBwuprKG5UwXNhjRlRAWfhTMCUZWN+NDf8E+ZQx0cQi9K2/g=="], - "bun-webgpu-win32-x64": ["bun-webgpu-win32-x64@0.1.4", "", { "os": "win32", "cpu": "x64" }, "sha512-Z5yAK28xrcm8Wb5k7TZ8FJKpOI/r+aVCRdlHYAqI2SDJFN3nD4mJs900X6kNVmG/xFzb5yOuKVYWGg+6ZXWbyA=="], + "bun-webgpu-win32-x64": ["bun-webgpu-win32-x64@0.1.5", "", { "os": "win32", "cpu": "x64" }, "sha512-zvnUl4EAsQbKsmZVu+lEJcH8axQ7MiCfqg2OmnHd6uw1THABmHaX0GbpKiHshdgadNN2Nf+4zDyTJB5YMcAdrA=="], "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], @@ -2242,7 +2242,7 @@ "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="], - "caniuse-lite": ["caniuse-lite@1.0.30001769", "", {}, "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg=="], + "caniuse-lite": ["caniuse-lite@1.0.30001770", "", {}, "sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw=="], "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], @@ -2476,7 +2476,7 @@ "enhanced-resolve": ["enhanced-resolve@5.19.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg=="], - "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], + "entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], "error-stack-parser": ["error-stack-parser@2.1.4", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ=="], @@ -2712,7 +2712,7 @@ "h3": ["h3@2.0.1-rc.4", "", { "dependencies": { "rou3": "^0.7.8", "srvx": "^0.9.1" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"] }, "sha512-vZq8pEUp6THsXKXrUXX44eOqfChic2wVQ1GlSzQCBr7DeFBkfIZAo2WyNND4GSv54TAa0E4LYIK73WSPdgKUgw=="], - "happy-dom": ["happy-dom@20.6.1", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "entities": "^6.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.18.3" } }, "sha512-+0vhESXXhFwkdjZnJ5DlmJIfUYGgIEEjzIjB+aKJbFuqlvvKyOi+XkI1fYbgYR9QCxG5T08koxsQ6HrQfa5gCQ=="], + "happy-dom": ["happy-dom@20.6.2", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "entities": "^7.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.18.3" } }, "sha512-Xk/Y0cuq9ngN/my8uvK4gKoyDl6sBKkIl8A/hJ0IabZVH7E5SJLHNE7uKRPVmSrQbhJaLIHTEcvTct4GgNtsRA=="], "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="], @@ -2924,7 +2924,7 @@ "is-whitespace": ["is-whitespace@0.3.0", "", {}, "sha512-RydPhl4S6JwAyj0JJjshWJEFG6hNye3pZFBRZaTUfZFwGHxzppNaNOVgQuS/E/SlhrApuMXrpnK1EEIXfdo3Dg=="], - "is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="], + "is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="], "is64bit": ["is64bit@2.0.0", "", { "dependencies": { "system-architecture": "^0.1.0" } }, "sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw=="], @@ -3502,7 +3502,7 @@ "punycode": ["punycode@1.3.2", "", {}, "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="], - "qs": ["qs@6.14.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q=="], + "qs": ["qs@6.15.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ=="], "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], @@ -3764,23 +3764,23 @@ "srvx": ["srvx@0.9.8", "", { "bin": { "srvx": "bin/srvx.mjs" } }, "sha512-RZaxTKJEE/14HYn8COLuUOJAt0U55N9l1Xf6jj+T0GoA01EUH1Xz5JtSUOI+EHn+AEgPCVn7gk6jHJffrr06fQ=="], - "sst": ["sst@3.17.23", "", { "dependencies": { "aws-sdk": "2.1692.0", "aws4fetch": "1.0.18", "jose": "5.2.3", "opencontrol": "0.0.6", "openid-client": "5.6.4" }, "optionalDependencies": { "sst-darwin-arm64": "3.17.23", "sst-darwin-x64": "3.17.23", "sst-linux-arm64": "3.17.23", "sst-linux-x64": "3.17.23", "sst-linux-x86": "3.17.23", "sst-win32-arm64": "3.17.23", "sst-win32-x64": "3.17.23", "sst-win32-x86": "3.17.23" }, "bin": { "sst": "bin/sst.mjs" } }, "sha512-TwKgUgDnZdc1Swe+bvCNeyO4dQnYz5cTodMpYj3jlXZdK9/KNz0PVxT1f0u5E76i1pmilXrUBL/f7iiMPw4RDg=="], + "sst": ["sst@3.18.10", "", { "dependencies": { "aws-sdk": "2.1692.0", "aws4fetch": "1.0.18", "jose": "5.2.3", "opencontrol": "0.0.6", "openid-client": "5.6.4" }, "optionalDependencies": { "sst-darwin-arm64": "3.18.10", "sst-darwin-x64": "3.18.10", "sst-linux-arm64": "3.18.10", "sst-linux-x64": "3.18.10", "sst-linux-x86": "3.18.10", "sst-win32-arm64": "3.18.10", "sst-win32-x64": "3.18.10", "sst-win32-x86": "3.18.10" }, "bin": { "sst": "bin/sst.mjs" } }, "sha512-SY+ldeJ9K5E9q+DhjXA3e2W3BEOzBwkE3IyLSD71uA3/5nRhUAST31iOWEpW36LbIvSQ9uOVDFcebztoLJ8s7w=="], - "sst-darwin-arm64": ["sst-darwin-arm64@3.17.23", "", { "os": "darwin", "cpu": "arm64" }, "sha512-R6kvmF+rUideOoU7KBs2SdvrIupoE+b+Dor/eq9Uo4Dojj7KvYDZI/EDm8sSCbbcx/opiWeyNqKtlnLEdCxE6g=="], + "sst-darwin-arm64": ["sst-darwin-arm64@3.18.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3MwIpMZhhdZKDqLp9ZQNlwkWix5+q+N0PWstuTomYwgZOxCCe6u9IIsoIszSk+GAJJN/jvGZyLiXKeV4iiQvw=="], - "sst-darwin-x64": ["sst-darwin-x64@3.17.23", "", { "os": "darwin", "cpu": "x64" }, "sha512-WW4P1S35iYCifQXxD+sE3wuzcN+LHLpuKMaNoaBqEcWGZnH3IPaDJ7rpLF0arkDAo/z3jZmWWzOCkr0JuqJ8vQ=="], + "sst-darwin-x64": ["sst-darwin-x64@3.18.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-nQ0jMKkPOa+kj6Ygz8+kYhBua/vgNTLkd+4r8NSmk7v+Zs78lKnx3T//kEzS0yik6Q6QwGfokwrTcA1Jii2xSw=="], - "sst-linux-arm64": ["sst-linux-arm64@3.17.23", "", { "os": "linux", "cpu": "arm64" }, "sha512-TjtNqgIh7RlAWgPLFCAt0mXvIB+J7WjmRvIRrAdX0mXsndOiBJ/DMOgXSLVsIWHCfPj8MIEot/hWpnJgXgIeag=="], + "sst-linux-arm64": ["sst-linux-arm64@3.18.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-mj9VNj3SvLS+HaXx2PhCX0aTA7CwJNoM6JhRc0s/zCilqchcvqDjbhpYBJO4brEPv6aOaaa7T3WvIQqtYauK4Q=="], - "sst-linux-x64": ["sst-linux-x64@3.17.23", "", { "os": "linux", "cpu": "x64" }, "sha512-qdqJiEbYfCjZlI3F/TA6eoIU7JXVkEEI/UMILNf2JWhky0KQdCW2Xyz+wb6c0msVJCWdUM/uj+1DaiP2eXvghw=="], + "sst-linux-x64": ["sst-linux-x64@3.18.10", "", { "os": "linux", "cpu": "x64" }, "sha512-7iy1Eq2eqnT9Ag/8OVgC04vRjV7AAQyf/BvzLc+6Sz+GvRiKA8VEuPnbXNYQF+NIvEqsawfcd7MknSTtImpsvQ=="], - "sst-linux-x86": ["sst-linux-x86@3.17.23", "", { "os": "linux", "cpu": "none" }, "sha512-aGmUujIvoNlmAABEGsOgfY1rxD9koC6hN8bnTLbDI+oI/u/zjHYh50jsbL0p3TlaHpwF/lxP3xFSuT6IKp+KgA=="], + "sst-linux-x86": ["sst-linux-x86@3.18.10", "", { "os": "linux", "cpu": "none" }, "sha512-77qZSuPZeQ5bdRCiq1pQEdY8EcGNHboKrx4P2yFid2FBDKJsXxOXtIxJdloyx+ljBn0+nxl/g040QBmXxdc9tA=="], - "sst-win32-arm64": ["sst-win32-arm64@3.17.23", "", { "os": "win32", "cpu": "arm64" }, "sha512-ZxdkGqYDrrZGz98rijDCN+m5yuCcwD6Bc9/6hubLsvdpNlVorUqzpg801Ec97xSK0nIC9g6pNiRyxAcsQQstUg=="], + "sst-win32-arm64": ["sst-win32-arm64@3.18.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-aY+FhMxvYs8crlrKALpLn/kKmud8YQj6LkMHsrOAAIJhfNyxhCja2vrYQaY+bcqdsS5W2LMVcS2hyaMqKXZKcg=="], - "sst-win32-x64": ["sst-win32-x64@3.17.23", "", { "os": "win32", "cpu": "x64" }, "sha512-yc9cor4MS49Ccy2tQCF1tf6M81yLeSGzGL+gjhUxpVKo2pN3bxl3w70eyU/mTXSEeyAmG9zEfbt6FNu4sy5cUA=="], + "sst-win32-x64": ["sst-win32-x64@3.18.10", "", { "os": "win32", "cpu": "x64" }, "sha512-rY+yJXOpG+P5xXnaQRpCvBK2zwwLhjzpYidGkp6F+cGgiVdh2Wre/CIQNRaVHr20ncj8lLe/RsHWa9QCNM48jg=="], - "sst-win32-x86": ["sst-win32-x86@3.17.23", "", { "os": "win32", "cpu": "none" }, "sha512-DIp3s54IpNAfdYjSRt6McvkbEPQDMxUu6RUeRAd2C+FcTJgTloon/ghAPQBaDgu2VoVgymjcJARO/XyfKcCLOQ=="], + "sst-win32-x86": ["sst-win32-x86@3.18.10", "", { "os": "win32", "cpu": "none" }, "sha512-pq8SmV0pIjBFMY6DraUZ4akyTxHnfjIKCRbBLdMxFUZK8TzA1NK2YdjRt1AwrgXRYGRyctrz/mt4WyO0SMOVQQ=="], "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], @@ -3846,19 +3846,19 @@ "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], - "tar": ["tar@7.5.7", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ=="], + "tar": ["tar@7.5.9", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg=="], "tar-stream": ["tar-stream@3.1.7", "", { "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ=="], "tarn": ["tarn@3.0.2", "", {}, "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ=="], - "tedious": ["tedious@19.2.1", "", { "dependencies": { "@azure/core-auth": "^1.7.2", "@azure/identity": "^4.2.1", "@azure/keyvault-keys": "^4.4.0", "@js-joda/core": "^5.6.5", "@types/node": ">=18", "bl": "^6.1.4", "iconv-lite": "^0.7.0", "js-md4": "^0.3.2", "native-duplexpair": "^1.0.0", "sprintf-js": "^1.1.3" } }, "sha512-pk1Q16Yl62iocuQB+RWbg6rFUFkIyzqOFQ6NfysCltRvQqKwfurgj8v/f2X+CKvDhSL4IJ0cCOfCHDg9PWEEYA=="], + "tedious": ["tedious@18.6.2", "", { "dependencies": { "@azure/core-auth": "^1.7.2", "@azure/identity": "^4.2.1", "@azure/keyvault-keys": "^4.4.0", "@js-joda/core": "^5.6.1", "@types/node": ">=18", "bl": "^6.0.11", "iconv-lite": "^0.6.3", "js-md4": "^0.3.2", "native-duplexpair": "^1.0.0", "sprintf-js": "^1.1.3" } }, "sha512-g7jC56o3MzLkE3lHkaFe2ZdOVFBahq5bsB60/M4NYUbocw/MCrS89IOEQUFr+ba6pb8ZHczZ/VqCyYeYq0xBAg=="], "terracotta": ["terracotta@1.1.0", "", { "dependencies": { "solid-use": "^0.9.1" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-kfQciWUBUBgYkXu7gh3CK3FAJng/iqZslAaY08C+k1Hdx17aVEpcFFb/WPaysxAfcupNH3y53s/pc53xxZauww=="], "terser": ["terser@5.46.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg=="], - "text-decoder": ["text-decoder@1.2.4", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-mzlffA3tBNhziEHPK5L5InZg1d/ElNIpJhnhbDRNUtem/edZcJ5zg5FgwKKKOyklxk+6Jt+TrSu83musmvrDlg=="], + "text-decoder": ["text-decoder@1.2.7", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ=="], "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], @@ -3966,7 +3966,7 @@ "uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="], - "undici": ["undici@7.21.0", "", {}, "sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg=="], + "undici": ["undici@7.22.0", "", {}, "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg=="], "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], @@ -4132,7 +4132,7 @@ "xml-parse-from-string": ["xml-parse-from-string@1.0.1", "", {}, "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g=="], - "xml2js": ["xml2js@0.6.2", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA=="], + "xml2js": ["xml2js@0.5.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA=="], "xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="], @@ -4282,8 +4282,6 @@ "@azure/core-http/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], - "@azure/core-http/xml2js": ["xml2js@0.5.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA=="], - "@azure/core-xml/fast-xml-parser": ["fast-xml-parser@5.2.5", "", { "dependencies": { "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ=="], "@azure/msal-node/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], @@ -4304,7 +4302,7 @@ "@fastify/proxy-addr/ipaddr.js": ["ipaddr.js@2.3.0", "", {}, "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg=="], - "@gitlab/gitlab-ai-provider/openai": ["openai@6.21.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-26dQFi76dB8IiN/WKGQOV+yKKTTlRCxQjoi2WLt0kMcH8pvxVyvfdBDkld5GTl7W1qvBpwVOtFcsqktj3fBRpA=="], + "@gitlab/gitlab-ai-provider/openai": ["openai@6.22.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-7Yvy17F33Bi9RutWbsaYt5hJEEJ/krRPOrwan+f9aCPuMat1WVsb2VNSII5W1EksKT6fF69TG/xj4XzodK3JZw=="], "@gitlab/gitlab-ai-provider/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -4506,7 +4504,9 @@ "accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "ai-gateway-provider/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.62", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-I3RhaOEMnWlWnrvjNBOYvUb19Dwf2nw01IruZrVJRDi688886e11wnd5DxrBZLd2V29Gizo3vpOPnnExsA+wTA=="], + "ai-gateway-provider/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.63", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-zXlUPCkumnvp8lWS9VFcen/MLF6CL/t1zAKDhpobYj9y/nmylQrKtRvn3RwH871Wd3dF3KYEUXd6M2c6dfCKOA=="], + + "ai-gateway-provider/@ai-sdk/google": ["@ai-sdk/google@2.0.53", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ccCxr5mrd3AC2CjLq4e1ST7+UiN5T2Pdmgi0XdWM3QohmNBwUQ/RBG7BvL+cB/ex/j6y64tkMmpYz9zBw/SEFQ=="], "ai-gateway-provider/@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@3.0.90", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.56", "@ai-sdk/google": "2.0.46", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-C9MLe1KZGg1ZbupV2osygHtL5qngyCDA6ATatunyfTbIe8TXKG8HGni/3O6ifbnI5qxTidIn150Ox7eIFZVMYg=="], @@ -4514,6 +4514,8 @@ "ai-gateway-provider/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.33", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-2KMcR2xAul3u5dGZD7gONgbIki3Hg7Ey+sFu7gsiJ4U2iRU0GDV3ccNq79dTuAEXPDFcOWCUpW8A8jXc0kxJxQ=="], + "ai-gateway-provider/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.21", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-veuMwTLxsgh31Jjn0SnBABnM1f7ebHhRWcV2ZuY3hP3iJDCZ8VXBaYqcHXoOQDqUXTCas08sKQcHyWK+zl882Q=="], + "ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], @@ -4534,6 +4536,8 @@ "aws-sdk/events": ["events@1.1.1", "", {}, "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw=="], + "aws-sdk/xml2js": ["xml2js@0.6.2", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA=="], + "babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="], "babel-plugin-module-resolver/glob": ["glob@9.3.5", "", { "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" } }, "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q=="], @@ -4544,6 +4548,10 @@ "body-parser/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], + "body-parser/qs": ["qs@6.14.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q=="], + + "buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + "bun-webgpu/@webgpu/types": ["@webgpu/types@0.1.69", "", {}, "sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ=="], "c12/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], @@ -4578,6 +4586,8 @@ "express/path-to-regexp": ["path-to-regexp@0.1.12", "", {}, "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="], + "express/qs": ["qs@6.14.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q=="], + "fetch-blob/web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -4586,7 +4596,7 @@ "gaxios/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], - "glob/minimatch": ["minimatch@10.2.0", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-ugkC31VaVg9cF0DFVoADH12k6061zNZkZON+aX8AWsR9GhPcErkcMBceb6znR8wLERM2AkkOxy2nWRLpT9Jq5w=="], + "glob/minimatch": ["minimatch@10.2.1", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A=="], "globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], @@ -4624,8 +4634,6 @@ "mssql/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], - "mssql/tedious": ["tedious@18.6.2", "", { "dependencies": { "@azure/core-auth": "^1.7.2", "@azure/identity": "^4.2.1", "@azure/keyvault-keys": "^4.4.0", "@js-joda/core": "^5.6.1", "@types/node": ">=18", "bl": "^6.0.11", "iconv-lite": "^0.6.3", "js-md4": "^0.3.2", "native-duplexpair": "^1.0.0", "sprintf-js": "^1.1.3" } }, "sha512-g7jC56o3MzLkE3lHkaFe2ZdOVFBahq5bsB60/M4NYUbocw/MCrS89IOEQUFr+ba6pb8ZHczZ/VqCyYeYq0xBAg=="], - "nitro/h3": ["h3@2.0.1-rc.5", "", { "dependencies": { "rou3": "^0.7.9", "srvx": "^0.9.1" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"] }, "sha512-qkohAzCab0nLzXNm78tBjZDvtKMTmtygS8BJLT3VPczAQofdqlFXDPkXdLMJN4r05+xqneG8snZJ0HgkERCZTg=="], "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], @@ -4654,10 +4662,10 @@ "p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], - "parse-bmfont-xml/xml2js": ["xml2js@0.5.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA=="], - "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], + "path-scurry/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="], "pixelmatch/pngjs": ["pngjs@6.0.0", "", {}, "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg=="], @@ -4714,6 +4722,8 @@ "tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], + "tedious/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], "token-types/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], @@ -4730,6 +4740,8 @@ "unifont/ofetch": ["ofetch@1.5.1", "", { "dependencies": { "destr": "^2.0.5", "node-fetch-native": "^1.6.7", "ufo": "^1.6.1" } }, "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA=="], + "unstorage/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="], + "utif2/pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="], "vitest/tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="], @@ -4750,6 +4762,8 @@ "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "xml2js/sax": ["sax@1.4.4", "", {}, "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw=="], + "yaml-language-server/lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], "yaml-language-server/request-light": ["request-light@0.5.8", "", {}, "sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg=="], @@ -5010,8 +5024,6 @@ "accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - "ai-gateway-provider/@ai-sdk/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.21", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-veuMwTLxsgh31Jjn0SnBABnM1f7ebHhRWcV2ZuY3hP3iJDCZ8VXBaYqcHXoOQDqUXTCas08sKQcHyWK+zl882Q=="], - "ai-gateway-provider/@ai-sdk/google-vertex/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.56", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-XHJKu0Yvfu9SPzRfsAFESa+9T7f2YJY6TxykKMfRsAwpeWAiX/Gbx5J5uM15AzYC3Rw8tVP3oH+j7jEivENirQ=="], "ai-gateway-provider/@ai-sdk/google-vertex/@ai-sdk/google": ["@ai-sdk/google@2.0.46", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8PK6u4sGE/kXebd7ZkTp+0aya4kNqzoqpS5m7cHY2NfTK6fhPc6GNvE+MZIZIoHQTp5ed86wGBdeBPpFaaUtyg=="], @@ -5020,7 +5032,7 @@ "ai-gateway-provider/@ai-sdk/google-vertex/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="], - "ai-gateway-provider/@ai-sdk/openai-compatible/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.21", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-veuMwTLxsgh31Jjn0SnBABnM1f7ebHhRWcV2ZuY3hP3iJDCZ8VXBaYqcHXoOQDqUXTCas08sKQcHyWK+zl882Q=="], + "ai-gateway-provider/@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.20", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ=="], "ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -5040,6 +5052,8 @@ "astro/unstorage/ofetch": ["ofetch@1.5.1", "", { "dependencies": { "destr": "^2.0.5", "node-fetch-native": "^1.6.7", "ufo": "^1.6.1" } }, "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA=="], + "aws-sdk/xml2js/sax": ["sax@1.4.4", "", {}, "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw=="], + "babel-plugin-module-resolver/glob/minimatch": ["minimatch@8.0.4", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA=="], "babel-plugin-module-resolver/glob/minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="], @@ -5074,8 +5088,6 @@ "lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], - "mssql/tedious/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], - "opencode/@ai-sdk/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.21", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-veuMwTLxsgh31Jjn0SnBABnM1f7ebHhRWcV2ZuY3hP3iJDCZ8VXBaYqcHXoOQDqUXTCas08sKQcHyWK+zl882Q=="], "opencontrol/@modelcontextprotocol/sdk/express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="], diff --git a/github/sst-env.d.ts b/github/sst-env.d.ts index f742a12004..3b8cffd4fd 100644 --- a/github/sst-env.d.ts +++ b/github/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/infra/console.ts b/infra/console.ts index 9089055821..3f3c2b8d93 100644 --- a/infra/console.ts +++ b/infra/console.ts @@ -214,9 +214,9 @@ new sst.cloudflare.x.SolidStart("Console", { }, transform: { server: { + placement: { region: "aws:us-east-1" }, transform: { worker: { - placement: { mode: "smart" }, tailConsumers: [{ service: logProcessor.nodes.worker.scriptName }], }, }, diff --git a/package.json b/package.json index e0008d1028..f1ba10269c 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "husky": "9.1.7", "prettier": "3.6.2", "semver": "^7.6.0", - "sst": "3.17.23", + "sst": "3.18.10", "turbo": "2.5.6" }, "dependencies": { diff --git a/packages/app/src/sst-env.d.ts b/packages/app/src/sst-env.d.ts index 47a8fbec7b..035e323c04 100644 --- a/packages/app/src/sst-env.d.ts +++ b/packages/app/src/sst-env.d.ts @@ -1,6 +1,8 @@ /* This file is auto-generated by SST. Do not edit. */ /* tslint:disable */ /* eslint-disable */ +/* biome-ignore-all lint: auto-generated */ + /// interface ImportMetaEnv { diff --git a/packages/app/sst-env.d.ts b/packages/app/sst-env.d.ts index b6a7e9066e..64441936d7 100644 --- a/packages/app/sst-env.d.ts +++ b/packages/app/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/packages/console/app/sst-env.d.ts b/packages/console/app/sst-env.d.ts index 9b9de73273..301538ccb2 100644 --- a/packages/console/app/sst-env.d.ts +++ b/packages/console/app/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/packages/console/core/sst-env.d.ts b/packages/console/core/sst-env.d.ts index 737af71d41..73f83d1676 100644 --- a/packages/console/core/sst-env.d.ts +++ b/packages/console/core/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ import "sst" declare module "sst" { diff --git a/packages/console/function/sst-env.d.ts b/packages/console/function/sst-env.d.ts index 737af71d41..73f83d1676 100644 --- a/packages/console/function/sst-env.d.ts +++ b/packages/console/function/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ import "sst" declare module "sst" { diff --git a/packages/console/mail/sst-env.d.ts b/packages/console/mail/sst-env.d.ts index 9b9de73273..301538ccb2 100644 --- a/packages/console/mail/sst-env.d.ts +++ b/packages/console/mail/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/packages/console/resource/sst-env.d.ts b/packages/console/resource/sst-env.d.ts index 737af71d41..73f83d1676 100644 --- a/packages/console/resource/sst-env.d.ts +++ b/packages/console/resource/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ import "sst" declare module "sst" { diff --git a/packages/desktop/sst-env.d.ts b/packages/desktop/sst-env.d.ts index b6a7e9066e..64441936d7 100644 --- a/packages/desktop/sst-env.d.ts +++ b/packages/desktop/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/packages/enterprise/sst-env.d.ts b/packages/enterprise/sst-env.d.ts index 737af71d41..73f83d1676 100644 --- a/packages/enterprise/sst-env.d.ts +++ b/packages/enterprise/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ import "sst" declare module "sst" { diff --git a/packages/function/sst-env.d.ts b/packages/function/sst-env.d.ts index 737af71d41..73f83d1676 100644 --- a/packages/function/sst-env.d.ts +++ b/packages/function/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ import "sst" declare module "sst" { diff --git a/packages/opencode/sst-env.d.ts b/packages/opencode/sst-env.d.ts index b6a7e9066e..64441936d7 100644 --- a/packages/opencode/sst-env.d.ts +++ b/packages/opencode/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/packages/plugin/sst-env.d.ts b/packages/plugin/sst-env.d.ts index b6a7e9066e..64441936d7 100644 --- a/packages/plugin/sst-env.d.ts +++ b/packages/plugin/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/packages/script/sst-env.d.ts b/packages/script/sst-env.d.ts index b6a7e9066e..64441936d7 100644 --- a/packages/script/sst-env.d.ts +++ b/packages/script/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/packages/sdk/js/sst-env.d.ts b/packages/sdk/js/sst-env.d.ts index 9b9de73273..301538ccb2 100644 --- a/packages/sdk/js/sst-env.d.ts +++ b/packages/sdk/js/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/packages/slack/sst-env.d.ts b/packages/slack/sst-env.d.ts index b6a7e9066e..64441936d7 100644 --- a/packages/slack/sst-env.d.ts +++ b/packages/slack/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/packages/ui/sst-env.d.ts b/packages/ui/sst-env.d.ts index b6a7e9066e..64441936d7 100644 --- a/packages/ui/sst-env.d.ts +++ b/packages/ui/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/packages/util/sst-env.d.ts b/packages/util/sst-env.d.ts index b6a7e9066e..64441936d7 100644 --- a/packages/util/sst-env.d.ts +++ b/packages/util/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/packages/web/sst-env.d.ts b/packages/web/sst-env.d.ts index b6a7e9066e..64441936d7 100644 --- a/packages/web/sst-env.d.ts +++ b/packages/web/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/sdks/vscode/sst-env.d.ts b/sdks/vscode/sst-env.d.ts index b6a7e9066e..64441936d7 100644 --- a/sdks/vscode/sst-env.d.ts +++ b/sdks/vscode/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ /// diff --git a/sst-env.d.ts b/sst-env.d.ts index b2ae763562..6b3ec54dee 100644 --- a/sst-env.d.ts +++ b/sst-env.d.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /* deno-fmt-ignore-file */ +/* biome-ignore-all lint: auto-generated */ declare module "sst" { export interface Resource { From c6bd32000302c0cf607c1e91c536537e43848237 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Wed, 18 Feb 2026 19:08:12 +0000 Subject: [PATCH 30/88] chore: update nix node_modules hashes --- nix/hashes.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/hashes.json b/nix/hashes.json index c3510c39f6..d0e314a74d 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,8 +1,8 @@ { "nodeModules": { - "x86_64-linux": "sha256-5sXHoHbRdXbqM/zRJZiXt26sm/yyyZN/4OOHUtdofhk=", - "aarch64-linux": "sha256-JCMm5X7e27BBV4wyaknCMM4CBt4Lr72SSvaGxEeNsJE=", - "aarch64-darwin": "sha256-DBQJURlTPqFt0OYUHSvZZ4H0NUf020aic4zNX5CXzDc=", - "x86_64-darwin": "sha256-t2luVxqCcRSgq/WNWkm4ZpKXO22n2RnAWP6msoTOr+A=" + "x86_64-linux": "sha256-7y6gQyIxyrdp2DaG/0oOEpuL+1n9oa8arUn1CuDiDhA=", + "aarch64-linux": "sha256-7dnHO2WqQZ9A8cG3EC8p7408YR9n2F5C6DG5rNWHqNY=", + "aarch64-darwin": "sha256-jxjhnVfE61RVOHaWvDO4mGLk6guQ8jHeXv/pbu5nbaE=", + "x86_64-darwin": "sha256-22yM4FEtVxGWRug6H0rKog86Q/cYE3QsADrRbLeJKVQ=" } } From 42aa28d512d4ea77bef6159530b8bac9c7c872a0 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 18 Feb 2026 13:23:20 -0600 Subject: [PATCH 31/88] chore: cleanup (#14181) --- packages/app/src/components/prompt-input.tsx | 14 +++---- .../src/components/session/session-header.tsx | 17 +------- packages/app/src/context/language.tsx | 16 +++----- packages/app/src/pages/layout.tsx | 21 +++++----- packages/app/src/pages/session.tsx | 4 +- packages/app/src/pages/session/file-tabs.tsx | 30 +++++++------- .../src/pages/session/session-prompt-dock.tsx | 39 ++++++++++++------- 7 files changed, 63 insertions(+), 78 deletions(-) diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 1ca085a428..b5a1019945 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -403,15 +403,10 @@ export const PromptInput: Component = (props) => { const [composing, setComposing] = createSignal(false) const isImeComposing = (event: KeyboardEvent) => event.isComposing || composing() || event.keyCode === 229 - createEffect(() => { - if (!isFocused()) closePopover() - }) - - // Safety: reset composing state on focus change to prevent stuck state - // This handles edge cases where compositionend event may not fire - createEffect(() => { - if (!isFocused()) setComposing(false) - }) + const handleBlur = () => { + closePopover() + setComposing(false) + } const agentList = createMemo(() => sync.data.agent @@ -1118,6 +1113,7 @@ export const PromptInput: Component = (props) => { onPaste={handlePaste} onCompositionStart={() => setComposing(true)} onCompositionEnd={() => setComposing(false)} + onBlur={handleBlur} onKeyDown={handleKeyDown} classList={{ "select-text": true, diff --git a/packages/app/src/components/session/session-header.tsx b/packages/app/src/components/session/session-header.tsx index 912e449cfe..3003d05148 100644 --- a/packages/app/src/components/session/session-header.tsx +++ b/packages/app/src/components/session/session-header.tsx @@ -257,27 +257,12 @@ export function SessionHeader() { ] as const }) - const checksReady = createMemo(() => { - if (platform.platform !== "desktop") return true - if (!platform.checkAppExists) return true - const list = apps() - return list.every((app) => exists[app.id] !== undefined) - }) - const [prefs, setPrefs] = persisted(Persist.global("open.app"), createStore({ app: "finder" as OpenApp })) const [menu, setMenu] = createStore({ open: false }) const canOpen = createMemo(() => platform.platform === "desktop" && !!platform.openPath && server.isLocal()) const current = createMemo(() => options().find((o) => o.id === prefs.app) ?? options()[0]) - createEffect(() => { - if (platform.platform !== "desktop") return - if (!checksReady()) return - const value = prefs.app - if (options().some((o) => o.id === value)) return - setPrefs("app", options()[0]?.id ?? "finder") - }) - const openDir = (app: OpenApp) => { const directory = projectDirectory() if (!directory) return @@ -398,7 +383,7 @@ export function SessionHeader() { {language.t("session.header.openIn")} { if (!OPEN_APPS.includes(value as OpenApp)) return setPrefs("app", value as OpenApp) diff --git a/packages/app/src/context/language.tsx b/packages/app/src/context/language.tsx index b21ec6d3cc..905305d3af 100644 --- a/packages/app/src/context/language.tsx +++ b/packages/app/src/context/language.tsx @@ -174,6 +174,10 @@ function detectLocale(): Locale { return "en" } +function normalizeLocale(value: string): Locale { + return LOCALES.includes(value as Locale) ? (value as Locale) : "en" +} + export const { use: useLanguage, provider: LanguageProvider } = createSimpleContext({ name: "Language", init: () => { @@ -184,15 +188,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont }), ) - const locale = createMemo(() => - LOCALES.includes(store.locale as Locale) ? (store.locale as Locale) : "en", - ) - - createEffect(() => { - const current = locale() - if (store.locale === current) return - setStore("locale", current) - }) + const locale = createMemo(() => normalizeLocale(store.locale)) const dict = createMemo(() => DICT[locale()]) @@ -213,7 +209,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont label, t, setLocale(next: Locale) { - setStore("locale", next) + setStore("locale", normalizeLocale(next)) }, } }, diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index e280b2f927..29ba142e51 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -177,7 +177,12 @@ export default function Layout(props: ParentProps) { const sidebarHovering = createMemo(() => !layout.sidebar.opened() && state.hoverProject !== undefined) const sidebarExpanded = createMemo(() => layout.sidebar.opened() || sidebarHovering()) - const clearHoverProjectSoon = () => queueMicrotask(() => setState("hoverProject", undefined)) + const setHoverProject = (value: string | undefined) => { + setState("hoverProject", value) + if (value !== undefined) return + aim.reset() + } + const clearHoverProjectSoon = () => queueMicrotask(() => setHoverProject(undefined)) const setHoverSession = (id: string | undefined) => setState("hoverSession", id) const hoverProjectData = createMemo(() => { @@ -188,13 +193,7 @@ export default function Layout(props: ParentProps) { createEffect(() => { if (!layout.sidebar.opened()) return - aim.reset() - setState("hoverProject", undefined) - }) - - createEffect(() => { - if (state.hoverProject !== undefined) return - aim.reset() + setHoverProject(undefined) }) const autoselecting = createMemo(() => { @@ -225,7 +224,7 @@ export default function Layout(props: ParentProps) { const clearSidebarHoverState = () => { if (layout.sidebar.opened()) return setState("hoverSession", undefined) - setState("hoverProject", undefined) + setHoverProject(undefined) } const navigateWithSidebarReset = (href: string) => { @@ -1490,7 +1489,7 @@ export default function Layout(props: ParentProps) { function handleDragStart(event: unknown) { const id = getDraggableId(event) if (!id) return - setState("hoverProject", undefined) + setHoverProject(undefined) setStore("activeProject", id) } @@ -1924,7 +1923,7 @@ export default function Layout(props: ParentProps) { if (navLeave.current !== undefined) clearTimeout(navLeave.current) navLeave.current = window.setTimeout(() => { navLeave.current = undefined - setState("hoverProject", undefined) + setHoverProject(undefined) setState("hoverSession", undefined) }, 300) }} diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 1658455640..21ba4e7d7b 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -1,4 +1,4 @@ -import { onCleanup, Show, Match, Switch, createMemo, createEffect, on } from "solid-js" +import { onCleanup, Show, Match, Switch, createMemo, createEffect, on, onMount } from "solid-js" import { createMediaQuery } from "@solid-primitives/media" import { createResizeObserver } from "@solid-primitives/resize-observer" import { useLocal } from "@/context/local" @@ -981,7 +981,7 @@ export default function Page() { consumePendingMessage: layout.pendingMessage.consume, }) - createEffect(() => { + onMount(() => { document.addEventListener("keydown", handleKeyDown) }) diff --git a/packages/app/src/pages/session/file-tabs.tsx b/packages/app/src/pages/session/file-tabs.tsx index 9e3a543114..ebc1f59227 100644 --- a/packages/app/src/pages/session/file-tabs.tsx +++ b/packages/app/src/pages/session/file-tabs.tsx @@ -168,6 +168,13 @@ export function FileTabContent(props: { tab: string }) { draftTop: undefined as number | undefined, }) + const setCommenting = (range: SelectedLineRange | null) => { + setNote("commenting", range) + scheduleComments() + if (!range) return + setNote("draft", "") + } + const getRoot = () => { const el = wrap if (!el) return @@ -260,13 +267,6 @@ export function FileTabContent(props: { tab: string }) { scheduleComments() }) - createEffect(() => { - const range = note.commenting - scheduleComments() - if (!range) return - setNote("draft", "") - }) - createEffect(() => { const focus = comments.focus() const p = path() @@ -278,7 +278,7 @@ export function FileTabContent(props: { tab: string }) { if (!target) return setNote("openedComment", target.id) - setNote("commenting", null) + setCommenting(null) file.setSelectedLines(p, target.selection) requestAnimationFrame(() => comments.clearFocus()) }) @@ -438,16 +438,16 @@ export function FileTabContent(props: { tab: string }) { const p = path() if (!p) return file.setSelectedLines(p, range) - if (!range) setNote("commenting", null) + if (!range) setCommenting(null) }} onLineSelectionEnd={(range: SelectedLineRange | null) => { if (!range) { - setNote("commenting", null) + setCommenting(null) return } setNote("openedComment", null) - setNote("commenting", range) + setCommenting(range) }} overflow="scroll" class="select-text" @@ -468,7 +468,7 @@ export function FileTabContent(props: { tab: string }) { onClick={() => { const p = path() if (!p) return - setNote("commenting", null) + setCommenting(null) setNote("openedComment", (current) => (current === comment.id ? null : comment.id)) file.setSelectedLines(p, comment.selection) }} @@ -483,12 +483,12 @@ export function FileTabContent(props: { tab: string }) { value={note.draft} selection={formatCommentLabel(range())} onInput={(value) => setNote("draft", value)} - onCancel={() => setNote("commenting", null)} + onCancel={() => setCommenting(null)} onSubmit={(value) => { const p = path() if (!p) return addCommentToContext({ file: p, selection: range(), comment: value, origin: "file" }) - setNote("commenting", null) + setCommenting(null) }} onPopoverFocusOut={(e: FocusEvent) => { const current = e.currentTarget as HTMLDivElement @@ -497,7 +497,7 @@ export function FileTabContent(props: { tab: string }) { setTimeout(() => { if (!document.activeElement || !current.contains(document.activeElement)) { - setNote("commenting", null) + setCommenting(null) } }, 0) }} diff --git a/packages/app/src/pages/session/session-prompt-dock.tsx b/packages/app/src/pages/session/session-prompt-dock.tsx index 3f0b7a6e8e..abe12bcb00 100644 --- a/packages/app/src/pages/session/session-prompt-dock.tsx +++ b/packages/app/src/pages/session/session-prompt-dock.tsx @@ -70,29 +70,28 @@ export function SessionPromptDock(props: { setSessionHandoff(sessionKey(), { prompt: previewPrompt() }) }) - const [responding, setResponding] = createSignal(false) - - createEffect( - on( - () => permissionRequest()?.id, - () => setResponding(false), - { defer: true }, - ), - ) + const [responding, setResponding] = createSignal() + const permissionResponding = () => { + const perm = permissionRequest() + if (!perm) return false + return responding() === perm.id + } const decide = (response: "once" | "always" | "reject") => { const perm = permissionRequest() if (!perm) return - if (responding()) return + if (responding() === perm.id) return - setResponding(true) + setResponding(perm.id) sdk.client.permission .respond({ sessionID: perm.sessionID, permissionID: perm.id, response }) .catch((err: unknown) => { const message = err instanceof Error ? err.message : String(err) showToast({ title: language.t("common.requestFailed"), description: message }) }) - .finally(() => setResponding(false)) + .finally(() => { + setResponding((id) => (id === perm.id ? undefined : id)) + }) } const done = createMemo( @@ -218,18 +217,28 @@ export function SessionPromptDock(props: { <>
- -
From 1133d87be043ab999be5002380584b21653e09c4 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 18 Feb 2026 13:38:46 -0600 Subject: [PATCH 32/88] chore: cleanup --- .../app/src/pages/session/helpers.test.ts | 33 ++++++++++++++++++- packages/app/src/pages/session/helpers.ts | 21 ++++++++++++ .../src/pages/session/session-side-panel.tsx | 19 +++++------ 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/packages/app/src/pages/session/helpers.test.ts b/packages/app/src/pages/session/helpers.test.ts index 8b9746507e..7d357e6572 100644 --- a/packages/app/src/pages/session/helpers.test.ts +++ b/packages/app/src/pages/session/helpers.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test" -import { createOpenReviewFile, focusTerminalById, getTabReorderIndex } from "./helpers" +import { createOpenReviewFile, createOpenSessionFileTab, focusTerminalById, getTabReorderIndex } from "./helpers" describe("createOpenReviewFile", () => { test("opens and loads selected review file", () => { @@ -20,6 +20,37 @@ describe("createOpenReviewFile", () => { }) }) +describe("createOpenSessionFileTab", () => { + test("activates the opened file tab", () => { + const calls: string[] = [] + const openTab = createOpenSessionFileTab({ + normalizeTab: (value) => { + calls.push(`normalize:${value}`) + return `file://${value}` + }, + openTab: (tab) => calls.push(`open:${tab}`), + pathFromTab: (tab) => { + calls.push(`path:${tab}`) + return tab.slice("file://".length) + }, + loadFile: (path) => calls.push(`load:${path}`), + openReviewPanel: () => calls.push("review"), + setActive: (tab) => calls.push(`active:${tab}`), + }) + + openTab("src/a.ts") + + expect(calls).toEqual([ + "normalize:src/a.ts", + "open:file://src/a.ts", + "path:file://src/a.ts", + "load:src/a.ts", + "review", + "active:file://src/a.ts", + ]) + }) +}) + describe("focusTerminalById", () => { test("focuses textarea when present", () => { document.body.innerHTML = `
` diff --git a/packages/app/src/pages/session/helpers.ts b/packages/app/src/pages/session/helpers.ts index 5ca355d1d2..995f6eb191 100644 --- a/packages/app/src/pages/session/helpers.ts +++ b/packages/app/src/pages/session/helpers.ts @@ -35,6 +35,27 @@ export const createOpenReviewFile = (input: { } } +export const createOpenSessionFileTab = (input: { + normalizeTab: (tab: string) => string + openTab: (tab: string) => void + pathFromTab: (tab: string) => string | undefined + loadFile: (path: string) => void + openReviewPanel: () => void + setActive: (tab: string) => void +}) => { + return (value: string) => { + const next = input.normalizeTab(value) + input.openTab(next) + + const path = input.pathFromTab(next) + if (!path) return + + input.loadFile(path) + input.openReviewPanel() + input.setActive(next) + } +} + export const getTabReorderIndex = (tabs: readonly string[], from: string, to: string) => { const fromIndex = tabs.indexOf(from) const toIndex = tabs.indexOf(to) diff --git a/packages/app/src/pages/session/session-side-panel.tsx b/packages/app/src/pages/session/session-side-panel.tsx index 68dfc346f9..7f2d4fc767 100644 --- a/packages/app/src/pages/session/session-side-panel.tsx +++ b/packages/app/src/pages/session/session-side-panel.tsx @@ -23,7 +23,7 @@ import { useLayout } from "@/context/layout" import { useSync } from "@/context/sync" import { createFileTabListSync } from "@/pages/session/file-tab-scroll" import { FileTabContent } from "@/pages/session/file-tabs" -import { getTabReorderIndex } from "@/pages/session/helpers" +import { createOpenSessionFileTab, getTabReorderIndex } from "@/pages/session/helpers" import { StickyAddButton } from "@/pages/session/review-tab" import { setSessionHandoff } from "@/pages/session/handoff" @@ -96,15 +96,14 @@ export function SessionSidePanel(props: { if (!view().reviewPanel.opened()) view().reviewPanel.open() } - const openTab = (value: string) => { - const next = normalizeTab(value) - tabs().open(next) - - const path = file.pathFromTab(next) - if (!path) return - file.load(path) - openReviewPanel() - } + const openTab = createOpenSessionFileTab({ + normalizeTab, + openTab: tabs().open, + pathFromTab: file.pathFromTab, + loadFile: file.load, + openReviewPanel, + setActive: tabs().setActive, + }) const contextOpen = createMemo(() => tabs().active() === "context" || tabs().all().includes("context")) const openedTabs = createMemo(() => From de25703e9dd33df4dff6b5b8ae9a722f6ca2aa81 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 18 Feb 2026 13:56:05 -0600 Subject: [PATCH 33/88] fix(app): terminal cross-talk (#14184) --- packages/opencode/src/pty/index.ts | 43 ++++++++++------- packages/opencode/src/server/routes/pty.ts | 16 +++++-- .../test/pty/pty-output-isolation.test.ts | 46 +++++++++++++++++++ 3 files changed, 86 insertions(+), 19 deletions(-) diff --git a/packages/opencode/src/pty/index.ts b/packages/opencode/src/pty/index.ts index a9052a79eb..c98e99daf5 100644 --- a/packages/opencode/src/pty/index.ts +++ b/packages/opencode/src/pty/index.ts @@ -18,18 +18,24 @@ export namespace Pty { type Socket = { readyState: number + data: object send: (data: string | Uint8Array | ArrayBuffer) => void close: (code?: number, reason?: string) => void } - const sockets = new WeakMap() - let socketCounter = 0 + // Bun's ServerWebSocket has a per-connection `.data` object (set during + // `server.upgrade`) that changes when the underlying connection is recycled. + // We keep a reference to a stable part of it so output can't leak even when + // websocket objects are reused. + const token = (ws: Socket) => { + const data = ws.data + const events = (data as { events?: unknown }).events + if (events && typeof events === "object") return events - const tagSocket = (ws: Socket) => { - if (!ws || typeof ws !== "object") return - const next = (socketCounter = (socketCounter + 1) % Number.MAX_SAFE_INTEGER) - sockets.set(ws, next) - return next + const url = (data as { url?: unknown }).url + if (url && typeof url === "object") return url + + return data } // WebSocket control frame: 0x00 + UTF-8 JSON (currently { cursor }). @@ -96,7 +102,7 @@ export namespace Pty { buffer: string bufferCursor: number cursor: number - subscribers: Map + subscribers: Map } const state = Instance.state( @@ -176,26 +182,27 @@ export namespace Pty { subscribers: new Map(), } state().set(id, session) - ptyProcess.onData((data) => { - session.cursor += data.length + ptyProcess.onData((chunk) => { + session.cursor += chunk.length - for (const [ws, id] of session.subscribers) { + for (const [ws, data] of session.subscribers) { if (ws.readyState !== 1) { session.subscribers.delete(ws) continue } - if (typeof ws === "object" && sockets.get(ws) !== id) { + + if (token(ws) !== data) { session.subscribers.delete(ws) continue } try { - ws.send(data) + ws.send(chunk) } catch { session.subscribers.delete(ws) } } - session.buffer += data + session.buffer += chunk if (session.buffer.length <= BUFFER_LIMIT) return const excess = session.buffer.length - BUFFER_LIMIT session.buffer = session.buffer.slice(excess) @@ -305,8 +312,12 @@ export namespace Pty { return } - const socketId = tagSocket(ws) - if (typeof socketId === "number") session.subscribers.set(ws, socketId) + if (!ws.data || typeof ws.data !== "object") { + ws.close() + return + } + + session.subscribers.set(ws, token(ws)) return { onMessage: (message: string | ArrayBuffer) => { session.process.write(String(message)) diff --git a/packages/opencode/src/server/routes/pty.ts b/packages/opencode/src/server/routes/pty.ts index 21156190dc..d516859f7f 100644 --- a/packages/opencode/src/server/routes/pty.ts +++ b/packages/opencode/src/server/routes/pty.ts @@ -163,6 +163,7 @@ export const PtyRoutes = lazy(() => type Socket = { readyState: number + data: object send: (data: string | Uint8Array | ArrayBuffer) => void close: (code?: number, reason?: string) => void } @@ -170,6 +171,10 @@ export const PtyRoutes = lazy(() => const isSocket = (value: unknown): value is Socket => { if (!value || typeof value !== "object") return false if (!("readyState" in value)) return false + if (!("data" in value)) return false + if (!((value as { data?: unknown }).data && typeof (value as { data?: unknown }).data === "object")) { + return false + } if (!("send" in value) || typeof (value as { send?: unknown }).send !== "function") return false if (!("close" in value) || typeof (value as { close?: unknown }).close !== "function") return false return typeof (value as { readyState?: unknown }).readyState === "number" @@ -177,11 +182,16 @@ export const PtyRoutes = lazy(() => return { onOpen(_event, ws) { - const socket = isSocket(ws.raw) ? ws.raw : ws - handler = Pty.connect(id, socket, cursor) + const raw = ws.raw + if (!isSocket(raw)) { + ws.close() + return + } + handler = Pty.connect(id, raw, cursor) }, onMessage(event) { - handler?.onMessage(String(event.data)) + if (typeof event.data !== "string") return + handler?.onMessage(event.data) }, onClose() { handler?.onClose() diff --git a/packages/opencode/test/pty/pty-output-isolation.test.ts b/packages/opencode/test/pty/pty-output-isolation.test.ts index b80d373458..337280d18d 100644 --- a/packages/opencode/test/pty/pty-output-isolation.test.ts +++ b/packages/opencode/test/pty/pty-output-isolation.test.ts @@ -18,6 +18,7 @@ describe("pty", () => { const ws = { readyState: 1, + data: { events: { connection: "a" } }, send: (data: unknown) => { outA.push(typeof data === "string" ? data : Buffer.from(data as Uint8Array).toString("utf8")) }, @@ -30,6 +31,7 @@ describe("pty", () => { Pty.connect(a.id, ws as any) // Now "reuse" the same ws object for another connection. + ws.data = { events: { connection: "b" } } ws.send = (data: unknown) => { outB.push(typeof data === "string" ? data : Buffer.from(data as Uint8Array).toString("utf8")) } @@ -51,4 +53,48 @@ describe("pty", () => { }, }) }) + + test("does not leak output when Bun recycles websocket objects before re-connect", async () => { + await using dir = await tmpdir({ git: true }) + + await Instance.provide({ + directory: dir.path, + fn: async () => { + const a = await Pty.create({ command: "cat", title: "a" }) + try { + const outA: string[] = [] + const outB: string[] = [] + + const ws = { + readyState: 1, + data: { events: { connection: "a" } }, + send: (data: unknown) => { + outA.push(typeof data === "string" ? data : Buffer.from(data as Uint8Array).toString("utf8")) + }, + close: () => { + // no-op (simulate abrupt drop) + }, + } + + // Connect "a" first. + Pty.connect(a.id, ws as any) + outA.length = 0 + + // Simulate Bun reusing the same websocket object for another connection + // before the new onOpen handler has a chance to tag it. + ws.data = { events: { connection: "b" } } + ws.send = (data: unknown) => { + outB.push(typeof data === "string" ? data : Buffer.from(data as Uint8Array).toString("utf8")) + } + + Pty.write(a.id, "AAA\n") + await Bun.sleep(100) + + expect(outB.join("")).not.toContain("AAA") + } finally { + await Pty.remove(a.id) + } + }, + }) + }) }) From 1aa18c6cd64412db89ccfb58c2641ab3e49233e4 Mon Sep 17 00:00:00 2001 From: Helge Tesdal Date: Wed, 18 Feb 2026 21:14:18 +0100 Subject: [PATCH 34/88] feat(plugin): pass sessionID and callID to shell.env hook input (#13662) --- packages/opencode/src/session/prompt.ts | 2 +- packages/opencode/src/tool/bash.ts | 2 +- packages/plugin/src/index.ts | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index 43ad9a09d3..c99eb72a73 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -1618,7 +1618,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the const args = matchingInvocation?.args const cwd = Instance.directory - const shellEnv = await Plugin.trigger("shell.env", { cwd }, { env: {} }) + const shellEnv = await Plugin.trigger("shell.env", { cwd, sessionID: input.sessionID, callID: part.callID }, { env: {} }) const proc = spawn(shell, args, { cwd, detached: process.platform !== "win32", diff --git a/packages/opencode/src/tool/bash.ts b/packages/opencode/src/tool/bash.ts index 67559b78c0..2b692db6ee 100644 --- a/packages/opencode/src/tool/bash.ts +++ b/packages/opencode/src/tool/bash.ts @@ -163,7 +163,7 @@ export const BashTool = Tool.define("bash", async () => { }) } - const shellEnv = await Plugin.trigger("shell.env", { cwd }, { env: {} }) + const shellEnv = await Plugin.trigger("shell.env", { cwd, sessionID: ctx.sessionID, callID: ctx.callID }, { env: {} }) const proc = spawn(params.command, { shell, cwd, diff --git a/packages/plugin/src/index.ts b/packages/plugin/src/index.ts index bd4ba53049..76370d1d5a 100644 --- a/packages/plugin/src/index.ts +++ b/packages/plugin/src/index.ts @@ -185,7 +185,10 @@ export interface Hooks { input: { tool: string; sessionID: string; callID: string }, output: { args: any }, ) => Promise - "shell.env"?: (input: { cwd: string }, output: { env: Record }) => Promise + "shell.env"?: ( + input: { cwd: string; sessionID?: string; callID?: string }, + output: { env: Record }, + ) => Promise "tool.execute.after"?: ( input: { tool: string; sessionID: string; callID: string; args: any }, output: { From 2d7c9c9692f9232d2977487f13ecddc758a4a250 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Wed, 18 Feb 2026 20:15:14 +0000 Subject: [PATCH 35/88] chore: generate --- packages/opencode/src/session/prompt.ts | 6 +++++- packages/opencode/src/tool/bash.ts | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index c99eb72a73..d1f4072586 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -1618,7 +1618,11 @@ NOTE: At any point in time through this workflow you should feel free to ask the const args = matchingInvocation?.args const cwd = Instance.directory - const shellEnv = await Plugin.trigger("shell.env", { cwd, sessionID: input.sessionID, callID: part.callID }, { env: {} }) + const shellEnv = await Plugin.trigger( + "shell.env", + { cwd, sessionID: input.sessionID, callID: part.callID }, + { env: {} }, + ) const proc = spawn(shell, args, { cwd, detached: process.platform !== "win32", diff --git a/packages/opencode/src/tool/bash.ts b/packages/opencode/src/tool/bash.ts index 2b692db6ee..ee2279bbfb 100644 --- a/packages/opencode/src/tool/bash.ts +++ b/packages/opencode/src/tool/bash.ts @@ -163,7 +163,11 @@ export const BashTool = Tool.define("bash", async () => { }) } - const shellEnv = await Plugin.trigger("shell.env", { cwd, sessionID: ctx.sessionID, callID: ctx.callID }, { env: {} }) + const shellEnv = await Plugin.trigger( + "shell.env", + { cwd, sessionID: ctx.sessionID, callID: ctx.callID }, + { env: {} }, + ) const proc = spawn(params.command, { shell, cwd, From d6331cf792e02c75a96f5f8a39adaedd9a2d1298 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 16:36:15 +0000 Subject: [PATCH 36/88] Update colors.css --- packages/ui/src/styles/colors.css | 144 ++++++++++++++++++++---------- 1 file changed, 96 insertions(+), 48 deletions(-) diff --git a/packages/ui/src/styles/colors.css b/packages/ui/src/styles/colors.css index 61e3ac950a..5ef17d1cc5 100644 --- a/packages/ui/src/styles/colors.css +++ b/packages/ui/src/styles/colors.css @@ -1,52 +1,100 @@ :root { - --smoke-dark-1: #131010; - --smoke-dark-2: #1b1818; - --smoke-dark-3: #252121; - --smoke-dark-4: #2d2828; - --smoke-dark-5: #343030; - --smoke-dark-6: #3e3939; - --smoke-dark-7: #4b4646; - --smoke-dark-8: #645f5f; - --smoke-dark-9: #716c6b; - --smoke-dark-10: #7f7979; - --smoke-dark-11: #b7b1b1; - --smoke-dark-12: #f1ecec; - --smoke-light-1: #fdfcfc; - --smoke-light-2: #f9f8f8; - --smoke-light-3: #f1f0f0; - --smoke-light-4: #e9e8e8; - --smoke-light-5: #e2e0e0; - --smoke-light-6: #dad9d9; - --smoke-light-7: #cfcecd; - --smoke-light-8: #bcbbbb; - --smoke-light-9: #8e8b8b; - --smoke-light-10: #848181; - --smoke-light-11: #656363; - --smoke-light-12: #211e1e; - --smoke-dark-alpha-1: #82383803; - --smoke-dark-alpha-2: #e6c6c60b; - --smoke-dark-alpha-3: #edd5d516; - --smoke-dark-alpha-4: #f2e1e11e; - --smoke-dark-alpha-5: #f5e8e826; - --smoke-dark-alpha-6: #f5e8e831; - --smoke-dark-alpha-7: #f7ecec3f; - --smoke-dark-alpha-8: #faf5f559; - --smoke-dark-alpha-9: #faf5f467; - --smoke-dark-alpha-10: #fbf5f576; - --smoke-dark-alpha-11: #fcf9f9b2; - --smoke-dark-alpha-12: #fdfbfbf0; - --smoke-light-alpha-1: #55000003; - --smoke-light-alpha-2: #25000007; - --smoke-light-alpha-3: #1100000f; - --smoke-light-alpha-4: #0c000017; - --smoke-light-alpha-5: #1100001f; - --smoke-light-alpha-6: #07000026; - --smoke-light-alpha-7: #0b060032; - --smoke-light-alpha-8: #04000044; - --smoke-light-alpha-9: #07000074; - --smoke-light-alpha-10: #0400009c; - --smoke-light-alpha-11: #0700007e; - --smoke-light-alpha-12: #020000df; + --gray-dark-1: #161616; + --gray-dark-2: #1C1C1C; + --gray-dark-3: #232323; + --gray-dark-4: #282828; + --gray-dark-5: #2E2E2E; + --gray-dark-6: #343434; + --gray-dark-7: #3E3E3E; + --gray-dark-8: #505050; + --gray-dark-9: #707070; + --gray-dark-10: #7E7E7E; + --gray-dark-11: #A0A0A0; + --gray-dark-12: #EDEDED; + --gray-light-1: #FCFCFC; + --gray-light-2: #F8F8F8; + --gray-light-3: #F3F3F3; + --gray-light-4: #EDEDED; + --gray-light-5: #E8E8E8; + --gray-light-6: #E2E2E2; + --gray-light-7: #DBDBDB; + --gray-light-8: #C7C7C7; + --gray-light-9: #8F8F8F; + --gray-light-10: #858585; + --gray-light-11: #6F6F6F; + --gray-light-12: #171717; + --gray-dark-alpha-1: #00000000; + --gray-dark-alpha-2: #FFFFFF08; + --gray-dark-alpha-3: #FFFFFF0F; + --gray-dark-alpha-4: #FFFFFF14; + --gray-dark-alpha-5: #FFFFFF1A; + --gray-dark-alpha-6: #FFFFFF21; + --gray-dark-alpha-7: #FFFFFF2B; + --gray-dark-alpha-8: #FFFFFF40; + --gray-dark-alpha-9: #FFFFFF63; + --gray-dark-alpha-10: #FFFFFF73; + --gray-dark-alpha-11: #FFFFFF96; + --gray-dark-alpha-12: #FFFFFFEB; + --gray-light-alpha-1: #00000003; + --gray-light-alpha-2: #00000008; + --gray-light-alpha-3: #0000000D; + --gray-light-alpha-4: #00000012; + --gray-light-alpha-5: #00000017; + --gray-light-alpha-6: #0000001C; + --gray-light-alpha-7: #00000024; + --gray-light-alpha-8: #00000038; + --gray-light-alpha-9: #00000070; + --gray-light-alpha-10: #0000007A; + --gray-light-alpha-11: #0000008F; + --gray-light-alpha-12: #000000E8; + --gray-dark-1: #131010; + --gray-dark-2: #1b1818; + --gray-dark-3: #252121; + --gray-dark-4: #2d2828; + --gray-dark-5: #343030; + --gray-dark-6: #3e3939; + --gray-dark-7: #4b4646; + --gray-dark-8: #645f5f; + --gray-dark-9: #716c6b; + --gray-dark-10: #7f7979; + --gray-dark-11: #b7b1b1; + --gray-dark-12: #f1ecec; + --gray-light-1: #fdfcfc; + --gray-light-2: #f9f8f8; + --gray-light-3: #f1f0f0; + --gray-light-4: #e9e8e8; + --gray-light-5: #e2e0e0; + --gray-light-6: #dad9d9; + --gray-light-7: #cfcecd; + --gray-light-8: #bcbbbb; + --gray-light-9: #8e8b8b; + --gray-light-10: #848181; + --gray-light-11: #656363; + --gray-light-12: #211e1e; + --gray-dark-alpha-1: #82383803; + --gray-dark-alpha-2: #e6c6c60b; + --gray-dark-alpha-3: #edd5d516; + --gray-dark-alpha-4: #f2e1e11e; + --gray-dark-alpha-5: #f5e8e826; + --gray-dark-alpha-6: #f5e8e831; + --gray-dark-alpha-7: #f7ecec3f; + --gray-dark-alpha-8: #faf5f559; + --gray-dark-alpha-9: #faf5f467; + --gray-dark-alpha-10: #fbf5f576; + --gray-dark-alpha-11: #fcf9f9b2; + --gray-dark-alpha-12: #fdfbfbf0; + --gray-light-alpha-1: #55000003; + --gray-light-alpha-2: #25000007; + --gray-light-alpha-3: #1100000f; + --gray-light-alpha-4: #0c000017; + --gray-light-alpha-5: #1100001f; + --gray-light-alpha-6: #07000026; + --gray-light-alpha-7: #0b060032; + --gray-light-alpha-8: #04000044; + --gray-light-alpha-9: #07000074; + --gray-light-alpha-10: #0400009c; + --gray-light-alpha-11: #0700007e; + --gray-light-alpha-12: #020000df; --yuzu-dark-1: #11120c; --yuzu-light-1: #fdfdfb; --yuzu-light-2: #fbfceb; From 12016c8eb451a119c1017b2fc5554b49232399e3 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 16:36:30 +0000 Subject: [PATCH 37/88] oc-2 theme init --- packages/ui/src/theme/default-themes.ts | 3 + packages/ui/src/theme/index.ts | 1 + packages/ui/src/theme/themes/oc-2.json | 532 ++++++++++++++++++++++++ 3 files changed, 536 insertions(+) create mode 100644 packages/ui/src/theme/themes/oc-2.json diff --git a/packages/ui/src/theme/default-themes.ts b/packages/ui/src/theme/default-themes.ts index 4d44c3b018..52b2b42eba 100644 --- a/packages/ui/src/theme/default-themes.ts +++ b/packages/ui/src/theme/default-themes.ts @@ -1,5 +1,6 @@ import type { DesktopTheme } from "./types" import oc1ThemeJson from "./themes/oc-1.json" +import oc2ThemeJson from "./themes/oc-2.json" import tokyoThemeJson from "./themes/tokyonight.json" import draculaThemeJson from "./themes/dracula.json" import monokaiThemeJson from "./themes/monokai.json" @@ -16,6 +17,7 @@ import gruvboxThemeJson from "./themes/gruvbox.json" import auraThemeJson from "./themes/aura.json" export const oc1Theme = oc1ThemeJson as DesktopTheme +export const oc2Theme = oc2ThemeJson as DesktopTheme export const tokyonightTheme = tokyoThemeJson as DesktopTheme export const draculaTheme = draculaThemeJson as DesktopTheme export const monokaiTheme = monokaiThemeJson as DesktopTheme @@ -33,6 +35,7 @@ export const auraTheme = auraThemeJson as DesktopTheme export const DEFAULT_THEMES: Record = { "oc-1": oc1Theme, + "oc-2": oc2Theme, aura: auraTheme, ayu: ayuTheme, carbonfox: carbonfoxTheme, diff --git a/packages/ui/src/theme/index.ts b/packages/ui/src/theme/index.ts index e8d2fe79f8..d2c60179ec 100644 --- a/packages/ui/src/theme/index.ts +++ b/packages/ui/src/theme/index.ts @@ -32,6 +32,7 @@ export { ThemeProvider, useTheme, type ColorScheme } from "./context" export { DEFAULT_THEMES, oc1Theme, + oc2Theme, tokyonightTheme, draculaTheme, monokaiTheme, diff --git a/packages/ui/src/theme/themes/oc-2.json b/packages/ui/src/theme/themes/oc-2.json new file mode 100644 index 0000000000..d47322aef4 --- /dev/null +++ b/packages/ui/src/theme/themes/oc-2.json @@ -0,0 +1,532 @@ +{ + "$schema": "https://opencode.ai/desktop-theme.json", + "name": "OC-2", + "id": "oc-2", + "light": { + "seeds": { + "neutral": "#8e8b8b", + "primary": "#dcde8d", + "success": "#12c905", + "warning": "#ffdc17", + "error": "#fc533a", + "info": "#a753ae", + "interactive": "#034cff", + "diffAdd": "#9ff29a", + "diffDelete": "#fc533a" + }, + "overrides": { + "background-base": "#f8f7f7", + "background-weak": "var(--gray-light-3)", + "background-strong": "var(--gray-light-1)", + "background-stronger": "#fcfcfc", + "surface-base": "var(--gray-light-alpha-2)", + "base": "var(--gray-light-alpha-2)", + "surface-base-hover": "#0500000f", + "surface-base-active": "var(--gray-light-alpha-3)", + "surface-base-interactive-active": "var(--cobalt-light-alpha-3)", + "base2": "var(--gray-light-alpha-2)", + "base3": "var(--gray-light-alpha-2)", + "surface-inset-base": "var(--gray-light-alpha-2)", + "surface-inset-base-hover": "var(--gray-light-alpha-3)", + "surface-inset-strong": "#1f000017", + "surface-inset-strong-hover": "#1f000017", + "surface-raised-base": "var(--gray-light-alpha-2)", + "surface-float-base": "var(--gray-dark-1)", + "surface-float-base-hover": "var(--gray-dark-2)", + "surface-raised-base-hover": "var(--gray-light-alpha-3)", + "surface-raised-base-active": "var(--gray-light-alpha-4)", + "surface-raised-strong": "var(--gray-light-1)", + "surface-raised-strong-hover": "var(--white)", + "surface-raised-stronger": "var(--white)", + "surface-raised-stronger-hover": "var(--white)", + "surface-weak": "var(--gray-light-alpha-3)", + "surface-weaker": "var(--gray-light-alpha-4)", + "surface-strong": "#ffffff", + "surface-raised-stronger-non-alpha": "var(--white)", + "surface-brand-base": "var(--yuzu-light-9)", + "surface-brand-hover": "var(--yuzu-light-10)", + "surface-interactive-base": "var(--cobalt-light-3)", + "surface-interactive-hover": "#E5F0FF", + "surface-interactive-weak": "var(--cobalt-light-2)", + "surface-interactive-weak-hover": "var(--cobalt-light-3)", + "surface-success-base": "var(--apple-light-3)", + "surface-success-weak": "var(--apple-light-2)", + "surface-success-strong": "var(--apple-light-9)", + "surface-warning-base": "var(--solaris-light-3)", + "surface-warning-weak": "var(--solaris-light-2)", + "surface-warning-strong": "var(--solaris-light-9)", + "surface-critical-base": "var(--ember-light-3)", + "surface-critical-weak": "var(--ember-light-2)", + "surface-critical-strong": "var(--ember-light-9)", + "surface-info-base": "var(--lilac-light-3)", + "surface-info-weak": "var(--lilac-light-2)", + "surface-info-strong": "var(--lilac-light-9)", + "surface-diff-unchanged-base": "#ffffff00", + "surface-diff-skip-base": "var(--gray-light-2)", + "surface-diff-hidden-base": "var(--blue-light-3)", + "surface-diff-hidden-weak": "var(--blue-light-2)", + "surface-diff-hidden-weaker": "var(--blue-light-1)", + "surface-diff-hidden-strong": "var(--blue-light-5)", + "surface-diff-hidden-stronger": "var(--blue-light-9)", + "surface-diff-add-base": "#dafbe0", + "surface-diff-add-weak": "var(--mint-light-2)", + "surface-diff-add-weaker": "var(--mint-light-1)", + "surface-diff-add-strong": "var(--mint-light-5)", + "surface-diff-add-stronger": "var(--mint-light-9)", + "surface-diff-delete-base": "var(--ember-light-3)", + "surface-diff-delete-weak": "var(--ember-light-2)", + "surface-diff-delete-weaker": "var(--ember-light-1)", + "surface-diff-delete-strong": "var(--ember-light-6)", + "surface-diff-delete-stronger": "var(--ember-light-9)", + "input-base": "var(--gray-light-1)", + "input-hover": "var(--gray-light-2)", + "input-active": "var(--cobalt-light-1)", + "input-selected": "var(--cobalt-light-4)", + "input-focus": "var(--cobalt-light-1)", + "input-disabled": "var(--gray-light-4)", + "text-base": "var(--gray-light-11)", + "text-weak": "var(--gray-light-9)", + "text-weaker": "var(--gray-light-8)", + "text-strong": "var(--gray-light-12)", + "text-invert-base": "var(--gray-dark-alpha-11)", + "text-invert-weak": "var(--gray-dark-alpha-9)", + "text-invert-weaker": "var(--gray-dark-alpha-8)", + "text-invert-strong": "var(--gray-dark-alpha-12)", + "text-interactive-base": "var(--cobalt-light-9)", + "text-on-brand-base": "var(--gray-light-alpha-11)", + "text-on-interactive-base": "var(--gray-light-1)", + "text-on-interactive-weak": "var(--gray-dark-alpha-11)", + "text-on-success-base": "var(--apple-light-10)", + "text-on-critical-base": "var(--ember-light-10)", + "text-on-critical-weak": "var(--ember-light-8)", + "text-on-critical-strong": "var(--ember-light-12)", + "text-on-warning-base": "var(--gray-dark-alpha-11)", + "text-on-info-base": "var(--gray-dark-alpha-11)", + "text-diff-add-base": "var(--mint-light-11)", + "text-diff-delete-base": "var(--ember-light-10)", + "text-diff-delete-strong": "var(--ember-light-12)", + "text-diff-add-strong": "var(--mint-light-12)", + "text-on-info-weak": "var(--gray-dark-alpha-9)", + "text-on-info-strong": "var(--gray-dark-alpha-12)", + "text-on-warning-weak": "var(--gray-dark-alpha-9)", + "text-on-warning-strong": "var(--gray-dark-alpha-12)", + "text-on-success-weak": "var(--apple-light-6)", + "text-on-success-strong": "var(--apple-light-12)", + "text-on-brand-weak": "var(--gray-light-alpha-9)", + "text-on-brand-weaker": "var(--gray-light-alpha-8)", + "text-on-brand-strong": "var(--gray-light-alpha-12)", + "button-primary-base": "var(--gray-light-12)", + "button-secondary-base": "#fdfcfc", + "button-secondary-hover": "#faf9f9", + "border-base": "var(--gray-light-alpha-7)", + "border-hover": "var(--gray-light-alpha-8)", + "border-active": "var(--gray-light-alpha-9)", + "border-selected": "var(--cobalt-light-alpha-9)", + "border-disabled": "var(--gray-light-alpha-8)", + "border-focus": "var(--gray-light-alpha-9)", + "border-weak-base": "var(--gray-light-alpha-5)", + "border-strong-base": "var(--gray-light-alpha-7)", + "border-strong-hover": "var(--gray-light-alpha-8)", + "border-strong-active": "var(--gray-light-alpha-7)", + "border-strong-selected": "var(--cobalt-light-alpha-6)", + "border-strong-disabled": "var(--gray-light-alpha-6)", + "border-strong-focus": "var(--gray-light-alpha-7)", + "border-weak-hover": "var(--gray-light-alpha-6)", + "border-weak-active": "var(--gray-light-alpha-7)", + "border-weak-selected": "var(--cobalt-light-alpha-5)", + "border-weak-disabled": "var(--gray-light-alpha-6)", + "border-weak-focus": "var(--gray-light-alpha-7)", + "border-interactive-base": "var(--cobalt-light-7)", + "border-interactive-hover": "var(--cobalt-light-8)", + "border-interactive-active": "var(--cobalt-light-9)", + "border-interactive-selected": "var(--cobalt-light-9)", + "border-interactive-disabled": "var(--gray-light-8)", + "border-interactive-focus": "var(--cobalt-light-9)", + "border-success-base": "var(--apple-light-6)", + "border-success-hover": "var(--apple-light-7)", + "border-success-selected": "var(--apple-light-9)", + "border-warning-base": "var(--solaris-light-6)", + "border-warning-hover": "var(--solaris-light-7)", + "border-warning-selected": "var(--solaris-light-9)", + "border-critical-base": "var(--ember-light-6)", + "border-critical-hover": "var(--ember-light-7)", + "border-critical-selected": "var(--ember-light-9)", + "border-info-base": "var(--lilac-light-6)", + "border-info-hover": "var(--lilac-light-7)", + "border-info-selected": "var(--lilac-light-9)", + "icon-base": "var(--gray-light-9)", + "icon-hover": "var(--gray-light-11)", + "icon-active": "var(--gray-light-12)", + "icon-selected": "var(--gray-light-12)", + "icon-disabled": "var(--gray-light-8)", + "icon-focus": "var(--gray-light-12)", + "icon-invert-base": "#ffffff", + "icon-weak-base": "var(--gray-light-7)", + "icon-weak-hover": "var(--gray-light-8)", + "icon-weak-active": "var(--gray-light-9)", + "icon-weak-selected": "var(--gray-light-10)", + "icon-weak-disabled": "var(--gray-light-6)", + "icon-weak-focus": "var(--gray-light-9)", + "icon-strong-base": "var(--gray-light-12)", + "icon-strong-hover": "#151313", + "icon-strong-active": "#020202", + "icon-strong-selected": "#020202", + "icon-strong-disabled": "var(--gray-light-8)", + "icon-strong-focus": "#020202", + "icon-brand-base": "var(--gray-light-12)", + "icon-interactive-base": "var(--cobalt-light-9)", + "icon-success-base": "var(--apple-light-7)", + "icon-success-hover": "var(--apple-light-8)", + "icon-success-active": "var(--apple-light-11)", + "icon-warning-base": "var(--amber-light-7)", + "icon-warning-hover": "var(--amber-light-8)", + "icon-warning-active": "var(--amber-light-11)", + "icon-critical-base": "var(--ember-light-10)", + "icon-critical-hover": "var(--ember-light-11)", + "icon-critical-active": "var(--ember-light-12)", + "icon-info-base": "var(--lilac-light-7)", + "icon-info-hover": "var(--lilac-light-8)", + "icon-info-active": "var(--lilac-light-11)", + "icon-on-brand-base": "var(--gray-light-alpha-11)", + "icon-on-brand-hover": "var(--gray-light-alpha-12)", + "icon-on-brand-selected": "var(--gray-light-alpha-12)", + "icon-on-interactive-base": "var(--gray-light-1)", + "icon-agent-plan-base": "var(--purple-light-9)", + "icon-agent-docs-base": "var(--amber-light-9)", + "icon-agent-ask-base": "var(--cyan-light-9)", + "icon-agent-build-base": "var(--cobalt-light-9)", + "icon-on-success-base": "var(--apple-light-alpha-9)", + "icon-on-success-hover": "var(--apple-light-alpha-10)", + "icon-on-success-selected": "var(--apple-light-alpha-11)", + "icon-on-warning-base": "var(--amber-lightalpha-9)", + "icon-on-warning-hover": "var(--amber-lightalpha-10)", + "icon-on-warning-selected": "var(--amber-lightalpha-11)", + "icon-on-critical-base": "var(--ember-light-alpha-9)", + "icon-on-critical-hover": "var(--ember-light-alpha-10)", + "icon-on-critical-selected": "var(--ember-light-alpha-11)", + "icon-on-info-base": "var(--lilac-light-9)", + "icon-on-info-hover": "var(--lilac-light-alpha-10)", + "icon-on-info-selected": "var(--lilac-light-alpha-11)", + "icon-diff-add-base": "var(--mint-light-11)", + "icon-diff-add-hover": "var(--mint-light-12)", + "icon-diff-add-active": "var(--mint-light-12)", + "icon-diff-delete-base": "var(--ember-light-10)", + "icon-diff-delete-hover": "var(--ember-light-11)", + "syntax-comment": "var(--text-weak)", + "syntax-regexp": "var(--text-base)", + "syntax-string": "#006656", + "syntax-keyword": "var(--text-weak)", + "syntax-primitive": "#fb4804", + "syntax-operator": "var(--text-base)", + "syntax-variable": "var(--text-strong)", + "syntax-property": "#ed6dc8", + "syntax-type": "#596600", + "syntax-constant": "#007b80", + "syntax-punctuation": "var(--text-base)", + "syntax-object": "var(--text-strong)", + "syntax-success": "var(--apple-light-10)", + "syntax-warning": "var(--amber-light-10)", + "syntax-critical": "var(--ember-light-10)", + "syntax-info": "#0092a8", + "syntax-diff-add": "var(--mint-light-11)", + "syntax-diff-delete": "var(--ember-light-11)", + "syntax-diff-unknown": "#ff0000", + "markdown-heading": "#d68c27", + "markdown-text": "#1a1a1a", + "markdown-link": "#3b7dd8", + "markdown-link-text": "#318795", + "markdown-code": "#3d9a57", + "markdown-block-quote": "#b0851f", + "markdown-emph": "#b0851f", + "markdown-strong": "#d68c27", + "markdown-horizontal-rule": "#8a8a8a", + "markdown-list-item": "#3b7dd8", + "markdown-list-enumeration": "#318795", + "markdown-image": "#3b7dd8", + "markdown-image-text": "#318795", + "markdown-code-block": "#1a1a1a", + "border-color": "#ffffff", + "border-weaker-base": "var(--gray-light-alpha-3)", + "border-weaker-hover": "var(--gray-light-alpha-4)", + "border-weaker-active": "var(--gray-light-alpha-6)", + "border-weaker-selected": "var(--cobalt-light-alpha-4)", + "border-weaker-disabled": "var(--gray-light-alpha-2)", + "border-weaker-focus": "var(--gray-light-alpha-6)", + "button-ghost-hover": "var(--gray-light-alpha-2)", + "button-ghost-hover2": "var(--gray-light-alpha-3)", + "avatar-background-pink": "#feeef8", + "avatar-background-mint": "#e1fbf4", + "avatar-background-orange": "#fff1e7", + "avatar-background-purple": "#f9f1fe", + "avatar-background-cyan": "#e7f9fb", + "avatar-background-lime": "#eefadc", + "avatar-text-pink": "#cd1d8d", + "avatar-text-mint": "#147d6f", + "avatar-text-orange": "#ed5f00", + "avatar-text-purple": "#8445bc", + "avatar-text-cyan": "#0894b3", + "avatar-text-lime": "#5d770d" + } + }, + "dark": { + "seeds": { + "neutral": "#716c6b", + "primary": "#fab283", + "success": "#12c905", + "warning": "#fcd53a", + "error": "#fc533a", + "info": "#edb2f1", + "interactive": "#034cff", + "diffAdd": "#c8ffc4", + "diffDelete": "#fc533a" + }, + "overrides": { + "background-base": "var(--gray-dark-1)", + "background-weak": "#1E1E1E", + "background-strong": "#181818", + "background-stronger": "#191919", + "surface-base": "var(--gray-dark-alpha-2)", + "base": "var(--gray-dark-alpha-2)", + "surface-base-hover": "#e0b7b716", + "surface-base-active": "var(--gray-dark-alpha-3)", + "surface-base-interactive-active": "var(--cobalt-dark-alpha-2)", + "base2": "var(--gray-dark-alpha-2)", + "base3": "var(--gray-dark-alpha-2)", + "surface-inset-base": "#0e0b0b7f", + "surface-inset-base-hover": "#0e0b0b7f", + "surface-inset-strong": "#060505cc", + "surface-inset-strong-hover": "#060505cc", + "surface-raised-base": "var(--gray-dark-alpha-3)", + "surface-float-base": "var(--gray-dark-1)", + "surface-float-base-hover": "var(--gray-dark-2)", + "surface-raised-base-hover": "var(--gray-dark-alpha-4)", + "surface-raised-base-active": "var(--gray-dark-alpha-5)", + "surface-raised-strong": "var(--gray-dark-alpha-4)", + "surface-raised-strong-hover": "var(--gray-dark-alpha-6)", + "surface-raised-stronger": "var(--gray-dark-alpha-6)", + "surface-raised-stronger-hover": "var(--gray-dark-alpha-7)", + "surface-weak": "var(--gray-dark-alpha-4)", + "surface-weaker": "var(--gray-dark-alpha-5)", + "surface-strong": "var(--gray-dark-alpha-7)", + "surface-raised-stronger-non-alpha": "var(--gray-dark-3)", + "surface-brand-base": "var(--yuzu-light-9)", + "surface-brand-hover": "var(--yuzu-light-10)", + "surface-interactive-base": "var(--cobalt-dark-3)", + "surface-interactive-hover": "#0A1D4D", + "surface-interactive-weak": "var(--cobalt-dark-2)", + "surface-interactive-weak-hover": "var(--cobalt-light-3)", + "surface-success-base": "var(--apple-dark-3)", + "surface-success-weak": "var(--apple-dark-2)", + "surface-success-strong": "var(--apple-dark-9)", + "surface-warning-base": "var(--solaris-light-3)", + "surface-warning-weak": "var(--solaris-light-2)", + "surface-warning-strong": "var(--solaris-light-9)", + "surface-critical-base": "var(--ember-dark-3)", + "surface-critical-weak": "var(--ember-dark-2)", + "surface-critical-strong": "var(--ember-dark-9)", + "surface-info-base": "var(--lilac-light-3)", + "surface-info-weak": "var(--lilac-light-2)", + "surface-info-strong": "var(--lilac-light-9)", + "surface-diff-unchanged-base": "var(--gray-dark-1)", + "surface-diff-skip-base": "var(--gray-dark-alpha-1)", + "surface-diff-hidden-base": "var(--blue-dark-2)", + "surface-diff-hidden-weak": "var(--blue-dark-1)", + "surface-diff-hidden-weaker": "var(--blue-dark-3)", + "surface-diff-hidden-strong": "var(--blue-dark-5)", + "surface-diff-hidden-stronger": "var(--blue-dark-11)", + "surface-diff-add-base": "var(--mint-dark-3)", + "surface-diff-add-weak": "var(--mint-dark-4)", + "surface-diff-add-weaker": "var(--mint-dark-3)", + "surface-diff-add-strong": "var(--mint-dark-5)", + "surface-diff-add-stronger": "var(--mint-dark-11)", + "surface-diff-delete-base": "var(--ember-dark-3)", + "surface-diff-delete-weak": "var(--ember-dark-4)", + "surface-diff-delete-weaker": "var(--ember-dark-3)", + "surface-diff-delete-strong": "var(--ember-dark-5)", + "surface-diff-delete-stronger": "var(--ember-dark-11)", + "input-base": "var(--gray-dark-2)", + "input-hover": "var(--gray-dark-2)", + "input-active": "var(--cobalt-dark-1)", + "input-selected": "var(--cobalt-dark-2)", + "input-focus": "var(--cobalt-dark-1)", + "input-disabled": "var(--gray-dark-4)", + "text-base": "var(--gray-dark-alpha-11)", + "text-weak": "var(--gray-dark-alpha-9)", + "text-weaker": "var(--gray-dark-alpha-8)", + "text-strong": "var(--gray-dark-alpha-12)", + "text-invert-base": "var(--gray-dark-alpha-11)", + "text-invert-weak": "var(--gray-dark-alpha-9)", + "text-invert-weaker": "var(--gray-dark-alpha-8)", + "text-invert-strong": "var(--gray-dark-alpha-12)", + "text-interactive-base": "var(--cobalt-dark-11)", + "text-on-brand-base": "var(--gray-dark-alpha-11)", + "text-on-interactive-base": "var(--gray-dark-12)", + "text-on-interactive-weak": "var(--gray-dark-alpha-11)", + "text-on-success-base": "var(--apple-dark-9)", + "text-on-critical-base": "var(--ember-dark-9)", + "text-on-critical-weak": "var(--ember-dark-8)", + "text-on-critical-strong": "var(--ember-dark-12)", + "text-on-warning-base": "var(--gray-dark-alpha-11)", + "text-on-info-base": "var(--gray-dark-alpha-11)", + "text-diff-add-base": "var(--mint-dark-11)", + "text-diff-delete-base": "var(--ember-dark-9)", + "text-diff-delete-strong": "var(--ember-dark-12)", + "text-diff-add-strong": "var(--mint-dark-8)", + "text-on-info-weak": "var(--gray-dark-alpha-9)", + "text-on-info-strong": "var(--gray-dark-alpha-12)", + "text-on-warning-weak": "var(--gray-dark-alpha-9)", + "text-on-warning-strong": "var(--gray-dark-alpha-12)", + "text-on-success-weak": "var(--apple-dark-8)", + "text-on-success-strong": "var(--apple-dark-12)", + "text-on-brand-weak": "var(--gray-dark-alpha-9)", + "text-on-brand-weaker": "var(--gray-dark-alpha-8)", + "text-on-brand-strong": "var(--gray-dark-alpha-12)", + "button-primary-base": "var(--gray-dark-12)", + "button-secondary-base": "#231f1f", + "button-secondary-hover": "#2a2727", + "border-base": "var(--gray-dark-alpha-7)", + "border-hover": "var(--gray-dark-alpha-8)", + "border-active": "var(--gray-dark-alpha-9)", + "border-selected": "var(--cobalt-dark-alpha-11)", + "border-disabled": "var(--gray-dark-alpha-8)", + "border-focus": "var(--gray-dark-alpha-9)", + "border-weak-base": "var(--gray-dark-alpha-4)", + "border-weak-hover": "var(--gray-dark-alpha-7)", + "border-weak-active": "var(--gray-dark-alpha-8)", + "border-weak-selected": "var(--cobalt-dark-alpha-6)", + "border-weak-disabled": "var(--gray-dark-alpha-6)", + "border-weak-focus": "var(--gray-dark-alpha-8)", + "border-strong-base": "var(--gray-dark-alpha-8)", + "border-interactive-base": "var(--cobalt-light-7)", + "border-interactive-hover": "var(--cobalt-light-8)", + "border-interactive-active": "var(--cobalt-light-9)", + "border-interactive-selected": "var(--cobalt-light-9)", + "border-interactive-disabled": "var(--gray-light-8)", + "border-interactive-focus": "var(--cobalt-light-9)", + "border-success-base": "var(--apple-light-6)", + "border-success-hover": "var(--apple-light-7)", + "border-success-selected": "var(--apple-light-9)", + "border-warning-base": "var(--solaris-light-6)", + "border-warning-hover": "var(--solaris-light-7)", + "border-warning-selected": "var(--solaris-light-9)", + "border-critical-base": "var(--ember-dark-5)", + "border-critical-hover": "var(--ember-dark-7)", + "border-critical-selected": "var(--ember-dark-9)", + "border-info-base": "var(--lilac-light-6)", + "border-info-hover": "var(--lilac-light-7)", + "border-info-selected": "var(--lilac-light-9)", + "icon-base": "var(--gray-dark-10)", + "icon-hover": "var(--gray-dark-11)", + "icon-active": "var(--gray-dark-12)", + "icon-selected": "var(--gray-dark-12)", + "icon-disabled": "var(--gray-dark-8)", + "icon-focus": "var(--gray-dark-12)", + "icon-invert-base": "var(--gray-dark-1)", + "icon-weak-base": "var(--gray-dark-6)", + "icon-weak-hover": "var(--gray-light-7)", + "icon-weak-active": "var(--gray-light-8)", + "icon-weak-selected": "var(--gray-light-9)", + "icon-weak-disabled": "var(--gray-light-4)", + "icon-weak-focus": "var(--gray-light-9)", + "icon-strong-base": "var(--gray-dark-12)", + "icon-strong-hover": "#F3F3F3", + "icon-strong-active": "#EBEBEB", + "icon-strong-selected": "#FCFCFC", + "icon-strong-disabled": "var(--gray-dark-8)", + "icon-strong-focus": "#FCFCFC", + "icon-brand-base": "var(--white)", + "icon-interactive-base": "var(--cobalt-dark-11)", + "icon-success-base": "var(--apple-dark-9)", + "icon-success-hover": "var(--apple-dark-10)", + "icon-success-active": "var(--apple-dark-11)", + "icon-warning-base": "var(--amber-dark-9)", + "icon-warning-hover": "var(--amber-dark-8)", + "icon-warning-active": "var(--amber-dark-11)", + "icon-critical-base": "var(--ember-dark-9)", + "icon-critical-hover": "var(--ember-dark-11)", + "icon-critical-active": "var(--ember-dark-12)", + "icon-info-base": "var(--lilac-dark-7)", + "icon-info-hover": "var(--lilac-dark-8)", + "icon-info-active": "var(--lilac-dark-11)", + "icon-on-brand-base": "var(--gray-light-alpha-11)", + "icon-on-brand-hover": "var(--gray-light-alpha-12)", + "icon-on-brand-selected": "var(--gray-light-alpha-12)", + "icon-on-interactive-base": "var(--gray-dark-12)", + "icon-agent-plan-base": "var(--purple-dark-9)", + "icon-agent-docs-base": "var(--amber-dark-9)", + "icon-agent-ask-base": "var(--cyan-dark-9)", + "icon-agent-build-base": "var(--cobalt-dark-11)", + "icon-on-success-base": "var(--apple-dark-alpha-9)", + "icon-on-success-hover": "var(--apple-dark-alpha-10)", + "icon-on-success-selected": "var(--apple-dark-alpha-11)", + "icon-on-warning-base": "var(--amber-darkalpha-9)", + "icon-on-warning-hover": "var(--amber-darkalpha-10)", + "icon-on-warning-selected": "var(--amber-darkalpha-11)", + "icon-on-critical-base": "var(--ember-dark-alpha-9)", + "icon-on-critical-hover": "var(--ember-dark-alpha-10)", + "icon-on-critical-selected": "var(--ember-dark-alpha-11)", + "icon-on-info-base": "var(--lilac-dark-9)", + "icon-on-info-hover": "var(--lilac-dark-alpha-10)", + "icon-on-info-selected": "var(--lilac-dark-alpha-11)", + "icon-diff-add-base": "var(--mint-dark-11)", + "icon-diff-add-hover": "var(--mint-dark-10)", + "icon-diff-add-active": "var(--mint-dark-11)", + "icon-diff-delete-base": "var(--ember-dark-9)", + "icon-diff-delete-hover": "var(--ember-dark-10)", + "syntax-comment": "var(--text-weak)", + "syntax-regexp": "var(--text-base)", + "syntax-string": "#00ceb9", + "syntax-keyword": "var(--text-weak)", + "syntax-primitive": "#ffba92", + "syntax-operator": "var(--text-weak)", + "syntax-variable": "var(--text-strong)", + "syntax-property": "#ff9ae2", + "syntax-type": "#ecf58c", + "syntax-constant": "#93e9f6", + "syntax-punctuation": "var(--text-weak)", + "syntax-object": "var(--text-strong)", + "syntax-success": "var(--apple-dark-10)", + "syntax-warning": "var(--amber-dark-10)", + "syntax-critical": "var(--ember-dark-10)", + "syntax-info": "#93e9f6", + "syntax-diff-add": "var(--mint-dark-11)", + "syntax-diff-delete": "var(--ember-dark-11)", + "syntax-diff-unknown": "#ff0000", + "markdown-heading": "#9d7cd8", + "markdown-text": "#eeeeee", + "markdown-link": "#fab283", + "markdown-link-text": "#56b6c2", + "markdown-code": "#7fd88f", + "markdown-block-quote": "#e5c07b", + "markdown-emph": "#e5c07b", + "markdown-strong": "#f5a742", + "markdown-horizontal-rule": "#808080", + "markdown-list-item": "#fab283", + "markdown-list-enumeration": "#56b6c2", + "markdown-image": "#fab283", + "markdown-image-text": "#56b6c2", + "markdown-code-block": "#eeeeee", + "border-color": "#ffffff", + "border-weaker-base": "var(--gray-dark-alpha-3)", + "border-weaker-hover": "var(--gray-dark-alpha-4)", + "border-weaker-active": "var(--gray-dark-alpha-6)", + "border-weaker-selected": "var(--cobalt-dark-alpha-3)", + "border-weaker-disabled": "var(--gray-dark-alpha-2)", + "border-weaker-focus": "var(--gray-dark-alpha-6)", + "button-ghost-hover": "var(--gray-dark-alpha-2)", + "button-ghost-hover2": "var(--gray-dark-alpha-3)", + "avatar-background-pink": "#501b3f", + "avatar-background-mint": "#033a34", + "avatar-background-orange": "#5f2a06", + "avatar-background-purple": "#432155", + "avatar-background-cyan": "#0f3058", + "avatar-background-lime": "#2b3711", + "avatar-text-pink": "#e34ba9", + "avatar-text-mint": "#95f3d9", + "avatar-text-orange": "#ff802b", + "avatar-text-purple": "#9d5bd2", + "avatar-text-cyan": "#369eff", + "avatar-text-lime": "#c4f042" + } + } +} From 5d69f00282376bdde4133459374593457ab33e83 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 16:36:40 +0000 Subject: [PATCH 38/88] button style tweaks --- packages/ui/src/components/button.css | 4 ---- packages/ui/src/components/icon-button.css | 4 ---- 2 files changed, 8 deletions(-) diff --git a/packages/ui/src/components/button.css b/packages/ui/src/components/button.css index 794002888a..2d803d95c6 100644 --- a/packages/ui/src/components/button.css +++ b/packages/ui/src/components/button.css @@ -171,10 +171,6 @@ } } -[data-component="button"].titlebar-icon[data-variant="ghost"]:hover:not(:disabled) { - background-color: var(--surface-raised-base-active); -} - [data-component="button"].titlebar-icon[data-variant="ghost"][aria-expanded="true"] { background-color: var(--surface-base-active); } diff --git a/packages/ui/src/components/icon-button.css b/packages/ui/src/components/icon-button.css index ad8200ae68..10337bbcc3 100644 --- a/packages/ui/src/components/icon-button.css +++ b/packages/ui/src/components/icon-button.css @@ -168,10 +168,6 @@ aspect-ratio: auto; } -[data-component="icon-button"].titlebar-icon[data-variant="ghost"]:hover:not(:disabled) { - background-color: var(--surface-raised-base-active); -} - [data-component="icon-button"].titlebar-icon[data-variant="ghost"][aria-expanded="true"] { background-color: var(--surface-base-active); } From 24ce49d9d7c225651eb04db49f4a92f57a0d3412 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 16:45:50 +0000 Subject: [PATCH 39/88] fix(ui): add previous smoke colors --- packages/ui/src/styles/colors.css | 196 +++++++++++++++++++++++++----- 1 file changed, 164 insertions(+), 32 deletions(-) diff --git a/packages/ui/src/styles/colors.css b/packages/ui/src/styles/colors.css index 5ef17d1cc5..893f252aa9 100644 --- a/packages/ui/src/styles/colors.css +++ b/packages/ui/src/styles/colors.css @@ -1,52 +1,52 @@ :root { --gray-dark-1: #161616; - --gray-dark-2: #1C1C1C; + --gray-dark-2: #1c1c1c; --gray-dark-3: #232323; --gray-dark-4: #282828; - --gray-dark-5: #2E2E2E; + --gray-dark-5: #2e2e2e; --gray-dark-6: #343434; - --gray-dark-7: #3E3E3E; + --gray-dark-7: #3e3e3e; --gray-dark-8: #505050; --gray-dark-9: #707070; - --gray-dark-10: #7E7E7E; - --gray-dark-11: #A0A0A0; - --gray-dark-12: #EDEDED; - --gray-light-1: #FCFCFC; - --gray-light-2: #F8F8F8; - --gray-light-3: #F3F3F3; - --gray-light-4: #EDEDED; - --gray-light-5: #E8E8E8; - --gray-light-6: #E2E2E2; - --gray-light-7: #DBDBDB; - --gray-light-8: #C7C7C7; - --gray-light-9: #8F8F8F; + --gray-dark-10: #7e7e7e; + --gray-dark-11: #a0a0a0; + --gray-dark-12: #ededed; + --gray-light-1: #fcfcfc; + --gray-light-2: #f8f8f8; + --gray-light-3: #f3f3f3; + --gray-light-4: #ededed; + --gray-light-5: #e8e8e8; + --gray-light-6: #e2e2e2; + --gray-light-7: #dbdbdb; + --gray-light-8: #c7c7c7; + --gray-light-9: #8f8f8f; --gray-light-10: #858585; - --gray-light-11: #6F6F6F; + --gray-light-11: #6f6f6f; --gray-light-12: #171717; --gray-dark-alpha-1: #00000000; - --gray-dark-alpha-2: #FFFFFF08; - --gray-dark-alpha-3: #FFFFFF0F; - --gray-dark-alpha-4: #FFFFFF14; - --gray-dark-alpha-5: #FFFFFF1A; - --gray-dark-alpha-6: #FFFFFF21; - --gray-dark-alpha-7: #FFFFFF2B; - --gray-dark-alpha-8: #FFFFFF40; - --gray-dark-alpha-9: #FFFFFF63; - --gray-dark-alpha-10: #FFFFFF73; - --gray-dark-alpha-11: #FFFFFF96; - --gray-dark-alpha-12: #FFFFFFEB; + --gray-dark-alpha-2: #ffffff08; + --gray-dark-alpha-3: #ffffff0f; + --gray-dark-alpha-4: #ffffff14; + --gray-dark-alpha-5: #ffffff1a; + --gray-dark-alpha-6: #ffffff21; + --gray-dark-alpha-7: #ffffff2b; + --gray-dark-alpha-8: #ffffff40; + --gray-dark-alpha-9: #ffffff63; + --gray-dark-alpha-10: #ffffff73; + --gray-dark-alpha-11: #ffffff96; + --gray-dark-alpha-12: #ffffffeb; --gray-light-alpha-1: #00000003; --gray-light-alpha-2: #00000008; - --gray-light-alpha-3: #0000000D; + --gray-light-alpha-3: #0000000d; --gray-light-alpha-4: #00000012; --gray-light-alpha-5: #00000017; - --gray-light-alpha-6: #0000001C; + --gray-light-alpha-6: #0000001c; --gray-light-alpha-7: #00000024; --gray-light-alpha-8: #00000038; --gray-light-alpha-9: #00000070; - --gray-light-alpha-10: #0000007A; - --gray-light-alpha-11: #0000008F; - --gray-light-alpha-12: #000000E8; + --gray-light-alpha-10: #0000007a; + --gray-light-alpha-11: #0000008f; + --gray-light-alpha-12: #000000e8; --gray-dark-1: #131010; --gray-dark-2: #1b1818; --gray-dark-3: #252121; @@ -95,6 +95,54 @@ --gray-light-alpha-10: #0400009c; --gray-light-alpha-11: #0700007e; --gray-light-alpha-12: #020000df; + --smoke-dark-1: #131010; + --smoke-dark-2: #1b1818; + --smoke-dark-3: #252121; + --smoke-dark-4: #2d2828; + --smoke-dark-5: #343030; + --smoke-dark-6: #3e3939; + --smoke-dark-7: #4b4646; + --smoke-dark-8: #645f5f; + --smoke-dark-9: #716c6b; + --smoke-dark-10: #7f7979; + --smoke-dark-11: #b7b1b1; + --smoke-dark-12: #f1ecec; + --smoke-light-1: #fdfcfc; + --smoke-light-2: #f9f8f8; + --smoke-light-3: #f1f0f0; + --smoke-light-4: #e9e8e8; + --smoke-light-5: #e2e0e0; + --smoke-light-6: #dad9d9; + --smoke-light-7: #cfcecd; + --smoke-light-8: #bcbbbb; + --smoke-light-9: #8e8b8b; + --smoke-light-10: #848181; + --smoke-light-11: #656363; + --smoke-light-12: #211e1e; + --smoke-dark-alpha-1: #82383803; + --smoke-dark-alpha-2: #e6c6c60b; + --smoke-dark-alpha-3: #edd5d516; + --smoke-dark-alpha-4: #f2e1e11e; + --smoke-dark-alpha-5: #f5e8e826; + --smoke-dark-alpha-6: #f5e8e831; + --smoke-dark-alpha-7: #f7ecec3f; + --smoke-dark-alpha-8: #faf5f559; + --smoke-dark-alpha-9: #faf5f467; + --smoke-dark-alpha-10: #fbf5f576; + --smoke-dark-alpha-11: #fcf9f9b2; + --smoke-dark-alpha-12: #fdfbfbf0; + --smoke-light-alpha-1: #55000003; + --smoke-light-alpha-2: #25000007; + --smoke-light-alpha-3: #1100000f; + --smoke-light-alpha-4: #0c000017; + --smoke-light-alpha-5: #1100001f; + --smoke-light-alpha-6: #07000026; + --smoke-light-alpha-7: #0b060032; + --smoke-light-alpha-8: #04000044; + --smoke-light-alpha-9: #07000074; + --smoke-light-alpha-10: #0400009c; + --smoke-light-alpha-11: #0700007e; + --smoke-light-alpha-12: #020000df; --yuzu-dark-1: #11120c; --yuzu-light-1: #fdfdfb; --yuzu-light-2: #fbfceb; @@ -637,4 +685,88 @@ --amber-dark-alpha-10: #ffce48f9; --amber-dark-alpha-11: #ffab0eef; --amber-dark-alpha-12: #fff8e1f9; + + /* Legacy palette aliases (keeps older themes working) */ + --smoke-light-1: var(--gray-light-1); + --smoke-light-2: var(--gray-light-2); + --smoke-light-3: var(--gray-light-3); + --smoke-light-4: var(--gray-light-4); + --smoke-light-5: var(--gray-light-5); + --smoke-light-6: var(--gray-light-6); + --smoke-light-7: var(--gray-light-7); + --smoke-light-8: var(--gray-light-8); + --smoke-light-9: var(--gray-light-9); + --smoke-light-10: var(--gray-light-10); + --smoke-light-11: var(--gray-light-11); + --smoke-light-12: var(--gray-light-12); + + --smoke-dark-1: var(--gray-dark-1); + --smoke-dark-2: var(--gray-dark-2); + --smoke-dark-3: var(--gray-dark-3); + --smoke-dark-4: var(--gray-dark-4); + --smoke-dark-5: var(--gray-dark-5); + --smoke-dark-6: var(--gray-dark-6); + --smoke-dark-7: var(--gray-dark-7); + --smoke-dark-8: var(--gray-dark-8); + --smoke-dark-9: var(--gray-dark-9); + --smoke-dark-10: var(--gray-dark-10); + --smoke-dark-11: var(--gray-dark-11); + --smoke-dark-12: var(--gray-dark-12); + + --smoke-light-alpha-1: var(--gray-light-alpha-1); + --smoke-light-alpha-2: var(--gray-light-alpha-2); + --smoke-light-alpha-3: var(--gray-light-alpha-3); + --smoke-light-alpha-4: var(--gray-light-alpha-4); + --smoke-light-alpha-5: var(--gray-light-alpha-5); + --smoke-light-alpha-6: var(--gray-light-alpha-6); + --smoke-light-alpha-7: var(--gray-light-alpha-7); + --smoke-light-alpha-8: var(--gray-light-alpha-8); + --smoke-light-alpha-9: var(--gray-light-alpha-9); + --smoke-light-alpha-10: var(--gray-light-alpha-10); + --smoke-light-alpha-11: var(--gray-light-alpha-11); + --smoke-light-alpha-12: var(--gray-light-alpha-12); + + --smoke-dark-alpha-1: var(--gray-dark-alpha-1); + --smoke-dark-alpha-2: var(--gray-dark-alpha-2); + --smoke-dark-alpha-3: var(--gray-dark-alpha-3); + --smoke-dark-alpha-4: var(--gray-dark-alpha-4); + --smoke-dark-alpha-5: var(--gray-dark-alpha-5); + --smoke-dark-alpha-6: var(--gray-dark-alpha-6); + --smoke-dark-alpha-7: var(--gray-dark-alpha-7); + --smoke-dark-alpha-8: var(--gray-dark-alpha-8); + --smoke-dark-alpha-9: var(--gray-dark-alpha-9); + --smoke-dark-alpha-10: var(--gray-dark-alpha-10); + --smoke-dark-alpha-11: var(--gray-dark-alpha-11); + --smoke-dark-alpha-12: var(--gray-dark-alpha-12); + + --amber-lightalpha-1: var(--amber-light-alpha-1); + --amber-lightalpha-2: var(--amber-light-alpha-2); + --amber-lightalpha-3: var(--amber-light-alpha-3); + --amber-lightalpha-4: var(--amber-light-alpha-4); + --amber-lightalpha-5: var(--amber-light-alpha-5); + --amber-lightalpha-6: var(--amber-light-alpha-6); + --amber-lightalpha-7: var(--amber-light-alpha-7); + --amber-lightalpha-8: var(--amber-light-alpha-8); + --amber-lightalpha-9: var(--amber-light-alpha-9); + --amber-lightalpha-10: var(--amber-light-alpha-10); + --amber-lightalpha-11: var(--amber-light-alpha-11); + --amber-lightalpha-12: var(--amber-light-alpha-12); + + --amber-darkalpha-1: var(--amber-dark-alpha-1); + --amber-darkalpha-2: var(--amber-dark-alpha-2); + --amber-darkalpha-3: var(--amber-dark-alpha-3); + --amber-darkalpha-4: var(--amber-dark-alpha-4); + --amber-darkalpha-5: var(--amber-dark-alpha-5); + --amber-darkalpha-6: var(--amber-dark-alpha-6); + --amber-darkalpha-7: var(--amber-dark-alpha-7); + --amber-darkalpha-8: var(--amber-dark-alpha-8); + --amber-darkalpha-9: var(--amber-dark-alpha-9); + --amber-darkalpha-10: var(--amber-dark-alpha-10); + --amber-darkalpha-11: var(--amber-dark-alpha-11); + --amber-darkalpha-12: var(--amber-dark-alpha-12); + + --purple-light-9: var(--lilac-light-9); + --purple-dark-9: var(--lilac-dark-9); + --cyan-light-9: var(--blue-light-9); + --cyan-dark-9: var(--blue-dark-9); } From 0888c02379f0dd57a17b42788469d713c71ddb51 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 16:58:23 +0000 Subject: [PATCH 40/88] tweak(ui): file tree background color --- packages/app/src/pages/session/session-side-panel.tsx | 4 ++-- packages/ui/src/components/tabs.css | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/app/src/pages/session/session-side-panel.tsx b/packages/app/src/pages/session/session-side-panel.tsx index 7f2d4fc767..07b18f3146 100644 --- a/packages/app/src/pages/session/session-side-panel.tsx +++ b/packages/app/src/pages/session/session-side-panel.tsx @@ -354,7 +354,7 @@ export function SessionSidePanel(props: { {language.t("session.files.all")} - + - + Date: Wed, 18 Feb 2026 16:58:36 +0000 Subject: [PATCH 41/88] tweak(ui): share button border --- packages/app/src/components/session/session-header.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/app/src/components/session/session-header.tsx b/packages/app/src/components/session/session-header.tsx index 3003d05148..58ffd15cd8 100644 --- a/packages/app/src/components/session/session-header.tsx +++ b/packages/app/src/components/session/session-header.tsx @@ -449,7 +449,7 @@ export function SessionHeader() { triggerProps={{ variant: "ghost", class: - "rounded-md h-[24px] px-3 border border-border-base bg-surface-panel shadow-none data-[expanded]:bg-surface-raised-base-active", + "rounded-md h-[24px] px-3 border border-border-weak-base bg-surface-panel shadow-none data-[expanded]:bg-surface-raised-base-active", classList: { "rounded-r-none": share.shareUrl() !== undefined }, style: { scale: 1 }, }} @@ -522,7 +522,7 @@ export function SessionHeader() { share.copyLink((error) => showRequestError(language, error))} disabled={share.state.unshare} aria-label={ From f20c0bffd3e6701ce191ed49dab1fa29400e866f Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 17:02:10 +0000 Subject: [PATCH 42/88] tweak(ui): unify titlebar expanded button background --- packages/ui/src/components/button.css | 4 ++-- packages/ui/src/components/icon-button.css | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ui/src/components/button.css b/packages/ui/src/components/button.css index 2d803d95c6..e22c7b2987 100644 --- a/packages/ui/src/components/button.css +++ b/packages/ui/src/components/button.css @@ -172,7 +172,7 @@ } [data-component="button"].titlebar-icon[data-variant="ghost"][aria-expanded="true"] { - background-color: var(--surface-base-active); + background-color: var(--surface-raised-base-active); } [data-component="button"].titlebar-icon[data-variant="ghost"][aria-expanded="true"] [data-slot="icon-svg"] { @@ -180,5 +180,5 @@ } [data-component="button"].titlebar-icon[data-variant="ghost"][aria-expanded="true"]:hover:not(:disabled) { - background-color: var(--surface-base-active); + background-color: var(--surface-raised-base-active); } diff --git a/packages/ui/src/components/icon-button.css b/packages/ui/src/components/icon-button.css index 10337bbcc3..01c555bfc7 100644 --- a/packages/ui/src/components/icon-button.css +++ b/packages/ui/src/components/icon-button.css @@ -169,7 +169,7 @@ } [data-component="icon-button"].titlebar-icon[data-variant="ghost"][aria-expanded="true"] { - background-color: var(--surface-base-active); + background-color: var(--surface-raised-base-active); } [data-component="icon-button"].titlebar-icon[data-variant="ghost"][aria-expanded="true"] [data-slot="icon-svg"] { @@ -177,5 +177,5 @@ } [data-component="icon-button"].titlebar-icon[data-variant="ghost"][aria-expanded="true"]:hover:not(:disabled) { - background-color: var(--surface-base-active); + background-color: var(--surface-raised-base-active); } From e5d52e4eb528055ffc0d461c451ff4c79fe7e99d Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 17:08:49 +0000 Subject: [PATCH 43/88] tweak(ui): align pill tabs pressed background --- packages/ui/src/components/tabs.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/ui/src/components/tabs.css b/packages/ui/src/components/tabs.css index fee929d344..2a75defa28 100644 --- a/packages/ui/src/components/tabs.css +++ b/packages/ui/src/components/tabs.css @@ -257,6 +257,10 @@ color: var(--text-strong); } + &:active:not(:disabled) { + background-color: var(--surface-raised-base-active); + } + &:has([data-selected]) { background-color: var(--surface-raised-base-active); color: var(--text-strong); From 4db2d94854500cf939b95fb030e35c29982f1fdf Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 17:15:44 +0000 Subject: [PATCH 44/88] tweak(ui): shrink filetree tab height --- packages/ui/src/components/tabs.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/src/components/tabs.css b/packages/ui/src/components/tabs.css index 2a75defa28..de5e1750e9 100644 --- a/packages/ui/src/components/tabs.css +++ b/packages/ui/src/components/tabs.css @@ -282,7 +282,7 @@ } [data-slot="tabs-trigger-wrapper"] { - height: 26px; + height: 24px; border-radius: 6px; color: var(--text-weak); From 08739080309bb84be71b5dd30ce6541e1bf9c029 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 17:25:50 +0000 Subject: [PATCH 45/88] tweak(ui): theme color updates --- packages/ui/src/theme/themes/oc-2.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ui/src/theme/themes/oc-2.json b/packages/ui/src/theme/themes/oc-2.json index d47322aef4..ab17d9b6f8 100644 --- a/packages/ui/src/theme/themes/oc-2.json +++ b/packages/ui/src/theme/themes/oc-2.json @@ -34,7 +34,7 @@ "surface-float-base": "var(--gray-dark-1)", "surface-float-base-hover": "var(--gray-dark-2)", "surface-raised-base-hover": "var(--gray-light-alpha-3)", - "surface-raised-base-active": "var(--gray-light-alpha-4)", + "surface-raised-base-active": "var(--gray-light-alpha-5)", "surface-raised-strong": "var(--gray-light-1)", "surface-raised-strong-hover": "var(--white)", "surface-raised-stronger": "var(--white)", @@ -281,10 +281,10 @@ "diffDelete": "#fc533a" }, "overrides": { - "background-base": "var(--gray-dark-1)", + "background-base": "#191919", "background-weak": "#1E1E1E", "background-strong": "#181818", - "background-stronger": "#191919", + "background-stronger": "#151515", "surface-base": "var(--gray-dark-alpha-2)", "base": "var(--gray-dark-alpha-2)", "surface-base-hover": "#e0b7b716", @@ -308,7 +308,7 @@ "surface-weak": "var(--gray-dark-alpha-4)", "surface-weaker": "var(--gray-dark-alpha-5)", "surface-strong": "var(--gray-dark-alpha-7)", - "surface-raised-stronger-non-alpha": "var(--gray-dark-3)", + "surface-raised-stronger-non-alpha": "var(--gray-dark-2)", "surface-brand-base": "var(--yuzu-light-9)", "surface-brand-hover": "var(--yuzu-light-10)", "surface-interactive-base": "var(--cobalt-dark-3)", From 1f9be63e962374e2a0c668d8098b4dccb4d0b79a Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 17:32:46 +0000 Subject: [PATCH 46/88] tweak(ui): use weak border and base icon color for secondary --- packages/ui/src/components/button.css | 4 ++-- packages/ui/src/components/icon-button.css | 2 +- packages/ui/src/components/session-review.tsx | 7 ++++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/ui/src/components/button.css b/packages/ui/src/components/button.css index e22c7b2987..8219ec92b9 100644 --- a/packages/ui/src/components/button.css +++ b/packages/ui/src/components/button.css @@ -76,7 +76,7 @@ border: transparent; background-color: var(--button-secondary-base); color: var(--text-strong); - box-shadow: var(--shadow-xs-border); + box-shadow: var(--shadow-xs-border-base); &:hover:not(:disabled) { background-color: var(--button-secondary-hover); @@ -104,7 +104,7 @@ } [data-slot="icon-svg"] { - color: var(--icon-strong-base); + color: var(--icon-base); } } diff --git a/packages/ui/src/components/icon-button.css b/packages/ui/src/components/icon-button.css index 01c555bfc7..de8aeb9d49 100644 --- a/packages/ui/src/components/icon-button.css +++ b/packages/ui/src/components/icon-button.css @@ -45,7 +45,7 @@ border: transparent; background-color: var(--button-secondary-base); color: var(--text-strong); - box-shadow: var(--shadow-xs-border); + box-shadow: var(--shadow-xs-border-base); &:hover:not(:disabled) { background-color: var(--button-secondary-hover); diff --git a/packages/ui/src/components/session-review.tsx b/packages/ui/src/components/session-review.tsx index 6ab922262b..1fdc2ede10 100644 --- a/packages/ui/src/components/session-review.tsx +++ b/packages/ui/src/components/session-review.tsx @@ -306,7 +306,12 @@ export const SessionReview = (props: SessionReviewProps) => { /> - + )} From c7a79f1877d0f13f194db5e072f2ee4cef5e174a Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 19:36:38 +0000 Subject: [PATCH 56/88] Update icon-button.css --- packages/ui/src/components/icon-button.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ui/src/components/icon-button.css b/packages/ui/src/components/icon-button.css index de8aeb9d49..7a47270fe9 100644 --- a/packages/ui/src/components/icon-button.css +++ b/packages/ui/src/components/icon-button.css @@ -84,23 +84,23 @@ } &:hover:not(:disabled) { - background-color: var(--surface-raised-base-hover); + background-color: var(--surface-base-hover); /* [data-slot="icon-svg"] { */ /* color: var(--icon-hover); */ /* } */ } &:focus-visible:not(:disabled) { - background-color: var(--surface-raised-base-hover); + background-color: var(--surface-base-hover); } &:active:not(:disabled) { - background-color: var(--surface-raised-base-active); + background-color: var(--surface-base-active); /* [data-slot="icon-svg"] { */ /* color: var(--icon-active); */ /* } */ } &:selected:not(:disabled) { - background-color: var(--surface-raised-base-active); + background-color: var(--surface-base-active); /* [data-slot="icon-svg"] { */ /* color: var(--icon-selected); */ /* } */ From e42cc8511299ce1a9f311d3446b03747823a23fc Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 19:36:42 +0000 Subject: [PATCH 57/88] Update oc-2.json --- packages/ui/src/theme/themes/oc-2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ui/src/theme/themes/oc-2.json b/packages/ui/src/theme/themes/oc-2.json index eae31e629e..e12ddc0b9a 100644 --- a/packages/ui/src/theme/themes/oc-2.json +++ b/packages/ui/src/theme/themes/oc-2.json @@ -284,9 +284,9 @@ "base": "var(--gray-dark-alpha-2)", "base2": "var(--gray-dark-alpha-2)", "base3": "var(--gray-dark-alpha-2)", - "background-base": "#191919", + "background-base": "#101010", "background-weak": "#1E1E1E", - "background-strong": "#181818", + "background-strong": "#121212", "background-stronger": "#151515", "surface-base": "var(--gray-dark-alpha-2)", "surface-base-hover": "#FFFFFF0A", From d730d8be01366999f4f453db3b7bddaf7970e0c1 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 19:38:12 +0000 Subject: [PATCH 58/88] tweak(ui): shrink review diff style toggle --- packages/ui/src/components/session-review.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/ui/src/components/session-review.tsx b/packages/ui/src/components/session-review.tsx index 1fdc2ede10..481379d45a 100644 --- a/packages/ui/src/components/session-review.tsx +++ b/packages/ui/src/components/session-review.tsx @@ -298,6 +298,7 @@ export const SessionReview = (props: SessionReviewProps) => { style} label={(style) => i18n.t(style === "unified" ? "ui.sessionReview.diffStyle.unified" : "ui.sessionReview.diffStyle.split") From 1571246ba8f9c0f41889de5516769116aee38692 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 19:39:14 +0000 Subject: [PATCH 59/88] tweak(ui): use default cursor for segmented control --- packages/ui/src/components/radio-group.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/src/components/radio-group.css b/packages/ui/src/components/radio-group.css index 9f7bd5a9ef..1da562b1d5 100644 --- a/packages/ui/src/components/radio-group.css +++ b/packages/ui/src/components/radio-group.css @@ -80,7 +80,7 @@ [data-slot="radio-group-item-label"] { color: var(--text-weak); - cursor: pointer; + cursor: default; display: flex; align-items: center; justify-content: center; From 1b67339e4dd9902b4d59abc444df8d9b52a6b67e Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 19:46:33 +0000 Subject: [PATCH 60/88] Update radio-group.css --- packages/ui/src/components/radio-group.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ui/src/components/radio-group.css b/packages/ui/src/components/radio-group.css index 1da562b1d5..4faaa33f43 100644 --- a/packages/ui/src/components/radio-group.css +++ b/packages/ui/src/components/radio-group.css @@ -38,9 +38,9 @@ } [data-slot="radio-group-indicator"] { - background: var(--surface-raised-stronger-non-alpha); + background: var(--button-secondary-base); border-radius: var(--radius-sm); - box-shadow: var(--shadow-xs-border); + box-shadow: var(--shadow-xs-border-base); content: ""; opacity: var(--indicator-opacity, 1); pointer-events: none; From 06b2304a5f66cc4f72c95900717b674a66b5f308 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 19:46:50 +0000 Subject: [PATCH 61/88] tweak(ui): override for the radio group in the review --- packages/ui/src/components/session-review.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/ui/src/components/session-review.css b/packages/ui/src/components/session-review.css index 46473b75e5..d5ad346e60 100644 --- a/packages/ui/src/components/session-review.css +++ b/packages/ui/src/components/session-review.css @@ -42,6 +42,14 @@ padding-right: 1px; } + [data-slot="session-review-actions"] [data-component="radio-group"] { + [data-slot="radio-group-wrapper"], + [data-slot="radio-group-indicator"], + [data-slot="radio-group-item-control"] { + border-radius: 6px; + } + } + [data-component="sticky-accordion-header"] { top: 40px; } From 31e964e7cf4f83abec80640bb1f70a950615c595 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 19:46:54 +0000 Subject: [PATCH 62/88] Update oc-2.json --- packages/ui/src/theme/themes/oc-2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ui/src/theme/themes/oc-2.json b/packages/ui/src/theme/themes/oc-2.json index e12ddc0b9a..b6c0a3aa77 100644 --- a/packages/ui/src/theme/themes/oc-2.json +++ b/packages/ui/src/theme/themes/oc-2.json @@ -116,7 +116,7 @@ "text-on-brand-weaker": "var(--gray-light-alpha-8)", "text-on-brand-strong": "var(--gray-light-alpha-12)", "button-primary-base": "var(--gray-light-12)", - "button-secondary-base": "var(--gray-light-alpha-2)", + "button-secondary-base": "var(--gray-light-1)", "button-secondary-hover": "FFFFFF0A", "border-base": "var(--gray-light-alpha-7)", "border-hover": "var(--gray-light-alpha-8)", @@ -382,7 +382,7 @@ "text-on-brand-weaker": "var(--gray-dark-alpha-8)", "text-on-brand-strong": "var(--gray-dark-alpha-12)", "button-primary-base": "var(--gray-dark-12)", - "button-secondary-base": "var(--gray-dark-alpha-2)", + "button-secondary-base": "var(--gray-dark-2)", "button-secondary-hover": "#FFFFFF0A", "border-base": "var(--gray-dark-alpha-7)", "border-hover": "var(--gray-dark-alpha-8)", From bb6d1d502fb9afb034da2c20078e6d4b5f9c6e2f Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 19:49:50 +0000 Subject: [PATCH 63/88] tweak(ui): adjust review diff style hover radius --- packages/ui/src/components/session-review.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/ui/src/components/session-review.css b/packages/ui/src/components/session-review.css index d5ad346e60..5f42d1dc16 100644 --- a/packages/ui/src/components/session-review.css +++ b/packages/ui/src/components/session-review.css @@ -48,6 +48,12 @@ [data-slot="radio-group-item-control"] { border-radius: 6px; } + + [data-slot="radio-group-item-input"]:not([data-checked], [data-disabled]) + + [data-slot="radio-group-item-label"]:hover + [data-slot="radio-group-item-control"] { + border-radius: 4px; + } } [data-component="sticky-accordion-header"] { From 47b4de3531ac8f32f90be3f867dba02120d2b83a Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 19:50:48 +0000 Subject: [PATCH 64/88] tweak(ui): tighten review header action spacing --- packages/ui/src/components/session-review.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/src/components/session-review.css b/packages/ui/src/components/session-review.css index 5f42d1dc16..c618ed58c8 100644 --- a/packages/ui/src/components/session-review.css +++ b/packages/ui/src/components/session-review.css @@ -38,7 +38,7 @@ [data-slot="session-review-actions"] { display: flex; align-items: center; - column-gap: 16px; + column-gap: 12px; padding-right: 1px; } From ba919fb619312c4c77865d4506d5a400d2abca26 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 18 Feb 2026 19:51:46 +0000 Subject: [PATCH 65/88] tweak(ui): shrink review expand/collapse width --- packages/ui/src/components/session-review.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/src/components/session-review.tsx b/packages/ui/src/components/session-review.tsx index 481379d45a..2a8685fac2 100644 --- a/packages/ui/src/components/session-review.tsx +++ b/packages/ui/src/components/session-review.tsx @@ -310,7 +310,7 @@ export const SessionReview = (props: SessionReviewProps) => {