From d75d90c53e9c4aff82d70e9af1fb2b01a676d7ab Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Sun, 23 Nov 2025 01:35:19 -0600 Subject: [PATCH 01/66] ci: fix action --- .github/workflows/duplicate-issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/duplicate-issues.yml b/.github/workflows/duplicate-issues.yml index 23dc9d39a82..3b5c39193f9 100644 --- a/.github/workflows/duplicate-issues.yml +++ b/.github/workflows/duplicate-issues.yml @@ -21,7 +21,7 @@ jobs: - name: Check for duplicate issues env: - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} OPENCODE_PERMISSION: | { From 7d11986a0a2ac0386a4289a4b05c6ea5fc598ba6 Mon Sep 17 00:00:00 2001 From: Ariane Emory <97994360+ariane-emory@users.noreply.github.com> Date: Sun, 23 Nov 2025 02:51:07 -0500 Subject: [PATCH 02/66] feature: optional selectedListItemText element in themes and luminance-based fallback to solve 4369 (#4572) Co-authored-by: knanao Co-authored-by: knanao --- .../cmd/tui/component/prompt/autocomplete.tsx | 8 +-- .../cli/cmd/tui/component/prompt/index.tsx | 15 ++-- .../src/cli/cmd/tui/context/theme.tsx | 71 ++++++++++++++++--- .../src/cli/cmd/tui/ui/dialog-alert.tsx | 2 +- .../src/cli/cmd/tui/ui/dialog-confirm.tsx | 4 +- .../src/cli/cmd/tui/ui/dialog-help.tsx | 2 +- .../src/cli/cmd/tui/ui/dialog-select.tsx | 17 ++--- packages/web/public/theme.json | 1 + 8 files changed, 90 insertions(+), 30 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index 3029eafcce3..8371c395fbe 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -5,7 +5,7 @@ import { createMemo, createResource, createEffect, onMount, For, Show } from "so import { createStore } from "solid-js/store" import { useSDK } from "@tui/context/sdk" import { useSync } from "@tui/context/sync" -import { useTheme } from "@tui/context/theme" +import { useTheme, selectedForeground } from "@tui/context/theme" import { SplitBorder } from "@tui/component/border" import { useCommandDialog } from "@tui/component/dialog-command" import { Locale } from "@/util/locale" @@ -455,7 +455,7 @@ export function Autocomplete(props: { {...SplitBorder} borderColor={theme.border} > - + - + {option.display} - + {option.description} 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 b04cb7c6043..f2e97ff2324 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -791,10 +791,17 @@ export function Prompt(props: PromptProps) { height={1} border={["bottom"]} borderColor={theme.backgroundElement} - customBorderChars={{ - ...EmptyBorder, - horizontal: "▀", - }} + customBorderChars={ + theme.background.a != 0 + ? { + ...EmptyBorder, + horizontal: "▀", + } + : { + ...EmptyBorder, + horizontal: " ", + } + } /> diff --git a/packages/opencode/src/cli/cmd/tui/context/theme.tsx b/packages/opencode/src/cli/cmd/tui/context/theme.tsx index abca5ba2aac..4e3cc35315e 100644 --- a/packages/opencode/src/cli/cmd/tui/context/theme.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/theme.tsx @@ -33,7 +33,7 @@ import { createStore, produce } from "solid-js/store" import { Global } from "@/global" import { Filesystem } from "@/util/filesystem" -type Theme = { +type ThemeColors = { primary: RGBA secondary: RGBA accent: RGBA @@ -43,9 +43,11 @@ type Theme = { info: RGBA text: RGBA textMuted: RGBA + selectedListItemText: RGBA background: RGBA backgroundPanel: RGBA backgroundElement: RGBA + backgroundMenu: RGBA border: RGBA borderActive: RGBA borderSubtle: RGBA @@ -86,6 +88,27 @@ type Theme = { syntaxPunctuation: RGBA } +type Theme = ThemeColors & { + _hasSelectedListItemText: boolean +} + +export function selectedForeground(theme: Theme): RGBA { + // If theme explicitly defines selectedListItemText, use it + if (theme._hasSelectedListItemText) { + return theme.selectedListItemText + } + + // For transparent backgrounds, calculate contrast based on primary color + if (theme.background.a === 0) { + const { r, g, b } = theme.primary + const luminance = 0.299 * r + 0.587 * g + 0.114 * b + return luminance > 0.5 ? RGBA.fromInts(0, 0, 0) : RGBA.fromInts(255, 255, 255) + } + + // Fall back to background color + return theme.background +} + type HexColor = `#${string}` type RefName = string type Variant = { @@ -96,7 +119,10 @@ type ColorValue = HexColor | RefName | Variant | RGBA type ThemeJson = { $schema?: string defs?: Record - theme: Record + theme: Omit, "selectedListItemText" | "backgroundMenu"> & { + selectedListItemText?: ColorValue + backgroundMenu?: ColorValue + } } export const DEFAULT_THEMES: Record = { @@ -137,19 +163,44 @@ function resolveTheme(theme: ThemeJson, mode: "dark" | "light") { if (defs[c]) { return resolveColor(defs[c]) - } else if (theme.theme[c as keyof Theme]) { - return resolveColor(theme.theme[c as keyof Theme]) + } else if (theme.theme[c as keyof ThemeColors] !== undefined) { + return resolveColor(theme.theme[c as keyof ThemeColors]!) } else { throw new Error(`Color reference "${c}" not found in defs or theme`) } } return resolveColor(c[mode]) } - return Object.fromEntries( - Object.entries(theme.theme).map(([key, value]) => { - return [key, resolveColor(value)] - }), - ) as Theme + + const resolved = Object.fromEntries( + Object.entries(theme.theme) + .filter(([key]) => key !== "selectedListItemText" && key !== "backgroundMenu") + .map(([key, value]) => { + return [key, resolveColor(value)] + }), + ) as Partial + + // Handle selectedListItemText separately since it's optional + const hasSelectedListItemText = theme.theme.selectedListItemText !== undefined + if (hasSelectedListItemText) { + resolved.selectedListItemText = resolveColor(theme.theme.selectedListItemText!) + } else { + // Backward compatibility: if selectedListItemText is not defined, use background color + // This preserves the current behavior for all existing themes + resolved.selectedListItemText = resolved.background + } + + // Handle backgroundMenu - optional with fallback to backgroundElement + if (theme.theme.backgroundMenu !== undefined) { + resolved.backgroundMenu = resolveColor(theme.theme.backgroundMenu) + } else { + resolved.backgroundMenu = resolved.backgroundElement + } + + return { + ...resolved, + _hasSelectedListItemText: hasSelectedListItemText, + } as Theme } export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({ @@ -288,11 +339,13 @@ function generateSystem(colors: TerminalColors, mode: "dark" | "light"): ThemeJs // Text colors text: fg, textMuted, + selectedListItemText: bg, // Background colors background: bg, backgroundPanel: grays[2], backgroundElement: grays[3], + backgroundMenu: grays[3], // Border colors borderSubtle: grays[6], diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-alert.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-alert.tsx index 6bb59d6c7bd..96ef982d7f2 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-alert.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-alert.tsx @@ -38,7 +38,7 @@ export function DialogAlert(props: DialogAlertProps) { dialog.clear() }} > - ok + ok diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx index dd5b238b11b..9d0e7d2c74f 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx @@ -53,7 +53,9 @@ export function DialogConfirm(props: DialogConfirmProps) { dialog.clear() }} > - {Locale.titlecase(key)} + + {Locale.titlecase(key)} + )} diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-help.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-help.tsx index f522fca9eeb..db9648f2c7d 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-help.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-help.tsx @@ -28,7 +28,7 @@ export function DialogHelp() { dialog.clear()}> - ok + ok diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx index b33641ecdaa..987bbd0b941 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx @@ -1,5 +1,5 @@ import { InputRenderable, RGBA, ScrollBoxRenderable, TextAttributes } from "@opentui/core" -import { useTheme } from "@tui/context/theme" +import { useTheme, selectedForeground } from "@tui/context/theme" import { entries, filter, flatMap, groupBy, pipe, take } from "remeda" import { batch, createEffect, createMemo, For, Show, type JSX } from "solid-js" import { createStore } from "solid-js/store" @@ -262,32 +262,29 @@ function Option(props: { onMouseOver?: () => void }) { const { theme } = useTheme() + const fg = selectedForeground(theme) return ( <> - - ◆ + + ● {Locale.truncate(props.title, 62)} - {props.description} + {props.description} - {props.footer} + {props.footer} diff --git a/packages/web/public/theme.json b/packages/web/public/theme.json index b3e97f7ca89..7c80776344f 100644 --- a/packages/web/public/theme.json +++ b/packages/web/public/theme.json @@ -46,6 +46,7 @@ "info": { "$ref": "#/definitions/colorValue" }, "text": { "$ref": "#/definitions/colorValue" }, "textMuted": { "$ref": "#/definitions/colorValue" }, + "selectedListItemText": { "$ref": "#/definitions/colorValue" }, "background": { "$ref": "#/definitions/colorValue" }, "backgroundPanel": { "$ref": "#/definitions/colorValue" }, "backgroundElement": { "$ref": "#/definitions/colorValue" }, From 55df80b80e93e5061ef8d3671324b047dbd334cd Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sun, 23 Nov 2025 12:04:01 +0000 Subject: [PATCH 03/66] ignore: update download stats 2025-11-23 --- STATS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/STATS.md b/STATS.md index 20ae6fbc9f8..1664627fef0 100644 --- a/STATS.md +++ b/STATS.md @@ -148,3 +148,4 @@ | 2025-11-20 | 814,620 (+10,211) | 757,907 (+10,283) | 1,572,527 (+20,494) | | 2025-11-21 | 826,309 (+11,689) | 769,307 (+11,400) | 1,595,616 (+23,089) | | 2025-11-22 | 837,269 (+10,960) | 780,996 (+11,689) | 1,618,265 (+22,649) | +| 2025-11-23 | 846,609 (+9,340) | 795,069 (+14,073) | 1,641,678 (+23,413) | From af96ec5a30dd2808f56539ae79904d1f353b6403 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sun, 23 Nov 2025 12:07:28 -0500 Subject: [PATCH 04/66] ignore: update @solidjs/start dependency and fix console redirect handling Updates the @solidjs/start dependency to latest version and removes deprecated getResponseHeaders usage from auth callback. Also adds error handling for workspace ID lookup to prevent redirect failures. --- bun.lock | 52 ++++++------------- package.json | 2 +- .../console/app/src/routes/auth/callback.ts | 6 +-- packages/console/app/src/routes/zen/index.tsx | 2 +- 4 files changed, 20 insertions(+), 42 deletions(-) diff --git a/bun.lock b/bun.lock index b2562dcc0e1..6cef39c61d3 100644 --- a/bun.lock +++ b/bun.lock @@ -437,7 +437,7 @@ "@pierre/precision-diffs": "0.5.4", "@solidjs/meta": "0.29.4", "@solidjs/router": "0.15.4", - "@solidjs/start": "https://pkg.pr.new/@solidjs/start@dbff19d", + "@solidjs/start": "https://pkg.pr.new/@solidjs/start@3643ff3", "@tailwindcss/vite": "4.1.11", "@tsconfig/bun": "1.0.9", "@tsconfig/node22": "22.0.2", @@ -1497,7 +1497,7 @@ "@solidjs/router": ["@solidjs/router@0.15.4", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-WOpgg9a9T638cR+5FGbFi/IV4l2FpmBs1GpIMSPa0Ce9vyJN7Wts+X2PqMf9IYn0zUj2MlSJtm1gp7/HI/n5TQ=="], - "@solidjs/start": ["@solidjs/start@https://pkg.pr.new/@solidjs/start@dbff19d", { "dependencies": { "@babel/core": "^7.28.3", "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.5", "@solidjs/meta": "^0.29.4", "@tanstack/server-functions-plugin": "1.134.5", "@types/babel__traverse": "^7.28.0", "@types/micromatch": "^4.0.9", "cookie-es": "^2.0.0", "defu": "^6.1.4", "error-stack-parser": "^2.1.4", "es-module-lexer": "^1.7.0", "esbuild": "^0.25.3", "fast-glob": "^3.3.3", "h3": "npm:h3@2.0.1-rc.4", "html-to-image": "^1.11.13", "micromatch": "^4.0.8", "path-to-regexp": "^8.2.0", "pathe": "^2.0.3", "radix3": "^1.1.2", "seroval": "^1.3.2", "seroval-plugins": "^1.2.1", "shiki": "^1.26.1", "solid-js": "^1.9.9", "source-map-js": "^1.2.1", "srvx": "^0.9.1", "terracotta": "^1.0.6", "vite": "7.1.10", "vite-plugin-solid": "^2.11.9", "vitest": "3.0.5" } }], + "@solidjs/start": ["@solidjs/start@https://pkg.pr.new/@solidjs/start@3643ff3", { "dependencies": { "@babel/core": "^7.28.3", "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.5", "@solidjs/meta": "^0.29.4", "@tanstack/server-functions-plugin": "1.134.5", "@types/babel__traverse": "^7.28.0", "@types/micromatch": "^4.0.9", "cookie-es": "^2.0.0", "defu": "^6.1.4", "error-stack-parser": "^2.1.4", "es-module-lexer": "^1.7.0", "esbuild": "^0.25.3", "fast-glob": "^3.3.3", "h3": "npm:h3@2.0.1-rc.4", "html-to-image": "^1.11.13", "micromatch": "^4.0.8", "path-to-regexp": "^8.2.0", "pathe": "^2.0.3", "radix3": "^1.1.2", "seroval": "^1.3.2", "seroval-plugins": "^1.2.1", "shiki": "^1.26.1", "solid-js": "^1.9.9", "source-map-js": "^1.2.1", "srvx": "^0.9.1", "terracotta": "^1.0.6", "vite": "7.1.10", "vite-plugin-solid": "^2.11.9", "vitest": "^4.0.10" } }], "@speed-highlight/core": ["@speed-highlight/core@1.2.12", "", {}, "sha512-uilwrK0Ygyri5dToHYdZSjcvpS2ZwX0w5aSt3GCEN9hrjxWCoeV4Z2DTXuxjwbntaLQIEEAlCeNQss5SoHvAEA=="], @@ -1597,10 +1597,14 @@ "@types/bun": ["@types/bun@1.3.3", "", { "dependencies": { "bun-types": "1.3.3" } }, "sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g=="], + "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], + "@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="], "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], + "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], @@ -1695,19 +1699,19 @@ "@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="], - "@vitest/expect": ["@vitest/expect@3.0.5", "", { "dependencies": { "@vitest/spy": "3.0.5", "@vitest/utils": "3.0.5", "chai": "^5.1.2", "tinyrainbow": "^2.0.0" } }, "sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA=="], + "@vitest/expect": ["@vitest/expect@4.0.13", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.0.13", "@vitest/utils": "4.0.13", "chai": "^6.2.1", "tinyrainbow": "^3.0.3" } }, "sha512-zYtcnNIBm6yS7Gpr7nFTmq8ncowlMdOJkWLqYvhr/zweY6tFbDkDi8BPPOeHxEtK1rSI69H7Fd4+1sqvEGli6w=="], - "@vitest/mocker": ["@vitest/mocker@3.0.5", "", { "dependencies": { "@vitest/spy": "3.0.5", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw=="], + "@vitest/mocker": ["@vitest/mocker@4.0.13", "", { "dependencies": { "@vitest/spy": "4.0.13", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-eNCwzrI5djoauklwP1fuslHBjrbR8rqIVbvNlAnkq1OTa6XT+lX68mrtPirNM9TnR69XUPt4puBCx2Wexseylg=="], - "@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="], + "@vitest/pretty-format": ["@vitest/pretty-format@4.0.13", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-ooqfze8URWbI2ozOeLDMh8YZxWDpGXoeY3VOgcDnsUxN0jPyPWSUvjPQWqDGCBks+opWlN1E4oP1UYl3C/2EQA=="], - "@vitest/runner": ["@vitest/runner@3.0.5", "", { "dependencies": { "@vitest/utils": "3.0.5", "pathe": "^2.0.2" } }, "sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A=="], + "@vitest/runner": ["@vitest/runner@4.0.13", "", { "dependencies": { "@vitest/utils": "4.0.13", "pathe": "^2.0.3" } }, "sha512-9IKlAru58wcVaWy7hz6qWPb2QzJTKt+IOVKjAx5vb5rzEFPTL6H4/R9BMvjZ2ppkxKgTrFONEJFtzvnyEpiT+A=="], - "@vitest/snapshot": ["@vitest/snapshot@3.0.5", "", { "dependencies": { "@vitest/pretty-format": "3.0.5", "magic-string": "^0.30.17", "pathe": "^2.0.2" } }, "sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA=="], + "@vitest/snapshot": ["@vitest/snapshot@4.0.13", "", { "dependencies": { "@vitest/pretty-format": "4.0.13", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-hb7Usvyika1huG6G6l191qu1urNPsq1iFc2hmdzQY3F5/rTgqQnwwplyf8zoYHkpt7H6rw5UfIw6i/3qf9oSxQ=="], - "@vitest/spy": ["@vitest/spy@3.0.5", "", { "dependencies": { "tinyspy": "^3.0.2" } }, "sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg=="], + "@vitest/spy": ["@vitest/spy@4.0.13", "", {}, "sha512-hSu+m4se0lDV5yVIcNWqjuncrmBgwaXa2utFLIrBkQCQkt+pSwyZTPFQAZiiF/63j8jYa8uAeUZ3RSfcdWaYWw=="], - "@vitest/utils": ["@vitest/utils@3.0.5", "", { "dependencies": { "@vitest/pretty-format": "3.0.5", "loupe": "^3.1.2", "tinyrainbow": "^2.0.0" } }, "sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg=="], + "@vitest/utils": ["@vitest/utils@4.0.13", "", { "dependencies": { "@vitest/pretty-format": "4.0.13", "tinyrainbow": "^3.0.3" } }, "sha512-ydozWyQ4LZuu8rLp47xFUWis5VOKMdHjXCWhs1LuJsTNKww+pTHQNK4e0assIB9K80TxFyskENL6vCu3j34EYA=="], "@webgpu/types": ["@webgpu/types@0.1.66", "", {}, "sha512-YA2hLrwLpDsRueNDXIMqN9NTzD6bCDkuXbOSe0heS+f8YE8usA6Gbv1prj81pzVHrbaAma7zObnIC+I6/sXJgA=="], @@ -1891,8 +1895,6 @@ "c12": ["c12@2.0.1", "", { "dependencies": { "chokidar": "^4.0.1", "confbox": "^0.1.7", "defu": "^6.1.4", "dotenv": "^16.4.5", "giget": "^1.2.3", "jiti": "^2.3.0", "mlly": "^1.7.1", "ohash": "^1.1.4", "pathe": "^1.1.2", "perfect-debounce": "^1.0.0", "pkg-types": "^1.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-Z4JgsKXHG37C6PYUtIxCfLJZvo6FyhHJoClwwb9ftUkLpPSkuYqn6Tr+vnaN8hymm0kIbcg6Ey3kv/Q71k5w/A=="], - "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], - "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], @@ -1909,7 +1911,7 @@ "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], - "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="], + "chai": ["chai@6.2.1", "", {}, "sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg=="], "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -1923,8 +1925,6 @@ "chart.js": ["chart.js@4.5.1", "", { "dependencies": { "@kurkle/color": "^0.3.0" } }, "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw=="], - "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], - "cheerio": ["cheerio@1.0.0-rc.12", "", { "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "domutils": "^3.0.1", "htmlparser2": "^8.0.1", "parse5": "^7.0.0", "parse5-htmlparser2-tree-adapter": "^7.0.0" } }, "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q=="], "cheerio-select": ["cheerio-select@2.1.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", "css-what": "^6.1.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1" } }, "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g=="], @@ -2029,8 +2029,6 @@ "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], - "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], - "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="], "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], @@ -2677,8 +2675,6 @@ "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], - "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="], - "lower-case": ["lower-case@2.0.2", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg=="], "lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], @@ -3021,8 +3017,6 @@ "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - "pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="], - "peberminta": ["peberminta@0.9.0", "", {}, "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ=="], "peek-readable": ["peek-readable@4.1.0", "", {}, "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg=="], @@ -3447,11 +3441,7 @@ "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], - "tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="], - - "tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="], - - "tinyspy": ["tinyspy@3.0.2", "", {}, "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q=="], + "tinyrainbow": ["tinyrainbow@3.0.3", "", {}, "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q=="], "titleize": ["titleize@4.0.0", "", {}, "sha512-ZgUJ1K83rhdu7uh7EHAC2BgY5DzoX8V5rTvoWI4vFysggi6YjLe5gUXABPWAU7VkvGP7P/0YiWq+dcPeYDsf1g=="], @@ -3605,8 +3595,6 @@ "vite": ["vite@7.1.4", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw=="], - "vite-node": ["vite-node@3.0.5", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.6.0", "pathe": "^2.0.2", "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A=="], - "vite-plugin-dynamic-import": ["vite-plugin-dynamic-import@1.6.0", "", { "dependencies": { "acorn": "^8.12.1", "es-module-lexer": "^1.5.4", "fast-glob": "^3.3.2", "magic-string": "^0.30.11" } }, "sha512-TM0sz70wfzTIo9YCxVFwS8OA9lNREsh+0vMHGSkWDTZ7bgd1Yjs5RV8EgB634l/91IsXJReg0xtmuQqP0mf+rg=="], "vite-plugin-icons-spritesheet": ["vite-plugin-icons-spritesheet@3.0.1", "", { "dependencies": { "chalk": "^5.4.1", "glob": "^11.0.1", "node-html-parser": "^7.0.1", "tinyexec": "^0.3.2" }, "peerDependencies": { "vite": ">=5.2.0" } }, "sha512-Cr0+Z6wRMwSwKisWW9PHeTjqmQFv0jwRQQMc3YgAhAgZEe03j21el0P/CA31KN/L5eiL1LhR14VTXl96LetonA=="], @@ -3615,7 +3603,7 @@ "vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="], - "vitest": ["vitest@3.0.5", "", { "dependencies": { "@vitest/expect": "3.0.5", "@vitest/mocker": "3.0.5", "@vitest/pretty-format": "^3.0.5", "@vitest/runner": "3.0.5", "@vitest/snapshot": "3.0.5", "@vitest/spy": "3.0.5", "@vitest/utils": "3.0.5", "chai": "^5.1.2", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", "pathe": "^2.0.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", "vite-node": "3.0.5", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.0.5", "@vitest/ui": "3.0.5", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q=="], + "vitest": ["vitest@4.0.13", "", { "dependencies": { "@vitest/expect": "4.0.13", "@vitest/mocker": "4.0.13", "@vitest/pretty-format": "4.0.13", "@vitest/runner": "4.0.13", "@vitest/snapshot": "4.0.13", "@vitest/spy": "4.0.13", "@vitest/utils": "4.0.13", "debug": "^4.4.3", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.21", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.10.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/debug": "^4.1.12", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.0.13", "@vitest/browser-preview": "4.0.13", "@vitest/browser-webdriverio": "4.0.13", "@vitest/ui": "4.0.13", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/debug", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-QSD4I0fN6uZQfftryIXuqvqgBxTvJ3ZNkF6RWECd82YGAYAfhcppBLFXzXJHQAAhVFyYEuFTrq6h0hQqjB7jIQ=="], "vscode-jsonrpc": ["vscode-jsonrpc@8.2.1", "", {}, "sha512-kdjOSJ2lLIn7r1rtrMbbNCHjyMPfRnowdKjBQ+mGq6NAW5QY2bEZC/khaC5OR8svbbjvLEaIXkOq45e2X9BIbQ=="], @@ -3941,10 +3929,6 @@ "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "@vitest/snapshot/@vitest/pretty-format": ["@vitest/pretty-format@3.0.5", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA=="], - - "@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@3.0.5", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA=="], - "accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], "ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "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-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="], @@ -4147,11 +4131,9 @@ "utif2/pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="], - "vite-node/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="], - "vite-plugin-icons-spritesheet/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], - "vitest/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="], + "vitest/vite": ["vite@7.1.10", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA=="], "vitest/why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], diff --git a/package.json b/package.json index c464b643b39..8190bad94a6 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "vite": "7.1.4", "@solidjs/meta": "0.29.4", "@solidjs/router": "0.15.4", - "@solidjs/start": "https://pkg.pr.new/@solidjs/start@dbff19d", + "@solidjs/start": "https://pkg.pr.new/@solidjs/start@3643ff3", "solid-js": "1.9.10", "vite-plugin-solid": "2.11.10" } diff --git a/packages/console/app/src/routes/auth/callback.ts b/packages/console/app/src/routes/auth/callback.ts index cdfc8822946..a793b85962a 100644 --- a/packages/console/app/src/routes/auth/callback.ts +++ b/packages/console/app/src/routes/auth/callback.ts @@ -1,5 +1,4 @@ import { redirect } from "@solidjs/router" -import { getResponseHeaders } from "@solidjs/start/http" import type { APIEvent } from "@solidjs/start/server" import { AuthClient } from "~/context/auth" import { useAuthSession } from "~/context/auth.session" @@ -29,8 +28,5 @@ export async function GET(input: APIEvent) { current: id, } }) - return redirect("/auth", { - status: 302, - headers: getResponseHeaders(), - }) + return redirect("/auth") } diff --git a/packages/console/app/src/routes/zen/index.tsx b/packages/console/app/src/routes/zen/index.tsx index 9c93b62dd0b..053f16e5f0c 100644 --- a/packages/console/app/src/routes/zen/index.tsx +++ b/packages/console/app/src/routes/zen/index.tsx @@ -21,7 +21,7 @@ import { getLastSeenWorkspaceID } from "../workspace/common" const checkLoggedIn = query(async () => { "use server" - const workspaceID = await getLastSeenWorkspaceID() + const workspaceID = await getLastSeenWorkspaceID().catch(() => {}) if (workspaceID) throw redirect(`/workspace/${workspaceID}`) }, "checkLoggedIn.get") From a256df98230f8e489461a0124cbdc4d0b6b21391 Mon Sep 17 00:00:00 2001 From: Github Action Date: Sun, 23 Nov 2025 17:09:33 +0000 Subject: [PATCH 05/66] Update Nix flake.lock and hashes --- nix/hashes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/hashes.json b/nix/hashes.json index e2bf82efc29..92bab11a140 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,3 +1,3 @@ { - "nodeModules": "sha256-IKC5nABVIUWryihszkSL+0EKKGQxrFeRn5GZr8DOTpY=" + "nodeModules": "sha256-j36TvDb0FDb1JCKSCVgDJRyvl3kzw3t+vFYJjw6vT8M=" } From 2509d03f42e86316ba05880514a4c637a148f945 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Sun, 23 Nov 2025 11:43:09 -0600 Subject: [PATCH 06/66] tweak: fix bool --- packages/opencode/src/session/prompt.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index 08c3d7809ab..e9827a09952 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -197,7 +197,7 @@ export namespace SessionPrompt { const message = await createUserMessage(input) await Session.touch(input.sessionID) - if (input.noReply) { + if (input.noReply === true) { return message } From 5814df7eaa8235e2af5657c155bfcdb3c7b72aae Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sun, 23 Nov 2025 12:18:47 -0500 Subject: [PATCH 07/66] sync --- package.json | 3 --- packages/console/app/src/routes/auth/logout.ts | 6 +----- patches/@solidjs%2Fstart@1.1.7.patch | 18 ------------------ 3 files changed, 1 insertion(+), 26 deletions(-) delete mode 100644 patches/@solidjs%2Fstart@1.1.7.patch diff --git a/package.json b/package.json index 8190bad94a6..9668bc3a130 100644 --- a/package.json +++ b/package.json @@ -82,9 +82,6 @@ "tree-sitter-bash", "web-tree-sitter" ], - "patchedDependencies": { - "@solidjs/start@1.1.7": "patches/@solidjs%2Fstart@1.1.7.patch" - }, "overrides": { "@types/bun": "catalog:", "@types/node": "catalog:" diff --git a/packages/console/app/src/routes/auth/logout.ts b/packages/console/app/src/routes/auth/logout.ts index 00a63f0c688..7fbe5199a74 100644 --- a/packages/console/app/src/routes/auth/logout.ts +++ b/packages/console/app/src/routes/auth/logout.ts @@ -1,6 +1,5 @@ import { redirect } from "@solidjs/router" import { APIEvent } from "@solidjs/start" -import { getResponseHeaders } from "@solidjs/start/http" import { useAuthSession } from "~/context/auth.session" export async function GET(event: APIEvent) { @@ -14,8 +13,5 @@ export async function GET(event: APIEvent) { event!.locals.actor = undefined return val }) - return redirect("/zen", { - status: 302, - headers: getResponseHeaders(), - }) + return redirect("/zen") } diff --git a/patches/@solidjs%2Fstart@1.1.7.patch b/patches/@solidjs%2Fstart@1.1.7.patch deleted file mode 100644 index 6cb6201247e..00000000000 --- a/patches/@solidjs%2Fstart@1.1.7.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff --git a/dist/server/StartServer.jsx b/dist/server/StartServer.jsx -index 0c6a9fe3121a88520db252570a8b5997a36e0452..b3479cdb78c70d7a655d302d8e6ab536b4ff07a3 100644 ---- a/dist/server/StartServer.jsx -+++ b/dist/server/StartServer.jsx -@@ -52,11 +52,11 @@ export function StartServer(props) { - else if (import.meta.env.DEV) - console.warn("No route matched for preloading js assets"); - } -- assets = await Promise.all(assetPromises).then(a => -+ assets = await Promise.all(assetPromises).then(a => - // dedupe assets - [...new Map(a.flat().map(item => [item.attrs.key, item])).values()].filter(asset => import.meta.env.START_ISLANDS - ? false -- : asset.attrs.rel === "modulepreload" && -+ : (asset.attrs.rel === "modulepreload" || asset.attrs.rel === "stylesheet") && - !context.assets.find((a) => a.attrs.key === asset.attrs.key))); - }); - useAssets(() => (assets.length ? assets.map(m => renderAsset(m)) : undefined)); From 604891e793b09fa78e157d769aaecd250881efb9 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sun, 23 Nov 2025 12:43:10 -0500 Subject: [PATCH 08/66] ci: stuff --- bun.lock | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++- package.json | 2 +- 2 files changed, 125 insertions(+), 3 deletions(-) diff --git a/bun.lock b/bun.lock index 6cef39c61d3..b38d0c5d185 100644 --- a/bun.lock +++ b/bun.lock @@ -437,7 +437,7 @@ "@pierre/precision-diffs": "0.5.4", "@solidjs/meta": "0.29.4", "@solidjs/router": "0.15.4", - "@solidjs/start": "https://pkg.pr.new/@solidjs/start@3643ff3", + "@solidjs/start": "https://pkg.pr.new/@solidjs/start@117e0b5", "@tailwindcss/vite": "4.1.11", "@tsconfig/bun": "1.0.9", "@tsconfig/node22": "22.0.2", @@ -759,6 +759,8 @@ "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw=="], + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.4", "", { "os": "sunos", "cpu": "x64" }, "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q=="], "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ=="], @@ -843,6 +845,8 @@ "@internationalized/number": ["@internationalized/number@3.6.5", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g=="], + "@ioredis/commands": ["@ioredis/commands@1.4.0", "", {}, "sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ=="], + "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="], @@ -1497,7 +1501,7 @@ "@solidjs/router": ["@solidjs/router@0.15.4", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-WOpgg9a9T638cR+5FGbFi/IV4l2FpmBs1GpIMSPa0Ce9vyJN7Wts+X2PqMf9IYn0zUj2MlSJtm1gp7/HI/n5TQ=="], - "@solidjs/start": ["@solidjs/start@https://pkg.pr.new/@solidjs/start@3643ff3", { "dependencies": { "@babel/core": "^7.28.3", "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.5", "@solidjs/meta": "^0.29.4", "@tanstack/server-functions-plugin": "1.134.5", "@types/babel__traverse": "^7.28.0", "@types/micromatch": "^4.0.9", "cookie-es": "^2.0.0", "defu": "^6.1.4", "error-stack-parser": "^2.1.4", "es-module-lexer": "^1.7.0", "esbuild": "^0.25.3", "fast-glob": "^3.3.3", "h3": "npm:h3@2.0.1-rc.4", "html-to-image": "^1.11.13", "micromatch": "^4.0.8", "path-to-regexp": "^8.2.0", "pathe": "^2.0.3", "radix3": "^1.1.2", "seroval": "^1.3.2", "seroval-plugins": "^1.2.1", "shiki": "^1.26.1", "solid-js": "^1.9.9", "source-map-js": "^1.2.1", "srvx": "^0.9.1", "terracotta": "^1.0.6", "vite": "7.1.10", "vite-plugin-solid": "^2.11.9", "vitest": "^4.0.10" } }], + "@solidjs/start": ["@solidjs/start@https://pkg.pr.new/@solidjs/start@117e0b5", { "dependencies": { "@babel/core": "^7.28.3", "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.5", "@solidjs/meta": "^0.29.4", "@tanstack/server-functions-plugin": "1.134.5", "@types/babel__traverse": "^7.28.0", "@types/micromatch": "^4.0.9", "cookie-es": "^2.0.0", "defu": "^6.1.4", "error-stack-parser": "^2.1.4", "es-module-lexer": "^1.7.0", "esbuild": "^0.25.3", "fast-glob": "^3.3.3", "h3": "npm:h3@2.0.1-rc.4", "html-to-image": "^1.11.13", "micromatch": "^4.0.8", "path-to-regexp": "^8.2.0", "pathe": "^2.0.3", "radix3": "^1.1.2", "seroval": "^1.3.2", "seroval-plugins": "^1.2.1", "shiki": "^1.26.1", "solid-js": "^1.9.9", "source-map-js": "^1.2.1", "srvx": "^0.9.1", "terracotta": "^1.0.6", "vite": "7.1.10", "vite-plugin-solid": "^2.11.9", "vitest": "^4.0.10" } }], "@speed-highlight/core": ["@speed-highlight/core@1.2.12", "", {}, "sha512-uilwrK0Ygyri5dToHYdZSjcvpS2ZwX0w5aSt3GCEN9hrjxWCoeV4Z2DTXuxjwbntaLQIEEAlCeNQss5SoHvAEA=="], @@ -1953,6 +1957,8 @@ "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + "cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="], + "collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="], "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], @@ -2465,6 +2471,8 @@ "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], + "ioredis": ["ioredis@5.8.2", "", { "dependencies": { "@ioredis/commands": "1.4.0", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q=="], + "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], "iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="], @@ -2653,8 +2661,12 @@ "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + "lodash.defaults": ["lodash.defaults@4.2.0", "", {}, "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="], + "lodash.includes": ["lodash.includes@4.3.0", "", {}, "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="], + "lodash.isarguments": ["lodash.isarguments@3.1.0", "", {}, "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="], + "lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="], "lodash.isinteger": ["lodash.isinteger@4.0.4", "", {}, "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="], @@ -3143,6 +3155,10 @@ "recma-stringify": ["recma-stringify@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-to-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g=="], + "redis-errors": ["redis-errors@1.2.0", "", {}, "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="], + + "redis-parser": ["redis-parser@3.0.0", "", { "dependencies": { "redis-errors": "^1.0.0" } }, "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A=="], + "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], "regex": ["regex@6.0.1", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA=="], @@ -3351,6 +3367,8 @@ "stage-js": ["stage-js@1.0.0-alpha.17", "", {}, "sha512-AzlMO+t51v6cFvKZ+Oe9DJnL1OXEH5s9bEy6di5aOrUpcP7PCzI/wIeXF0u3zg0L89gwnceoKxrLId0ZpYnNXw=="], + "standard-as-callback": ["standard-as-callback@2.1.0", "", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="], + "statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="], @@ -3911,6 +3929,8 @@ "@slack/web-api/p-queue": ["p-queue@6.6.2", "", { "dependencies": { "eventemitter3": "^4.0.4", "p-timeout": "^3.2.0" } }, "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ=="], + "@solidjs/start/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + "@solidjs/start/path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="], "@solidjs/start/shiki": ["shiki@1.29.2", "", { "dependencies": { "@shikijs/core": "1.29.2", "@shikijs/engine-javascript": "1.29.2", "@shikijs/engine-oniguruma": "1.29.2", "@shikijs/langs": "1.29.2", "@shikijs/themes": "1.29.2", "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg=="], @@ -4421,6 +4441,56 @@ "@slack/web-api/p-queue/p-timeout": ["p-timeout@3.2.0", "", { "dependencies": { "p-finally": "^1.0.0" } }, "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg=="], + "@solidjs/start/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], + + "@solidjs/start/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], + + "@solidjs/start/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], + + "@solidjs/start/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], + + "@solidjs/start/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], + + "@solidjs/start/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], + + "@solidjs/start/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], + + "@solidjs/start/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], + + "@solidjs/start/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], + + "@solidjs/start/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], + + "@solidjs/start/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], + + "@solidjs/start/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], + + "@solidjs/start/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], + + "@solidjs/start/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], + + "@solidjs/start/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], + + "@solidjs/start/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], + + "@solidjs/start/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], + + "@solidjs/start/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], + + "@solidjs/start/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], + + "@solidjs/start/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], + + "@solidjs/start/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], + + "@solidjs/start/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], + + "@solidjs/start/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], + + "@solidjs/start/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], + + "@solidjs/start/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], + "@solidjs/start/shiki/@shikijs/core": ["@shikijs/core@1.29.2", "", { "dependencies": { "@shikijs/engine-javascript": "1.29.2", "@shikijs/engine-oniguruma": "1.29.2", "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.4" } }, "sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ=="], "@solidjs/start/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@1.29.2", "", { "dependencies": { "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "oniguruma-to-es": "^2.2.0" } }, "sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A=="], @@ -4583,6 +4653,8 @@ "type-is/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + "vitest/vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], @@ -4737,6 +4809,56 @@ "tw-to-css/tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + "vitest/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], + + "vitest/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], + + "vitest/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], + + "vitest/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], + + "vitest/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], + + "vitest/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], + + "vitest/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], + + "vitest/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], + + "vitest/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], + + "vitest/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], + + "vitest/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], + + "vitest/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], + + "vitest/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], + + "vitest/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], + + "vitest/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], + + "vitest/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], + + "vitest/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], + + "vitest/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], + + "vitest/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], + + "vitest/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], + + "vitest/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], + + "vitest/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], + + "vitest/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], + + "vitest/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], + + "vitest/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], + "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/token-providers/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.782.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/hash-node": "^4.0.2", "@smithy/invalid-dependency": "^4.0.2", "@smithy/middleware-content-length": "^4.0.2", "@smithy/middleware-endpoint": "^4.1.0", "@smithy/middleware-retry": "^4.1.0", "@smithy/middleware-serde": "^4.0.3", "@smithy/middleware-stack": "^4.0.2", "@smithy/node-config-provider": "^4.0.2", "@smithy/node-http-handler": "^4.0.4", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.0", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.8", "@smithy/util-defaults-mode-node": "^4.0.8", "@smithy/util-endpoints": "^3.0.2", "@smithy/util-middleware": "^4.0.2", "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-QOYC8q7luzHFXrP0xYAqBctoPkynjfV0r9dqntFu4/IWMTyC1vlo1UTxFAjIPyclYw92XJyEkVCVg9v/nQnsUA=="], "@jsx-email/cli/tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], diff --git a/package.json b/package.json index 9668bc3a130..45aa6f6252c 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "vite": "7.1.4", "@solidjs/meta": "0.29.4", "@solidjs/router": "0.15.4", - "@solidjs/start": "https://pkg.pr.new/@solidjs/start@3643ff3", + "@solidjs/start": "https://pkg.pr.new/@solidjs/start@117e0b5", "solid-js": "1.9.10", "vite-plugin-solid": "2.11.10" } From 76b5870f890e03c79f6eba121c85fe19646405b1 Mon Sep 17 00:00:00 2001 From: Github Action Date: Sun, 23 Nov 2025 17:45:24 +0000 Subject: [PATCH 09/66] Update Nix flake.lock and hashes --- nix/hashes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/hashes.json b/nix/hashes.json index 92bab11a140..e07f0d3ef34 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,3 +1,3 @@ { - "nodeModules": "sha256-j36TvDb0FDb1JCKSCVgDJRyvl3kzw3t+vFYJjw6vT8M=" + "nodeModules": "sha256-m+sgVc5dO29+cGwKgjWUkVHIPQ0dbvTobrFGOEBq1t4=" } From 8e2f9f6544d4cadc235a6db2f8e7698df40bfb04 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sun, 23 Nov 2025 12:55:24 -0500 Subject: [PATCH 10/66] ci: stuff --- bun.lock | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bun.lock b/bun.lock index b38d0c5d185..2038ac83025 100644 --- a/bun.lock +++ b/bun.lock @@ -437,7 +437,7 @@ "@pierre/precision-diffs": "0.5.4", "@solidjs/meta": "0.29.4", "@solidjs/router": "0.15.4", - "@solidjs/start": "https://pkg.pr.new/@solidjs/start@117e0b5", + "@solidjs/start": "https://pkg.pr.new/@solidjs/start@dfb2020", "@tailwindcss/vite": "4.1.11", "@tsconfig/bun": "1.0.9", "@tsconfig/node22": "22.0.2", @@ -1501,7 +1501,7 @@ "@solidjs/router": ["@solidjs/router@0.15.4", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-WOpgg9a9T638cR+5FGbFi/IV4l2FpmBs1GpIMSPa0Ce9vyJN7Wts+X2PqMf9IYn0zUj2MlSJtm1gp7/HI/n5TQ=="], - "@solidjs/start": ["@solidjs/start@https://pkg.pr.new/@solidjs/start@117e0b5", { "dependencies": { "@babel/core": "^7.28.3", "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.5", "@solidjs/meta": "^0.29.4", "@tanstack/server-functions-plugin": "1.134.5", "@types/babel__traverse": "^7.28.0", "@types/micromatch": "^4.0.9", "cookie-es": "^2.0.0", "defu": "^6.1.4", "error-stack-parser": "^2.1.4", "es-module-lexer": "^1.7.0", "esbuild": "^0.25.3", "fast-glob": "^3.3.3", "h3": "npm:h3@2.0.1-rc.4", "html-to-image": "^1.11.13", "micromatch": "^4.0.8", "path-to-regexp": "^8.2.0", "pathe": "^2.0.3", "radix3": "^1.1.2", "seroval": "^1.3.2", "seroval-plugins": "^1.2.1", "shiki": "^1.26.1", "solid-js": "^1.9.9", "source-map-js": "^1.2.1", "srvx": "^0.9.1", "terracotta": "^1.0.6", "vite": "7.1.10", "vite-plugin-solid": "^2.11.9", "vitest": "^4.0.10" } }], + "@solidjs/start": ["@solidjs/start@https://pkg.pr.new/@solidjs/start@dfb2020", { "dependencies": { "@babel/core": "^7.28.3", "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.5", "@solidjs/meta": "^0.29.4", "@tanstack/server-functions-plugin": "1.134.5", "@types/babel__traverse": "^7.28.0", "@types/micromatch": "^4.0.9", "cookie-es": "^2.0.0", "defu": "^6.1.4", "error-stack-parser": "^2.1.4", "es-module-lexer": "^1.7.0", "esbuild": "^0.25.3", "fast-glob": "^3.3.3", "h3": "npm:h3@2.0.1-rc.4", "html-to-image": "^1.11.13", "micromatch": "^4.0.8", "path-to-regexp": "^8.2.0", "pathe": "^2.0.3", "radix3": "^1.1.2", "seroval": "^1.3.2", "seroval-plugins": "^1.2.1", "shiki": "^1.26.1", "solid-js": "^1.9.9", "source-map-js": "^1.2.1", "srvx": "^0.9.1", "terracotta": "^1.0.6", "vite": "7.1.10", "vite-plugin-solid": "^2.11.9", "vitest": "^4.0.10" } }], "@speed-highlight/core": ["@speed-highlight/core@1.2.12", "", {}, "sha512-uilwrK0Ygyri5dToHYdZSjcvpS2ZwX0w5aSt3GCEN9hrjxWCoeV4Z2DTXuxjwbntaLQIEEAlCeNQss5SoHvAEA=="], diff --git a/package.json b/package.json index 45aa6f6252c..ba583142b43 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "vite": "7.1.4", "@solidjs/meta": "0.29.4", "@solidjs/router": "0.15.4", - "@solidjs/start": "https://pkg.pr.new/@solidjs/start@117e0b5", + "@solidjs/start": "https://pkg.pr.new/@solidjs/start@dfb2020", "solid-js": "1.9.10", "vite-plugin-solid": "2.11.10" } From 25b3846694fd548074e72a4cc694d5e7374f6235 Mon Sep 17 00:00:00 2001 From: Github Action Date: Sun, 23 Nov 2025 17:57:34 +0000 Subject: [PATCH 11/66] Update Nix flake.lock and hashes --- nix/hashes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/hashes.json b/nix/hashes.json index e07f0d3ef34..02cbc3d3ca0 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,3 +1,3 @@ { - "nodeModules": "sha256-m+sgVc5dO29+cGwKgjWUkVHIPQ0dbvTobrFGOEBq1t4=" + "nodeModules": "sha256-4RvQ+/XhT/cEF6cGHEMY4UiPG7I90fNVTCw8L8jJe7Y=" } From 27ae34168474273d7c1aa122069d82b839758974 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Sun, 23 Nov 2025 12:29:15 -0600 Subject: [PATCH 12/66] fix bash tool wsl --- packages/opencode/src/tool/bash.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/opencode/src/tool/bash.ts b/packages/opencode/src/tool/bash.ts index 83a5c820663..d8af0a77f46 100644 --- a/packages/opencode/src/tool/bash.ts +++ b/packages/opencode/src/tool/bash.ts @@ -70,6 +70,12 @@ export const BashTool = Tool.define("bash", async () => { return "/bin/zsh" } + if (process.platform === "win32") { + // Let Bun / Node pick COMSPEC (usually cmd.exe) + // or explicitly: + return process.env.COMSPEC || true + } + const bash = Bun.which("bash") if (bash) { return bash From de4660ac129676fa4028c6c93d13c1eb9178b0ac Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sun, 23 Nov 2025 14:28:10 -0500 Subject: [PATCH 13/66] ci: ignore --- bun.lock | 1 + infra/enterprise.ts | 30 ++++++++++++++++++++++++++++++ packages/enterprise/package.json | 1 + packages/enterprise/tsconfig.json | 2 +- sst.config.ts | 2 +- 5 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 infra/enterprise.ts diff --git a/bun.lock b/bun.lock index 2038ac83025..6bb1b73d4ae 100644 --- a/bun.lock +++ b/bun.lock @@ -177,6 +177,7 @@ "zod": "catalog:", }, "devDependencies": { + "@cloudflare/workers-types": "catalog:", "@tailwindcss/vite": "catalog:", "@types/luxon": "catalog:", "@typescript/native-preview": "catalog:", diff --git a/infra/enterprise.ts b/infra/enterprise.ts new file mode 100644 index 00000000000..677c8e41269 --- /dev/null +++ b/infra/enterprise.ts @@ -0,0 +1,30 @@ +import { domain } from "./stage" + +const storage = new sst.cloudflare.Bucket("EnterpriseStorage") +const token = new cloudflare.ApiToken("EnterpriseStorageToken", { + name: `${$app.name}-${$app.stage}-enterprise-storage`, + policies: [ + { + effect: "allow", + resources: { + "com.cloudflare.api.account.*": "*", + }, + permissionGroups: [ + { + id: "c8d07a38f1654800b34e33e59b4e8f41", + }, + ], + }, + ], +}) + +const enterprise = new sst.cloudflare.x.SolidStart("Enterprise", { + domain: "enterprise." + domain, + environment: { + OPENCODE_STORAGE_ADAPTER: "r2", + OPENCODE_STORAGE_ACCOUNT_ID: sst.cloudflare.DEFAULT_ACCOUNT_ID, + OPENCODE_STORAGE_ACCESS_KEY_ID: "---", + OPENCODE_STORAGE_SECRET_ACCESS_KEY: "---", + OPENCODE_STORAGE_BUCKET: storage.name, + }, +}) diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index 985ed203b08..78d61aeee33 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -24,6 +24,7 @@ "zod": "catalog:" }, "devDependencies": { + "@cloudflare/workers-types": "catalog:", "@tailwindcss/vite": "catalog:", "@typescript/native-preview": "catalog:", "@types/luxon": "catalog:", diff --git a/packages/enterprise/tsconfig.json b/packages/enterprise/tsconfig.json index 6bdc0f9ee9c..af4ce16490f 100644 --- a/packages/enterprise/tsconfig.json +++ b/packages/enterprise/tsconfig.json @@ -11,7 +11,7 @@ "allowJs": true, "noEmit": true, "strict": true, - "types": ["vite/client"], + "types": ["@cloudflare/workers-types", "vite/client"], "isolatedModules": true, "paths": { "~/*": ["./src/*"] diff --git a/sst.config.ts b/sst.config.ts index a1878739120..1698721ce51 100644 --- a/sst.config.ts +++ b/sst.config.ts @@ -9,7 +9,7 @@ export default $config({ home: "cloudflare", providers: { stripe: { - apiKey: process.env.STRIPE_SECRET_KEY, + apiKey: process.env.STRIPE_SECRET_KEY!, }, planetscale: "0.4.1", }, From 488d33c1ed3672ccbb89a9d0d4af9fa0fe45a002 Mon Sep 17 00:00:00 2001 From: opencode Date: Sun, 23 Nov 2025 19:35:38 +0000 Subject: [PATCH 14/66] release: v1.0.106 --- bun.lock | 30 +++++++++++++------------- packages/console/app/package.json | 2 +- packages/console/core/package.json | 2 +- packages/console/function/package.json | 2 +- packages/console/mail/package.json | 2 +- packages/desktop/package.json | 2 +- packages/enterprise/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +++++------ packages/function/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 4 ++-- packages/sdk/js/package.json | 4 ++-- packages/slack/package.json | 2 +- packages/tauri/package.json | 2 +- packages/ui/package.json | 2 +- packages/util/package.json | 2 +- packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- 18 files changed, 39 insertions(+), 39 deletions(-) diff --git a/bun.lock b/bun.lock index 6bb1b73d4ae..58f41a67a64 100644 --- a/bun.lock +++ b/bun.lock @@ -19,7 +19,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -46,7 +46,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -73,7 +73,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -97,7 +97,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -121,7 +121,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -162,7 +162,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -188,7 +188,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "22.0.0", @@ -204,7 +204,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.105", + "version": "1.0.106", "bin": { "opencode": "./bin/opencode", }, @@ -290,7 +290,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -310,7 +310,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.105", + "version": "1.0.106", "devDependencies": { "@hey-api/openapi-ts": "0.81.0", "@tsconfig/node22": "catalog:", @@ -321,7 +321,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -334,7 +334,7 @@ }, "packages/tauri": { "name": "@opencode-ai/tauri", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "@tauri-apps/api": "^2", "@tauri-apps/plugin-opener": "^2", @@ -347,7 +347,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -379,7 +379,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "zod": "catalog:", }, @@ -389,7 +389,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 28d9934479f..322afb56fb3 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.0.105", + "version": "1.0.106", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 19382c802b3..3aa4b52d50e 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/console-core", - "version": "1.0.105", + "version": "1.0.106", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 5188ff38827..6b6cccd5a46 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.105", + "version": "1.0.106", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/console/mail/package.json b/packages/console/mail/package.json index 5fc5e15c280..42a1647feca 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.105", + "version": "1.0.106", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index c7cbba1a1ee..c3d8d8070a0 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.105", + "version": "1.0.106", "description": "", "type": "module", "scripts": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index 78d61aeee33..4bdcd970047 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.0.105", + "version": "1.0.106", "private": true, "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index d90ed352860..771be59333a 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "opencode" name = "OpenCode" description = "The AI coding agent built for the terminal" -version = "1.0.105" +version = "1.0.106" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/sst/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.105/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.106/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.105/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.106/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.105/opencode-linux-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.106/opencode-linux-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.105/opencode-linux-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.106/opencode-linux-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.105/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.106/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index 356739cf241..e2abb624639 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.105", + "version": "1.0.106", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 753b5872a8b..d275033a2c1 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.105", + "version": "1.0.106", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 90cf1ad8425..3499c37101d 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/plugin", - "version": "1.0.105", + "version": "1.0.106", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} +} \ No newline at end of file diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 65f4d72d1fe..cded47d9a2b 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/sdk", - "version": "1.0.105", + "version": "1.0.106", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -26,4 +26,4 @@ "publishConfig": { "directory": "dist" } -} +} \ No newline at end of file diff --git a/packages/slack/package.json b/packages/slack/package.json index 67b1732009f..2c2d7dbe4d0 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.105", + "version": "1.0.106", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/tauri/package.json b/packages/tauri/package.json index dc2fbdd1713..d7af0cab32f 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/tauri", "private": true, - "version": "1.0.105", + "version": "1.0.106", "type": "module", "scripts": { "dev": "vite", diff --git a/packages/ui/package.json b/packages/ui/package.json index 09adefaa4ed..229bd80c2f0 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.105", + "version": "1.0.106", "type": "module", "exports": { "./*": "./src/components/*.tsx", diff --git a/packages/util/package.json b/packages/util/package.json index 381fb3533d4..f1f242e0e0d 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.0.105", + "version": "1.0.106", "private": true, "type": "module", "exports": { diff --git a/packages/web/package.json b/packages/web/package.json index b8faec7766a..99c93a9a445 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.105", + "version": "1.0.106", "scripts": { "dev": "astro dev", "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 473f1d3fb8c..760701bf1c3 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "1.0.105", + "version": "1.0.106", "publisher": "sst-dev", "repository": { "type": "git", From 2c93f065cb62b8619a9a6255cd6a90e25ec5f1a7 Mon Sep 17 00:00:00 2001 From: Github Action Date: Sun, 23 Nov 2025 19:30:19 +0000 Subject: [PATCH 15/66] Update Nix flake.lock and hashes --- nix/hashes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/hashes.json b/nix/hashes.json index 02cbc3d3ca0..6063a49bd3f 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,3 +1,3 @@ { - "nodeModules": "sha256-4RvQ+/XhT/cEF6cGHEMY4UiPG7I90fNVTCw8L8jJe7Y=" + "nodeModules": "sha256-/ZkyVHgRMjhzBpnDNTR6X+TomtTMarVU7gmq9Z8Czr8=" } From 59a3e7e3cc3103602618f4fd7b9f6bddc3e14c60 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sun, 23 Nov 2025 14:31:03 -0500 Subject: [PATCH 16/66] ci: ignore --- sst.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/sst.config.ts b/sst.config.ts index 1698721ce51..342af095f03 100644 --- a/sst.config.ts +++ b/sst.config.ts @@ -19,5 +19,6 @@ export default $config({ await import("./infra/app.js") await import("./infra/console.js") await import("./infra/desktop.js") + await import("./infra/enterprise.js") }, }) From 5e112a17a585929b2163bd1b2a0025687f50d3ab Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sun, 23 Nov 2025 14:32:41 -0500 Subject: [PATCH 17/66] token --- infra/enterprise.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/infra/enterprise.ts b/infra/enterprise.ts index 677c8e41269..71acf20b3d9 100644 --- a/infra/enterprise.ts +++ b/infra/enterprise.ts @@ -1,22 +1,6 @@ import { domain } from "./stage" const storage = new sst.cloudflare.Bucket("EnterpriseStorage") -const token = new cloudflare.ApiToken("EnterpriseStorageToken", { - name: `${$app.name}-${$app.stage}-enterprise-storage`, - policies: [ - { - effect: "allow", - resources: { - "com.cloudflare.api.account.*": "*", - }, - permissionGroups: [ - { - id: "c8d07a38f1654800b34e33e59b4e8f41", - }, - ], - }, - ], -}) const enterprise = new sst.cloudflare.x.SolidStart("Enterprise", { domain: "enterprise." + domain, From 38b70f78774d0dae6e30d8c05adc99664582e743 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sun, 23 Nov 2025 14:36:25 -0500 Subject: [PATCH 18/66] ci: secret --- infra/enterprise.ts | 5 +++-- infra/secret.ts | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 infra/secret.ts diff --git a/infra/enterprise.ts b/infra/enterprise.ts index 71acf20b3d9..8da0ba19b56 100644 --- a/infra/enterprise.ts +++ b/infra/enterprise.ts @@ -1,3 +1,4 @@ +import { SECRET } from "./secret" import { domain } from "./stage" const storage = new sst.cloudflare.Bucket("EnterpriseStorage") @@ -7,8 +8,8 @@ const enterprise = new sst.cloudflare.x.SolidStart("Enterprise", { environment: { OPENCODE_STORAGE_ADAPTER: "r2", OPENCODE_STORAGE_ACCOUNT_ID: sst.cloudflare.DEFAULT_ACCOUNT_ID, - OPENCODE_STORAGE_ACCESS_KEY_ID: "---", - OPENCODE_STORAGE_SECRET_ACCESS_KEY: "---", + OPENCODE_STORAGE_ACCESS_KEY_ID: SECRET.R2AccessKey.value, + OPENCODE_STORAGE_SECRET_ACCESS_KEY: SECRET.R2SecretKey.value, OPENCODE_STORAGE_BUCKET: storage.name, }, }) diff --git a/infra/secret.ts b/infra/secret.ts new file mode 100644 index 00000000000..0b1870fa155 --- /dev/null +++ b/infra/secret.ts @@ -0,0 +1,4 @@ +export const SECRET = { + R2AccessKey: new sst.Secret("R2AccessKey", "unknown"), + R2SecretKey: new sst.Secret("R2SecretKey", "unknown"), +} From 8f2a8086c01fbc25aca2364a7ba1d04e0854f6df Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sun, 23 Nov 2025 19:37:19 +0000 Subject: [PATCH 19/66] chore: format code --- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 3499c37101d..46f4353dcbb 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} \ No newline at end of file +} diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index cded47d9a2b..3f77d8ca4fb 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -26,4 +26,4 @@ "publishConfig": { "directory": "dist" } -} \ No newline at end of file +} From 5ade90416ec17951b5591aa3d97b314eb11f5286 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sun, 23 Nov 2025 14:43:54 -0500 Subject: [PATCH 20/66] ci: ignore --- infra/enterprise.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/infra/enterprise.ts b/infra/enterprise.ts index 8da0ba19b56..fa044e109f1 100644 --- a/infra/enterprise.ts +++ b/infra/enterprise.ts @@ -3,6 +3,7 @@ import { domain } from "./stage" const storage = new sst.cloudflare.Bucket("EnterpriseStorage") +console.log(SECRET.R2AccessKey.value, SECRET.R2SecretKey.value) const enterprise = new sst.cloudflare.x.SolidStart("Enterprise", { domain: "enterprise." + domain, environment: { From bf81e3108cfa87921875f292b39b801ec65a8466 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sun, 23 Nov 2025 14:46:57 -0500 Subject: [PATCH 21/66] ci: ignore --- infra/enterprise.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/infra/enterprise.ts b/infra/enterprise.ts index fa044e109f1..c7a6dd13916 100644 --- a/infra/enterprise.ts +++ b/infra/enterprise.ts @@ -7,6 +7,7 @@ console.log(SECRET.R2AccessKey.value, SECRET.R2SecretKey.value) const enterprise = new sst.cloudflare.x.SolidStart("Enterprise", { domain: "enterprise." + domain, environment: { + OPENCODE_DEPLOYMENT_TARGET: "cloudflare", OPENCODE_STORAGE_ADAPTER: "r2", OPENCODE_STORAGE_ACCOUNT_ID: sst.cloudflare.DEFAULT_ACCOUNT_ID, OPENCODE_STORAGE_ACCESS_KEY_ID: SECRET.R2AccessKey.value, From 24683058fdf2e9f57bc231f93a051e35e790a2ff Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sun, 23 Nov 2025 14:56:06 -0500 Subject: [PATCH 22/66] ci: ignore --- infra/enterprise.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/infra/enterprise.ts b/infra/enterprise.ts index c7a6dd13916..436d11e8e9d 100644 --- a/infra/enterprise.ts +++ b/infra/enterprise.ts @@ -6,8 +6,9 @@ const storage = new sst.cloudflare.Bucket("EnterpriseStorage") console.log(SECRET.R2AccessKey.value, SECRET.R2SecretKey.value) const enterprise = new sst.cloudflare.x.SolidStart("Enterprise", { domain: "enterprise." + domain, + path: "packages/enterprise", + buildCommand: "bun run build:cloudflare", environment: { - OPENCODE_DEPLOYMENT_TARGET: "cloudflare", OPENCODE_STORAGE_ADAPTER: "r2", OPENCODE_STORAGE_ACCOUNT_ID: sst.cloudflare.DEFAULT_ACCOUNT_ID, OPENCODE_STORAGE_ACCESS_KEY_ID: SECRET.R2AccessKey.value, From 7579c3bb1591c527eef97bb5eb35d7c6a2d66e75 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sun, 23 Nov 2025 15:00:29 -0500 Subject: [PATCH 23/66] ci: remove log --- infra/enterprise.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/infra/enterprise.ts b/infra/enterprise.ts index 436d11e8e9d..70693846a11 100644 --- a/infra/enterprise.ts +++ b/infra/enterprise.ts @@ -3,7 +3,6 @@ import { domain } from "./stage" const storage = new sst.cloudflare.Bucket("EnterpriseStorage") -console.log(SECRET.R2AccessKey.value, SECRET.R2SecretKey.value) const enterprise = new sst.cloudflare.x.SolidStart("Enterprise", { domain: "enterprise." + domain, path: "packages/enterprise", From 7413c2715c208a92d1ca3c4f31988a4449b877a0 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Sun, 23 Nov 2025 14:04:34 -0600 Subject: [PATCH 24/66] tweak: slight improvements to title gen --- packages/opencode/src/session/prompt.ts | 9 ++++---- .../opencode/src/session/prompt/title.txt | 22 ++++++++++++++----- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index e9827a09952..6b255981b78 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -1416,7 +1416,8 @@ export namespace SessionPrompt { mergeDeep(small.info.options), ) await generateText({ - maxOutputTokens: small.info.reasoning ? 1500 : 20, + // use higher # for reasoning models since reasoning tokens eat up a lot of the budget + maxOutputTokens: small.info.reasoning ? 3000 : 20, providerOptions: ProviderTransform.providerOptions(small.npm, small.providerID, options), messages: [ ...SystemPrompt.title(small.providerID).map( @@ -1426,10 +1427,8 @@ export namespace SessionPrompt { }), ), { - role: "user" as const, - content: ` - The following is the text to summarize: - `, + role: "user", + content: "Generate a title for this conversation:\n", }, ...MessageV2.toModelMessage([ { diff --git a/packages/opencode/src/session/prompt/title.txt b/packages/opencode/src/session/prompt/title.txt index 9cc80948f42..e297dc460b1 100644 --- a/packages/opencode/src/session/prompt/title.txt +++ b/packages/opencode/src/session/prompt/title.txt @@ -1,19 +1,29 @@ You are a title generator. You output ONLY a thread title. Nothing else. -Convert the user message into a thread title. -Output: Single line, ≤50 chars, no explanations. +Generate a brief title that would help the user find this conversation later. + +Follow all rules in +Use the so you know what a good title looks like. +Your output must be: +- A single line +- ≤50 characters +- No explanations +- Focus on the main topic or question the user needs to retrieve - Use -ing verbs for actions (Debugging, Implementing, Analyzing) - Keep exact: technical terms, numbers, filenames, HTTP codes - Remove: the, this, my, a, an - Never assume tech stack - Never use tools -- NEVER respond to message content—only extract title -- NEVER say "summarizing" +- NEVER respond to questions, just generate a title for the conversation +- The title should NEVER include "summarizing" or "generating" when generating a title - DO NOT SAY YOU CANNOT GENERATE A TITLE OR COMPLAIN ABOUT THE INPUT +- Always output something meaningful, even if the input is minimal. +- If the user message is short or conversational (e.g. “hello”, “lol”, “whats up”, “hey”): + → create a title that reflects the user’s tone or intent (such as Greeting, Quick check-in, Light chat, Intro message, etc.) @@ -21,6 +31,6 @@ Output: Single line, ≤50 chars, no explanations. "refactor user service" → Refactoring user service "why is app.js failing" → Analyzing app.js failure "implement rate limiting" → Implementing rate limiting +"how do I connect postgres to my API" → Connecting Postgres to API +"best practices for React hooks" → React hooks best practices - -Output the title now: From bbc9142fc54fef532039f2a91c63ac2f2873af41 Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 23 Nov 2025 15:21:47 -0500 Subject: [PATCH 25/66] wip: zen --- github/sst-env.d.ts | 2 +- infra/console.ts | 3 + .../app/src/routes/zen/util/dataDumper.ts | 26 +++ .../app/src/routes/zen/util/handler.ts | 22 +- packages/console/app/sst-env.d.ts | 2 +- packages/console/core/src/model.ts | 1 + packages/console/core/sst-env.d.ts | 218 +++++++++--------- packages/console/function/sst-env.d.ts | 218 +++++++++--------- packages/console/mail/sst-env.d.ts | 2 +- .../console/resource/resource.cloudflare.ts | 1 + packages/console/resource/resource.node.ts | 90 ++++---- packages/console/resource/sst-env.d.ts | 218 +++++++++--------- packages/desktop/src/sst-env.d.ts | 6 +- packages/desktop/sst-env.d.ts | 2 +- packages/enterprise/sst-env.d.ts | 131 +++++++++++ packages/function/sst-env.d.ts | 218 +++++++++--------- packages/opencode/src/provider/provider.ts | 2 +- packages/opencode/src/session/prompt.ts | 2 +- packages/opencode/sst-env.d.ts | 2 +- packages/plugin/sst-env.d.ts | 2 +- packages/script/sst-env.d.ts | 2 +- packages/sdk/js/sst-env.d.ts | 2 +- packages/sdk/python/sst.pyi | 12 + packages/slack/sst-env.d.ts | 2 +- packages/tauri/sst-env.d.ts | 9 + packages/ui/sst-env.d.ts | 2 +- packages/util/sst-env.d.ts | 2 +- packages/web/sst-env.d.ts | 2 +- sdks/vscode/sst-env.d.ts | 2 +- sst-env.d.ts | 206 +++++++++-------- 30 files changed, 837 insertions(+), 572 deletions(-) create mode 100644 packages/console/app/src/routes/zen/util/dataDumper.ts create mode 100644 packages/enterprise/sst-env.d.ts create mode 100644 packages/tauri/sst-env.d.ts diff --git a/github/sst-env.d.ts b/github/sst-env.d.ts index 6b69016e718..f742a120044 100644 --- a/github/sst-env.d.ts +++ b/github/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} +export {} \ No newline at end of file diff --git a/infra/console.ts b/infra/console.ts index b614da41187..eddc97d2f18 100644 --- a/infra/console.ts +++ b/infra/console.ts @@ -116,6 +116,8 @@ const gatewayKv = new sst.cloudflare.Kv("GatewayKv") // CONSOLE //////////////// +const bucket = new sst.cloudflare.Bucket("ConsoleData") + const AWS_SES_ACCESS_KEY_ID = new sst.Secret("AWS_SES_ACCESS_KEY_ID") const AWS_SES_SECRET_ACCESS_KEY = new sst.Secret("AWS_SES_SECRET_ACCESS_KEY") @@ -132,6 +134,7 @@ new sst.cloudflare.x.SolidStart("Console", { domain, path: "packages/console/app", link: [ + bucket, database, AUTH_API_URL, STRIPE_WEBHOOK_SECRET, diff --git a/packages/console/app/src/routes/zen/util/dataDumper.ts b/packages/console/app/src/routes/zen/util/dataDumper.ts new file mode 100644 index 00000000000..6a064138a7e --- /dev/null +++ b/packages/console/app/src/routes/zen/util/dataDumper.ts @@ -0,0 +1,26 @@ +import { Resource, waitUntil } from "@opencode-ai/console-resource" + +export function createDataDumper(sessionId: string, requestId: string) { + if (Resource.App.stage !== "production") return + + let data: Record = {} + let modelName: string | undefined + + return { + provideModel: (model?: string) => (modelName = model), + provideRequest: (request: string) => (data.request = request), + provideResponse: (response: string) => (data.response = response), + provideStream: (chunk: string) => (data.response = (data.response ?? "") + chunk), + flush: () => { + if (!modelName) return + + const str = new Date().toISOString().replace(/[^0-9]/g, "") + const yyyymmdd = str.substring(0, 8) + const hh = str.substring(8, 10) + + waitUntil( + Resource.ConsoleData.put(`${yyyymmdd}/${hh}/${modelName}/${sessionId}/${requestId}.json`, JSON.stringify(data)), + ) + }, + } +} diff --git a/packages/console/app/src/routes/zen/util/handler.ts b/packages/console/app/src/routes/zen/util/handler.ts index 3453a6d3810..c40db6e1d4e 100644 --- a/packages/console/app/src/routes/zen/util/handler.ts +++ b/packages/console/app/src/routes/zen/util/handler.ts @@ -19,6 +19,7 @@ import { googleHelper } from "./provider/google" import { openaiHelper } from "./provider/openai" import { oaCompatHelper } from "./provider/openai-compatible" import { createRateLimiter } from "./rateLimiter" +import { createDataDumper } from "./dataDumper" type ZenData = Awaited> type RetryOptions = { @@ -48,16 +49,19 @@ export async function handler( try { const url = input.request.url const body = await input.request.json() - const ip = input.request.headers.get("x-real-ip") ?? "" const model = opts.parseModel(url, body) const isStream = opts.parseIsStream(url, body) + const ip = input.request.headers.get("x-real-ip") ?? "" + const sessionId = input.request.headers.get("x-opencode-session") + const requestId = input.request.headers.get("x-opencode-request") logger.metric({ is_tream: isStream, - session: input.request.headers.get("x-opencode-session"), - request: input.request.headers.get("x-opencode-request"), + session: sessionId, + request: requestId, }) const zenData = ZenData.list() const modelInfo = validateModel(zenData, model) + const dataDumper = createDataDumper(sessionId, requestId) const rateLimiter = createRateLimiter(modelInfo.id, modelInfo.rateLimit, ip) await rateLimiter?.check() @@ -104,10 +108,14 @@ export async function handler( }) } - return { providerInfo, authInfo, res, startTimestamp } + return { providerInfo, authInfo, reqBody, res, startTimestamp } } - const { providerInfo, authInfo, res, startTimestamp } = await retriableRequest() + const { providerInfo, authInfo, reqBody, res, startTimestamp } = await retriableRequest() + + // Store model request + dataDumper?.provideModel(providerInfo.storeModel) + dataDumper?.provideRequest(reqBody) // Scrub response headers const resHeaders = new Headers() @@ -126,6 +134,8 @@ export async function handler( const body = JSON.stringify(responseConverter(json)) logger.metric({ response_length: body.length }) logger.debug("RESPONSE: " + body) + dataDumper?.provideResponse(body) + dataDumper?.flush() await rateLimiter?.track() await trackUsage(authInfo, modelInfo, providerInfo, json.usage) await reload(authInfo) @@ -155,6 +165,7 @@ export async function handler( response_length: responseLength, "timestamp.last_byte": Date.now(), }) + dataDumper?.flush() await rateLimiter?.track() const usage = usageParser.retrieve() if (usage) { @@ -174,6 +185,7 @@ export async function handler( } responseLength += value.length buffer += decoder.decode(value, { stream: true }) + dataDumper?.provideStream(buffer) const parts = buffer.split(providerInfo.streamSeparator) buffer = parts.pop() ?? "" diff --git a/packages/console/app/sst-env.d.ts b/packages/console/app/sst-env.d.ts index bd558821739..9b9de73273f 100644 --- a/packages/console/app/sst-env.d.ts +++ b/packages/console/app/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/console/core/src/model.ts b/packages/console/core/src/model.ts index ed7911ab999..fd6cd095e94 100644 --- a/packages/console/core/src/model.ts +++ b/packages/console/core/src/model.ts @@ -32,6 +32,7 @@ export namespace ZenData { model: z.string(), weight: z.number().optional(), disabled: z.boolean().optional(), + storeModel: z.string().optional(), }), ), }) diff --git a/packages/console/core/sst-env.d.ts b/packages/console/core/sst-env.d.ts index 0862ae4e377..8e38d38251b 100644 --- a/packages/console/core/sst-env.d.ts +++ b/packages/console/core/sst-env.d.ts @@ -6,116 +6,126 @@ import "sst" declare module "sst" { export interface Resource { - ADMIN_SECRET: { - type: "sst.sst.Secret" - value: string - } - AUTH_API_URL: { - type: "sst.sst.Linkable" - value: string - } - AWS_SES_ACCESS_KEY_ID: { - type: "sst.sst.Secret" - value: string - } - AWS_SES_SECRET_ACCESS_KEY: { - type: "sst.sst.Secret" - value: string - } - CLOUDFLARE_API_TOKEN: { - type: "sst.sst.Secret" - value: string - } - CLOUDFLARE_DEFAULT_ACCOUNT_ID: { - type: "sst.sst.Secret" - value: string - } - Console: { - type: "sst.cloudflare.SolidStart" - url: string - } - Database: { - database: string - host: string - password: string - port: number - type: "sst.sst.Linkable" - username: string - } - Desktop: { - type: "sst.cloudflare.StaticSite" - url: string - } - EMAILOCTOPUS_API_KEY: { - type: "sst.sst.Secret" - value: string - } - GITHUB_APP_ID: { - type: "sst.sst.Secret" - value: string - } - GITHUB_APP_PRIVATE_KEY: { - type: "sst.sst.Secret" - value: string - } - GITHUB_CLIENT_ID_CONSOLE: { - type: "sst.sst.Secret" - value: string - } - GITHUB_CLIENT_SECRET_CONSOLE: { - type: "sst.sst.Secret" - value: string - } - GOOGLE_CLIENT_ID: { - type: "sst.sst.Secret" - value: string - } - HONEYCOMB_API_KEY: { - type: "sst.sst.Secret" - value: string - } - STRIPE_SECRET_KEY: { - type: "sst.sst.Secret" - value: string - } - STRIPE_WEBHOOK_SECRET: { - type: "sst.sst.Linkable" - value: string - } - Web: { - type: "sst.cloudflare.Astro" - url: string - } - ZEN_MODELS1: { - type: "sst.sst.Secret" - value: string - } - ZEN_MODELS2: { - type: "sst.sst.Secret" - value: string - } - ZEN_MODELS3: { - type: "sst.sst.Secret" - value: string - } - ZEN_MODELS4: { - type: "sst.sst.Secret" - value: string + "ADMIN_SECRET": { + "type": "sst.sst.Secret" + "value": string + } + "AUTH_API_URL": { + "type": "sst.sst.Linkable" + "value": string + } + "AWS_SES_ACCESS_KEY_ID": { + "type": "sst.sst.Secret" + "value": string + } + "AWS_SES_SECRET_ACCESS_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "CLOUDFLARE_API_TOKEN": { + "type": "sst.sst.Secret" + "value": string + } + "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { + "type": "sst.sst.Secret" + "value": string + } + "Console": { + "type": "sst.cloudflare.SolidStart" + "url": string + } + "Database": { + "database": string + "host": string + "password": string + "port": number + "type": "sst.sst.Linkable" + "username": string + } + "Desktop": { + "type": "sst.cloudflare.StaticSite" + "url": string + } + "EMAILOCTOPUS_API_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_APP_ID": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_APP_PRIVATE_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_CLIENT_ID_CONSOLE": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_CLIENT_SECRET_CONSOLE": { + "type": "sst.sst.Secret" + "value": string + } + "GOOGLE_CLIENT_ID": { + "type": "sst.sst.Secret" + "value": string + } + "HONEYCOMB_API_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "R2AccessKey": { + "type": "sst.sst.Secret" + "value": string + } + "R2SecretKey": { + "type": "sst.sst.Secret" + "value": string + } + "STRIPE_SECRET_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "STRIPE_WEBHOOK_SECRET": { + "type": "sst.sst.Linkable" + "value": string + } + "Web": { + "type": "sst.cloudflare.Astro" + "url": string + } + "ZEN_MODELS1": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS2": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS3": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS4": { + "type": "sst.sst.Secret" + "value": string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types" +// cloudflare +import * as cloudflare from "@cloudflare/workers-types"; declare module "sst" { export interface Resource { - Api: cloudflare.Service - AuthApi: cloudflare.Service - AuthStorage: cloudflare.KVNamespace - Bucket: cloudflare.R2Bucket - GatewayKv: cloudflare.KVNamespace - LogProcessor: cloudflare.Service + "Api": cloudflare.Service + "AuthApi": cloudflare.Service + "AuthStorage": cloudflare.KVNamespace + "Bucket": cloudflare.R2Bucket + "ConsoleData": cloudflare.R2Bucket + "EnterpriseStorage": cloudflare.R2Bucket + "GatewayKv": cloudflare.KVNamespace + "LogProcessor": cloudflare.Service } } import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/console/function/sst-env.d.ts b/packages/console/function/sst-env.d.ts index 0862ae4e377..8e38d38251b 100644 --- a/packages/console/function/sst-env.d.ts +++ b/packages/console/function/sst-env.d.ts @@ -6,116 +6,126 @@ import "sst" declare module "sst" { export interface Resource { - ADMIN_SECRET: { - type: "sst.sst.Secret" - value: string - } - AUTH_API_URL: { - type: "sst.sst.Linkable" - value: string - } - AWS_SES_ACCESS_KEY_ID: { - type: "sst.sst.Secret" - value: string - } - AWS_SES_SECRET_ACCESS_KEY: { - type: "sst.sst.Secret" - value: string - } - CLOUDFLARE_API_TOKEN: { - type: "sst.sst.Secret" - value: string - } - CLOUDFLARE_DEFAULT_ACCOUNT_ID: { - type: "sst.sst.Secret" - value: string - } - Console: { - type: "sst.cloudflare.SolidStart" - url: string - } - Database: { - database: string - host: string - password: string - port: number - type: "sst.sst.Linkable" - username: string - } - Desktop: { - type: "sst.cloudflare.StaticSite" - url: string - } - EMAILOCTOPUS_API_KEY: { - type: "sst.sst.Secret" - value: string - } - GITHUB_APP_ID: { - type: "sst.sst.Secret" - value: string - } - GITHUB_APP_PRIVATE_KEY: { - type: "sst.sst.Secret" - value: string - } - GITHUB_CLIENT_ID_CONSOLE: { - type: "sst.sst.Secret" - value: string - } - GITHUB_CLIENT_SECRET_CONSOLE: { - type: "sst.sst.Secret" - value: string - } - GOOGLE_CLIENT_ID: { - type: "sst.sst.Secret" - value: string - } - HONEYCOMB_API_KEY: { - type: "sst.sst.Secret" - value: string - } - STRIPE_SECRET_KEY: { - type: "sst.sst.Secret" - value: string - } - STRIPE_WEBHOOK_SECRET: { - type: "sst.sst.Linkable" - value: string - } - Web: { - type: "sst.cloudflare.Astro" - url: string - } - ZEN_MODELS1: { - type: "sst.sst.Secret" - value: string - } - ZEN_MODELS2: { - type: "sst.sst.Secret" - value: string - } - ZEN_MODELS3: { - type: "sst.sst.Secret" - value: string - } - ZEN_MODELS4: { - type: "sst.sst.Secret" - value: string + "ADMIN_SECRET": { + "type": "sst.sst.Secret" + "value": string + } + "AUTH_API_URL": { + "type": "sst.sst.Linkable" + "value": string + } + "AWS_SES_ACCESS_KEY_ID": { + "type": "sst.sst.Secret" + "value": string + } + "AWS_SES_SECRET_ACCESS_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "CLOUDFLARE_API_TOKEN": { + "type": "sst.sst.Secret" + "value": string + } + "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { + "type": "sst.sst.Secret" + "value": string + } + "Console": { + "type": "sst.cloudflare.SolidStart" + "url": string + } + "Database": { + "database": string + "host": string + "password": string + "port": number + "type": "sst.sst.Linkable" + "username": string + } + "Desktop": { + "type": "sst.cloudflare.StaticSite" + "url": string + } + "EMAILOCTOPUS_API_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_APP_ID": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_APP_PRIVATE_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_CLIENT_ID_CONSOLE": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_CLIENT_SECRET_CONSOLE": { + "type": "sst.sst.Secret" + "value": string + } + "GOOGLE_CLIENT_ID": { + "type": "sst.sst.Secret" + "value": string + } + "HONEYCOMB_API_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "R2AccessKey": { + "type": "sst.sst.Secret" + "value": string + } + "R2SecretKey": { + "type": "sst.sst.Secret" + "value": string + } + "STRIPE_SECRET_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "STRIPE_WEBHOOK_SECRET": { + "type": "sst.sst.Linkable" + "value": string + } + "Web": { + "type": "sst.cloudflare.Astro" + "url": string + } + "ZEN_MODELS1": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS2": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS3": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS4": { + "type": "sst.sst.Secret" + "value": string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types" +// cloudflare +import * as cloudflare from "@cloudflare/workers-types"; declare module "sst" { export interface Resource { - Api: cloudflare.Service - AuthApi: cloudflare.Service - AuthStorage: cloudflare.KVNamespace - Bucket: cloudflare.R2Bucket - GatewayKv: cloudflare.KVNamespace - LogProcessor: cloudflare.Service + "Api": cloudflare.Service + "AuthApi": cloudflare.Service + "AuthStorage": cloudflare.KVNamespace + "Bucket": cloudflare.R2Bucket + "ConsoleData": cloudflare.R2Bucket + "EnterpriseStorage": cloudflare.R2Bucket + "GatewayKv": cloudflare.KVNamespace + "LogProcessor": cloudflare.Service } } import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/console/mail/sst-env.d.ts b/packages/console/mail/sst-env.d.ts index bd558821739..9b9de73273f 100644 --- a/packages/console/mail/sst-env.d.ts +++ b/packages/console/mail/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/console/resource/resource.cloudflare.ts b/packages/console/resource/resource.cloudflare.ts index a56b1e4174d..745212ca9c9 100644 --- a/packages/console/resource/resource.cloudflare.ts +++ b/packages/console/resource/resource.cloudflare.ts @@ -1,4 +1,5 @@ import { env } from "cloudflare:workers" +export { waitUntil } from "cloudflare:workers" export const Resource = new Proxy( {}, diff --git a/packages/console/resource/resource.node.ts b/packages/console/resource/resource.node.ts index f63d7bada92..46b9629ed2d 100644 --- a/packages/console/resource/resource.node.ts +++ b/packages/console/resource/resource.node.ts @@ -2,54 +2,66 @@ import type { KVNamespaceListOptions, KVNamespaceListResult, KVNamespacePutOptio import { Resource as ResourceBase } from "sst" import Cloudflare from "cloudflare" +export const waitUntil = async (fn: () => Promise) => { + await fn() +} + export const Resource = new Proxy( {}, { get(_target, prop: keyof typeof ResourceBase) { const value = ResourceBase[prop] - // @ts-ignore - if ("type" in value && value.type === "sst.cloudflare.Kv") { - const client = new Cloudflare({ - apiToken: ResourceBase.CLOUDFLARE_API_TOKEN.value, - }) + if ("type" in value) { + // @ts-ignore + if (value.type === "sst.cloudflare.Bucket") { + return { + put: async () => {}, + } + } // @ts-ignore - const namespaceId = value.namespaceId - const accountId = ResourceBase.CLOUDFLARE_DEFAULT_ACCOUNT_ID.value - return { - get: (k: string | string[]) => { - const isMulti = Array.isArray(k) - return client.kv.namespaces - .bulkGet(namespaceId, { - keys: Array.isArray(k) ? k : [k], + if (value.type === "sst.cloudflare.Kv") { + const client = new Cloudflare({ + apiToken: ResourceBase.CLOUDFLARE_API_TOKEN.value, + }) + // @ts-ignore + const namespaceId = value.namespaceId + const accountId = ResourceBase.CLOUDFLARE_DEFAULT_ACCOUNT_ID.value + return { + get: (k: string | string[]) => { + const isMulti = Array.isArray(k) + return client.kv.namespaces + .bulkGet(namespaceId, { + keys: Array.isArray(k) ? k : [k], + account_id: accountId, + }) + .then((result) => (isMulti ? new Map(Object.entries(result?.values ?? {})) : result?.values?.[k])) + }, + put: (k: string, v: string, opts?: KVNamespacePutOptions) => + client.kv.namespaces.values.update(namespaceId, k, { account_id: accountId, - }) - .then((result) => (isMulti ? new Map(Object.entries(result?.values ?? {})) : result?.values?.[k])) - }, - put: (k: string, v: string, opts?: KVNamespacePutOptions) => - client.kv.namespaces.values.update(namespaceId, k, { - account_id: accountId, - value: v, - expiration: opts?.expiration, - expiration_ttl: opts?.expirationTtl, - metadata: opts?.metadata, - }), - delete: (k: string) => - client.kv.namespaces.values.delete(namespaceId, k, { - account_id: accountId, - }), - list: (opts?: KVNamespaceListOptions): Promise> => - client.kv.namespaces.keys - .list(namespaceId, { + value: v, + expiration: opts?.expiration, + expiration_ttl: opts?.expirationTtl, + metadata: opts?.metadata, + }), + delete: (k: string) => + client.kv.namespaces.values.delete(namespaceId, k, { account_id: accountId, - prefix: opts?.prefix ?? undefined, - }) - .then((result) => { - return { - keys: result.result, - list_complete: true, - cacheStatus: null, - } }), + list: (opts?: KVNamespaceListOptions): Promise> => + client.kv.namespaces.keys + .list(namespaceId, { + account_id: accountId, + prefix: opts?.prefix ?? undefined, + }) + .then((result) => { + return { + keys: result.result, + list_complete: true, + cacheStatus: null, + } + }), + } } } return value diff --git a/packages/console/resource/sst-env.d.ts b/packages/console/resource/sst-env.d.ts index 0862ae4e377..8e38d38251b 100644 --- a/packages/console/resource/sst-env.d.ts +++ b/packages/console/resource/sst-env.d.ts @@ -6,116 +6,126 @@ import "sst" declare module "sst" { export interface Resource { - ADMIN_SECRET: { - type: "sst.sst.Secret" - value: string - } - AUTH_API_URL: { - type: "sst.sst.Linkable" - value: string - } - AWS_SES_ACCESS_KEY_ID: { - type: "sst.sst.Secret" - value: string - } - AWS_SES_SECRET_ACCESS_KEY: { - type: "sst.sst.Secret" - value: string - } - CLOUDFLARE_API_TOKEN: { - type: "sst.sst.Secret" - value: string - } - CLOUDFLARE_DEFAULT_ACCOUNT_ID: { - type: "sst.sst.Secret" - value: string - } - Console: { - type: "sst.cloudflare.SolidStart" - url: string - } - Database: { - database: string - host: string - password: string - port: number - type: "sst.sst.Linkable" - username: string - } - Desktop: { - type: "sst.cloudflare.StaticSite" - url: string - } - EMAILOCTOPUS_API_KEY: { - type: "sst.sst.Secret" - value: string - } - GITHUB_APP_ID: { - type: "sst.sst.Secret" - value: string - } - GITHUB_APP_PRIVATE_KEY: { - type: "sst.sst.Secret" - value: string - } - GITHUB_CLIENT_ID_CONSOLE: { - type: "sst.sst.Secret" - value: string - } - GITHUB_CLIENT_SECRET_CONSOLE: { - type: "sst.sst.Secret" - value: string - } - GOOGLE_CLIENT_ID: { - type: "sst.sst.Secret" - value: string - } - HONEYCOMB_API_KEY: { - type: "sst.sst.Secret" - value: string - } - STRIPE_SECRET_KEY: { - type: "sst.sst.Secret" - value: string - } - STRIPE_WEBHOOK_SECRET: { - type: "sst.sst.Linkable" - value: string - } - Web: { - type: "sst.cloudflare.Astro" - url: string - } - ZEN_MODELS1: { - type: "sst.sst.Secret" - value: string - } - ZEN_MODELS2: { - type: "sst.sst.Secret" - value: string - } - ZEN_MODELS3: { - type: "sst.sst.Secret" - value: string - } - ZEN_MODELS4: { - type: "sst.sst.Secret" - value: string + "ADMIN_SECRET": { + "type": "sst.sst.Secret" + "value": string + } + "AUTH_API_URL": { + "type": "sst.sst.Linkable" + "value": string + } + "AWS_SES_ACCESS_KEY_ID": { + "type": "sst.sst.Secret" + "value": string + } + "AWS_SES_SECRET_ACCESS_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "CLOUDFLARE_API_TOKEN": { + "type": "sst.sst.Secret" + "value": string + } + "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { + "type": "sst.sst.Secret" + "value": string + } + "Console": { + "type": "sst.cloudflare.SolidStart" + "url": string + } + "Database": { + "database": string + "host": string + "password": string + "port": number + "type": "sst.sst.Linkable" + "username": string + } + "Desktop": { + "type": "sst.cloudflare.StaticSite" + "url": string + } + "EMAILOCTOPUS_API_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_APP_ID": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_APP_PRIVATE_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_CLIENT_ID_CONSOLE": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_CLIENT_SECRET_CONSOLE": { + "type": "sst.sst.Secret" + "value": string + } + "GOOGLE_CLIENT_ID": { + "type": "sst.sst.Secret" + "value": string + } + "HONEYCOMB_API_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "R2AccessKey": { + "type": "sst.sst.Secret" + "value": string + } + "R2SecretKey": { + "type": "sst.sst.Secret" + "value": string + } + "STRIPE_SECRET_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "STRIPE_WEBHOOK_SECRET": { + "type": "sst.sst.Linkable" + "value": string + } + "Web": { + "type": "sst.cloudflare.Astro" + "url": string + } + "ZEN_MODELS1": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS2": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS3": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS4": { + "type": "sst.sst.Secret" + "value": string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types" +// cloudflare +import * as cloudflare from "@cloudflare/workers-types"; declare module "sst" { export interface Resource { - Api: cloudflare.Service - AuthApi: cloudflare.Service - AuthStorage: cloudflare.KVNamespace - Bucket: cloudflare.R2Bucket - GatewayKv: cloudflare.KVNamespace - LogProcessor: cloudflare.Service + "Api": cloudflare.Service + "AuthApi": cloudflare.Service + "AuthStorage": cloudflare.KVNamespace + "Bucket": cloudflare.R2Bucket + "ConsoleData": cloudflare.R2Bucket + "EnterpriseStorage": cloudflare.R2Bucket + "GatewayKv": cloudflare.KVNamespace + "LogProcessor": cloudflare.Service } } import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/desktop/src/sst-env.d.ts b/packages/desktop/src/sst-env.d.ts index 1b1683a1e74..47a8fbec7bf 100644 --- a/packages/desktop/src/sst-env.d.ts +++ b/packages/desktop/src/sst-env.d.ts @@ -2,7 +2,9 @@ /* tslint:disable */ /* eslint-disable */ /// -interface ImportMetaEnv {} +interface ImportMetaEnv { + +} interface ImportMeta { readonly env: ImportMetaEnv -} +} \ No newline at end of file diff --git a/packages/desktop/sst-env.d.ts b/packages/desktop/sst-env.d.ts index 0397645b50f..b6a7e9066ef 100644 --- a/packages/desktop/sst-env.d.ts +++ b/packages/desktop/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/enterprise/sst-env.d.ts b/packages/enterprise/sst-env.d.ts new file mode 100644 index 00000000000..8e38d38251b --- /dev/null +++ b/packages/enterprise/sst-env.d.ts @@ -0,0 +1,131 @@ +/* This file is auto-generated by SST. Do not edit. */ +/* tslint:disable */ +/* eslint-disable */ +/* deno-fmt-ignore-file */ + +import "sst" +declare module "sst" { + export interface Resource { + "ADMIN_SECRET": { + "type": "sst.sst.Secret" + "value": string + } + "AUTH_API_URL": { + "type": "sst.sst.Linkable" + "value": string + } + "AWS_SES_ACCESS_KEY_ID": { + "type": "sst.sst.Secret" + "value": string + } + "AWS_SES_SECRET_ACCESS_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "CLOUDFLARE_API_TOKEN": { + "type": "sst.sst.Secret" + "value": string + } + "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { + "type": "sst.sst.Secret" + "value": string + } + "Console": { + "type": "sst.cloudflare.SolidStart" + "url": string + } + "Database": { + "database": string + "host": string + "password": string + "port": number + "type": "sst.sst.Linkable" + "username": string + } + "Desktop": { + "type": "sst.cloudflare.StaticSite" + "url": string + } + "EMAILOCTOPUS_API_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_APP_ID": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_APP_PRIVATE_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_CLIENT_ID_CONSOLE": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_CLIENT_SECRET_CONSOLE": { + "type": "sst.sst.Secret" + "value": string + } + "GOOGLE_CLIENT_ID": { + "type": "sst.sst.Secret" + "value": string + } + "HONEYCOMB_API_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "R2AccessKey": { + "type": "sst.sst.Secret" + "value": string + } + "R2SecretKey": { + "type": "sst.sst.Secret" + "value": string + } + "STRIPE_SECRET_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "STRIPE_WEBHOOK_SECRET": { + "type": "sst.sst.Linkable" + "value": string + } + "Web": { + "type": "sst.cloudflare.Astro" + "url": string + } + "ZEN_MODELS1": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS2": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS3": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS4": { + "type": "sst.sst.Secret" + "value": string + } + } +} +// cloudflare +import * as cloudflare from "@cloudflare/workers-types"; +declare module "sst" { + export interface Resource { + "Api": cloudflare.Service + "AuthApi": cloudflare.Service + "AuthStorage": cloudflare.KVNamespace + "Bucket": cloudflare.R2Bucket + "ConsoleData": cloudflare.R2Bucket + "EnterpriseStorage": cloudflare.R2Bucket + "GatewayKv": cloudflare.KVNamespace + "LogProcessor": cloudflare.Service + } +} + +import "sst" +export {} \ No newline at end of file diff --git a/packages/function/sst-env.d.ts b/packages/function/sst-env.d.ts index 0862ae4e377..8e38d38251b 100644 --- a/packages/function/sst-env.d.ts +++ b/packages/function/sst-env.d.ts @@ -6,116 +6,126 @@ import "sst" declare module "sst" { export interface Resource { - ADMIN_SECRET: { - type: "sst.sst.Secret" - value: string - } - AUTH_API_URL: { - type: "sst.sst.Linkable" - value: string - } - AWS_SES_ACCESS_KEY_ID: { - type: "sst.sst.Secret" - value: string - } - AWS_SES_SECRET_ACCESS_KEY: { - type: "sst.sst.Secret" - value: string - } - CLOUDFLARE_API_TOKEN: { - type: "sst.sst.Secret" - value: string - } - CLOUDFLARE_DEFAULT_ACCOUNT_ID: { - type: "sst.sst.Secret" - value: string - } - Console: { - type: "sst.cloudflare.SolidStart" - url: string - } - Database: { - database: string - host: string - password: string - port: number - type: "sst.sst.Linkable" - username: string - } - Desktop: { - type: "sst.cloudflare.StaticSite" - url: string - } - EMAILOCTOPUS_API_KEY: { - type: "sst.sst.Secret" - value: string - } - GITHUB_APP_ID: { - type: "sst.sst.Secret" - value: string - } - GITHUB_APP_PRIVATE_KEY: { - type: "sst.sst.Secret" - value: string - } - GITHUB_CLIENT_ID_CONSOLE: { - type: "sst.sst.Secret" - value: string - } - GITHUB_CLIENT_SECRET_CONSOLE: { - type: "sst.sst.Secret" - value: string - } - GOOGLE_CLIENT_ID: { - type: "sst.sst.Secret" - value: string - } - HONEYCOMB_API_KEY: { - type: "sst.sst.Secret" - value: string - } - STRIPE_SECRET_KEY: { - type: "sst.sst.Secret" - value: string - } - STRIPE_WEBHOOK_SECRET: { - type: "sst.sst.Linkable" - value: string - } - Web: { - type: "sst.cloudflare.Astro" - url: string - } - ZEN_MODELS1: { - type: "sst.sst.Secret" - value: string - } - ZEN_MODELS2: { - type: "sst.sst.Secret" - value: string - } - ZEN_MODELS3: { - type: "sst.sst.Secret" - value: string - } - ZEN_MODELS4: { - type: "sst.sst.Secret" - value: string + "ADMIN_SECRET": { + "type": "sst.sst.Secret" + "value": string + } + "AUTH_API_URL": { + "type": "sst.sst.Linkable" + "value": string + } + "AWS_SES_ACCESS_KEY_ID": { + "type": "sst.sst.Secret" + "value": string + } + "AWS_SES_SECRET_ACCESS_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "CLOUDFLARE_API_TOKEN": { + "type": "sst.sst.Secret" + "value": string + } + "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { + "type": "sst.sst.Secret" + "value": string + } + "Console": { + "type": "sst.cloudflare.SolidStart" + "url": string + } + "Database": { + "database": string + "host": string + "password": string + "port": number + "type": "sst.sst.Linkable" + "username": string + } + "Desktop": { + "type": "sst.cloudflare.StaticSite" + "url": string + } + "EMAILOCTOPUS_API_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_APP_ID": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_APP_PRIVATE_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_CLIENT_ID_CONSOLE": { + "type": "sst.sst.Secret" + "value": string + } + "GITHUB_CLIENT_SECRET_CONSOLE": { + "type": "sst.sst.Secret" + "value": string + } + "GOOGLE_CLIENT_ID": { + "type": "sst.sst.Secret" + "value": string + } + "HONEYCOMB_API_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "R2AccessKey": { + "type": "sst.sst.Secret" + "value": string + } + "R2SecretKey": { + "type": "sst.sst.Secret" + "value": string + } + "STRIPE_SECRET_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "STRIPE_WEBHOOK_SECRET": { + "type": "sst.sst.Linkable" + "value": string + } + "Web": { + "type": "sst.cloudflare.Astro" + "url": string + } + "ZEN_MODELS1": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS2": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS3": { + "type": "sst.sst.Secret" + "value": string + } + "ZEN_MODELS4": { + "type": "sst.sst.Secret" + "value": string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types" +// cloudflare +import * as cloudflare from "@cloudflare/workers-types"; declare module "sst" { export interface Resource { - Api: cloudflare.Service - AuthApi: cloudflare.Service - AuthStorage: cloudflare.KVNamespace - Bucket: cloudflare.R2Bucket - GatewayKv: cloudflare.KVNamespace - LogProcessor: cloudflare.Service + "Api": cloudflare.Service + "AuthApi": cloudflare.Service + "AuthStorage": cloudflare.KVNamespace + "Bucket": cloudflare.R2Bucket + "ConsoleData": cloudflare.R2Bucket + "EnterpriseStorage": cloudflare.R2Bucket + "GatewayKv": cloudflare.KVNamespace + "LogProcessor": cloudflare.Service } } import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index bc212629d33..d632085cfc1 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -676,7 +676,7 @@ export namespace Provider { if (providerID === "github-copilot") { priority = priority.filter((m) => m !== "claude-haiku-4.5") } - if (providerID === "opencode" || providerID === "local") { + if (providerID.startsWith("opencode")) { priority = ["gpt-5-nano"] } for (const item of priority) { diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index 6b255981b78..f550005b341 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -534,7 +534,7 @@ export namespace SessionPrompt { } }, headers: { - ...(model.providerID === "opencode" + ...(model.providerID.startsWith("opencode") ? { "x-opencode-session": sessionID, "x-opencode-request": lastUser.id, diff --git a/packages/opencode/sst-env.d.ts b/packages/opencode/sst-env.d.ts index 0397645b50f..b6a7e9066ef 100644 --- a/packages/opencode/sst-env.d.ts +++ b/packages/opencode/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/plugin/sst-env.d.ts b/packages/plugin/sst-env.d.ts index 0397645b50f..b6a7e9066ef 100644 --- a/packages/plugin/sst-env.d.ts +++ b/packages/plugin/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/script/sst-env.d.ts b/packages/script/sst-env.d.ts index 0397645b50f..b6a7e9066ef 100644 --- a/packages/script/sst-env.d.ts +++ b/packages/script/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/sdk/js/sst-env.d.ts b/packages/sdk/js/sst-env.d.ts index bd558821739..9b9de73273f 100644 --- a/packages/sdk/js/sst-env.d.ts +++ b/packages/sdk/js/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/sdk/python/sst.pyi b/packages/sdk/python/sst.pyi index 0598229ca34..1c423e9ac5c 100644 --- a/packages/sdk/python/sst.pyi +++ b/packages/sdk/python/sst.pyi @@ -39,6 +39,9 @@ class Resource: class Console: type: str url: str + class ConsoleData: + name: str + type: str class Database: database: str host: str @@ -52,6 +55,9 @@ class Resource: class EMAILOCTOPUS_API_KEY: type: str value: str + class EnterpriseStorage: + name: str + type: str class GITHUB_APP_ID: type: str value: str @@ -75,6 +81,12 @@ class Resource: value: str class LogProcessor: type: str + class R2AccessKey: + type: str + value: str + class R2SecretKey: + type: str + value: str class STRIPE_SECRET_KEY: type: str value: str diff --git a/packages/slack/sst-env.d.ts b/packages/slack/sst-env.d.ts index 0397645b50f..b6a7e9066ef 100644 --- a/packages/slack/sst-env.d.ts +++ b/packages/slack/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/tauri/sst-env.d.ts b/packages/tauri/sst-env.d.ts new file mode 100644 index 00000000000..b6a7e9066ef --- /dev/null +++ b/packages/tauri/sst-env.d.ts @@ -0,0 +1,9 @@ +/* This file is auto-generated by SST. Do not edit. */ +/* tslint:disable */ +/* eslint-disable */ +/* deno-fmt-ignore-file */ + +/// + +import "sst" +export {} \ No newline at end of file diff --git a/packages/ui/sst-env.d.ts b/packages/ui/sst-env.d.ts index 0397645b50f..b6a7e9066ef 100644 --- a/packages/ui/sst-env.d.ts +++ b/packages/ui/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/util/sst-env.d.ts b/packages/util/sst-env.d.ts index 0397645b50f..b6a7e9066ef 100644 --- a/packages/util/sst-env.d.ts +++ b/packages/util/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} +export {} \ No newline at end of file diff --git a/packages/web/sst-env.d.ts b/packages/web/sst-env.d.ts index 0397645b50f..b6a7e9066ef 100644 --- a/packages/web/sst-env.d.ts +++ b/packages/web/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} +export {} \ No newline at end of file diff --git a/sdks/vscode/sst-env.d.ts b/sdks/vscode/sst-env.d.ts index 0397645b50f..b6a7e9066ef 100644 --- a/sdks/vscode/sst-env.d.ts +++ b/sdks/vscode/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} +export {} \ No newline at end of file diff --git a/sst-env.d.ts b/sst-env.d.ts index 171ff4a071a..361c2fdfa8e 100644 --- a/sst-env.d.ts +++ b/sst-env.d.ts @@ -5,128 +5,144 @@ declare module "sst" { export interface Resource { - ADMIN_SECRET: { - type: "sst.sst.Secret" - value: string - } - AUTH_API_URL: { - type: "sst.sst.Linkable" - value: string - } - AWS_SES_ACCESS_KEY_ID: { - type: "sst.sst.Secret" - value: string - } - AWS_SES_SECRET_ACCESS_KEY: { - type: "sst.sst.Secret" - value: string - } - Api: { - type: "sst.cloudflare.Worker" - url: string + "ADMIN_SECRET": { + "type": "sst.sst.Secret" + "value": string + } + "AUTH_API_URL": { + "type": "sst.sst.Linkable" + "value": string + } + "AWS_SES_ACCESS_KEY_ID": { + "type": "sst.sst.Secret" + "value": string + } + "AWS_SES_SECRET_ACCESS_KEY": { + "type": "sst.sst.Secret" + "value": string + } + "Api": { + "type": "sst.cloudflare.Worker" + "url": string + } + "AuthApi": { + "type": "sst.cloudflare.Worker" + "url": string + } + "AuthStorage": { + "namespaceId": string + "type": "sst.cloudflare.Kv" + } + "Bucket": { + "name": string + "type": "sst.cloudflare.Bucket" + } + "CLOUDFLARE_API_TOKEN": { + "type": "sst.sst.Secret" + "value": string } - AuthApi: { - type: "sst.cloudflare.Worker" - url: string + "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { + "type": "sst.sst.Secret" + "value": string } - AuthStorage: { - namespaceId: string - type: "sst.cloudflare.Kv" + "Console": { + "type": "sst.cloudflare.SolidStart" + "url": string } - Bucket: { - name: string - type: "sst.cloudflare.Bucket" + "ConsoleData": { + "name": string + "type": "sst.cloudflare.Bucket" } - CLOUDFLARE_API_TOKEN: { - type: "sst.sst.Secret" - value: string + "Database": { + "database": string + "host": string + "password": string + "port": number + "type": "sst.sst.Linkable" + "username": string } - CLOUDFLARE_DEFAULT_ACCOUNT_ID: { - type: "sst.sst.Secret" - value: string + "Desktop": { + "type": "sst.cloudflare.StaticSite" + "url": string } - Console: { - type: "sst.cloudflare.SolidStart" - url: string + "EMAILOCTOPUS_API_KEY": { + "type": "sst.sst.Secret" + "value": string } - Database: { - database: string - host: string - password: string - port: number - type: "sst.sst.Linkable" - username: string + "EnterpriseStorage": { + "name": string + "type": "sst.cloudflare.Bucket" } - Desktop: { - type: "sst.cloudflare.StaticSite" - url: string + "GITHUB_APP_ID": { + "type": "sst.sst.Secret" + "value": string } - EMAILOCTOPUS_API_KEY: { - type: "sst.sst.Secret" - value: string + "GITHUB_APP_PRIVATE_KEY": { + "type": "sst.sst.Secret" + "value": string } - GITHUB_APP_ID: { - type: "sst.sst.Secret" - value: string + "GITHUB_CLIENT_ID_CONSOLE": { + "type": "sst.sst.Secret" + "value": string } - GITHUB_APP_PRIVATE_KEY: { - type: "sst.sst.Secret" - value: string + "GITHUB_CLIENT_SECRET_CONSOLE": { + "type": "sst.sst.Secret" + "value": string } - GITHUB_CLIENT_ID_CONSOLE: { - type: "sst.sst.Secret" - value: string + "GOOGLE_CLIENT_ID": { + "type": "sst.sst.Secret" + "value": string } - GITHUB_CLIENT_SECRET_CONSOLE: { - type: "sst.sst.Secret" - value: string + "GatewayKv": { + "namespaceId": string + "type": "sst.cloudflare.Kv" } - GOOGLE_CLIENT_ID: { - type: "sst.sst.Secret" - value: string + "HONEYCOMB_API_KEY": { + "type": "sst.sst.Secret" + "value": string } - GatewayKv: { - namespaceId: string - type: "sst.cloudflare.Kv" + "LogProcessor": { + "type": "sst.cloudflare.Worker" } - HONEYCOMB_API_KEY: { - type: "sst.sst.Secret" - value: string + "R2AccessKey": { + "type": "sst.sst.Secret" + "value": string } - LogProcessor: { - type: "sst.cloudflare.Worker" + "R2SecretKey": { + "type": "sst.sst.Secret" + "value": string } - STRIPE_SECRET_KEY: { - type: "sst.sst.Secret" - value: string + "STRIPE_SECRET_KEY": { + "type": "sst.sst.Secret" + "value": string } - STRIPE_WEBHOOK_SECRET: { - type: "sst.sst.Linkable" - value: string + "STRIPE_WEBHOOK_SECRET": { + "type": "sst.sst.Linkable" + "value": string } - Web: { - type: "sst.cloudflare.Astro" - url: string + "Web": { + "type": "sst.cloudflare.Astro" + "url": string } - ZEN_MODELS1: { - type: "sst.sst.Secret" - value: string + "ZEN_MODELS1": { + "type": "sst.sst.Secret" + "value": string } - ZEN_MODELS2: { - type: "sst.sst.Secret" - value: string + "ZEN_MODELS2": { + "type": "sst.sst.Secret" + "value": string } - ZEN_MODELS3: { - type: "sst.sst.Secret" - value: string + "ZEN_MODELS3": { + "type": "sst.sst.Secret" + "value": string } - ZEN_MODELS4: { - type: "sst.sst.Secret" - value: string + "ZEN_MODELS4": { + "type": "sst.sst.Secret" + "value": string } } } /// import "sst" -export {} +export {} \ No newline at end of file From 4a81bd0f50a8d07159a414807b567a3f16967ed8 Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 23 Nov 2025 15:58:55 -0500 Subject: [PATCH 26/66] wip: zen --- packages/console/app/src/routes/zen/util/handler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/console/app/src/routes/zen/util/handler.ts b/packages/console/app/src/routes/zen/util/handler.ts index c40db6e1d4e..2e4993787ad 100644 --- a/packages/console/app/src/routes/zen/util/handler.ts +++ b/packages/console/app/src/routes/zen/util/handler.ts @@ -52,8 +52,8 @@ export async function handler( const model = opts.parseModel(url, body) const isStream = opts.parseIsStream(url, body) const ip = input.request.headers.get("x-real-ip") ?? "" - const sessionId = input.request.headers.get("x-opencode-session") - const requestId = input.request.headers.get("x-opencode-request") + const sessionId = input.request.headers.get("x-opencode-session") ?? "" + const requestId = input.request.headers.get("x-opencode-request") ?? "" logger.metric({ is_tream: isStream, session: sessionId, From eb009d595921e1cdc91f8c2e396e0a86e3b66117 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sun, 23 Nov 2025 20:59:37 +0000 Subject: [PATCH 27/66] chore: format code --- github/sst-env.d.ts | 2 +- packages/console/app/sst-env.d.ts | 2 +- packages/console/core/sst-env.d.ts | 228 ++++++++++++------------- packages/console/function/sst-env.d.ts | 228 ++++++++++++------------- packages/console/mail/sst-env.d.ts | 2 +- packages/console/resource/sst-env.d.ts | 228 ++++++++++++------------- packages/desktop/src/sst-env.d.ts | 6 +- packages/desktop/sst-env.d.ts | 2 +- packages/enterprise/sst-env.d.ts | 228 ++++++++++++------------- packages/function/sst-env.d.ts | 228 ++++++++++++------------- packages/opencode/sst-env.d.ts | 2 +- packages/plugin/sst-env.d.ts | 2 +- packages/script/sst-env.d.ts | 2 +- packages/sdk/js/sst-env.d.ts | 2 +- packages/slack/sst-env.d.ts | 2 +- packages/tauri/sst-env.d.ts | 2 +- packages/ui/sst-env.d.ts | 2 +- packages/util/sst-env.d.ts | 2 +- packages/web/sst-env.d.ts | 2 +- sdks/vscode/sst-env.d.ts | 2 +- sst-env.d.ts | 222 ++++++++++++------------ 21 files changed, 697 insertions(+), 699 deletions(-) diff --git a/github/sst-env.d.ts b/github/sst-env.d.ts index f742a120044..6b69016e718 100644 --- a/github/sst-env.d.ts +++ b/github/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/console/app/sst-env.d.ts b/packages/console/app/sst-env.d.ts index 9b9de73273f..bd558821739 100644 --- a/packages/console/app/sst-env.d.ts +++ b/packages/console/app/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/console/core/sst-env.d.ts b/packages/console/core/sst-env.d.ts index 8e38d38251b..08710b63eef 100644 --- a/packages/console/core/sst-env.d.ts +++ b/packages/console/core/sst-env.d.ts @@ -6,126 +6,126 @@ import "sst" declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string - } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string - } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string - } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "CLOUDFLARE_API_TOKEN": { - "type": "sst.sst.Secret" - "value": string - } - "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string - } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string - } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string - } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "R2AccessKey": { - "type": "sst.sst.Secret" - "value": string - } - "R2SecretKey": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string - } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string - } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS3": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS4": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string + } + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string + } + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string + } + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string + } + CLOUDFLARE_API_TOKEN: { + type: "sst.sst.Secret" + value: string + } + CLOUDFLARE_DEFAULT_ACCOUNT_ID: { + type: "sst.sst.Secret" + value: string + } + Console: { + type: "sst.cloudflare.SolidStart" + url: string + } + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string + } + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string + } + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string + } + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string + } + R2AccessKey: { + type: "sst.sst.Secret" + value: string + } + R2SecretKey: { + type: "sst.sst.Secret" + value: string + } + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string + } + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string + } + Web: { + type: "sst.cloudflare.Astro" + url: string + } + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS3: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS4: { + type: "sst.sst.Secret" + value: string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types"; +// cloudflare +import * as cloudflare from "@cloudflare/workers-types" declare module "sst" { export interface Resource { - "Api": cloudflare.Service - "AuthApi": cloudflare.Service - "AuthStorage": cloudflare.KVNamespace - "Bucket": cloudflare.R2Bucket - "ConsoleData": cloudflare.R2Bucket - "EnterpriseStorage": cloudflare.R2Bucket - "GatewayKv": cloudflare.KVNamespace - "LogProcessor": cloudflare.Service + Api: cloudflare.Service + AuthApi: cloudflare.Service + AuthStorage: cloudflare.KVNamespace + Bucket: cloudflare.R2Bucket + ConsoleData: cloudflare.R2Bucket + EnterpriseStorage: cloudflare.R2Bucket + GatewayKv: cloudflare.KVNamespace + LogProcessor: cloudflare.Service } } import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/console/function/sst-env.d.ts b/packages/console/function/sst-env.d.ts index 8e38d38251b..08710b63eef 100644 --- a/packages/console/function/sst-env.d.ts +++ b/packages/console/function/sst-env.d.ts @@ -6,126 +6,126 @@ import "sst" declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string - } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string - } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string - } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "CLOUDFLARE_API_TOKEN": { - "type": "sst.sst.Secret" - "value": string - } - "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string - } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string - } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string - } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "R2AccessKey": { - "type": "sst.sst.Secret" - "value": string - } - "R2SecretKey": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string - } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string - } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS3": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS4": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string + } + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string + } + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string + } + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string + } + CLOUDFLARE_API_TOKEN: { + type: "sst.sst.Secret" + value: string + } + CLOUDFLARE_DEFAULT_ACCOUNT_ID: { + type: "sst.sst.Secret" + value: string + } + Console: { + type: "sst.cloudflare.SolidStart" + url: string + } + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string + } + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string + } + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string + } + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string + } + R2AccessKey: { + type: "sst.sst.Secret" + value: string + } + R2SecretKey: { + type: "sst.sst.Secret" + value: string + } + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string + } + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string + } + Web: { + type: "sst.cloudflare.Astro" + url: string + } + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS3: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS4: { + type: "sst.sst.Secret" + value: string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types"; +// cloudflare +import * as cloudflare from "@cloudflare/workers-types" declare module "sst" { export interface Resource { - "Api": cloudflare.Service - "AuthApi": cloudflare.Service - "AuthStorage": cloudflare.KVNamespace - "Bucket": cloudflare.R2Bucket - "ConsoleData": cloudflare.R2Bucket - "EnterpriseStorage": cloudflare.R2Bucket - "GatewayKv": cloudflare.KVNamespace - "LogProcessor": cloudflare.Service + Api: cloudflare.Service + AuthApi: cloudflare.Service + AuthStorage: cloudflare.KVNamespace + Bucket: cloudflare.R2Bucket + ConsoleData: cloudflare.R2Bucket + EnterpriseStorage: cloudflare.R2Bucket + GatewayKv: cloudflare.KVNamespace + LogProcessor: cloudflare.Service } } import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/console/mail/sst-env.d.ts b/packages/console/mail/sst-env.d.ts index 9b9de73273f..bd558821739 100644 --- a/packages/console/mail/sst-env.d.ts +++ b/packages/console/mail/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/console/resource/sst-env.d.ts b/packages/console/resource/sst-env.d.ts index 8e38d38251b..08710b63eef 100644 --- a/packages/console/resource/sst-env.d.ts +++ b/packages/console/resource/sst-env.d.ts @@ -6,126 +6,126 @@ import "sst" declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string - } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string - } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string - } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "CLOUDFLARE_API_TOKEN": { - "type": "sst.sst.Secret" - "value": string - } - "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string - } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string - } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string - } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "R2AccessKey": { - "type": "sst.sst.Secret" - "value": string - } - "R2SecretKey": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string - } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string - } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS3": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS4": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string + } + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string + } + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string + } + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string + } + CLOUDFLARE_API_TOKEN: { + type: "sst.sst.Secret" + value: string + } + CLOUDFLARE_DEFAULT_ACCOUNT_ID: { + type: "sst.sst.Secret" + value: string + } + Console: { + type: "sst.cloudflare.SolidStart" + url: string + } + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string + } + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string + } + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string + } + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string + } + R2AccessKey: { + type: "sst.sst.Secret" + value: string + } + R2SecretKey: { + type: "sst.sst.Secret" + value: string + } + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string + } + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string + } + Web: { + type: "sst.cloudflare.Astro" + url: string + } + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS3: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS4: { + type: "sst.sst.Secret" + value: string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types"; +// cloudflare +import * as cloudflare from "@cloudflare/workers-types" declare module "sst" { export interface Resource { - "Api": cloudflare.Service - "AuthApi": cloudflare.Service - "AuthStorage": cloudflare.KVNamespace - "Bucket": cloudflare.R2Bucket - "ConsoleData": cloudflare.R2Bucket - "EnterpriseStorage": cloudflare.R2Bucket - "GatewayKv": cloudflare.KVNamespace - "LogProcessor": cloudflare.Service + Api: cloudflare.Service + AuthApi: cloudflare.Service + AuthStorage: cloudflare.KVNamespace + Bucket: cloudflare.R2Bucket + ConsoleData: cloudflare.R2Bucket + EnterpriseStorage: cloudflare.R2Bucket + GatewayKv: cloudflare.KVNamespace + LogProcessor: cloudflare.Service } } import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/desktop/src/sst-env.d.ts b/packages/desktop/src/sst-env.d.ts index 47a8fbec7bf..1b1683a1e74 100644 --- a/packages/desktop/src/sst-env.d.ts +++ b/packages/desktop/src/sst-env.d.ts @@ -2,9 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /// -interface ImportMetaEnv { - -} +interface ImportMetaEnv {} interface ImportMeta { readonly env: ImportMetaEnv -} \ No newline at end of file +} diff --git a/packages/desktop/sst-env.d.ts b/packages/desktop/sst-env.d.ts index b6a7e9066ef..0397645b50f 100644 --- a/packages/desktop/sst-env.d.ts +++ b/packages/desktop/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/enterprise/sst-env.d.ts b/packages/enterprise/sst-env.d.ts index 8e38d38251b..08710b63eef 100644 --- a/packages/enterprise/sst-env.d.ts +++ b/packages/enterprise/sst-env.d.ts @@ -6,126 +6,126 @@ import "sst" declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string - } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string - } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string - } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "CLOUDFLARE_API_TOKEN": { - "type": "sst.sst.Secret" - "value": string - } - "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string - } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string - } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string - } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "R2AccessKey": { - "type": "sst.sst.Secret" - "value": string - } - "R2SecretKey": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string - } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string - } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS3": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS4": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string + } + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string + } + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string + } + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string + } + CLOUDFLARE_API_TOKEN: { + type: "sst.sst.Secret" + value: string + } + CLOUDFLARE_DEFAULT_ACCOUNT_ID: { + type: "sst.sst.Secret" + value: string + } + Console: { + type: "sst.cloudflare.SolidStart" + url: string + } + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string + } + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string + } + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string + } + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string + } + R2AccessKey: { + type: "sst.sst.Secret" + value: string + } + R2SecretKey: { + type: "sst.sst.Secret" + value: string + } + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string + } + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string + } + Web: { + type: "sst.cloudflare.Astro" + url: string + } + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS3: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS4: { + type: "sst.sst.Secret" + value: string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types"; +// cloudflare +import * as cloudflare from "@cloudflare/workers-types" declare module "sst" { export interface Resource { - "Api": cloudflare.Service - "AuthApi": cloudflare.Service - "AuthStorage": cloudflare.KVNamespace - "Bucket": cloudflare.R2Bucket - "ConsoleData": cloudflare.R2Bucket - "EnterpriseStorage": cloudflare.R2Bucket - "GatewayKv": cloudflare.KVNamespace - "LogProcessor": cloudflare.Service + Api: cloudflare.Service + AuthApi: cloudflare.Service + AuthStorage: cloudflare.KVNamespace + Bucket: cloudflare.R2Bucket + ConsoleData: cloudflare.R2Bucket + EnterpriseStorage: cloudflare.R2Bucket + GatewayKv: cloudflare.KVNamespace + LogProcessor: cloudflare.Service } } import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/function/sst-env.d.ts b/packages/function/sst-env.d.ts index 8e38d38251b..08710b63eef 100644 --- a/packages/function/sst-env.d.ts +++ b/packages/function/sst-env.d.ts @@ -6,126 +6,126 @@ import "sst" declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string - } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string - } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string - } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "CLOUDFLARE_API_TOKEN": { - "type": "sst.sst.Secret" - "value": string - } - "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string - } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string - } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string - } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "R2AccessKey": { - "type": "sst.sst.Secret" - "value": string - } - "R2SecretKey": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string - } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string - } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS3": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS4": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string + } + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string + } + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string + } + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string + } + CLOUDFLARE_API_TOKEN: { + type: "sst.sst.Secret" + value: string + } + CLOUDFLARE_DEFAULT_ACCOUNT_ID: { + type: "sst.sst.Secret" + value: string + } + Console: { + type: "sst.cloudflare.SolidStart" + url: string + } + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string + } + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string + } + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string + } + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string + } + R2AccessKey: { + type: "sst.sst.Secret" + value: string + } + R2SecretKey: { + type: "sst.sst.Secret" + value: string + } + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string + } + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string + } + Web: { + type: "sst.cloudflare.Astro" + url: string + } + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS3: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS4: { + type: "sst.sst.Secret" + value: string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types"; +// cloudflare +import * as cloudflare from "@cloudflare/workers-types" declare module "sst" { export interface Resource { - "Api": cloudflare.Service - "AuthApi": cloudflare.Service - "AuthStorage": cloudflare.KVNamespace - "Bucket": cloudflare.R2Bucket - "ConsoleData": cloudflare.R2Bucket - "EnterpriseStorage": cloudflare.R2Bucket - "GatewayKv": cloudflare.KVNamespace - "LogProcessor": cloudflare.Service + Api: cloudflare.Service + AuthApi: cloudflare.Service + AuthStorage: cloudflare.KVNamespace + Bucket: cloudflare.R2Bucket + ConsoleData: cloudflare.R2Bucket + EnterpriseStorage: cloudflare.R2Bucket + GatewayKv: cloudflare.KVNamespace + LogProcessor: cloudflare.Service } } import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/opencode/sst-env.d.ts b/packages/opencode/sst-env.d.ts index b6a7e9066ef..0397645b50f 100644 --- a/packages/opencode/sst-env.d.ts +++ b/packages/opencode/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/plugin/sst-env.d.ts b/packages/plugin/sst-env.d.ts index b6a7e9066ef..0397645b50f 100644 --- a/packages/plugin/sst-env.d.ts +++ b/packages/plugin/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/script/sst-env.d.ts b/packages/script/sst-env.d.ts index b6a7e9066ef..0397645b50f 100644 --- a/packages/script/sst-env.d.ts +++ b/packages/script/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/sdk/js/sst-env.d.ts b/packages/sdk/js/sst-env.d.ts index 9b9de73273f..bd558821739 100644 --- a/packages/sdk/js/sst-env.d.ts +++ b/packages/sdk/js/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/slack/sst-env.d.ts b/packages/slack/sst-env.d.ts index b6a7e9066ef..0397645b50f 100644 --- a/packages/slack/sst-env.d.ts +++ b/packages/slack/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/tauri/sst-env.d.ts b/packages/tauri/sst-env.d.ts index b6a7e9066ef..0397645b50f 100644 --- a/packages/tauri/sst-env.d.ts +++ b/packages/tauri/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/ui/sst-env.d.ts b/packages/ui/sst-env.d.ts index b6a7e9066ef..0397645b50f 100644 --- a/packages/ui/sst-env.d.ts +++ b/packages/ui/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/util/sst-env.d.ts b/packages/util/sst-env.d.ts index b6a7e9066ef..0397645b50f 100644 --- a/packages/util/sst-env.d.ts +++ b/packages/util/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/web/sst-env.d.ts b/packages/web/sst-env.d.ts index b6a7e9066ef..0397645b50f 100644 --- a/packages/web/sst-env.d.ts +++ b/packages/web/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/sdks/vscode/sst-env.d.ts b/sdks/vscode/sst-env.d.ts index b6a7e9066ef..0397645b50f 100644 --- a/sdks/vscode/sst-env.d.ts +++ b/sdks/vscode/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/sst-env.d.ts b/sst-env.d.ts index 361c2fdfa8e..f877fc89ed9 100644 --- a/sst-env.d.ts +++ b/sst-env.d.ts @@ -5,144 +5,144 @@ declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string - } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string - } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string - } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "Api": { - "type": "sst.cloudflare.Worker" - "url": string - } - "AuthApi": { - "type": "sst.cloudflare.Worker" - "url": string - } - "AuthStorage": { - "namespaceId": string - "type": "sst.cloudflare.Kv" - } - "Bucket": { - "name": string - "type": "sst.cloudflare.Bucket" - } - "CLOUDFLARE_API_TOKEN": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string + } + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string + } + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string + } + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string + } + Api: { + type: "sst.cloudflare.Worker" + url: string + } + AuthApi: { + type: "sst.cloudflare.Worker" + url: string + } + AuthStorage: { + namespaceId: string + type: "sst.cloudflare.Kv" + } + Bucket: { + name: string + type: "sst.cloudflare.Bucket" + } + CLOUDFLARE_API_TOKEN: { + type: "sst.sst.Secret" + value: string } - "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { - "type": "sst.sst.Secret" - "value": string + CLOUDFLARE_DEFAULT_ACCOUNT_ID: { + type: "sst.sst.Secret" + value: string } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string + Console: { + type: "sst.cloudflare.SolidStart" + url: string } - "ConsoleData": { - "name": string - "type": "sst.cloudflare.Bucket" + ConsoleData: { + name: string + type: "sst.cloudflare.Bucket" } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string } - "EnterpriseStorage": { - "name": string - "type": "sst.cloudflare.Bucket" + EnterpriseStorage: { + name: string + type: "sst.cloudflare.Bucket" } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string } - "GatewayKv": { - "namespaceId": string - "type": "sst.cloudflare.Kv" + GatewayKv: { + namespaceId: string + type: "sst.cloudflare.Kv" } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string } - "LogProcessor": { - "type": "sst.cloudflare.Worker" + LogProcessor: { + type: "sst.cloudflare.Worker" } - "R2AccessKey": { - "type": "sst.sst.Secret" - "value": string + R2AccessKey: { + type: "sst.sst.Secret" + value: string } - "R2SecretKey": { - "type": "sst.sst.Secret" - "value": string + R2SecretKey: { + type: "sst.sst.Secret" + value: string } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string + Web: { + type: "sst.cloudflare.Astro" + url: string } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string } - "ZEN_MODELS3": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS3: { + type: "sst.sst.Secret" + value: string } - "ZEN_MODELS4": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS4: { + type: "sst.sst.Secret" + value: string } } } /// import "sst" -export {} \ No newline at end of file +export {} From b4fd4bb25757250b1bcd4da9e6398011ed07e2f3 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Mon, 24 Nov 2025 12:51:15 +0800 Subject: [PATCH 28/66] fix: add explicit fallback model and prevent direct opencode provider calls (#4653) Co-authored-by: Aiden Cline --- packages/opencode/src/provider/provider.ts | 9 ++++++++- packages/opencode/src/session/prompt.ts | 3 ++- packages/opencode/src/session/summary.ts | 5 ++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index d632085cfc1..e6f7f5f888c 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -685,7 +685,14 @@ export namespace Provider { } } } - return getModel("opencode", "gpt-5-nano") + + // Check if opencode provider is available before using it + const opencodeProvider = await state().then((state) => state.providers["opencode"]) + if (opencodeProvider && opencodeProvider.info.models["gpt-5-nano"]) { + return getModel("opencode", "gpt-5-nano") + } + + return undefined } const priority = ["gpt-5", "claude-sonnet-4", "big-pickle", "gemini-3-pro"] diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index f550005b341..b3c3c467168 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -1408,7 +1408,8 @@ export namespace SessionPrompt { input.history.filter((m) => m.info.role === "user" && !m.parts.every((p) => "synthetic" in p && p.synthetic)) .length === 1 if (!isFirst) return - const small = await Provider.getSmallModel(input.providerID) + const small = + (await Provider.getSmallModel(input.providerID)) ?? (await Provider.getModel(input.providerID, input.modelID)) const options = pipe( {}, mergeDeep(ProviderTransform.options(small.providerID, small.modelID, small.npm ?? "", input.session.id)), diff --git a/packages/opencode/src/session/summary.ts b/packages/opencode/src/session/summary.ts index de2ef2e5c92..d9247f182dc 100644 --- a/packages/opencode/src/session/summary.ts +++ b/packages/opencode/src/session/summary.ts @@ -73,7 +73,10 @@ export namespace SessionSummary { await Session.updateMessage(userMsg) const assistantMsg = messages.find((m) => m.info.role === "assistant")!.info as MessageV2.Assistant - const small = await Provider.getSmallModel(assistantMsg.providerID) + const small = + (await Provider.getSmallModel(assistantMsg.providerID)) ?? + (await Provider.getModel(assistantMsg.providerID, assistantMsg.modelID)) + const options = pipe( {}, mergeDeep(ProviderTransform.options(small.providerID, small.modelID, small.npm ?? "", assistantMsg.sessionID)), From a3a239967f170423e91382bfdaf1058755befbb8 Mon Sep 17 00:00:00 2001 From: Albert O'Shea Date: Mon, 24 Nov 2025 15:54:29 +1100 Subject: [PATCH 29/66] nix: bundle js dist with bun and patch tree-sitter wasm paths (#4644) Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Co-authored-by: Github Action --- nix/bundle.ts | 40 +++++++++ nix/opencode.nix | 93 +++++++++++++-------- nix/scripts/canonicalize-node-modules.ts | 31 +++++-- nix/scripts/patch-wasm.ts | 39 +++++++++ packages/opencode/src/cli/cmd/tui/thread.ts | 14 ++-- 5 files changed, 168 insertions(+), 49 deletions(-) create mode 100644 nix/bundle.ts create mode 100644 nix/scripts/patch-wasm.ts diff --git a/nix/bundle.ts b/nix/bundle.ts new file mode 100644 index 00000000000..effb1dff7cc --- /dev/null +++ b/nix/bundle.ts @@ -0,0 +1,40 @@ +#!/usr/bin/env bun + +import solidPlugin from "./node_modules/@opentui/solid/scripts/solid-plugin" +import path from "path" +import fs from "fs" + +const dir = process.cwd() +const parser = fs.realpathSync(path.join(dir, "node_modules/@opentui/core/parser.worker.js")) +const worker = "./src/cli/cmd/tui/worker.ts" +const version = process.env.OPENCODE_VERSION ?? "local" +const channel = process.env.OPENCODE_CHANNEL ?? "local" + +fs.rmSync(path.join(dir, "dist"), { recursive: true, force: true }) + +const result = await Bun.build({ + entrypoints: ["./src/index.ts", worker, parser], + outdir: "./dist", + target: "bun", + sourcemap: "none", + tsconfig: "./tsconfig.json", + plugins: [solidPlugin], + external: ["@opentui/core"], + define: { + OPENCODE_VERSION: `'${version}'`, + OPENCODE_CHANNEL: `'${channel}'`, + // Leave undefined so runtime picks bundled/dist worker or fallback in code. + OPENCODE_WORKER_PATH: "undefined", + OTUI_TREE_SITTER_WORKER_PATH: 'new URL("./cli/cmd/tui/parser.worker.js", import.meta.url).href', + }, +}) + +if (!result.success) { + console.error("bundle failed") + for (const log of result.logs) console.error(log) + process.exit(1) +} + +const parserOut = path.join(dir, "dist/src/cli/cmd/tui/parser.worker.js") +fs.mkdirSync(path.dirname(parserOut), { recursive: true }) +await Bun.write(parserOut, Bun.file(parser)) diff --git a/nix/opencode.nix b/nix/opencode.nix index bec2997608e..ff536cf8ff8 100644 --- a/nix/opencode.nix +++ b/nix/opencode.nix @@ -1,4 +1,4 @@ -{ lib, stdenv, stdenvNoCC, bun, fzf, ripgrep, makeBinaryWrapper }: +{ lib, stdenvNoCC, bun, fzf, ripgrep, makeBinaryWrapper }: args: let scripts = args.scripts; @@ -28,64 +28,89 @@ stdenvNoCC.mkDerivation (finalAttrs: { makeBinaryWrapper ]; - configurePhase = '' - runHook preConfigure - cp -R ${finalAttrs.node_modules}/. . - runHook postConfigure - ''; - env.MODELS_DEV_API_JSON = args.modelsDev; env.OPENCODE_VERSION = args.version; env.OPENCODE_CHANNEL = "stable"; + dontConfigure = true; buildPhase = '' runHook preBuild - cp ${scripts + "/bun-build.ts"} bun-build.ts + cp -r ${finalAttrs.node_modules}/node_modules . + cp -r ${finalAttrs.node_modules}/packages . - substituteInPlace bun-build.ts \ - --replace '@VERSION@' "${finalAttrs.version}" + ( + cd packages/opencode - export BUN_COMPILE_TARGET=${args.target} - bun --bun bun-build.ts + chmod -R u+w ./node_modules + mkdir -p ./node_modules/@opencode-ai + rm -f ./node_modules/@opencode-ai/{script,sdk,plugin} + ln -s $(pwd)/../../packages/script ./node_modules/@opencode-ai/script + ln -s $(pwd)/../../packages/sdk/js ./node_modules/@opencode-ai/sdk + ln -s $(pwd)/../../packages/plugin ./node_modules/@opencode-ai/plugin + + cp ${./bundle.ts} ./bundle.ts + chmod +x ./bundle.ts + bun run ./bundle.ts + ) runHook postBuild ''; - dontStrip = true; - installPhase = '' runHook preInstall cd packages/opencode - if [ ! -f opencode ]; then - echo "ERROR: opencode binary not found in $(pwd)" - ls -la + if [ ! -d dist ]; then + echo "ERROR: dist directory missing after bundle step" exit 1 fi - if [ ! -f opencode-worker.js ]; then - echo "ERROR: opencode worker bundle not found in $(pwd)" - ls -la + + mkdir -p $out/lib/opencode + cp -r dist $out/lib/opencode/ + chmod -R u+w $out/lib/opencode/dist + + # Select bundled worker assets deterministically (sorted find output) + worker_file=$(find "$out/lib/opencode/dist" -type f \( -path '*/tui/worker.*' -o -name 'worker.*' \) | sort | head -n1) + parser_worker_file=$(find "$out/lib/opencode/dist" -type f -name 'parser.worker.*' | sort | head -n1) + if [ -z "$worker_file" ]; then + echo "ERROR: bundled worker not found" exit 1 fi - install -Dm755 opencode $out/bin/opencode - install -Dm644 opencode-worker.js $out/bin/opencode-worker.js - if [ -f opencode-assets.manifest ]; then - while IFS= read -r asset; do - [ -z "$asset" ] && continue - if [ ! -f "$asset" ]; then - echo "ERROR: referenced asset \"$asset\" missing" - exit 1 - fi - install -Dm644 "$asset" "$out/bin/$(basename "$asset")" - done < opencode-assets.manifest - fi + main_wasm=$(printf '%s\n' "$out"/lib/opencode/dist/tree-sitter-*.wasm | sort | head -n1) + wasm_list=$(find "$out/lib/opencode/dist" -maxdepth 1 -name 'tree-sitter-*.wasm' -print) + for patch_file in "$worker_file" "$parser_worker_file"; do + [ -z "$patch_file" ] && continue + [ ! -f "$patch_file" ] && continue + if [ -n "$wasm_list" ] && grep -q 'tree-sitter' "$patch_file"; then + # Rewrite wasm references to absolute store paths to avoid runtime resolve failures. + bun --bun ${scripts + "/patch-wasm.ts"} "$patch_file" "$main_wasm" $wasm_list + fi + done + + mkdir -p $out/lib/opencode/node_modules + cp -r ../../node_modules/.bun $out/lib/opencode/node_modules/ + mkdir -p $out/lib/opencode/node_modules/@opentui + + mkdir -p $out/bin + makeWrapper ${bun}/bin/bun $out/bin/opencode \ + --add-flags "run" \ + --add-flags "$out/lib/opencode/dist/src/index.js" \ + --prefix PATH : ${lib.makeBinPath [ fzf ripgrep ]} \ + --argv0 opencode + runHook postInstall ''; - postFixup = '' - wrapProgram "$out/bin/opencode" --prefix PATH : ${lib.makeBinPath [ fzf ripgrep ]} + postInstall = '' + for pkg in $out/lib/opencode/node_modules/.bun/@opentui+core-* $out/lib/opencode/node_modules/.bun/@opentui+solid-* $out/lib/opencode/node_modules/.bun/@opentui+core@* $out/lib/opencode/node_modules/.bun/@opentui+solid@*; do + if [ -d "$pkg" ]; then + pkgName=$(basename "$pkg" | sed 's/@opentui+\([^@]*\)@.*/\1/') + ln -sf ../.bun/$(basename "$pkg")/node_modules/@opentui/$pkgName \ + $out/lib/opencode/node_modules/@opentui/$pkgName + fi + done ''; meta = { diff --git a/nix/scripts/canonicalize-node-modules.ts b/nix/scripts/canonicalize-node-modules.ts index bb004f3c54c..828a18fbc7e 100644 --- a/nix/scripts/canonicalize-node-modules.ts +++ b/nix/scripts/canonicalize-node-modules.ts @@ -24,15 +24,13 @@ for (const entry of directories) { if (!info.isDirectory()) { continue } - const marker = entry.lastIndexOf("@") - if (marker <= 0) { + const parsed = parseEntry(entry) + if (!parsed) { continue } - const slug = entry.slice(0, marker).replace(/\+/g, "/") - const version = entry.slice(marker + 1) - const list = versions.get(slug) ?? [] - list.push({ dir: full, version, label: entry }) - versions.set(slug, list) + const list = versions.get(parsed.name) ?? [] + list.push({ dir: full, version: parsed.version, label: entry }) + versions.set(parsed.name, list) } const semverModule = (await import(join(bunRoot, "node_modules/semver"))) as @@ -79,6 +77,12 @@ for (const [slug, entry] of Array.from(selections.entries()).sort((a, b) => a[0] await mkdir(parent, { recursive: true }) const linkPath = join(parent, leaf) const desired = join(entry.dir, "node_modules", slug) + const exists = await lstat(desired) + .then(info => info.isDirectory()) + .catch(() => false) + if (!exists) { + continue + } const relativeTarget = relative(parent, desired) const resolved = relativeTarget.length === 0 ? "." : relativeTarget await rm(linkPath, { recursive: true, force: true }) @@ -94,3 +98,16 @@ for (const line of rewrites.slice(0, 20)) { if (rewrites.length > 20) { console.log(" ...") } + +function parseEntry(label: string) { + const marker = label.startsWith("@") ? label.indexOf("@", 1) : label.indexOf("@") + if (marker <= 0) { + return null + } + const name = label.slice(0, marker).replace(/\+/g, "/") + const version = label.slice(marker + 1) + if (!name || !version) { + return null + } + return { name, version } +} diff --git a/nix/scripts/patch-wasm.ts b/nix/scripts/patch-wasm.ts new file mode 100644 index 00000000000..99f8a40e9f3 --- /dev/null +++ b/nix/scripts/patch-wasm.ts @@ -0,0 +1,39 @@ +#!/usr/bin/env bun + +import fs from "fs" +import path from "path" + +/** + * Rewrite tree-sitter wasm references inside a JS file to absolute paths. + * argv: [node, script, file, mainWasm, ...wasmPaths] + */ +const [, , file, mainWasm, ...wasmPaths] = process.argv + +if (!file || !mainWasm) { + console.error("usage: patch-wasm [wasmPaths...]") + process.exit(1) +} + +const content = fs.readFileSync(file, "utf8") +const byName = new Map() + +for (const wasm of wasmPaths) { + const name = path.basename(wasm) + byName.set(name, wasm) +} + +let next = content + +for (const [name, wasmPath] of byName) { + next = next.replaceAll(name, wasmPath) +} + +next = next.replaceAll("tree-sitter.wasm", mainWasm).replaceAll("web-tree-sitter/tree-sitter.wasm", mainWasm) + +// Collapse any relative prefixes before absolute store paths (e.g., "../../../..//nix/store/...") +next = next.replace(/(\.\/)+/g, "./") +next = next.replace(/(\.\.\/)+\/?(\/nix\/store[^"']+)/g, "/$2") +next = next.replace(/(["'])\/{2,}(\/nix\/store[^"']+)(["'])/g, "$1/$2$3") +next = next.replace(/(["'])\/\/(nix\/store[^"']+)(["'])/g, "$1/$2$3") + +if (next !== content) fs.writeFileSync(file, next) diff --git a/packages/opencode/src/cli/cmd/tui/thread.ts b/packages/opencode/src/cli/cmd/tui/thread.ts index 89d61d0f3c5..79638c5e876 100644 --- a/packages/opencode/src/cli/cmd/tui/thread.ts +++ b/packages/opencode/src/cli/cmd/tui/thread.ts @@ -58,16 +58,14 @@ export const TuiThreadCommand = cmd({ // Resolve relative paths against PWD to preserve behavior when using --cwd flag const baseCwd = process.env.PWD ?? process.cwd() const cwd = args.project ? path.resolve(baseCwd, args.project) : process.cwd() - const defaultWorker = new URL("./worker.ts", import.meta.url) - // Nix build creates a bundled worker next to the binary; prefer it when present. + const localWorker = new URL("./worker.ts", import.meta.url) + const distWorker = new URL("./cli/cmd/tui/worker.js", import.meta.url) const execDir = path.dirname(process.execPath) - const bundledWorker = path.join(execDir, "opencode-worker.js") - const hasBundledWorker = await Bun.file(bundledWorker).exists() - const workerPath = (() => { + const workerPath = await iife(async () => { if (typeof OPENCODE_WORKER_PATH !== "undefined") return OPENCODE_WORKER_PATH - if (hasBundledWorker) return bundledWorker - return defaultWorker - })() + if (await Bun.file(distWorker).exists()) return distWorker + return localWorker + }) try { process.chdir(cwd) } catch (e) { From 83186b6fedb23807814a4d00a2f9997df16bbf44 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Mon, 24 Nov 2025 04:55:13 +0000 Subject: [PATCH 30/66] chore: format code --- nix/scripts/canonicalize-node-modules.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/scripts/canonicalize-node-modules.ts b/nix/scripts/canonicalize-node-modules.ts index 828a18fbc7e..faa6f63402e 100644 --- a/nix/scripts/canonicalize-node-modules.ts +++ b/nix/scripts/canonicalize-node-modules.ts @@ -78,7 +78,7 @@ for (const [slug, entry] of Array.from(selections.entries()).sort((a, b) => a[0] const linkPath = join(parent, leaf) const desired = join(entry.dir, "node_modules", slug) const exists = await lstat(desired) - .then(info => info.isDirectory()) + .then((info) => info.isDirectory()) .catch(() => false) if (!exists) { continue From b9b071c744814e205ccaf2a94631c1410ea16688 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Sun, 23 Nov 2025 23:56:15 -0600 Subject: [PATCH 31/66] fix: fatal: undefined is not an object (evaluating 'color.buffer') --- packages/opencode/src/cli/cmd/tui/context/local.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/opencode/src/cli/cmd/tui/context/local.tsx b/packages/opencode/src/cli/cmd/tui/context/local.tsx index f9963fae880..c3b38aab2a2 100644 --- a/packages/opencode/src/cli/cmd/tui/context/local.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/local.tsx @@ -94,6 +94,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const agent = agents().find((x) => x.name === name) if (agent?.color) return RGBA.fromHex(agent.color) const index = agents().findIndex((x) => x.name === name) + if (index === -1) return colors()[0] return colors()[index % colors().length] }, } From ac1e2bfd49c6520e14b8b4c8e4bc03a4edee8554 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Sun, 23 Nov 2025 22:40:15 -0800 Subject: [PATCH 32/66] bump copilot plugin, give better error message for copilot (#4678) --- packages/opencode/src/global/index.ts | 2 +- packages/opencode/src/plugin/index.ts | 2 +- packages/opencode/src/provider/transform.ts | 8 ++++++++ packages/opencode/src/session/message-v2.ts | 4 +++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/global/index.ts b/packages/opencode/src/global/index.ts index 3b480706625..e98b1628d23 100644 --- a/packages/opencode/src/global/index.ts +++ b/packages/opencode/src/global/index.ts @@ -30,7 +30,7 @@ await Promise.all([ fs.mkdir(Global.Path.bin, { recursive: true }), ]) -const CACHE_VERSION = "10" +const CACHE_VERSION = "11" const version = await Bun.file(path.join(Global.Path.cache, "version")) .text() diff --git a/packages/opencode/src/plugin/index.ts b/packages/opencode/src/plugin/index.ts index ff07e68a7ff..7d1f50ec8b2 100644 --- a/packages/opencode/src/plugin/index.ts +++ b/packages/opencode/src/plugin/index.ts @@ -28,7 +28,7 @@ export namespace Plugin { } const plugins = [...(config.plugin ?? [])] if (!Flag.OPENCODE_DISABLE_DEFAULT_PLUGINS) { - plugins.push("opencode-copilot-auth@0.0.5") + plugins.push("opencode-copilot-auth@0.0.7") plugins.push("opencode-anthropic-auth@0.0.2") } for (let plugin of plugins) { diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index ad04f7ef88c..6cf03fc06d0 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -272,4 +272,12 @@ export namespace ProviderTransform { return schema } + + export function error(providerID: string, message: string) { + if (providerID === "github-copilot" && message.includes("The requested model is not supported")) { + message += + "\n\nMake sure the model is enabled in your copilot settings: https://github.com/settings/copilot/features" + } + return message + } } diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index 87cd77e1275..c451ae2b38d 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -8,6 +8,7 @@ import { LSP } from "../lsp" import { Snapshot } from "@/snapshot" import { fn } from "@/util/fn" import { Storage } from "@/storage/storage" +import { ProviderTransform } from "@/provider/transform" export namespace MessageV2 { export const OutputLengthError = NamedError.create("MessageOutputLengthError", z.object({})) @@ -737,9 +738,10 @@ export namespace MessageV2 { { cause: e }, ).toObject() case APICallError.isInstance(e): + const message = ProviderTransform.error(ctx.providerID, e.message) return new MessageV2.APIError( { - message: e.message, + message, statusCode: e.statusCode, isRetryable: e.isRetryable, responseHeaders: e.responseHeaders, From 502e85b903f3986e2fe9f4e6db01b479d5dddfb8 Mon Sep 17 00:00:00 2001 From: opencode Date: Mon, 24 Nov 2025 07:06:41 +0000 Subject: [PATCH 33/66] release: v1.0.107 --- bun.lock | 30 +++++++++++++------------- packages/console/app/package.json | 2 +- packages/console/core/package.json | 2 +- packages/console/function/package.json | 2 +- packages/console/mail/package.json | 2 +- packages/desktop/package.json | 2 +- packages/enterprise/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +++++------ packages/function/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 4 ++-- packages/sdk/js/package.json | 4 ++-- packages/slack/package.json | 2 +- packages/tauri/package.json | 2 +- packages/ui/package.json | 2 +- packages/util/package.json | 2 +- packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- 18 files changed, 39 insertions(+), 39 deletions(-) diff --git a/bun.lock b/bun.lock index 58f41a67a64..2f8cd602322 100644 --- a/bun.lock +++ b/bun.lock @@ -19,7 +19,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -46,7 +46,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -73,7 +73,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -97,7 +97,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -121,7 +121,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -162,7 +162,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -188,7 +188,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "22.0.0", @@ -204,7 +204,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.106", + "version": "1.0.107", "bin": { "opencode": "./bin/opencode", }, @@ -290,7 +290,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -310,7 +310,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.106", + "version": "1.0.107", "devDependencies": { "@hey-api/openapi-ts": "0.81.0", "@tsconfig/node22": "catalog:", @@ -321,7 +321,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -334,7 +334,7 @@ }, "packages/tauri": { "name": "@opencode-ai/tauri", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "@tauri-apps/api": "^2", "@tauri-apps/plugin-opener": "^2", @@ -347,7 +347,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -379,7 +379,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "zod": "catalog:", }, @@ -389,7 +389,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 322afb56fb3..1669fb50a61 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.0.106", + "version": "1.0.107", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 3aa4b52d50e..db0904e3ba5 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/console-core", - "version": "1.0.106", + "version": "1.0.107", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 6b6cccd5a46..34e7944fbec 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.106", + "version": "1.0.107", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/console/mail/package.json b/packages/console/mail/package.json index 42a1647feca..8bcde9ee4d3 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.106", + "version": "1.0.107", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index c3d8d8070a0..aef78d8d476 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.106", + "version": "1.0.107", "description": "", "type": "module", "scripts": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index 4bdcd970047..37970c2ee89 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.0.106", + "version": "1.0.107", "private": true, "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index 771be59333a..f1c6a36e7e3 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "opencode" name = "OpenCode" description = "The AI coding agent built for the terminal" -version = "1.0.106" +version = "1.0.107" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/sst/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.106/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.107/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.106/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.107/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.106/opencode-linux-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.107/opencode-linux-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.106/opencode-linux-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.107/opencode-linux-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.106/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.107/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index e2abb624639..9ee6a260812 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.106", + "version": "1.0.107", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index d275033a2c1..25ee3983bfb 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.106", + "version": "1.0.107", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 46f4353dcbb..0a9239f6fde 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/plugin", - "version": "1.0.106", + "version": "1.0.107", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} +} \ No newline at end of file diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 3f77d8ca4fb..2f4c1cd1fe5 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/sdk", - "version": "1.0.106", + "version": "1.0.107", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -26,4 +26,4 @@ "publishConfig": { "directory": "dist" } -} +} \ No newline at end of file diff --git a/packages/slack/package.json b/packages/slack/package.json index 2c2d7dbe4d0..9fda47a2fd1 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.106", + "version": "1.0.107", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/tauri/package.json b/packages/tauri/package.json index d7af0cab32f..8b7d4c98857 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/tauri", "private": true, - "version": "1.0.106", + "version": "1.0.107", "type": "module", "scripts": { "dev": "vite", diff --git a/packages/ui/package.json b/packages/ui/package.json index 229bd80c2f0..8edf23bc375 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.106", + "version": "1.0.107", "type": "module", "exports": { "./*": "./src/components/*.tsx", diff --git a/packages/util/package.json b/packages/util/package.json index f1f242e0e0d..ea8be33cd3d 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.0.106", + "version": "1.0.107", "private": true, "type": "module", "exports": { diff --git a/packages/web/package.json b/packages/web/package.json index 99c93a9a445..4bcb0835aa2 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.106", + "version": "1.0.107", "scripts": { "dev": "astro dev", "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 760701bf1c3..db9f63ec691 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "1.0.106", + "version": "1.0.107", "publisher": "sst-dev", "repository": { "type": "git", From d4f6deb9ef9c78b183b9d8c3c145f9b64b5e9e2f Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Mon, 24 Nov 2025 01:12:26 -0600 Subject: [PATCH 34/66] tweak: modified files sidebar --- packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx index 9ba799f09e4..d0241d42238 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx @@ -188,6 +188,7 @@ export function Sidebar(props: { sessionID: string }) { const splits = item.file.split(path.sep).filter(Boolean) const last = splits.at(-1)! const rest = splits.slice(0, -1).join(path.sep) + if (!rest) return last return Locale.truncateMiddle(rest, 30 - last.length) + "/" + last }) return ( From abdc7b276ab717981c0db93f5f619c9401042aa6 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Mon, 24 Nov 2025 01:26:47 -0600 Subject: [PATCH 35/66] fix: persist light vs dark mode --- packages/opencode/src/cli/cmd/tui/context/theme.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/cmd/tui/context/theme.tsx b/packages/opencode/src/cli/cmd/tui/context/theme.tsx index 4e3cc35315e..88b9616b06a 100644 --- a/packages/opencode/src/cli/cmd/tui/context/theme.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/theme.tsx @@ -210,7 +210,7 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({ const kv = useKV() const [store, setStore] = createStore({ themes: DEFAULT_THEMES, - mode: props.mode, + mode: kv.get("theme_mode", props.mode), active: (sync.data.config.theme ?? kv.get("theme", "opencode")) as string, ready: false, }) @@ -262,6 +262,7 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({ }, setMode(mode: "dark" | "light") { setStore("mode", mode) + kv.set("theme_mode", mode) }, set(theme: string) { setStore("active", theme) From 840d2694b4f94c7cd81f929bc660a3b66f6ee4ec Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Mon, 24 Nov 2025 07:51:59 +0000 Subject: [PATCH 36/66] chore: format code --- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 0a9239f6fde..9f284756d9b 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} \ No newline at end of file +} diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 2f4c1cd1fe5..b43cd27837e 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -26,4 +26,4 @@ "publishConfig": { "directory": "dist" } -} \ No newline at end of file +} From 75c0c0a0985400bb8470b55cfcafb94744130bc0 Mon Sep 17 00:00:00 2001 From: Ariane Emory <97994360+ariane-emory@users.noreply.github.com> Date: Mon, 24 Nov 2025 03:02:04 -0500 Subject: [PATCH 37/66] tweak: display MCPs in alphabetic order in the sidebar. (#4680) Co-authored-by: Github Action --- flake.lock | 6 +++--- nix/hashes.json | 2 +- .../src/cli/cmd/tui/routes/session/sidebar.tsx | 13 ++++++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 1150e275150..826bf4d8608 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1763618868, - "narHash": "sha256-v5afmLjn/uyD9EQuPBn7nZuaZVV9r+JerayK/4wvdWA=", + "lastModified": 1763806073, + "narHash": "sha256-FHsEKDvfWpzdADWj99z7vBk4D716Ujdyveo5+A048aI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a8d610af3f1a5fb71e23e08434d8d61a466fc942", + "rev": "878e468e02bfabeda08c79250f7ad583037f2227", "type": "github" }, "original": { diff --git a/nix/hashes.json b/nix/hashes.json index 6063a49bd3f..16424b3a035 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,3 +1,3 @@ { - "nodeModules": "sha256-/ZkyVHgRMjhzBpnDNTR6X+TomtTMarVU7gmq9Z8Czr8=" + "nodeModules": "sha256-m7hL9Uzqk+oa2/FtgkzEPgi+m/VZP1SvjpgYHNjiS1c=" } diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx index d0241d42238..8302bfefe95 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx @@ -18,6 +18,9 @@ export function Sidebar(props: { sessionID: string }) { const [todoExpanded, setTodoExpanded] = createSignal(true) const [lspExpanded, setLspExpanded] = createSignal(true) + // Sort MCP servers alphabetically for consistent display order + const mcpEntries = createMemo(() => Object.entries(sync.data.mcp).sort(([a], [b]) => a.localeCompare(b))) + const cost = createMemo(() => { const total = messages().reduce((sum, x) => sum + (x.role === "assistant" ? x.cost : 0), 0) return new Intl.NumberFormat("en-US", { @@ -58,22 +61,22 @@ export function Sidebar(props: { sessionID: string }) { {context()?.percentage ?? 0}% used {cost()} spent - 0}> + 0}> Object.keys(sync.data.mcp).length > 2 && setMcpExpanded(!mcpExpanded())} + onMouseDown={() => mcpEntries().length > 2 && setMcpExpanded(!mcpExpanded())} > - 2}> + 2}> {mcpExpanded() ? "▼" : "▶"} MCP - - + + {([key, item]) => ( Date: Mon, 24 Nov 2025 09:06:09 +0100 Subject: [PATCH 38/66] TUI: fix: add null check for user.time in duration calculation (#4679) --- packages/opencode/src/cli/cmd/tui/routes/session/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index 547b9a7d2a1..0169c68e617 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -1008,7 +1008,7 @@ function AssistantMessage(props: { message: AssistantMessage; parts: Part[]; las if (!final()) return 0 if (!props.message.time.completed) return 0 const user = messages().find((x) => x.role === "user" && x.id === props.message.parentID) - if (!user) return 0 + if (!user || !user.time) return 0 return props.message.time.completed - user.time.created }) From e6bf1754c33490570f9103c6cf3849bc4ec68296 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Mon, 24 Nov 2025 12:04:34 +0000 Subject: [PATCH 39/66] ignore: update download stats 2025-11-24 --- STATS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/STATS.md b/STATS.md index 1664627fef0..4ac864e5780 100644 --- a/STATS.md +++ b/STATS.md @@ -149,3 +149,4 @@ | 2025-11-21 | 826,309 (+11,689) | 769,307 (+11,400) | 1,595,616 (+23,089) | | 2025-11-22 | 837,269 (+10,960) | 780,996 (+11,689) | 1,618,265 (+22,649) | | 2025-11-23 | 846,609 (+9,340) | 795,069 (+14,073) | 1,641,678 (+23,413) | +| 2025-11-24 | 856,733 (+10,124) | 804,033 (+8,964) | 1,660,766 (+19,088) | From 883ed4d424082a8b132d6c7ba985161bb0d7e7a7 Mon Sep 17 00:00:00 2001 From: Frankie Seabrook <75613843+fifthfrankie@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:51:16 +0000 Subject: [PATCH 40/66] docs: add Ollama Cloud provider setup to providers.mdx (#4693) --- packages/web/src/content/docs/providers.mdx | 48 +++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/packages/web/src/content/docs/providers.mdx b/packages/web/src/content/docs/providers.mdx index ec468205a90..01395656933 100644 --- a/packages/web/src/content/docs/providers.mdx +++ b/packages/web/src/content/docs/providers.mdx @@ -762,6 +762,54 @@ If tool calls aren't working, try increasing `num_ctx` in Ollama. Start around 1 --- +### Ollama Cloud + +To use Ollama Cloud with OpenCode: + +1. Head over to [https://ollama.com/](https://ollama.com/) and sign in or create an account. + +2. Navigate to **Settings** > **Keys** and click **Add API Key** to generate a new API key. + +3. Copy the API key for use in OpenCode. + +4. Run `opencode auth login` and select **Ollama Cloud**. + + ```bash + $ opencode auth login + + ┌ Add credential + │ + ◆ Select provider + │ ● Ollama Cloud + │ ... + └ + ``` + +5. Enter your Ollama Cloud API key. + + ```bash + $ opencode auth login + + ┌ Add credential + │ + ◇ Select provider + │ Ollama Cloud + │ + ◇ Enter your API key + │ _ + └ + ``` + +6. **Important**: Before using cloud models in OpenCode, you must pull the model information locally: + + ```bash + ollama pull gpt-oss:20b-cloud + ``` + +7. Run the `/models` command to select your Ollama Cloud model. + +--- + ### OpenAI 1. Head over to the [OpenAI Platform console](https://platform.openai.com/api-keys), click **Create new secret key**, and copy the key. From 82ebf66cbada3513fdfee7af784dfcf120462fec Mon Sep 17 00:00:00 2001 From: Sebastian Herrlinger Date: Mon, 24 Nov 2025 19:39:09 +0100 Subject: [PATCH 41/66] non-corpo loading spinner --- bun.lock | 5 + packages/opencode/package.json | 1 + .../cli/cmd/tui/component/prompt/index.tsx | 59 +-- .../opencode/src/cli/cmd/tui/ui/shimmer.tsx | 56 --- .../opencode/src/cli/cmd/tui/ui/spinner.ts | 405 ++++++++++++++++++ 5 files changed, 434 insertions(+), 92 deletions(-) delete mode 100644 packages/opencode/src/cli/cmd/tui/ui/shimmer.tsx create mode 100644 packages/opencode/src/cli/cmd/tui/ui/spinner.ts diff --git a/bun.lock b/bun.lock index 2f8cd602322..d6207f3cd3d 100644 --- a/bun.lock +++ b/bun.lock @@ -252,6 +252,7 @@ "jsonc-parser": "3.3.1", "minimatch": "10.0.3", "open": "10.1.2", + "opentui-spinner": "0.0.5", "partial-json": "0.1.7", "remeda": "catalog:", "solid-js": "catalog:", @@ -1948,6 +1949,8 @@ "cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="], + "cli-spinners": ["cli-spinners@3.3.0", "", {}, "sha512-/+40ljC3ONVnYIttjMWrlL51nItDAbBrq2upN8BPyvGU/2n5Oxw3tbNwORCaNuNqLJnxGqOfjUuhsv7l5Q4IsQ=="], + "clipboardy": ["clipboardy@4.0.0", "", { "dependencies": { "execa": "^8.0.1", "is-wsl": "^3.1.0", "is64bit": "^2.0.0" } }, "sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w=="], "cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="], @@ -2962,6 +2965,8 @@ "openid-client": ["openid-client@5.6.4", "", { "dependencies": { "jose": "^4.15.4", "lru-cache": "^6.0.0", "object-hash": "^2.2.0", "oidc-token-hash": "^5.0.3" } }, "sha512-T1h3B10BRPKfcObdBklX639tVz+xh34O7GjofqrqiAQdm7eHsQ00ih18x6wuJ/E6FxdtS2u3FmUGPDeEcMwzNA=="], + "opentui-spinner": ["opentui-spinner@0.0.5", "", { "dependencies": { "cli-spinners": "^3.3.0" }, "peerDependencies": { "@opentui/core": "^0.1.49", "@opentui/react": "^0.1.49", "@opentui/solid": "^0.1.49", "typescript": "^5" }, "optionalPeers": ["@opentui/react", "@opentui/solid"] }, "sha512-abSWzWA7eyuD0PjerAWbBznLmOQn+8xRDaLGCVIs4ctETi2laNFr5KwicYnPXsHZpPc2neV7WtQm+diCEfOhLA=="], + "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="], "oxc-minify": ["oxc-minify@0.96.0", "", { "optionalDependencies": { "@oxc-minify/binding-android-arm64": "0.96.0", "@oxc-minify/binding-darwin-arm64": "0.96.0", "@oxc-minify/binding-darwin-x64": "0.96.0", "@oxc-minify/binding-freebsd-x64": "0.96.0", "@oxc-minify/binding-linux-arm-gnueabihf": "0.96.0", "@oxc-minify/binding-linux-arm-musleabihf": "0.96.0", "@oxc-minify/binding-linux-arm64-gnu": "0.96.0", "@oxc-minify/binding-linux-arm64-musl": "0.96.0", "@oxc-minify/binding-linux-riscv64-gnu": "0.96.0", "@oxc-minify/binding-linux-s390x-gnu": "0.96.0", "@oxc-minify/binding-linux-x64-gnu": "0.96.0", "@oxc-minify/binding-linux-x64-musl": "0.96.0", "@oxc-minify/binding-wasm32-wasi": "0.96.0", "@oxc-minify/binding-win32-arm64-msvc": "0.96.0", "@oxc-minify/binding-win32-x64-msvc": "0.96.0" } }, "sha512-dXeeGrfPJJ4rMdw+NrqiCRtbzVX2ogq//R0Xns08zql2HjV3Zi2SBJ65saqfDaJzd2bcHqvGWH+M44EQCHPAcA=="], diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 25ee3983bfb..3b6e0760455 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -82,6 +82,7 @@ "jsonc-parser": "3.3.1", "minimatch": "10.0.3", "open": "10.1.2", + "opentui-spinner": "0.0.5", "partial-json": "0.1.7", "remeda": "catalog:", "solid-js": "catalog:", 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 f2e97ff2324..4e2fa9d3577 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -1,5 +1,6 @@ import { BoxRenderable, TextareaRenderable, MouseEvent, PasteEvent, t, dim, fg, type KeyBinding } from "@opentui/core" import { createEffect, createMemo, type JSX, onMount, createSignal, onCleanup, Show, Switch, Match } from "solid-js" +import "opentui-spinner/solid"; import { useLocal } from "@tui/context/local" import { useTheme } from "@tui/context/theme" import { EmptyBorder } from "@tui/component/border" @@ -20,7 +21,7 @@ import type { FilePart } from "@opencode-ai/sdk" import { TuiEvent } from "../../event" import { iife } from "@/util/iife" import { Locale } from "@/util/locale" -import { Shimmer } from "../../ui/shimmer" +import { createColors, createFrames } from "../../ui/spinner.ts" export type PromptProps = { sessionID?: string @@ -545,6 +546,22 @@ export function Prompt(props: PromptProps) { return local.agent.color(local.agent.current().name) }) + const spinnerDef = createMemo(() => { + const color = local.agent.color(local.agent.current().name) + return { + frames: createFrames({ + color, + style: "blocks", + inactiveFactor: 0.25, + }), + color: createColors({ + color, + style: "blocks", + inactiveFactor: 0.25, + }), + } + }) + createEffect(() => { renderer.setCursorColor(highlight()) }) @@ -813,7 +830,11 @@ export function Prompt(props: PromptProps) { justifyContent={status().type === "retry" ? "space-between" : "flex-start"} > - + {(() => { const retry = createMemo(() => { @@ -884,37 +905,3 @@ export function Prompt(props: PromptProps) { ) } -function Loader() { - const FRAMES = [ - "▱▱▱▱▱▱▱", - "▱▱▱▱▱▱▱", - "▱▱▱▱▱▱▱", - "▱▱▱▱▱▱▱", - "▰▱▱▱▱▱▱", - "▰▰▱▱▱▱▱", - "▰▰▰▱▱▱▱", - "▱▰▰▰▱▱▱", - "▱▱▰▰▰▱▱", - "▱▱▱▰▰▰▱", - "▱▱▱▱▰▰▰", - "▱▱▱▱▱▰▰", - "▱▱▱▱▱▱▰", - "▱▱▱▱▱▱▱", - "▱▱▱▱▱▱▱", - "▱▱▱▱▱▱▱", - "▱▱▱▱▱▱▱", - ] - const [frame, setFrame] = createSignal(0) - - onMount(() => { - const timer = setInterval(() => { - setFrame((frame() + 1) % FRAMES.length) - }, 100) - onCleanup(() => { - clearInterval(timer) - }) - }) - - const { theme } = useTheme() - return {FRAMES[frame()]} -} diff --git a/packages/opencode/src/cli/cmd/tui/ui/shimmer.tsx b/packages/opencode/src/cli/cmd/tui/ui/shimmer.tsx deleted file mode 100644 index 6c5629b8a71..00000000000 --- a/packages/opencode/src/cli/cmd/tui/ui/shimmer.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { RGBA } from "@opentui/core" -import { useTimeline } from "@opentui/solid" -import { createMemo, createSignal } from "solid-js" - -export type ShimmerProps = { - text: string - color: RGBA -} - -const DURATION = 2_500 - -export function Shimmer(props: ShimmerProps) { - const timeline = useTimeline({ - duration: DURATION, - loop: true, - }) - const characters = props.text.split("") - const color = props.color - - const shimmerSignals = characters.map((_, i) => { - const [shimmer, setShimmer] = createSignal(0.4) - const target = { - shimmer: shimmer(), - setShimmer, - } - - timeline!.add( - target, - { - shimmer: 1, - duration: DURATION / (props.text.length + 1), - ease: "linear", - alternate: true, - loop: 2, - onUpdate: () => { - target.setShimmer(target.shimmer) - }, - }, - (i * (DURATION / (props.text.length + 1))) / 2, - ) - - return shimmer - }) - - return ( - - {(() => { - return characters.map((ch, i) => { - const shimmer = shimmerSignals[i] - const fg = RGBA.fromInts(color.r * 255, color.g * 255, color.b * 255, shimmer() * 255) - return {ch} - }) - })()} - - ) -} diff --git a/packages/opencode/src/cli/cmd/tui/ui/spinner.ts b/packages/opencode/src/cli/cmd/tui/ui/spinner.ts new file mode 100644 index 00000000000..e09b079b4a4 --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/ui/spinner.ts @@ -0,0 +1,405 @@ +import type { ColorInput } from "@opentui/core"; +import { RGBA } from "@opentui/core"; +import type { ColorGenerator } from "opentui-spinner"; + +interface AdvancedGradientOptions { + colors: ColorInput[]; + trailLength: number; + defaultColor?: ColorInput; + direction?: "forward" | "backward" | "bidirectional"; + holdFrames?: { start?: number; end?: number }; +} + +interface ScannerState { + activePosition: number; + isHolding: boolean; + holdProgress: number; + holdTotal: number; + movementProgress: number; + movementTotal: number; + isMovingForward: boolean; +} + +function getScannerState( + frameIndex: number, + totalChars: number, + options: Pick, +): ScannerState { + const { direction = "forward", holdFrames = {} } = options; + + if (direction === "bidirectional") { + const forwardFrames = totalChars; + const holdEndFrames = holdFrames.end ?? 0; + const backwardFrames = totalChars - 1; + + if (frameIndex < forwardFrames) { + // Moving forward + return { + activePosition: frameIndex, + isHolding: false, + holdProgress: 0, + holdTotal: 0, + movementProgress: frameIndex, + movementTotal: forwardFrames, + isMovingForward: true, + }; + } else if (frameIndex < forwardFrames + holdEndFrames) { + // Holding at end + return { + activePosition: totalChars - 1, + isHolding: true, + holdProgress: frameIndex - forwardFrames, + holdTotal: holdEndFrames, + movementProgress: 0, + movementTotal: 0, + isMovingForward: true, + }; + } else if (frameIndex < forwardFrames + holdEndFrames + backwardFrames) { + // Moving backward + const backwardIndex = frameIndex - forwardFrames - holdEndFrames; + return { + activePosition: totalChars - 2 - backwardIndex, + isHolding: false, + holdProgress: 0, + holdTotal: 0, + movementProgress: backwardIndex, + movementTotal: backwardFrames, + isMovingForward: false, + }; + } else { + // Holding at start + return { + activePosition: 0, + isHolding: true, + holdProgress: + frameIndex - forwardFrames - holdEndFrames - backwardFrames, + holdTotal: holdFrames.start ?? 0, + movementProgress: 0, + movementTotal: 0, + isMovingForward: false, + }; + } + } else if (direction === "backward") { + return { + activePosition: totalChars - 1 - (frameIndex % totalChars), + isHolding: false, + holdProgress: 0, + holdTotal: 0, + movementProgress: frameIndex % totalChars, + movementTotal: totalChars, + isMovingForward: false, + }; + } else { + return { + activePosition: frameIndex % totalChars, + isHolding: false, + holdProgress: 0, + holdTotal: 0, + movementProgress: frameIndex % totalChars, + movementTotal: totalChars, + isMovingForward: true, + }; + } +} + +function calculateColorIndex( + frameIndex: number, + charIndex: number, + totalChars: number, + options: Pick< + AdvancedGradientOptions, + "direction" | "holdFrames" | "trailLength" + >, + state?: ScannerState, +): number { + const { trailLength } = options; + const { activePosition, isHolding, holdProgress, isMovingForward } = + state ?? getScannerState(frameIndex, totalChars, options); + + // Calculate directional distance (positive means trailing behind) + const directionalDistance = isMovingForward + ? activePosition - charIndex // For forward: trail is to the left (lower indices) + : charIndex - activePosition; // For backward: trail is to the right (higher indices) + + // Handle hold frame fading: keep the lead bright, fade the trail + if (isHolding) { + // Shift the color index by how long we've been holding + return directionalDistance + holdProgress; + } + + // Normal movement - show gradient trail only behind the movement direction + if (directionalDistance > 0 && directionalDistance < trailLength) { + return directionalDistance; + } + + // At the active position, show the brightest color + if (directionalDistance === 0) { + return 0; + } + + return -1; +} + +function createKnightRiderTrail( + options: AdvancedGradientOptions, +): ColorGenerator { + const { colors, defaultColor } = options; + + // Use the provided defaultColor if it's an RGBA instance, otherwise convert/default + // We use RGBA.fromHex for the fallback to ensure we have an RGBA object. + // Note: If defaultColor is a string, we convert it once here. + const defaultRgba = + defaultColor instanceof RGBA + ? defaultColor + : RGBA.fromHex((defaultColor as string) || "#000000"); + + let cachedFrameIndex = -1; + let cachedState: ScannerState | null = null; + + return ( + frameIndex: number, + charIndex: number, + _totalFrames: number, + totalChars: number, + ) => { + if (frameIndex !== cachedFrameIndex) { + cachedFrameIndex = frameIndex; + cachedState = getScannerState(frameIndex, totalChars, options); + } + + const state = cachedState!; + + const index = calculateColorIndex( + frameIndex, + charIndex, + totalChars, + options, + state, + ); + + // Calculate global fade for inactive dots during hold or movement + const { + isHolding, + holdProgress, + holdTotal, + movementProgress, + movementTotal, + } = state; + + let alpha = 1.0; + if (isHolding && holdTotal > 0) { + // Fade out linearly + const progress = Math.min(holdProgress / holdTotal, 1); + alpha = Math.max(0, 1 - progress); + } else if (!isHolding && movementTotal > 0) { + // Fade in linearly during movement + const progress = Math.min( + movementProgress / Math.max(1, movementTotal - 1), + 1, + ); + alpha = progress; + } + + // Mutate the alpha of the default RGBA object + // This assumes single-threaded, synchronous rendering per frame + // where we can modify the state for the current frame. + // Since this is run for every char in the frame, setting it repeatedly to the same value is fine. + defaultRgba.a = alpha; + + if (index === -1) { + return defaultRgba; + } + + return colors[index] ?? defaultRgba; + }; +} + +/** + * Derives a gradient of tail colors from a single bright color + * @param brightColor The brightest color (center/head of the scanner) + * @param steps Number of gradient steps (default: 6) + * @returns Array of RGBA colors from brightest to darkest + */ +export function deriveTrailColors( + brightColor: ColorInput, + steps: number = 6, +): RGBA[] { + const baseRgba = + brightColor instanceof RGBA + ? brightColor + : RGBA.fromHex(brightColor as string); + + const colors: RGBA[] = []; + + for (let i = 0; i < steps; i++) { + // Progressive darkening: + // i=0: 100% brightness (original color) + // i=1: add slight bloom/glare (lighten) + // i=2+: progressively darken + let factor: number; + + if (i === 0) { + factor = 1.0; // Original brightness + } else if (i === 1) { + factor = 1.2; // Slight bloom/glare effect + } else { + // Exponential decay for natural-looking trail fade + factor = Math.pow(0.6, i - 1); + } + + const r = Math.min(1.0, baseRgba.r * factor); + const g = Math.min(1.0, baseRgba.g * factor); + const b = Math.min(1.0, baseRgba.b * factor); + + colors.push(RGBA.fromValues(r, g, b, 1.0)); + } + + return colors; +} + +/** + * Derives the inactive/default color from a bright color + * @param brightColor The brightest color (center/head of the scanner) + * @param factor Brightness factor for inactive color (default: 0.2) + * @returns A much darker version suitable for inactive dots + */ +export function deriveInactiveColor( + brightColor: ColorInput, + factor: number = 0.2, +): RGBA { + const baseRgba = + brightColor instanceof RGBA + ? brightColor + : RGBA.fromHex(brightColor as string); + + const r = baseRgba.r * factor; + const g = baseRgba.g * factor; + const b = baseRgba.b * factor; + + return RGBA.fromValues(r, g, b, 1.0); +} + +export type KnightRiderStyle = "blocks" | "diamonds"; + +export interface KnightRiderOptions { + width?: number; + style?: KnightRiderStyle; + holdStart?: number; + holdEnd?: number; + colors?: ColorInput[]; + /** Single color to derive trail from (alternative to providing colors array) */ + color?: ColorInput; + /** Number of trail steps when using single color (default: 6) */ + trailSteps?: number; + defaultColor?: ColorInput; + /** Brightness factor for inactive color when using single color (default: 0.2) */ + inactiveFactor?: number; +} + +/** + * Creates frame strings for a Knight Rider style scanner animation + * @param options Configuration options for the Knight Rider effect + * @returns Array of frame strings + */ +export function createFrames(options: KnightRiderOptions = {}): string[] { + const width = options.width ?? 8; + const style = options.style ?? "diamonds"; + const holdStart = options.holdStart ?? 30; + const holdEnd = options.holdEnd ?? 9; + + const colors = + options.colors ?? + (options.color + ? deriveTrailColors(options.color, options.trailSteps) + : [ + RGBA.fromHex("#ff0000"), // Brightest Red (Center) + RGBA.fromHex("#ff5555"), // Glare/Bloom + RGBA.fromHex("#dd0000"), // Trail 1 + RGBA.fromHex("#aa0000"), // Trail 2 + RGBA.fromHex("#770000"), // Trail 3 + RGBA.fromHex("#440000"), // Trail 4 + ]); + + const defaultColor = + options.defaultColor ?? + (options.color + ? deriveInactiveColor(options.color, options.inactiveFactor) + : RGBA.fromHex("#330000")); + + const trailOptions = { + colors, + trailLength: colors.length, + defaultColor, + direction: "bidirectional" as const, + holdFrames: { start: holdStart, end: holdEnd }, + }; + + // Bidirectional cycle: Forward (width) + Hold End + Backward (width-1) + Hold Start + const totalFrames = width + holdEnd + (width - 1) + holdStart; + + // Generate dynamic frames where inactive pixels are dots and active ones are blocks + const frames = Array.from({ length: totalFrames }, (_, frameIndex) => { + return Array.from({ length: width }, (_, charIndex) => { + const index = calculateColorIndex( + frameIndex, + charIndex, + width, + trailOptions, + ); + + if (style === "diamonds") { + const shapes = ["⬥", "◆", "⬩", "⬪"]; + if (index >= 0 && index < trailOptions.colors.length) { + return shapes[Math.min(index, shapes.length - 1)]; + } + return "·"; + } + + // Default to blocks + // It's active if we have a valid color index that is within our colors array + const isActive = index >= 0 && index < trailOptions.colors.length; + return isActive ? "■" : "⬝"; + }).join(""); + }); + + return frames; +} + +/** + * Creates a color generator function for Knight Rider style scanner animation + * @param options Configuration options for the Knight Rider effect + * @returns ColorGenerator function + */ +export function createColors(options: KnightRiderOptions = {}): ColorGenerator { + const holdStart = options.holdStart ?? 30; + const holdEnd = options.holdEnd ?? 9; + + const colors = + options.colors ?? + (options.color + ? deriveTrailColors(options.color, options.trailSteps) + : [ + RGBA.fromHex("#ff0000"), // Brightest Red (Center) + RGBA.fromHex("#ff5555"), // Glare/Bloom + RGBA.fromHex("#dd0000"), // Trail 1 + RGBA.fromHex("#aa0000"), // Trail 2 + RGBA.fromHex("#770000"), // Trail 3 + RGBA.fromHex("#440000"), // Trail 4 + ]); + + const defaultColor = + options.defaultColor ?? + (options.color + ? deriveInactiveColor(options.color, options.inactiveFactor) + : RGBA.fromHex("#330000")); + + const trailOptions = { + colors, + trailLength: colors.length, + defaultColor, + direction: "bidirectional" as const, + holdFrames: { start: holdStart, end: holdEnd }, + }; + + return createKnightRiderTrail(trailOptions); +} From 8167e9080148a72bdf1460dbcd0da99ddc2ca8cb Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Mon, 24 Nov 2025 18:40:01 +0000 Subject: [PATCH 42/66] chore: format code --- .../cli/cmd/tui/component/prompt/index.tsx | 9 +- .../opencode/src/cli/cmd/tui/ui/spinner.ts | 272 +++++++----------- 2 files changed, 113 insertions(+), 168 deletions(-) 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 4e2fa9d3577..7a48137028a 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -1,6 +1,6 @@ import { BoxRenderable, TextareaRenderable, MouseEvent, PasteEvent, t, dim, fg, type KeyBinding } from "@opentui/core" import { createEffect, createMemo, type JSX, onMount, createSignal, onCleanup, Show, Switch, Match } from "solid-js" -import "opentui-spinner/solid"; +import "opentui-spinner/solid" import { useLocal } from "@tui/context/local" import { useTheme } from "@tui/context/theme" import { EmptyBorder } from "@tui/component/border" @@ -830,11 +830,7 @@ export function Prompt(props: PromptProps) { justifyContent={status().type === "retry" ? "space-between" : "flex-start"} > - + {(() => { const retry = createMemo(() => { @@ -904,4 +900,3 @@ export function Prompt(props: PromptProps) { ) } - diff --git a/packages/opencode/src/cli/cmd/tui/ui/spinner.ts b/packages/opencode/src/cli/cmd/tui/ui/spinner.ts index e09b079b4a4..5c99acccb4c 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/spinner.ts +++ b/packages/opencode/src/cli/cmd/tui/ui/spinner.ts @@ -1,23 +1,23 @@ -import type { ColorInput } from "@opentui/core"; -import { RGBA } from "@opentui/core"; -import type { ColorGenerator } from "opentui-spinner"; +import type { ColorInput } from "@opentui/core" +import { RGBA } from "@opentui/core" +import type { ColorGenerator } from "opentui-spinner" interface AdvancedGradientOptions { - colors: ColorInput[]; - trailLength: number; - defaultColor?: ColorInput; - direction?: "forward" | "backward" | "bidirectional"; - holdFrames?: { start?: number; end?: number }; + colors: ColorInput[] + trailLength: number + defaultColor?: ColorInput + direction?: "forward" | "backward" | "bidirectional" + holdFrames?: { start?: number; end?: number } } interface ScannerState { - activePosition: number; - isHolding: boolean; - holdProgress: number; - holdTotal: number; - movementProgress: number; - movementTotal: number; - isMovingForward: boolean; + activePosition: number + isHolding: boolean + holdProgress: number + holdTotal: number + movementProgress: number + movementTotal: number + isMovingForward: boolean } function getScannerState( @@ -25,12 +25,12 @@ function getScannerState( totalChars: number, options: Pick, ): ScannerState { - const { direction = "forward", holdFrames = {} } = options; + const { direction = "forward", holdFrames = {} } = options if (direction === "bidirectional") { - const forwardFrames = totalChars; - const holdEndFrames = holdFrames.end ?? 0; - const backwardFrames = totalChars - 1; + const forwardFrames = totalChars + const holdEndFrames = holdFrames.end ?? 0 + const backwardFrames = totalChars - 1 if (frameIndex < forwardFrames) { // Moving forward @@ -42,7 +42,7 @@ function getScannerState( movementProgress: frameIndex, movementTotal: forwardFrames, isMovingForward: true, - }; + } } else if (frameIndex < forwardFrames + holdEndFrames) { // Holding at end return { @@ -53,10 +53,10 @@ function getScannerState( movementProgress: 0, movementTotal: 0, isMovingForward: true, - }; + } } else if (frameIndex < forwardFrames + holdEndFrames + backwardFrames) { // Moving backward - const backwardIndex = frameIndex - forwardFrames - holdEndFrames; + const backwardIndex = frameIndex - forwardFrames - holdEndFrames return { activePosition: totalChars - 2 - backwardIndex, isHolding: false, @@ -65,19 +65,18 @@ function getScannerState( movementProgress: backwardIndex, movementTotal: backwardFrames, isMovingForward: false, - }; + } } else { // Holding at start return { activePosition: 0, isHolding: true, - holdProgress: - frameIndex - forwardFrames - holdEndFrames - backwardFrames, + holdProgress: frameIndex - forwardFrames - holdEndFrames - backwardFrames, holdTotal: holdFrames.start ?? 0, movementProgress: 0, movementTotal: 0, isMovingForward: false, - }; + } } } else if (direction === "backward") { return { @@ -88,7 +87,7 @@ function getScannerState( movementProgress: frameIndex % totalChars, movementTotal: totalChars, isMovingForward: false, - }; + } } else { return { activePosition: frameIndex % totalChars, @@ -98,7 +97,7 @@ function getScannerState( movementProgress: frameIndex % totalChars, movementTotal: totalChars, isMovingForward: true, - }; + } } } @@ -106,112 +105,84 @@ function calculateColorIndex( frameIndex: number, charIndex: number, totalChars: number, - options: Pick< - AdvancedGradientOptions, - "direction" | "holdFrames" | "trailLength" - >, + options: Pick, state?: ScannerState, ): number { - const { trailLength } = options; + const { trailLength } = options const { activePosition, isHolding, holdProgress, isMovingForward } = - state ?? getScannerState(frameIndex, totalChars, options); + state ?? getScannerState(frameIndex, totalChars, options) // Calculate directional distance (positive means trailing behind) const directionalDistance = isMovingForward ? activePosition - charIndex // For forward: trail is to the left (lower indices) - : charIndex - activePosition; // For backward: trail is to the right (higher indices) + : charIndex - activePosition // For backward: trail is to the right (higher indices) // Handle hold frame fading: keep the lead bright, fade the trail if (isHolding) { // Shift the color index by how long we've been holding - return directionalDistance + holdProgress; + return directionalDistance + holdProgress } // Normal movement - show gradient trail only behind the movement direction if (directionalDistance > 0 && directionalDistance < trailLength) { - return directionalDistance; + return directionalDistance } // At the active position, show the brightest color if (directionalDistance === 0) { - return 0; + return 0 } - return -1; + return -1 } -function createKnightRiderTrail( - options: AdvancedGradientOptions, -): ColorGenerator { - const { colors, defaultColor } = options; +function createKnightRiderTrail(options: AdvancedGradientOptions): ColorGenerator { + const { colors, defaultColor } = options // Use the provided defaultColor if it's an RGBA instance, otherwise convert/default // We use RGBA.fromHex for the fallback to ensure we have an RGBA object. // Note: If defaultColor is a string, we convert it once here. - const defaultRgba = - defaultColor instanceof RGBA - ? defaultColor - : RGBA.fromHex((defaultColor as string) || "#000000"); - - let cachedFrameIndex = -1; - let cachedState: ScannerState | null = null; - - return ( - frameIndex: number, - charIndex: number, - _totalFrames: number, - totalChars: number, - ) => { + const defaultRgba = defaultColor instanceof RGBA ? defaultColor : RGBA.fromHex((defaultColor as string) || "#000000") + + let cachedFrameIndex = -1 + let cachedState: ScannerState | null = null + + return (frameIndex: number, charIndex: number, _totalFrames: number, totalChars: number) => { if (frameIndex !== cachedFrameIndex) { - cachedFrameIndex = frameIndex; - cachedState = getScannerState(frameIndex, totalChars, options); + cachedFrameIndex = frameIndex + cachedState = getScannerState(frameIndex, totalChars, options) } - const state = cachedState!; + const state = cachedState! - const index = calculateColorIndex( - frameIndex, - charIndex, - totalChars, - options, - state, - ); + const index = calculateColorIndex(frameIndex, charIndex, totalChars, options, state) // Calculate global fade for inactive dots during hold or movement - const { - isHolding, - holdProgress, - holdTotal, - movementProgress, - movementTotal, - } = state; - - let alpha = 1.0; + const { isHolding, holdProgress, holdTotal, movementProgress, movementTotal } = state + + let alpha = 1.0 if (isHolding && holdTotal > 0) { // Fade out linearly - const progress = Math.min(holdProgress / holdTotal, 1); - alpha = Math.max(0, 1 - progress); + const progress = Math.min(holdProgress / holdTotal, 1) + alpha = Math.max(0, 1 - progress) } else if (!isHolding && movementTotal > 0) { // Fade in linearly during movement - const progress = Math.min( - movementProgress / Math.max(1, movementTotal - 1), - 1, - ); - alpha = progress; + const progress = Math.min(movementProgress / Math.max(1, movementTotal - 1), 1) + alpha = progress } // Mutate the alpha of the default RGBA object // This assumes single-threaded, synchronous rendering per frame // where we can modify the state for the current frame. // Since this is run for every char in the frame, setting it repeatedly to the same value is fine. - defaultRgba.a = alpha; + defaultRgba.a = alpha if (index === -1) { - return defaultRgba; + return defaultRgba } - return colors[index] ?? defaultRgba; - }; + return colors[index] ?? defaultRgba + } } /** @@ -220,41 +191,35 @@ function createKnightRiderTrail( * @param steps Number of gradient steps (default: 6) * @returns Array of RGBA colors from brightest to darkest */ -export function deriveTrailColors( - brightColor: ColorInput, - steps: number = 6, -): RGBA[] { - const baseRgba = - brightColor instanceof RGBA - ? brightColor - : RGBA.fromHex(brightColor as string); +export function deriveTrailColors(brightColor: ColorInput, steps: number = 6): RGBA[] { + const baseRgba = brightColor instanceof RGBA ? brightColor : RGBA.fromHex(brightColor as string) - const colors: RGBA[] = []; + const colors: RGBA[] = [] for (let i = 0; i < steps; i++) { // Progressive darkening: // i=0: 100% brightness (original color) // i=1: add slight bloom/glare (lighten) // i=2+: progressively darken - let factor: number; + let factor: number if (i === 0) { - factor = 1.0; // Original brightness + factor = 1.0 // Original brightness } else if (i === 1) { - factor = 1.2; // Slight bloom/glare effect + factor = 1.2 // Slight bloom/glare effect } else { // Exponential decay for natural-looking trail fade - factor = Math.pow(0.6, i - 1); + factor = Math.pow(0.6, i - 1) } - const r = Math.min(1.0, baseRgba.r * factor); - const g = Math.min(1.0, baseRgba.g * factor); - const b = Math.min(1.0, baseRgba.b * factor); + const r = Math.min(1.0, baseRgba.r * factor) + const g = Math.min(1.0, baseRgba.g * factor) + const b = Math.min(1.0, baseRgba.b * factor) - colors.push(RGBA.fromValues(r, g, b, 1.0)); + colors.push(RGBA.fromValues(r, g, b, 1.0)) } - return colors; + return colors } /** @@ -263,37 +228,31 @@ export function deriveTrailColors( * @param factor Brightness factor for inactive color (default: 0.2) * @returns A much darker version suitable for inactive dots */ -export function deriveInactiveColor( - brightColor: ColorInput, - factor: number = 0.2, -): RGBA { - const baseRgba = - brightColor instanceof RGBA - ? brightColor - : RGBA.fromHex(brightColor as string); - - const r = baseRgba.r * factor; - const g = baseRgba.g * factor; - const b = baseRgba.b * factor; - - return RGBA.fromValues(r, g, b, 1.0); +export function deriveInactiveColor(brightColor: ColorInput, factor: number = 0.2): RGBA { + const baseRgba = brightColor instanceof RGBA ? brightColor : RGBA.fromHex(brightColor as string) + + const r = baseRgba.r * factor + const g = baseRgba.g * factor + const b = baseRgba.b * factor + + return RGBA.fromValues(r, g, b, 1.0) } -export type KnightRiderStyle = "blocks" | "diamonds"; +export type KnightRiderStyle = "blocks" | "diamonds" export interface KnightRiderOptions { - width?: number; - style?: KnightRiderStyle; - holdStart?: number; - holdEnd?: number; - colors?: ColorInput[]; + width?: number + style?: KnightRiderStyle + holdStart?: number + holdEnd?: number + colors?: ColorInput[] /** Single color to derive trail from (alternative to providing colors array) */ - color?: ColorInput; + color?: ColorInput /** Number of trail steps when using single color (default: 6) */ - trailSteps?: number; - defaultColor?: ColorInput; + trailSteps?: number + defaultColor?: ColorInput /** Brightness factor for inactive color when using single color (default: 0.2) */ - inactiveFactor?: number; + inactiveFactor?: number } /** @@ -302,10 +261,10 @@ export interface KnightRiderOptions { * @returns Array of frame strings */ export function createFrames(options: KnightRiderOptions = {}): string[] { - const width = options.width ?? 8; - const style = options.style ?? "diamonds"; - const holdStart = options.holdStart ?? 30; - const holdEnd = options.holdEnd ?? 9; + const width = options.width ?? 8 + const style = options.style ?? "diamonds" + const holdStart = options.holdStart ?? 30 + const holdEnd = options.holdEnd ?? 9 const colors = options.colors ?? @@ -318,13 +277,11 @@ export function createFrames(options: KnightRiderOptions = {}): string[] { RGBA.fromHex("#aa0000"), // Trail 2 RGBA.fromHex("#770000"), // Trail 3 RGBA.fromHex("#440000"), // Trail 4 - ]); + ]) const defaultColor = options.defaultColor ?? - (options.color - ? deriveInactiveColor(options.color, options.inactiveFactor) - : RGBA.fromHex("#330000")); + (options.color ? deriveInactiveColor(options.color, options.inactiveFactor) : RGBA.fromHex("#330000")) const trailOptions = { colors, @@ -332,37 +289,32 @@ export function createFrames(options: KnightRiderOptions = {}): string[] { defaultColor, direction: "bidirectional" as const, holdFrames: { start: holdStart, end: holdEnd }, - }; + } // Bidirectional cycle: Forward (width) + Hold End + Backward (width-1) + Hold Start - const totalFrames = width + holdEnd + (width - 1) + holdStart; + const totalFrames = width + holdEnd + (width - 1) + holdStart // Generate dynamic frames where inactive pixels are dots and active ones are blocks const frames = Array.from({ length: totalFrames }, (_, frameIndex) => { return Array.from({ length: width }, (_, charIndex) => { - const index = calculateColorIndex( - frameIndex, - charIndex, - width, - trailOptions, - ); + const index = calculateColorIndex(frameIndex, charIndex, width, trailOptions) if (style === "diamonds") { - const shapes = ["⬥", "◆", "⬩", "⬪"]; + const shapes = ["⬥", "◆", "⬩", "⬪"] if (index >= 0 && index < trailOptions.colors.length) { - return shapes[Math.min(index, shapes.length - 1)]; + return shapes[Math.min(index, shapes.length - 1)] } - return "·"; + return "·" } // Default to blocks // It's active if we have a valid color index that is within our colors array - const isActive = index >= 0 && index < trailOptions.colors.length; - return isActive ? "■" : "⬝"; - }).join(""); - }); + const isActive = index >= 0 && index < trailOptions.colors.length + return isActive ? "■" : "⬝" + }).join("") + }) - return frames; + return frames } /** @@ -371,8 +323,8 @@ export function createFrames(options: KnightRiderOptions = {}): string[] { * @returns ColorGenerator function */ export function createColors(options: KnightRiderOptions = {}): ColorGenerator { - const holdStart = options.holdStart ?? 30; - const holdEnd = options.holdEnd ?? 9; + const holdStart = options.holdStart ?? 30 + const holdEnd = options.holdEnd ?? 9 const colors = options.colors ?? @@ -385,13 +337,11 @@ export function createColors(options: KnightRiderOptions = {}): ColorGenerator { RGBA.fromHex("#aa0000"), // Trail 2 RGBA.fromHex("#770000"), // Trail 3 RGBA.fromHex("#440000"), // Trail 4 - ]); + ]) const defaultColor = options.defaultColor ?? - (options.color - ? deriveInactiveColor(options.color, options.inactiveFactor) - : RGBA.fromHex("#330000")); + (options.color ? deriveInactiveColor(options.color, options.inactiveFactor) : RGBA.fromHex("#330000")) const trailOptions = { colors, @@ -399,7 +349,7 @@ export function createColors(options: KnightRiderOptions = {}): ColorGenerator { defaultColor, direction: "bidirectional" as const, holdFrames: { start: holdStart, end: holdEnd }, - }; + } - return createKnightRiderTrail(trailOptions); + return createKnightRiderTrail(trailOptions) } From 125af820d02b6c0825099fc08d5000e1eb0786ca Mon Sep 17 00:00:00 2001 From: opencode Date: Mon, 24 Nov 2025 19:16:14 +0000 Subject: [PATCH 43/66] release: v1.0.108 --- bun.lock | 30 +++++++++++++------------- packages/console/app/package.json | 2 +- packages/console/core/package.json | 2 +- packages/console/function/package.json | 2 +- packages/console/mail/package.json | 2 +- packages/desktop/package.json | 2 +- packages/enterprise/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +++++------ packages/function/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 4 ++-- packages/sdk/js/package.json | 4 ++-- packages/slack/package.json | 2 +- packages/tauri/package.json | 2 +- packages/ui/package.json | 2 +- packages/util/package.json | 2 +- packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- 18 files changed, 39 insertions(+), 39 deletions(-) diff --git a/bun.lock b/bun.lock index d6207f3cd3d..17d961b7328 100644 --- a/bun.lock +++ b/bun.lock @@ -19,7 +19,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -46,7 +46,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -73,7 +73,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -97,7 +97,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -121,7 +121,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -162,7 +162,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -188,7 +188,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "22.0.0", @@ -204,7 +204,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.107", + "version": "1.0.108", "bin": { "opencode": "./bin/opencode", }, @@ -291,7 +291,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -311,7 +311,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.107", + "version": "1.0.108", "devDependencies": { "@hey-api/openapi-ts": "0.81.0", "@tsconfig/node22": "catalog:", @@ -322,7 +322,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -335,7 +335,7 @@ }, "packages/tauri": { "name": "@opencode-ai/tauri", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "@tauri-apps/api": "^2", "@tauri-apps/plugin-opener": "^2", @@ -348,7 +348,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -380,7 +380,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "zod": "catalog:", }, @@ -390,7 +390,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 1669fb50a61..153c07c5843 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.0.107", + "version": "1.0.108", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index db0904e3ba5..1e004638508 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/console-core", - "version": "1.0.107", + "version": "1.0.108", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 34e7944fbec..c247f10be37 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.107", + "version": "1.0.108", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/console/mail/package.json b/packages/console/mail/package.json index 8bcde9ee4d3..12f8b318c11 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.107", + "version": "1.0.108", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index aef78d8d476..a23150d626f 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.107", + "version": "1.0.108", "description": "", "type": "module", "scripts": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index 37970c2ee89..12bac8bbccb 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.0.107", + "version": "1.0.108", "private": true, "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index f1c6a36e7e3..2929c179da6 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "opencode" name = "OpenCode" description = "The AI coding agent built for the terminal" -version = "1.0.107" +version = "1.0.108" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/sst/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.107/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.108/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.107/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.108/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.107/opencode-linux-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.108/opencode-linux-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.107/opencode-linux-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.108/opencode-linux-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.107/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.108/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index 9ee6a260812..f40b10a7abe 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.107", + "version": "1.0.108", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 3b6e0760455..595a99255f4 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.107", + "version": "1.0.108", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 9f284756d9b..46b0878c760 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/plugin", - "version": "1.0.107", + "version": "1.0.108", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} +} \ No newline at end of file diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index b43cd27837e..104b2033dec 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/sdk", - "version": "1.0.107", + "version": "1.0.108", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -26,4 +26,4 @@ "publishConfig": { "directory": "dist" } -} +} \ No newline at end of file diff --git a/packages/slack/package.json b/packages/slack/package.json index 9fda47a2fd1..99fe097ae3e 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.107", + "version": "1.0.108", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/tauri/package.json b/packages/tauri/package.json index 8b7d4c98857..b14db25bbb2 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/tauri", "private": true, - "version": "1.0.107", + "version": "1.0.108", "type": "module", "scripts": { "dev": "vite", diff --git a/packages/ui/package.json b/packages/ui/package.json index 8edf23bc375..57a8319e3ee 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.107", + "version": "1.0.108", "type": "module", "exports": { "./*": "./src/components/*.tsx", diff --git a/packages/util/package.json b/packages/util/package.json index ea8be33cd3d..88bef625b4f 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.0.107", + "version": "1.0.108", "private": true, "type": "module", "exports": { diff --git a/packages/web/package.json b/packages/web/package.json index 4bcb0835aa2..61eb81beb5f 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.107", + "version": "1.0.108", "scripts": { "dev": "astro dev", "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index db9f63ec691..2fa403f5e9e 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "1.0.107", + "version": "1.0.108", "publisher": "sst-dev", "repository": { "type": "git", From b6c1df41fba66e43dbef26a613a1a4d246e13b94 Mon Sep 17 00:00:00 2001 From: Sebastian Herrlinger Date: Mon, 24 Nov 2025 20:50:54 +0100 Subject: [PATCH 44/66] textarea highlight cursor color --- .../opencode/src/cli/cmd/tui/component/prompt/index.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) 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 7a48137028a..43aeef2137c 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -562,10 +562,6 @@ export function Prompt(props: PromptProps) { } }) - createEffect(() => { - renderer.setCursorColor(highlight()) - }) - return ( <> (input = r)} onMouseDown={(r: MouseEvent) => r.target?.focus()} focusedBackgroundColor={theme.backgroundElement} - cursorColor={theme.primary} + cursorColor={highlight()} syntaxStyle={syntax()} /> From 80b9cd12923f228c9d27bc65f64c70bcef568bc4 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Mon, 24 Nov 2025 19:53:00 +0000 Subject: [PATCH 45/66] chore: format code --- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 46b0878c760..264df7b5a27 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} \ No newline at end of file +} diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 104b2033dec..02474c3e6f2 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -26,4 +26,4 @@ "publishConfig": { "directory": "dist" } -} \ No newline at end of file +} From 0ed7fac5fb9034248153c8a7630d397916d159ec Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 24 Nov 2025 15:24:43 -0500 Subject: [PATCH 46/66] wip: zen --- packages/console/core/package.json | 1 + packages/console/core/script/pull-models.ts | 31 +++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100755 packages/console/core/script/pull-models.ts diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 1e004638508..6d139b7144a 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -30,6 +30,7 @@ "update-models": "script/update-models.ts", "promote-models-to-dev": "script/promote-models.ts dev", "promote-models-to-prod": "script/promote-models.ts production", + "pull-models-from-dev": "script/pull-models.ts dev", "typecheck": "tsgo --noEmit" }, "devDependencies": { diff --git a/packages/console/core/script/pull-models.ts b/packages/console/core/script/pull-models.ts new file mode 100755 index 00000000000..a89e3951c8d --- /dev/null +++ b/packages/console/core/script/pull-models.ts @@ -0,0 +1,31 @@ +#!/usr/bin/env bun + +import { $ } from "bun" +import path from "path" +import { ZenData } from "../src/model" + +const stage = process.argv[2] +if (!stage) throw new Error("Stage is required") + +const root = path.resolve(process.cwd(), "..", "..", "..") + +// read the secret +const ret = await $`bun sst secret list --stage ${stage}`.cwd(root).text() +const lines = ret.split("\n") +const value1 = lines.find((line) => line.startsWith("ZEN_MODELS1"))?.split("=")[1] +const value2 = lines.find((line) => line.startsWith("ZEN_MODELS2"))?.split("=")[1] +const value3 = lines.find((line) => line.startsWith("ZEN_MODELS3"))?.split("=")[1] +const value4 = lines.find((line) => line.startsWith("ZEN_MODELS4"))?.split("=")[1] +if (!value1) throw new Error("ZEN_MODELS1 not found") +if (!value2) throw new Error("ZEN_MODELS2 not found") +if (!value3) throw new Error("ZEN_MODELS3 not found") +if (!value4) throw new Error("ZEN_MODELS4 not found") + +// validate value +ZenData.validate(JSON.parse(value1 + value2 + value3 + value4)) + +// update the secret +await $`bun sst secret set ZEN_MODELS1 ${value1}` +await $`bun sst secret set ZEN_MODELS2 ${value2}` +await $`bun sst secret set ZEN_MODELS3 ${value3}` +await $`bun sst secret set ZEN_MODELS4 ${value4}` From ccde319937b7ffb84aadd283a260bfe0f98c9bbb Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Mon, 24 Nov 2025 14:26:53 -0600 Subject: [PATCH 47/66] ci: nix hash --- .github/workflows/update-nix-hashes.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/update-nix-hashes.yml b/.github/workflows/update-nix-hashes.yml index 2f0aeac20d4..c0ff77b5640 100644 --- a/.github/workflows/update-nix-hashes.yml +++ b/.github/workflows/update-nix-hashes.yml @@ -28,6 +28,7 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 + ref: ${{ github.head_ref || github.ref_name }} - name: Setup Nix uses: DeterminateSystems/nix-installer-action@v20 @@ -79,6 +80,7 @@ jobs: git commit -m "Update Nix flake.lock and hashes" BRANCH="${TARGET_BRANCH:-${GITHUB_REF_NAME}}" + git pull --rebase origin "$BRANCH" git push origin HEAD:"$BRANCH" summarize "committed $(git rev-parse --short HEAD)" From a9a2c23736bafda2d316ce7d667772e3cbe36bd5 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Mon, 24 Nov 2025 14:32:38 -0600 Subject: [PATCH 48/66] add autoupdate: notify --- packages/opencode/src/cli/upgrade.ts | 3 +++ packages/opencode/src/config/config.ts | 7 ++++++- packages/sdk/js/src/gen/types.gen.ts | 4 ++-- packages/web/src/content/docs/config.mdx | 2 ++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/cli/upgrade.ts b/packages/opencode/src/cli/upgrade.ts index ca5cba27c5a..2bea760b33b 100644 --- a/packages/opencode/src/cli/upgrade.ts +++ b/packages/opencode/src/cli/upgrade.ts @@ -10,6 +10,9 @@ export async function upgrade() { if (Installation.VERSION === latest) return if (config.autoupdate === false || Flag.OPENCODE_DISABLE_AUTOUPDATE) { + return + } + if (config.autoupdate === "notify") { await Bus.publish(Installation.Event.UpdateAvailable, { version: latest }) return } diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 837899be575..79f969eeaf6 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -479,7 +479,12 @@ export namespace Config { .boolean() .optional() .describe("@deprecated Use 'share' field instead. Share newly created sessions automatically"), - autoupdate: z.boolean().optional().describe("Automatically update to the latest version"), + autoupdate: z + .union([z.boolean(), z.literal("notify")]) + .optional() + .describe( + "Automatically update to the latest version. Set to true to auto-update, false to disable, or 'notify' to show update notifications", + ), disabled_providers: z.array(z.string()).optional().describe("Disable providers that are loaded automatically"), enabled_providers: z .array(z.string()) diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts index e2e611db13a..3ba41cc2390 100644 --- a/packages/sdk/js/src/gen/types.gen.ts +++ b/packages/sdk/js/src/gen/types.gen.ts @@ -1021,9 +1021,9 @@ export type Config = { */ autoshare?: boolean /** - * Automatically update to the latest version + * Automatically update to the latest version. Set to true to auto-update, false to disable, or 'notify' to show update notifications */ - autoupdate?: boolean + autoupdate?: boolean | "notify" /** * Disable providers that are loaded automatically */ diff --git a/packages/web/src/content/docs/config.mdx b/packages/web/src/content/docs/config.mdx index 68f75b7a67a..46d0d82685a 100644 --- a/packages/web/src/content/docs/config.mdx +++ b/packages/web/src/content/docs/config.mdx @@ -267,6 +267,8 @@ OpenCode will automatically download any new updates when it starts up. You can } ``` +If you don't want updates but want to be notified when a new version is available, set `autoupdate` to `"notify"`. + --- ### Formatters From 46a76a778aef3a575f4eecd0042cd4b4c701cee5 Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 24 Nov 2025 15:39:37 -0500 Subject: [PATCH 49/66] zen: add opus 4.5 --- packages/web/src/content/docs/zen.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/web/src/content/docs/zen.mdx b/packages/web/src/content/docs/zen.mdx index bed629f205f..f2fc746df92 100644 --- a/packages/web/src/content/docs/zen.mdx +++ b/packages/web/src/content/docs/zen.mdx @@ -73,6 +73,7 @@ You can also access our models through the following API endpoints. | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -130,6 +131,7 @@ We support a pay-as-you-go model. Below are the prices **per 1M tokens**. | Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | | Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | | Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | | Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | From 3fb57044d120618c92214b734d1fc831955e39a2 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Sun, 23 Nov 2025 19:28:48 -0600 Subject: [PATCH 50/66] wip(share): more styling --- .opencode/opencode.jsonc | 10 ++++--- packages/enterprise/src/core/share.ts | 9 +++++- .../src/routes/share/[sessionID].tsx | 27 +++++++++++------- packages/opencode/src/share/share-next.ts | 28 +++++++++++++++++++ 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/.opencode/opencode.jsonc b/.opencode/opencode.jsonc index dd5a4c750fb..aadc0240878 100644 --- a/.opencode/opencode.jsonc +++ b/.opencode/opencode.jsonc @@ -1,9 +1,11 @@ { "$schema": "https://opencode.ai/config.json", - "plugin": ["opencode-openai-codex-auth"], - // "enterprise": { - // "url": "http://localhost:3000", - // }, + "plugin": [ + "opencode-openai-codex-auth" + ], + "enterprise": { + "url": "http://localhost:3000", + }, "provider": { "opencode": { "options": { diff --git a/packages/enterprise/src/core/share.ts b/packages/enterprise/src/core/share.ts index a7dfbfdcc0d..c24077ec365 100644 --- a/packages/enterprise/src/core/share.ts +++ b/packages/enterprise/src/core/share.ts @@ -1,4 +1,4 @@ -import { FileDiff, Message, Part, Session, SessionStatus } from "@opencode-ai/sdk" +import { FileDiff, Message, Model, Part, Session, SessionStatus } from "@opencode-ai/sdk" import { fn } from "@opencode-ai/util/fn" import { iife } from "@opencode-ai/util/iife" import z from "zod" @@ -32,6 +32,10 @@ export namespace Share { type: z.literal("session_status"), data: z.custom(), }), + z.object({ + type: z.literal("model"), + data: z.custom(), + }), ]) export type Data = z.infer @@ -111,6 +115,9 @@ export namespace Share { case "session_status": await Storage.write(["share_data", input.share.id, "session_status"], item.data) break + case "model": + await Storage.write(["share_data", input.share.id, "model"], item.data) + break } }), ) diff --git a/packages/enterprise/src/routes/share/[sessionID].tsx b/packages/enterprise/src/routes/share/[sessionID].tsx index 0ff0482f170..a2365aa1dbb 100644 --- a/packages/enterprise/src/routes/share/[sessionID].tsx +++ b/packages/enterprise/src/routes/share/[sessionID].tsx @@ -1,7 +1,7 @@ -import { FileDiff, Message, Part, Session, SessionStatus, UserMessage } from "@opencode-ai/sdk" +import { FileDiff, Message, Model, Part, Session, SessionStatus, UserMessage } from "@opencode-ai/sdk" import { SessionTurn } from "@opencode-ai/ui/session-turn" import { SessionReview } from "@opencode-ai/ui/session-review" -import { DataProvider, useData } from "@opencode-ai/ui/context" +import { DataProvider } from "@opencode-ai/ui/context" import { createAsync, query, RouteDefinition, useParams } from "@solidjs/router" import { createMemo, Show } from "solid-js" import { Share } from "~/core/share" @@ -29,6 +29,9 @@ const getData = query(async (sessionID) => { part: { [messageID: string]: Part[] } + model: { + [sessionID: string]: Model[] + } } = { session: [], session_diff: { @@ -41,6 +44,7 @@ const getData = query(async (sessionID) => { }, message: {}, part: {}, + model: {}, } for (const item of data) { switch (item.type) { @@ -61,6 +65,9 @@ const getData = query(async (sessionID) => { result.part[item.data.messageID] = result.part[item.data.messageID] ?? [] result.part[item.data.messageID].push(item.data) break + case "model": + result.model[sessionID] = item.data + break } } return result @@ -82,15 +89,14 @@ export default function () { {(data) => ( {iife(() => { - const data = useData() const [store, setStore] = createStore({ messageId: undefined as string | undefined, }) - const match = createMemo(() => Binary.search(data.session, params.sessionID!, (s) => s.id)) + const match = createMemo(() => Binary.search(data().session, params.sessionID!, (s) => s.id)) if (!match().found) throw new Error(`Session ${params.sessionID} not found`) - const info = createMemo(() => data.session[match().index]) + const info = createMemo(() => data().session[match().index]) const messages = createMemo(() => - params.sessionID ? (data.message[params.sessionID]?.filter((m) => m.role === "user") ?? []) : [], + params.sessionID ? (data().message[params.sessionID]?.filter((m) => m.role === "user") ?? []) : [], ) const firstUserMessage = createMemo(() => messages().at(0)) const activeMessage = createMemo( @@ -104,8 +110,9 @@ export default function () { } } const provider = createMemo(() => activeMessage()?.model?.providerID) - const model = createMemo(() => activeMessage()?.model?.modelID) - const diffs = createMemo(() => data.session_diff[params.sessionID!] ?? []) + const modelID = createMemo(() => activeMessage()?.model?.modelID) + const model = createMemo(() => data().model[params.sessionID!]?.find((m) => m.id === modelID())) + const diffs = createMemo(() => data().session_diff[params.sessionID!] ?? []) return (
@@ -152,7 +159,7 @@ export default function () { src={`https://models.dev/logos/${provider()}.svg`} class="size-4 shrink-0 dark:invert" /> -
{model()}
+
{model()?.name ?? modelID()}
{DateTime.fromMillis(info().time.created).toFormat("dd MMM yyyy, HH:mm")} @@ -163,7 +170,7 @@ export default function () {
1}> m.info, + ), + ], + }, + ]) + } }) Bus.subscribe(MessageV2.Event.PartUpdated, async (evt) => { await sync(evt.properties.part.sessionID, [ @@ -90,6 +104,10 @@ export namespace ShareNext { type: "session_diff" data: SDK.FileDiff[] } + | { + type: "model" + data: ModelsDev.Model[] + } async function sync(sessionID: string, data: Data[]) { const url = await Config.get().then((x) => x.enterprise!.url) @@ -129,6 +147,12 @@ export namespace ShareNext { const session = await Session.get(sessionID) const diffs = await Session.diff(sessionID) const messages = await Array.fromAsync(MessageV2.stream(sessionID)) + const models = await Promise.all( + messages + .filter((m) => m.info.role === "user") + .map((m) => (m.info as SDK.UserMessage).model) + .map((m) => Provider.getModel(m.providerID, m.modelID).then((m) => m.info)), + ) await sync(sessionID, [ { type: "session", @@ -143,6 +167,10 @@ export namespace ShareNext { type: "session_diff", data: diffs, }, + { + type: "model", + data: models, + }, ]) } } From acf1dd85006a0bb4009ef601ae7f7a60eb36af4d Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Mon, 24 Nov 2025 11:56:00 -0600 Subject: [PATCH 51/66] wip(share): more styling --- packages/desktop/src/pages/session.tsx | 2 +- packages/enterprise/src/app.css | 17 -- packages/enterprise/src/app.tsx | 17 +- .../src/routes/share/[sessionID].tsx | 279 +++++++++++------- packages/opencode/src/bun/index.ts | 2 +- packages/opencode/src/cli/ui.ts | 2 +- packages/opencode/src/config/config.ts | 2 +- packages/opencode/src/config/markdown.ts | 2 +- packages/opencode/src/file/fzf.ts | 2 +- packages/opencode/src/file/ripgrep.ts | 2 +- packages/opencode/src/ide/index.ts | 2 +- packages/opencode/src/index.ts | 2 +- packages/opencode/src/installation/index.ts | 2 +- packages/opencode/src/lsp/client.ts | 2 +- packages/opencode/src/mcp/index.ts | 2 +- packages/opencode/src/provider/auth.ts | 2 +- packages/opencode/src/provider/provider.ts | 2 +- packages/opencode/src/server/server.ts | 2 +- packages/opencode/src/session/message-v2.ts | 2 +- packages/opencode/src/session/message.ts | 2 +- packages/opencode/src/session/prompt.ts | 2 +- packages/opencode/src/storage/storage.ts | 2 +- packages/ui/src/assets/fonts/tx-02.otf | Bin 0 -> 85940 bytes packages/ui/src/assets/fonts/tx-02.ttf | Bin 0 -> 129876 bytes packages/ui/src/assets/fonts/tx-02.woff2 | Bin 0 -> 51664 bytes packages/ui/src/components/fonts.tsx | 12 +- packages/ui/src/components/message-nav.css | 57 ++-- packages/ui/src/components/message-nav.tsx | 30 +- packages/ui/src/styles/theme.css | 4 +- .../{opencode/src/util => util/src}/error.ts | 0 30 files changed, 264 insertions(+), 190 deletions(-) create mode 100644 packages/ui/src/assets/fonts/tx-02.otf create mode 100644 packages/ui/src/assets/fonts/tx-02.ttf create mode 100644 packages/ui/src/assets/fonts/tx-02.woff2 rename packages/{opencode/src/util => util/src}/error.ts (100%) diff --git a/packages/desktop/src/pages/session.tsx b/packages/desktop/src/pages/session.tsx index f2c572c3f97..84c7d64f23f 100644 --- a/packages/desktop/src/pages/session.tsx +++ b/packages/desktop/src/pages/session.tsx @@ -339,7 +339,7 @@ export default function Page() {
1}> ( - <> - - - - - {props.children} - - - - + + + + {props.children} + + )} > diff --git a/packages/enterprise/src/routes/share/[sessionID].tsx b/packages/enterprise/src/routes/share/[sessionID].tsx index a2365aa1dbb..96a651391a9 100644 --- a/packages/enterprise/src/routes/share/[sessionID].tsx +++ b/packages/enterprise/src/routes/share/[sessionID].tsx @@ -3,15 +3,26 @@ import { SessionTurn } from "@opencode-ai/ui/session-turn" import { SessionReview } from "@opencode-ai/ui/session-review" import { DataProvider } from "@opencode-ai/ui/context" import { createAsync, query, RouteDefinition, useParams } from "@solidjs/router" -import { createMemo, Show } from "solid-js" +import { createMemo, ErrorBoundary, Show } from "solid-js" import { Share } from "~/core/share" import { Logo, Mark } from "@opencode-ai/ui/logo" import { IconButton } from "@opencode-ai/ui/icon-button" import { iife } from "@opencode-ai/util/iife" import { Binary } from "@opencode-ai/util/binary" +import { NamedError } from "@opencode-ai/util/error" import { DateTime } from "luxon" import { MessageNav } from "@opencode-ai/ui/message-nav" import { createStore } from "solid-js/store" +import z from "zod" +import NotFound from "../[...404]" + +const SessionDataMissingError = NamedError.create( + "SessionDataMissingError", + z.object({ + sessionID: z.string(), + message: z.string().optional(), + }), +) const getData = query(async (sessionID) => { const data = await Share.data(sessionID) @@ -70,6 +81,8 @@ const getData = query(async (sessionID) => { break } } + const match = Binary.search(result.session, sessionID!, (s) => s.id) + if (!match.found) throw new SessionDataMissingError({ sessionID }) return result }, "getShareData") @@ -80,126 +93,172 @@ export const route = { export default function () { const params = useParams() const data = createAsync(async () => { - if (!params.sessionID) return + if (!params.sessionID) throw new Error("Missing sessionID") return getData(params.sessionID) }) return ( - - {(data) => ( - - {iife(() => { - const [store, setStore] = createStore({ - messageId: undefined as string | undefined, - }) - const match = createMemo(() => Binary.search(data().session, params.sessionID!, (s) => s.id)) - if (!match().found) throw new Error(`Session ${params.sessionID} not found`) - const info = createMemo(() => data().session[match().index]) - const messages = createMemo(() => - params.sessionID ? (data().message[params.sessionID]?.filter((m) => m.role === "user") ?? []) : [], - ) - const firstUserMessage = createMemo(() => messages().at(0)) - const activeMessage = createMemo( - () => messages().find((m) => m.id === store.messageId) ?? firstUserMessage(), - ) - function setActiveMessage(message: UserMessage | undefined) { - if (message) { - setStore("messageId", message.id) - } else { - setStore("messageId", undefined) + { + return ( + + + + ) + }} + > + + {(data) => ( + + {iife(() => { + const [store, setStore] = createStore({ + messageId: undefined as string | undefined, + }) + const match = createMemo(() => Binary.search(data().session, params.sessionID!, (s) => s.id)) + if (!match().found) throw new Error(`Session ${params.sessionID} not found`) + const info = createMemo(() => data().session[match().index]) + const messages = createMemo(() => + params.sessionID + ? (data().message[params.sessionID]?.filter((m) => m.role === "user") ?? []).sort( + (a, b) => b.time.created - a.time.created, + ) + : [], + ) + const firstUserMessage = createMemo(() => messages().at(0)) + const activeMessage = createMemo( + () => messages().find((m) => m.id === store.messageId) ?? firstUserMessage(), + ) + function setActiveMessage(message: UserMessage | undefined) { + if (message) { + setStore("messageId", message.id) + } else { + setStore("messageId", undefined) + } } - } - const provider = createMemo(() => activeMessage()?.model?.providerID) - const modelID = createMemo(() => activeMessage()?.model?.modelID) - const model = createMemo(() => data().model[params.sessionID!]?.find((m) => m.id === modelID())) - const diffs = createMemo(() => data().session_diff[params.sessionID!] ?? []) + const provider = createMemo(() => activeMessage()?.model?.providerID) + const modelID = createMemo(() => activeMessage()?.model?.modelID) + const model = createMemo(() => data().model[params.sessionID!]?.find((m) => m.id === modelID())) + const diffs = createMemo(() => data().session_diff[params.sessionID!] ?? []) - return ( -
-
-
- - - -
-
- - + const title = ( +
+
+
+ +
v{info().version}
+
+
+ +
{model()?.name ?? modelID()}
+
+
+ {DateTime.fromMillis(info().time.created).toFormat("dd MMM yyyy, HH:mm")} +
-
-
-
-
0, - "px-6 max-w-2xl": diffs().length === 0, - }} - > -
-
-
- -
v{info().version}
-
-
- -
{model()?.name ?? modelID()}
-
-
- {DateTime.fromMillis(info().time.created).toFormat("dd MMM yyyy, HH:mm")} -
+
{info().title}
+
+ ) + + return ( +
+
+
+ + + +
+
+ + +
+
+
+
+
0, + "px-6 max-w-2xl": diffs().length === 0, + }} + > + {title} +
+ 1}> + <> +
0, + "absolute right-full": diffs().length === 0, + }} + > + 0, + }} + messages={messages()} + current={activeMessage()} + onMessageSelect={setActiveMessage} + size={!diffs().length ? "normal" : "compact"} + /> +
+
0, + "absolute right-full": diffs().length === 0, + }} + > + 0, + }} + messages={messages()} + current={activeMessage()} + onMessageSelect={setActiveMessage} + size={!diffs().length ? "normal" : "compact"} + /> +
+ +
+ +
+ +
+
-
{info().title}
-
-
- 1}> - - - -
- -
-
+ +
+ +
+
- -
- -
-
-
- ) - })} - - )} - + ) + })} + + )} + + ) } diff --git a/packages/opencode/src/bun/index.ts b/packages/opencode/src/bun/index.ts index 7c19c303b0e..edf74c31097 100644 --- a/packages/opencode/src/bun/index.ts +++ b/packages/opencode/src/bun/index.ts @@ -2,7 +2,7 @@ import z from "zod" import { Global } from "../global" import { Log } from "../util/log" import path from "path" -import { NamedError } from "../util/error" +import { NamedError } from "@opencode-ai/util/error" import { readableStreamToText } from "bun" import { createRequire } from "module" import { Lock } from "../util/lock" diff --git a/packages/opencode/src/cli/ui.ts b/packages/opencode/src/cli/ui.ts index 43760a65af5..acd1383a070 100644 --- a/packages/opencode/src/cli/ui.ts +++ b/packages/opencode/src/cli/ui.ts @@ -1,6 +1,6 @@ import z from "zod" import { EOL } from "os" -import { NamedError } from "../util/error" +import { NamedError } from "@opencode-ai/util/error" export namespace UI { const LOGO = [ diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 79f969eeaf6..779a4e8e2a3 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -8,7 +8,7 @@ import { mergeDeep, pipe } from "remeda" import { Global } from "../global" import fs from "fs/promises" import { lazy } from "../util/lazy" -import { NamedError } from "../util/error" +import { NamedError } from "@opencode-ai/util/error" import { Flag } from "../flag/flag" import { Auth } from "../auth" import { type ParseError as JsoncParseError, parse as parseJsonc, printParseErrorCode } from "jsonc-parser" diff --git a/packages/opencode/src/config/markdown.ts b/packages/opencode/src/config/markdown.ts index 3e84bbf43f7..f20842c41a9 100644 --- a/packages/opencode/src/config/markdown.ts +++ b/packages/opencode/src/config/markdown.ts @@ -1,4 +1,4 @@ -import { NamedError } from "@/util/error" +import { NamedError } from "@opencode-ai/util/error" import matter from "gray-matter" import { z } from "zod" diff --git a/packages/opencode/src/file/fzf.ts b/packages/opencode/src/file/fzf.ts index cd0aa4fc8e3..50db8901d70 100644 --- a/packages/opencode/src/file/fzf.ts +++ b/packages/opencode/src/file/fzf.ts @@ -2,7 +2,7 @@ import path from "path" import { Global } from "../global" import fs from "fs/promises" import z from "zod" -import { NamedError } from "../util/error" +import { NamedError } from "@opencode-ai/util/error" import { lazy } from "../util/lazy" import { Log } from "../util/log" import { ZipReader, BlobReader, BlobWriter } from "@zip.js/zip.js" diff --git a/packages/opencode/src/file/ripgrep.ts b/packages/opencode/src/file/ripgrep.ts index 7c871fafba2..00d9e8c3867 100644 --- a/packages/opencode/src/file/ripgrep.ts +++ b/packages/opencode/src/file/ripgrep.ts @@ -3,7 +3,7 @@ import path from "path" import { Global } from "../global" import fs from "fs/promises" import z from "zod" -import { NamedError } from "../util/error" +import { NamedError } from "@opencode-ai/util/error" import { lazy } from "../util/lazy" import { $ } from "bun" diff --git a/packages/opencode/src/ide/index.ts b/packages/opencode/src/ide/index.ts index 035bccecfb9..268f115fc30 100644 --- a/packages/opencode/src/ide/index.ts +++ b/packages/opencode/src/ide/index.ts @@ -1,6 +1,6 @@ import { spawn } from "bun" import z from "zod" -import { NamedError } from "../util/error" +import { NamedError } from "@opencode-ai/util/error" import { Log } from "../util/log" import { Bus } from "../bus" diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts index acd7ee1c099..38b6b5a3f0b 100644 --- a/packages/opencode/src/index.ts +++ b/packages/opencode/src/index.ts @@ -9,7 +9,7 @@ import { UpgradeCommand } from "./cli/cmd/upgrade" import { ModelsCommand } from "./cli/cmd/models" import { UI } from "./cli/ui" import { Installation } from "./installation" -import { NamedError } from "./util/error" +import { NamedError } from "@opencode-ai/util/error" import { FormatError } from "./cli/error" import { ServeCommand } from "./cli/cmd/serve" import { DebugCommand } from "./cli/cmd/debug" diff --git a/packages/opencode/src/installation/index.ts b/packages/opencode/src/installation/index.ts index cfb590013c2..7ac2980c46a 100644 --- a/packages/opencode/src/installation/index.ts +++ b/packages/opencode/src/installation/index.ts @@ -1,7 +1,7 @@ import path from "path" import { $ } from "bun" import z from "zod" -import { NamedError } from "../util/error" +import { NamedError } from "@opencode-ai/util/error" import { Bus } from "../bus" import { Log } from "../util/log" diff --git a/packages/opencode/src/lsp/client.ts b/packages/opencode/src/lsp/client.ts index 02363a599ca..f8b7db7aebe 100644 --- a/packages/opencode/src/lsp/client.ts +++ b/packages/opencode/src/lsp/client.ts @@ -6,7 +6,7 @@ import { LANGUAGE_EXTENSIONS } from "./language" import { Bus } from "../bus" import z from "zod" import type { LSPServer } from "./server" -import { NamedError } from "../util/error" +import { NamedError } from "@opencode-ai/util/error" import { withTimeout } from "../util/timeout" import { Instance } from "../project/instance" diff --git a/packages/opencode/src/mcp/index.ts b/packages/opencode/src/mcp/index.ts index 8ef1a138e9e..a68a1716f0c 100644 --- a/packages/opencode/src/mcp/index.ts +++ b/packages/opencode/src/mcp/index.ts @@ -5,7 +5,7 @@ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js" import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js" import { Config } from "../config/config" import { Log } from "../util/log" -import { NamedError } from "../util/error" +import { NamedError } from "@opencode-ai/util/error" import z from "zod/v4" import { Instance } from "../project/instance" import { withTimeout } from "@/util/timeout" diff --git a/packages/opencode/src/provider/auth.ts b/packages/opencode/src/provider/auth.ts index fb001603936..d06253ab4ad 100644 --- a/packages/opencode/src/provider/auth.ts +++ b/packages/opencode/src/provider/auth.ts @@ -4,7 +4,7 @@ import { map, filter, pipe, fromEntries, mapValues } from "remeda" import z from "zod" import { fn } from "@/util/fn" import type { AuthOuathResult, Hooks } from "@opencode-ai/plugin" -import { NamedError } from "@/util/error" +import { NamedError } from "@opencode-ai/util/error" import { Auth } from "@/auth" export namespace ProviderAuth { diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index e6f7f5f888c..8267b458a7e 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -7,7 +7,7 @@ import { Log } from "../util/log" import { BunProc } from "../bun" import { Plugin } from "../plugin" import { ModelsDev } from "./models" -import { NamedError } from "../util/error" +import { NamedError } from "@opencode-ai/util/error" import { Auth } from "../auth" import { Instance } from "../project/instance" import { Flag } from "../flag/flag" diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index f6530ee99c8..fec174454c2 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -9,7 +9,7 @@ import { Session } from "../session" import z from "zod" import { Provider } from "../provider/provider" import { mapValues } from "remeda" -import { NamedError } from "../util/error" +import { NamedError } from "@opencode-ai/util/error" import { ModelsDev } from "../provider/models" import { Ripgrep } from "../file/ripgrep" import { Config } from "../config/config" diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index c451ae2b38d..20b612f5480 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -1,6 +1,6 @@ import z from "zod" import { Bus } from "../bus" -import { NamedError } from "../util/error" +import { NamedError } from "@opencode-ai/util/error" import { Message } from "./message" import { APICallError, convertToModelMessages, LoadAPIKeyError, type ModelMessage, type UIMessage } from "ai" import { Identifier } from "../id/id" diff --git a/packages/opencode/src/session/message.ts b/packages/opencode/src/session/message.ts index 4471f923592..5c950d0e402 100644 --- a/packages/opencode/src/session/message.ts +++ b/packages/opencode/src/session/message.ts @@ -1,5 +1,5 @@ import z from "zod" -import { NamedError } from "../util/error" +import { NamedError } from "@opencode-ai/util/error" export namespace Message { export const OutputLengthError = NamedError.create("MessageOutputLengthError", z.object({})) diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index b3c3c467168..741e3cc7e05 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -43,7 +43,7 @@ import { Command } from "../command" import { $, fileURLToPath } from "bun" import { ConfigMarkdown } from "../config/markdown" import { SessionSummary } from "./summary" -import { NamedError } from "@/util/error" +import { NamedError } from "@opencode-ai/util/error" import { fn } from "@/util/fn" import { SessionProcessor } from "./processor" import { TaskTool } from "@/tool/task" diff --git a/packages/opencode/src/storage/storage.ts b/packages/opencode/src/storage/storage.ts index 5d4f639431d..8b4042ea13f 100644 --- a/packages/opencode/src/storage/storage.ts +++ b/packages/opencode/src/storage/storage.ts @@ -5,7 +5,7 @@ import { Global } from "../global" import { lazy } from "../util/lazy" import { Lock } from "../util/lock" import { $ } from "bun" -import { NamedError } from "@/util/error" +import { NamedError } from "@opencode-ai/util/error" import z from "zod" export namespace Storage { diff --git a/packages/ui/src/assets/fonts/tx-02.otf b/packages/ui/src/assets/fonts/tx-02.otf new file mode 100644 index 0000000000000000000000000000000000000000..dfdd2800bea2dad97bd5c00c24b6e3b9eab86bc3 GIT binary patch literal 85940 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 AoB#j- literal 0 HcmV?d00001 diff --git a/packages/ui/src/assets/fonts/tx-02.ttf b/packages/ui/src/assets/fonts/tx-02.ttf new file mode 100644 index 0000000000000000000000000000000000000000..dcad94c21667f7a5bb1e543845f1e9f99ae9b451 GIT binary patch literal 129876 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�>B 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⁢?RpT=*bBie(d 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 BQ { return ( @@ -22,14 +22,14 @@ export const Fonts = () => { line-gap-override: 1%; } @font-face { - font-family: "Geist Mono"; - src: url("${geistMono}") format("woff2-variations"); + font-family: "Berkeley Mono"; + src: url("${tx02}") format("woff2-variations"); font-display: swap; font-style: normal; - font-weight: 100 900; + font-weight: 400 700; } @font-face { - font-family: "Geist Mono Fallback"; + font-family: "Berkeley Mono Fallback"; src: local("Courier New"); size-adjust: 100%; ascent-override: 97%; @@ -38,7 +38,7 @@ export const Fonts = () => { } `} - + ) } diff --git a/packages/ui/src/components/message-nav.css b/packages/ui/src/components/message-nav.css index 6e9d96a2604..57316fbde85 100644 --- a/packages/ui/src/components/message-nav.css +++ b/packages/ui/src/components/message-nav.css @@ -1,6 +1,4 @@ [data-component="message-nav"] { - /* margin-right: 32px; */ - /* margin-top: 12px; */ flex-shrink: 0; display: flex; flex-direction: column; @@ -9,15 +7,8 @@ list-style: none; &[data-size="normal"] { - position: absolute; - right: 100%; width: 240px; - /* margin-top: 12px; */ - - @media (min-width: 80rem) { - gap: 8px; - /* margin-top: 4px; */ - } + gap: 4px; } } @@ -36,10 +27,8 @@ display: flex; align-items: center; justify-content: flex-start; - height: 8px; - width: 32px; - /* margin-right: -12px; */ - cursor: pointer; + height: 12px; + width: 24px; border: none; background: none; padding: 0; @@ -52,7 +41,7 @@ [data-slot="message-nav-tick-line"] { height: 1px; - width: 20px; + width: 16px; background-color: var(--icon-base); transition: width 0.2s, @@ -69,11 +58,12 @@ align-items: center; align-self: stretch; width: 100%; - column-gap: 8px; + column-gap: 12px; cursor: default; border: none; background: none; - padding: 0; + padding: 4px 12px; + border-radius: var(--radius-sm); } [data-slot="message-nav-title-preview"] { @@ -90,6 +80,37 @@ } } -[data-slot="message-nav-item"]:hover [data-slot="message-nav-title-preview"] { +[data-slot="message-nav-item"]:hover [data-slot="message-nav-message-button"] { + background-color: var(--surface-base); +} +[data-slot="message-nav-item"]:active [data-slot="message-nav-message-button"] { + background-color: var(--surface-base-active); +} + +[data-slot="message-nav-item"]:active [data-slot="message-nav-title-preview"] { color: var(--text-base); } + +[data-slot="message-nav-tooltip"] { + z-index: 1000; +} + +[data-slot="message-nav-tooltip-content"] { + display: flex; + padding: 4px 4px 6px 4px; + justify-content: center; + align-items: center; + border-radius: var(--radius-md); + background: var(--surface-raised-stronger-non-alpha); + + /* border/shadow-xs/base */ + box-shadow: + 0 0 0 1px var(--border-weak-base, rgba(17, 0, 0, 0.12)), + 0 1px 2px -1px rgba(19, 16, 16, 0.04), + 0 1px 2px 0 rgba(19, 16, 16, 0.06), + 0 1px 3px 0 rgba(19, 16, 16, 0.08); + + * { + margin: 0 !important; + } +} diff --git a/packages/ui/src/components/message-nav.tsx b/packages/ui/src/components/message-nav.tsx index 8475c320643..333ad374328 100644 --- a/packages/ui/src/components/message-nav.tsx +++ b/packages/ui/src/components/message-nav.tsx @@ -2,6 +2,8 @@ import { UserMessage } from "@opencode-ai/sdk" import { ComponentProps, createMemo, For, Match, Show, splitProps, Switch } from "solid-js" import { DiffChanges } from "./diff-changes" import { Spinner } from "./spinner" +import { HoverCard } from "@kobalte/core/hover-card" +import { Tooltip } from "@kobalte/core/tooltip" export function MessageNav( props: ComponentProps<"ul"> & { @@ -17,7 +19,7 @@ export function MessageNav( return local.messages?.at(0) }) - return ( + const content = (
    {(message) => { @@ -28,13 +30,9 @@ export function MessageNav(
  • - +
setOpenBreakdownId(null)}>{totalInputTokens()} - +
e.stopPropagation()}>
Input @@ -136,7 +143,32 @@ export function UsageSection() {
- {usage.outputTokens} + +
e.stopPropagation()}> + + setOpenBreakdownId(null)}>{totalOutputTokens()} + +
e.stopPropagation()}> +
+ Output + {usage.outputTokens} +
+
+ Reasoning + {usage.reasoningTokens ?? 0} +
+
+
+
+ ${((usage.cost ?? 0) / 100000000).toFixed(4)} ) From d39bcd9c55c4e56f412abf43d194538978a9f254 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:57:41 -0600 Subject: [PATCH 60/66] fix(desktop): layout --- packages/desktop/src/pages/session.tsx | 30 +++++++++++++++++++------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/packages/desktop/src/pages/session.tsx b/packages/desktop/src/pages/session.tsx index 84c7d64f23f..028917e0bf7 100644 --- a/packages/desktop/src/pages/session.tsx +++ b/packages/desktop/src/pages/session.tsx @@ -338,14 +338,28 @@ export default function Page() {
1}> - + <> + + + Date: Mon, 24 Nov 2025 22:06:51 +0000 Subject: [PATCH 61/66] Add --refresh flag to models command (#4707) --- packages/opencode/src/cli/cmd/models.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/opencode/src/cli/cmd/models.ts b/packages/opencode/src/cli/cmd/models.ts index f7da2462a9f..8ce27c28472 100644 --- a/packages/opencode/src/cli/cmd/models.ts +++ b/packages/opencode/src/cli/cmd/models.ts @@ -1,6 +1,7 @@ import type { Argv } from "yargs" import { Instance } from "../../project/instance" import { Provider } from "../../provider/provider" +import { ModelsDev } from "../../provider/models" import { cmd } from "./cmd" import { UI } from "../ui" import { EOL } from "os" @@ -19,8 +20,17 @@ export const ModelsCommand = cmd({ describe: "use more verbose model output (includes metadata like costs)", type: "boolean", }) + .option("refresh", { + describe: "refresh the models cache from models.dev", + type: "boolean", + }) }, handler: async (args) => { + if (args.refresh) { + await ModelsDev.refresh() + UI.println(UI.Style.TEXT_SUCCESS_BOLD + "Models cache refreshed" + UI.Style.TEXT_NORMAL) + } + await Instance.provide({ directory: process.cwd(), async fn() { From 9bd6be5c6de6a8628f68e93b5d7f03c24563957c Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 24 Nov 2025 17:09:53 -0500 Subject: [PATCH 62/66] zen: byok for gemini --- .../console/app/src/routes/workspace/[id]/provider-section.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/console/app/src/routes/workspace/[id]/provider-section.tsx b/packages/console/app/src/routes/workspace/[id]/provider-section.tsx index ff2cc7dd03a..dbb170b6227 100644 --- a/packages/console/app/src/routes/workspace/[id]/provider-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/provider-section.tsx @@ -8,6 +8,7 @@ import styles from "./provider-section.module.css" const PROVIDERS = [ { name: "OpenAI", key: "openai", prefix: "sk-" }, { name: "Anthropic", key: "anthropic", prefix: "sk-ant-" }, + { name: "Google Gemini", key: "google", prefix: "AI" }, ] as const type Provider = (typeof PROVIDERS)[number] From 23a721f0a2e2a5b9d99a2163d30e5da07799ea8a Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Mon, 24 Nov 2025 15:57:25 -0600 Subject: [PATCH 63/66] remove hardcoded openrouter provider --- packages/opencode/src/provider/provider.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index a55fbfad7eb..1cf0312ea6f 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -516,12 +516,6 @@ export namespace Provider { continue } - // TODO: set this in models.dev, not set due to breaking issues on older OC versions - // u have to set include usage to true w/ this provider, setting in models.dev would cause undefined issue when accessing usage in older versions - if (providerID === "openrouter") { - provider.info.npm = "@openrouter/ai-sdk-provider" - } - log.info("found", { providerID, npm: provider.info.npm }) } From 2458e7597b569f6b12ffbf31683d383e97bf1548 Mon Sep 17 00:00:00 2001 From: opencode Date: Mon, 24 Nov 2025 22:30:42 +0000 Subject: [PATCH 64/66] release: v1.0.109 --- bun.lock | 30 +++++++++++++------------- packages/console/app/package.json | 2 +- packages/console/core/package.json | 2 +- packages/console/function/package.json | 2 +- packages/console/mail/package.json | 2 +- packages/desktop/package.json | 2 +- packages/enterprise/package.json | 2 +- packages/extensions/zed/extension.toml | 12 +++++------ packages/function/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 4 ++-- packages/sdk/js/package.json | 4 ++-- packages/slack/package.json | 2 +- packages/tauri/package.json | 2 +- packages/ui/package.json | 2 +- packages/util/package.json | 2 +- packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- 18 files changed, 39 insertions(+), 39 deletions(-) diff --git a/bun.lock b/bun.lock index 17d961b7328..5d505ae1c04 100644 --- a/bun.lock +++ b/bun.lock @@ -19,7 +19,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -46,7 +46,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -73,7 +73,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -97,7 +97,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -121,7 +121,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -162,7 +162,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -188,7 +188,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "22.0.0", @@ -204,7 +204,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.108", + "version": "1.0.109", "bin": { "opencode": "./bin/opencode", }, @@ -291,7 +291,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -311,7 +311,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.108", + "version": "1.0.109", "devDependencies": { "@hey-api/openapi-ts": "0.81.0", "@tsconfig/node22": "catalog:", @@ -322,7 +322,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -335,7 +335,7 @@ }, "packages/tauri": { "name": "@opencode-ai/tauri", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "@tauri-apps/api": "^2", "@tauri-apps/plugin-opener": "^2", @@ -348,7 +348,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -380,7 +380,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "zod": "catalog:", }, @@ -390,7 +390,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 153c07c5843..d273a6fa3c9 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.0.108", + "version": "1.0.109", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 6d139b7144a..c5f502e217f 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/console-core", - "version": "1.0.108", + "version": "1.0.109", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index c247f10be37..898bce7a0a9 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.108", + "version": "1.0.109", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/console/mail/package.json b/packages/console/mail/package.json index 12f8b318c11..b8d09c844db 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.108", + "version": "1.0.109", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index a23150d626f..761eb31c52c 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.108", + "version": "1.0.109", "description": "", "type": "module", "scripts": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index 12bac8bbccb..b6ebaafe835 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.0.108", + "version": "1.0.109", "private": true, "type": "module", "scripts": { diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index 2929c179da6..c6cbc24363e 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "opencode" name = "OpenCode" description = "The AI coding agent built for the terminal" -version = "1.0.108" +version = "1.0.109" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/sst/opencode" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.108/opencode-darwin-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.109/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.108/opencode-darwin-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.109/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.108/opencode-linux-arm64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.109/opencode-linux-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.108/opencode-linux-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.109/opencode-linux-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/sst/opencode/releases/download/v1.0.108/opencode-windows-x64.zip" +archive = "https://github.com/sst/opencode/releases/download/v1.0.109/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index f40b10a7abe..e887ec5be10 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.108", + "version": "1.0.109", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 595a99255f4..a17f226a729 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.108", + "version": "1.0.109", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 264df7b5a27..38f0b529640 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/plugin", - "version": "1.0.108", + "version": "1.0.109", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} +} \ No newline at end of file diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 02474c3e6f2..2738e6a9f2a 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/sdk", - "version": "1.0.108", + "version": "1.0.109", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", @@ -26,4 +26,4 @@ "publishConfig": { "directory": "dist" } -} +} \ No newline at end of file diff --git a/packages/slack/package.json b/packages/slack/package.json index 99fe097ae3e..37f939aa46e 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.108", + "version": "1.0.109", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/tauri/package.json b/packages/tauri/package.json index b14db25bbb2..481d9e4cfba 100644 --- a/packages/tauri/package.json +++ b/packages/tauri/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/tauri", "private": true, - "version": "1.0.108", + "version": "1.0.109", "type": "module", "scripts": { "dev": "vite", diff --git a/packages/ui/package.json b/packages/ui/package.json index 57a8319e3ee..193e69d270e 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.108", + "version": "1.0.109", "type": "module", "exports": { "./*": "./src/components/*.tsx", diff --git a/packages/util/package.json b/packages/util/package.json index 88bef625b4f..2adb927b633 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.0.108", + "version": "1.0.109", "private": true, "type": "module", "exports": { diff --git a/packages/web/package.json b/packages/web/package.json index 61eb81beb5f..03cd0141532 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.108", + "version": "1.0.109", "scripts": { "dev": "astro dev", "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 2fa403f5e9e..6cc5d83b87d 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "1.0.108", + "version": "1.0.109", "publisher": "sst-dev", "repository": { "type": "git", From 7990520b01e8dd7398fd053f2332cb7166992533 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Mon, 24 Nov 2025 22:34:53 +0000 Subject: [PATCH 65/66] chore: format code --- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 38f0b529640..d1a80371122 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} \ No newline at end of file +} diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 2738e6a9f2a..5696b0c31b4 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -26,4 +26,4 @@ "publishConfig": { "directory": "dist" } -} \ No newline at end of file +} From d43386fc61e4e9cda180b65b19ba467de86fd480 Mon Sep 17 00:00:00 2001 From: Github Action Date: Mon, 24 Nov 2025 22:36:14 +0000 Subject: [PATCH 66/66] Update Nix flake.lock and hashes --- flake.lock | 6 +++--- nix/hashes.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 826bf4d8608..1f734968321 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1763806073, - "narHash": "sha256-FHsEKDvfWpzdADWj99z7vBk4D716Ujdyveo5+A048aI=", + "lastModified": 1763934636, + "narHash": "sha256-9glbI7f1uU+yzQCq5LwLgdZqx6svOhZWkd4JRY265fc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "878e468e02bfabeda08c79250f7ad583037f2227", + "rev": "ee09932cedcef15aaf476f9343d1dea2cb77e261", "type": "github" }, "original": { diff --git a/nix/hashes.json b/nix/hashes.json index 16424b3a035..448ae1308d2 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,3 +1,3 @@ { - "nodeModules": "sha256-m7hL9Uzqk+oa2/FtgkzEPgi+m/VZP1SvjpgYHNjiS1c=" + "nodeModules": "sha256-83nrKWOCUJhSHqtSApFuXxggEwO86rIWhy5d2vtfz4Y=" }