diff --git a/.github/TEAM_MEMBERS b/.github/TEAM_MEMBERS index 5268ff59ddc8..866d466a8b4c 100644 --- a/.github/TEAM_MEMBERS +++ b/.github/TEAM_MEMBERS @@ -20,3 +20,4 @@ Slickstef11 usrnk1 vimtor StarpTech +vaprdev diff --git a/.github/workflows/models-snapshot.yml b/.github/workflows/models-snapshot.yml new file mode 100644 index 000000000000..8b731908213c --- /dev/null +++ b/.github/workflows/models-snapshot.yml @@ -0,0 +1,62 @@ +name: models-snapshot + +permissions: + contents: write + +on: + workflow_dispatch: + schedule: + - cron: "0 12 * * *" + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: false + +jobs: + refresh: + if: github.repository == 'anomalyco/opencode' + runs-on: blacksmith-4vcpu-ubuntu-2404 + + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false + ref: v2 + + # The refresh script only needs `fetch`; skip the monorepo install. + - name: Setup Bun + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 + with: + bun-version-file: package.json + + - name: Setup git committer + uses: ./.github/actions/setup-git-committer + with: + opencode-app-id: ${{ vars.OPENCODE_APP_ID }} + opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} + + - name: Refresh snapshot + run: bun packages/core/script/update-models-snapshot.ts + + - name: Commit changes + run: | + set -euo pipefail + + FILE="packages/core/src/models-dev/snapshot.txt" + + if [ -z "$(git status --short -- "$FILE")" ]; then + echo "No changes to commit" + echo "### models.dev snapshot" >> "$GITHUB_STEP_SUMMARY" + echo "Status: no changes" >> "$GITHUB_STEP_SUMMARY" + exit 0 + fi + + git add "$FILE" + git commit -m "chore(core): refresh bundled models.dev snapshot" + + git pull --rebase --autostash origin v2 + git push origin HEAD:v2 --no-verify + + echo "### models.dev snapshot" >> "$GITHUB_STEP_SUMMARY" + echo "Status: committed $(git rev-parse --short HEAD)" >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f723fddc9464..910c1213751e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -57,7 +57,15 @@ jobs: - name: Install ripgrep if: runner.os == 'Windows' - run: choco install ripgrep --version 15.1.0 --yes --no-progress + shell: pwsh + run: | + $archive = Join-Path $env:RUNNER_TEMP "ripgrep.zip" + Invoke-WebRequest "https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-x86_64-pc-windows-msvc.zip" -OutFile $archive + if ((Get-FileHash $archive -Algorithm SHA256).Hash.ToLowerInvariant() -ne "124510b94b6baa3380d051fdf4650eaa80a302c876d611e9dba0b2e18d87493a") { + throw "Ripgrep checksum mismatch" + } + Expand-Archive $archive -DestinationPath "$env:RUNNER_TEMP/ripgrep" + "$env:RUNNER_TEMP/ripgrep/ripgrep-15.1.0-x86_64-pc-windows-msvc" >> $env:GITHUB_PATH - name: Cache Turbo uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 @@ -69,8 +77,8 @@ jobs: turbo-${{ runner.os }}- - name: Run unit tests - timeout-minutes: 20 - run: GITHUB_ACTIONS=false bun turbo test --concurrency=${{ github.repository == 'anomalyco/opencode' && '10' || '2' }} + timeout-minutes: ${{ github.repository != 'anomalyco/opencode' && runner.os == 'Windows' && 60 || 20 }} + run: GITHUB_ACTIONS=false bun turbo test --log-order=stream --concurrency=${{ github.repository == 'anomalyco/opencode' && '10' || (runner.os == 'Windows' && '1' || '2') }} env: OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER: ${{ runner.os == 'Windows' && 'true' || 'false' }} diff --git a/bun.lock b/bun.lock index bf1936aff331..a10100525605 100644 --- a/bun.lock +++ b/bun.lock @@ -29,7 +29,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@corvu/drawer": "catalog:", "@dnd-kit/abstract": "0.5.0", @@ -98,7 +98,7 @@ }, "packages/cli": { "name": "@opencode-ai/cli", - "version": "1.18.29", + "version": "1.18.32", "bin": { "lildax": "./bin/lildax.cjs", }, @@ -146,7 +146,7 @@ }, "packages/codemode": { "name": "@opencode-ai/codemode", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "acorn": "8.15.0", "effect": "catalog:", @@ -160,7 +160,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -197,7 +197,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -224,7 +224,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@ai-sdk/anthropic": "3.0.82", "@ai-sdk/openai": "3.0.48", @@ -247,7 +247,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -271,7 +271,7 @@ }, "packages/console/support": { "name": "@opencode-ai/console-support", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@opencode-ai/console-core": "workspace:*", @@ -291,7 +291,7 @@ }, "packages/core": { "name": "@opencode-ai/core", - "version": "1.18.29", + "version": "1.18.32", "bin": { "opencode": "./bin/opencode", }, @@ -299,21 +299,21 @@ "@ai-sdk/alibaba": "1.0.17", "@ai-sdk/amazon-bedrock": "4.0.166", "@ai-sdk/anthropic": "3.0.111", - "@ai-sdk/azure": "3.0.88", + "@ai-sdk/azure": "3.0.93", "@ai-sdk/cerebras": "2.0.41", "@ai-sdk/cohere": "3.0.27", "@ai-sdk/deepinfra": "2.0.41", - "@ai-sdk/gateway": "3.0.104", + "@ai-sdk/gateway": "3.0.191", "@ai-sdk/google": "3.0.73", "@ai-sdk/google-vertex": "4.0.181", "@ai-sdk/groq": "3.0.31", "@ai-sdk/mistral": "3.0.51", - "@ai-sdk/openai": "3.0.84", + "@ai-sdk/openai": "3.0.88", "@ai-sdk/openai-compatible": "2.0.41", "@ai-sdk/perplexity": "3.0.26", - "@ai-sdk/provider": "3.0.8", - "@ai-sdk/provider-utils": "4.0.23", - "@ai-sdk/togetherai": "2.0.41", + "@ai-sdk/provider": "3.0.16", + "@ai-sdk/provider-utils": "4.0.51", + "@ai-sdk/togetherai": "2.0.68", "@ai-sdk/vercel": "2.0.39", "@ai-sdk/xai": "3.0.102", "@aws-sdk/credential-providers": "3.1057.0", @@ -345,7 +345,7 @@ "drizzle-orm": "catalog:", "effect": "catalog:", "fuzzysort": "3.1.0", - "gitlab-ai-provider": "6.13.0", + "gitlab-ai-provider": "6.15.0", "glob": "13.0.5", "google-auth-library": "10.5.0", "gray-matter": "4.0.3", @@ -389,7 +389,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@zip.js/zip.js": "2.7.62", "drizzle-orm": "catalog:", @@ -443,7 +443,7 @@ }, "packages/effect-drizzle-sqlite": { "name": "@opencode-ai/effect-drizzle-sqlite", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "drizzle-orm": "catalog:", "effect": "catalog:", @@ -457,7 +457,7 @@ }, "packages/effect-sqlite-node": { "name": "@opencode-ai/effect-sqlite-node", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "effect": "catalog:", }, @@ -469,7 +469,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@hono/standard-validator": "catalog:", "@opencode-ai/core": "workspace:*", @@ -501,7 +501,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -517,7 +517,7 @@ }, "packages/http-recorder": { "name": "@opencode-ai/http-recorder", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@effect/platform-node": "4.0.0-beta.83", "@effect/platform-node-shared": "4.0.0-beta.83", @@ -548,7 +548,7 @@ }, "packages/llm": { "name": "@opencode-ai/llm", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@opencode-ai/schema": "workspace:*", "@smithy/eventstream-codec": "4.2.14", @@ -567,7 +567,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.18.29", + "version": "1.18.32", "bin": { "opencode": "./bin/opencode", }, @@ -578,20 +578,20 @@ "@ai-sdk/alibaba": "1.0.17", "@ai-sdk/amazon-bedrock": "4.0.166", "@ai-sdk/anthropic": "3.0.111", - "@ai-sdk/azure": "3.0.88", + "@ai-sdk/azure": "3.0.93", "@ai-sdk/cerebras": "2.0.60", "@ai-sdk/cohere": "3.0.27", "@ai-sdk/deepinfra": "2.0.41", - "@ai-sdk/gateway": "3.0.104", + "@ai-sdk/gateway": "3.0.191", "@ai-sdk/google": "3.0.73", "@ai-sdk/google-vertex": "4.0.181", "@ai-sdk/groq": "3.0.31", "@ai-sdk/mistral": "3.0.51", - "@ai-sdk/openai": "3.0.84", + "@ai-sdk/openai": "3.0.88", "@ai-sdk/openai-compatible": "2.0.41", "@ai-sdk/perplexity": "3.0.26", - "@ai-sdk/provider": "3.0.8", - "@ai-sdk/togetherai": "2.0.41", + "@ai-sdk/provider": "3.0.16", + "@ai-sdk/togetherai": "2.0.68", "@ai-sdk/vercel": "2.0.39", "@ai-sdk/xai": "3.0.102", "@aws-sdk/credential-providers": "3.1057.0", @@ -641,7 +641,7 @@ "drizzle-orm": "catalog:", "effect": "catalog:", "fuzzysort": "3.1.0", - "gitlab-ai-provider": "6.13.0", + "gitlab-ai-provider": "6.15.0", "glob": "13.0.5", "google-auth-library": "10.5.0", "gray-matter": "4.0.3", @@ -699,7 +699,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@ai-sdk/provider": "3.0.8", "@opencode-ai/sdk": "workspace:*", @@ -775,7 +775,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "cross-spawn": "catalog:", }, @@ -790,7 +790,7 @@ }, "packages/server": { "name": "@opencode-ai/server", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@opencode-ai/core": "workspace:*", "@opencode-ai/protocol": "workspace:*", @@ -805,7 +805,7 @@ }, "packages/session-ui": { "name": "@opencode-ai/session-ui", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/client": "file:../app/vendor/opencode-ai-client-1.17.13-v2.tgz", @@ -845,7 +845,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -858,7 +858,7 @@ }, "packages/stats/app": { "name": "@opencode-ai/stats-app", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@ibm/plex": "6.4.1", "@kobalte/core": "catalog:", @@ -885,7 +885,7 @@ }, "packages/stats/core": { "name": "@opencode-ai/stats-core", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@aws-sdk/client-athena": "3.933.0", "@planetscale/database": "1.19.0", @@ -904,7 +904,7 @@ }, "packages/stats/server": { "name": "@opencode-ai/stats-server", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@aws-sdk/client-firehose": "3.933.0", "@effect/platform-node": "catalog:", @@ -946,7 +946,7 @@ }, "packages/tui": { "name": "@opencode-ai/tui", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@opencode-ai/client": "workspace:*", "@opencode-ai/core": "workspace:*", @@ -974,7 +974,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@kobalte/core": "catalog:", "@pierre/diffs": "catalog:", @@ -1025,7 +1025,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.18.29", + "version": "1.18.32", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", @@ -1072,6 +1072,7 @@ "@ai-sdk/xai@3.0.102": "patches/@ai-sdk%2Fxai@3.0.102.patch", "@modelcontextprotocol/sdk@1.29.0": "patches/@modelcontextprotocol%2Fsdk@1.29.0.patch", "gcp-metadata@8.1.2": "patches/gcp-metadata@8.1.2.patch", + "@ai-sdk/openai@3.0.88": "patches/@ai-sdk%2Fopenai@3.0.88.patch", "@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch", "effect@4.0.0-beta.83": "patches/effect@4.0.0-beta.83.patch", "@ai-sdk/anthropic@3.0.111": "patches/@ai-sdk%2Fanthropic@3.0.111.patch", @@ -1183,7 +1184,7 @@ "@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.111", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.46" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-atgBW8jZPr/KuaKX5FvDIHuXBI8VCol6kVeoD4P0657+VXR73QsLogXQVN/Zt5FHtq9WzpdIZseCJiXPqkgwwA=="], - "@ai-sdk/azure": ["@ai-sdk/azure@3.0.88", "", { "dependencies": { "@ai-sdk/deepseek": "2.0.47", "@ai-sdk/openai": "3.0.84", "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.38" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-RRjZkB1lYplh8dpBarnvkl1j7sYLHsyXua7erL3oNcMK7fHcl4bPO5C7iQhD1O/DqD/zCceDifnege1s+8yEvw=="], + "@ai-sdk/azure": ["@ai-sdk/azure@3.0.93", "", { "dependencies": { "@ai-sdk/deepseek": "2.0.50", "@ai-sdk/openai": "3.0.88", "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.40" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-9nKNmRtopjE3+L+286/4sLBDfDvmdsL7fiQXG0TE38NywxkDDLUhdr0KSllkRQ+m1/8bO7x4rIVhHSjQQiqmnQ=="], "@ai-sdk/cerebras": ["@ai-sdk/cerebras@2.0.41", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.37", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kDMEpjaRdRXIUi1EH8WHwLRahyDTYv9SAJnP6VCCeq8X+tVqZbMLCqqxSG5dRknrI65ucjvzQt+FiDKTAa7AHg=="], @@ -1193,13 +1194,13 @@ "@ai-sdk/deepinfra": ["@ai-sdk/deepinfra@2.0.41", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.37", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-y6RoOP7DGWmDSiSxrUSt5p18sbz+Ixe5lMVPmdE7x+Tr5rlrzvftyHhjWHfqlAtoYERZTGFbP6tPW1OfQcrb4A=="], - "@ai-sdk/deepseek": ["@ai-sdk/deepseek@2.0.47", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.38" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MzcQ321JO8OY+TVLFI81A7cIIuoeLLxrLCDD+8C1E3Ro6UFyfMtRXo9bw9OhTMRSDMo6hgSDOo4Fekz8aJtQYQ=="], + "@ai-sdk/deepseek": ["@ai-sdk/deepseek@2.0.50", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.40" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-pnl22aGBIdpK0sXSJN4zDykIXTdyO9m3gFhno3SBPpdwT4Tq041Uy0i/EDWSxIiFa9JEokFGiCt4NNzcE5ntRA=="], "@ai-sdk/elevenlabs": ["@ai-sdk/elevenlabs@2.0.51", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.45" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-XFONX6rAsu6d13cJVUfZfkq4a+qdThlxvoEfzYlSRa1AvALlzwX7Y6bunXxevuifT3n882+nDdWrdiYvFP0+Fw=="], "@ai-sdk/fireworks": ["@ai-sdk/fireworks@2.0.76", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.67", "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.45" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-yg1ulgemh6BLMrs2vBNbtjV70NhenFI3Z7psB7s94FOEcGevvyV1qdFoqsgBZ7QyuUGwnC645c+eBFFtPAr5SQ=="], - "@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.104", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZKX5n74io8VIRlhIMSLWVlvT3sXC8Z7cZ9GHuWBWZDVi96+62AIsWuLGvMfcBA1STYuSoDrp6rIziZmvrTq0TA=="], + "@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.191", "", { "dependencies": { "@ai-sdk/provider": "3.0.16", "@ai-sdk/provider-utils": "4.0.51", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-7f9h+Vb/kmBTiqj6wtoKZbOuckvnpRp/eoxzYZg0GOAfYkdnixs+8JTGW3+nlHZXza17riNL5FpC0pEuh8aV1Q=="], "@ai-sdk/google": ["@ai-sdk/google@3.0.73", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-o2MuIeyvZrFIeIbnbA8Thrr63irdyUBh0uWBZ2lY6yFeXuE/tcwyXF74bDKS4KvTu84uFpQfpbS/LXHGKKXz+g=="], @@ -1215,11 +1216,11 @@ "@ai-sdk/perplexity": ["@ai-sdk/perplexity@3.0.26", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-dXzrVsLR5f6tr+U04jq4AXoRroGFBTvODnLgss0SWbzNjGGQg3XqtQ9j7rCLo6o8qbYGuAHvqUrIpUCuiscuFg=="], - "@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], + "@ai-sdk/provider": ["@ai-sdk/provider@3.0.16", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-9Av6kg0t/IN/dcYAAmEJ4B9OPhcEJqwSR+GfHEA8olRkindXpUHadc3p3cyvgFUQFTVm1G5thtsmgZ9yVb2w3A=="], - "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.23", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-z8GlDaCmRSDlqkMF2f4/RFgWxdarvIbyuk+m6WXT1LYgsnGiXRJGTD2Z1+SDl3LqtFuRtGX1aghYvQLoHL/9pg=="], + "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.51", "", { "dependencies": { "@ai-sdk/provider": "3.0.16", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8", "undici": "^6.28.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ukLTs9x1Xm6lxSIwbJIxYQxbZHmVeIczNntARZrBcOa6pjdBhqeZnATNnJMHa7M9dZ8Ji5NJbpKpvz7o5XyBtg=="], - "@ai-sdk/togetherai": ["@ai-sdk/togetherai@2.0.41", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.37", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-k3p9e3k0/gpDDyTtvafsK4HYR4D/aUQW/kzCwWo1+CzdBU84i4L14gWISC/mv6tgSicMXHcEUd521fPufQwNlg=="], + "@ai-sdk/togetherai": ["@ai-sdk/togetherai@2.0.68", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.62", "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.40" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-rwPJyf5XJkzT0b4TZ1zwr55kb8Z3NJJ/rIVXdwdRHngYNQnUo8SNEzzyfwKUH3Fz7bFiZO+WXztfCCkHjZDFNg=="], "@ai-sdk/vercel": ["@ai-sdk/vercel@2.0.39", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.37", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8eu3ljJpkCTP4ppcyYB+NcBrkcBoSOFthCSgk5VnjaxnDaOJFaxnPwfddM7wx3RwMk2CiK1O61Px/LlqNc7QkQ=="], @@ -1449,8 +1450,6 @@ "@babel/types": ["@babel/types@7.29.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA=="], - "@bcoe/v8-coverage": ["@bcoe/v8-coverage@1.0.2", "", {}, "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA=="], - "@bufbuild/protobuf": ["@bufbuild/protobuf@2.12.0", "", {}, "sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA=="], "@bufbuild/protoplugin": ["@bufbuild/protoplugin@2.12.0", "", { "dependencies": { "@bufbuild/protobuf": "2.12.0", "@typescript/vfs": "^1.6.2", "typescript": "5.4.5" } }, "sha512-ORlDITp8AFUXzIhLRoMCG+ud+D3MPKWb5HQXBoskMMnjeyEjE1H1qLonVNPyOr8lkx3xSfYUo8a0dvOZJVAzow=="], @@ -3003,8 +3002,6 @@ "@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/coverage-v8": ["@vitest/coverage-v8@4.1.8", "", { "dependencies": { "@bcoe/v8-coverage": "^1.0.2", "@vitest/utils": "4.1.8", "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.2.0", "magicast": "^0.5.2", "obug": "^2.1.1", "std-env": "^4.0.0-rc.1", "tinyrainbow": "^3.1.0" }, "peerDependencies": { "@vitest/browser": "4.1.8", "vitest": "4.1.8" }, "optionalPeers": ["@vitest/browser"] }, "sha512-lt3kovsyHwYe00wq4D1ti0Z974fWj4NLp6siqiyEufUpyFwK9Yhi7rBhac9JL5aA0zoMrJqc4vYPZRUnI7l7nw=="], - "@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="], "@vitest/mocker": ["@vitest/mocker@4.1.7", "", { "dependencies": { "@vitest/spy": "4.1.7", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA=="], @@ -3125,8 +3122,6 @@ "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="], - "ast-v8-to-istanbul": ["ast-v8-to-istanbul@1.0.3", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.31", "estree-walker": "^3.0.3", "js-tokens": "^10.0.0" } }, "sha512-jCMQ6ZylLPudp0CDfBmQBZUsrh1/8psbmu9ibeVWKuHWD0YrH9YABwlKu5kVEFoT0GCQQW9Z/SxfuEbbkGQCRg=="], - "astral-regex": ["astral-regex@2.0.0", "", {}, "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="], "astring": ["astring@1.9.0", "", { "bin": { "astring": "bin/astring" } }, "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg=="], @@ -3611,8 +3606,6 @@ "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], - "encoding": ["encoding@0.1.13", "", { "dependencies": { "iconv-lite": "^0.6.2" } }, "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="], - "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], "engine.io-client": ["engine.io-client@6.6.5", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1", "engine.io-parser": "~5.2.1", "ws": "~8.20.1", "xmlhttprequest-ssl": "~2.1.1" } }, "sha512-QCwxUDULPlXv8F6tqMMKx5dNkTe6OaBYRMPYeXKBlyOoKvAmE0ac6pW7fFhSscJ/5SI7666/U/B+MElbsrJlIg=="], @@ -3855,7 +3848,7 @@ "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], - "gitlab-ai-provider": ["gitlab-ai-provider@6.13.0", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.0", "@anycable/core": "^0.9.2", "graphql-request": "^6.1.0", "isomorphic-ws": "^5.0.0", "openai": "^6.16.0", "socket.io-client": "^4.8.1", "vscode-jsonrpc": "^8.2.1", "zod": "^3.25.76" }, "peerDependencies": { "@ai-sdk/provider": ">=3.0.0", "@ai-sdk/provider-utils": ">=4.0.0" } }, "sha512-JDZhNjvoiB7xBfesNegXNDg6ItKf9M2l8/DifuIyuvYmGgaZnDDbl89QrOKSoIzAOpo/+3Om0qviBPm84nGEbg=="], + "gitlab-ai-provider": ["gitlab-ai-provider@6.15.0", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.0", "@anycable/core": "^0.9.2", "graphql-request": "^6.1.0", "isomorphic-ws": "^5.0.0", "openai": "^6.16.0", "socket.io-client": "^4.8.1", "vscode-jsonrpc": "^8.2.1", "zod": "^3.25.76" }, "peerDependencies": { "@ai-sdk/provider": ">=3.0.0", "@ai-sdk/provider-utils": ">=4.0.0" } }, "sha512-hHJsb4WP+WPTMtMC0gZcTi0wreMvR6WdEPeUPRHNlyW7yX0HuFG7v1oZ/ethbF6y/FG3/7NcirNgjZLjNneW7g=="], "glob": ["glob@13.0.5", "", { "dependencies": { "minimatch": "^10.2.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw=="], @@ -4135,12 +4128,6 @@ "isomorphic-ws": ["isomorphic-ws@5.0.0", "", { "peerDependencies": { "ws": "*" } }, "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw=="], - "istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="], - - "istanbul-lib-report": ["istanbul-lib-report@3.0.1", "", { "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", "supports-color": "^7.1.0" } }, "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw=="], - - "istanbul-reports": ["istanbul-reports@3.2.0", "", { "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA=="], - "iterate-iterator": ["iterate-iterator@1.0.2", "", {}, "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw=="], "iterate-value": ["iterate-value@1.0.2", "", { "dependencies": { "es-get-iterator": "^1.0.2", "iterate-iterator": "^1.0.1" } }, "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ=="], @@ -4309,8 +4296,6 @@ "magicast": ["magicast@0.3.5", "", { "dependencies": { "@babel/parser": "^7.25.4", "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ=="], - "make-dir": ["make-dir@4.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw=="], - "make-fetch-happen": ["make-fetch-happen@15.0.6", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/agent": "^4.0.0", "@npmcli/redact": "^4.0.0", "cacache": "^20.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", "minipass-fetch": "^5.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^6.0.0", "ssri": "^13.0.0" } }, "sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw=="], "markdown-extensions": ["markdown-extensions@2.0.0", "", {}, "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q=="], @@ -4521,7 +4506,7 @@ "nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="], - "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], + "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], "neotraverse": ["neotraverse@0.6.18", "", {}, "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA=="], @@ -5641,6 +5626,10 @@ "@ai-sdk/alibaba/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="], + "@ai-sdk/alibaba/@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], + + "@ai-sdk/alibaba/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.23", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-z8GlDaCmRSDlqkMF2f4/RFgWxdarvIbyuk+m6WXT1LYgsnGiXRJGTD2Z1+SDl3LqtFuRtGX1aghYvQLoHL/9pg=="], + "@ai-sdk/amazon-bedrock/@ai-sdk/openai": ["@ai-sdk/openai@3.0.105", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.50" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-umx95F8gqGuhPdoW+4ofq83fuSN6aMHwISxvY6dZU51Iix5ZKId0FNru+0FQeu+xfFUrVNmf3vYQNc2FLN85xA=="], "@ai-sdk/amazon-bedrock/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="], @@ -5655,25 +5644,31 @@ "@ai-sdk/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.46", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8", "undici": "^6.28.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-tEtld97plCFiYevsJuOkGkeuhQndeMWFBVrJS4AjnbD5AqrNSXRCe0p+BZ3Cju/sxDeeZ9ym3q9YUV8fASA7aQ=="], - "@ai-sdk/azure/@ai-sdk/openai": ["@ai-sdk/openai@3.0.84", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.38" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-cmgbeJL0bbY0yTJH4/AdmP5E7MjWRL9G8UdhIi0JlV/So03o82ORJofW8OzwCZPTORVQblFbpZXYGDcUd9NdUQ=="], + "@ai-sdk/azure/@ai-sdk/openai": ["@ai-sdk/openai@3.0.88", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.40" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-6M4+bxK/UMijDYK2ia1hCKYma1iajFYxHDlhbinFUdhH2WbFsjoZRMpSjEMlTOBptqmh2J1JclKnprGulF8WwQ=="], "@ai-sdk/azure/@ai-sdk/provider": ["@ai-sdk/provider@3.0.14", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-5X1k57JBJ4H7H1QjX7CnJYAB1I19r/trVZTMcSms7/kLNZ8RaU4Nt2agcwZzv82Hfx6Q7/TOLU7agAKeFfc8cA=="], - "@ai-sdk/azure/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.38", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-/HHGmtKllqjg1OLc023v9w9kK3laW7Z6TzfZukYQWCsGBbzB9p60zTvvpXFVcs44NZBVXL3viOa1HRKUbeee8g=="], + "@ai-sdk/azure/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.40", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OL5IrpUm9Y8Dwy+w/vvFwPotS6m52O9W0op2oXgXdCROMJIBalBI0oro6OIBYkPxvm5Xg02GSkoQN25RlR0bnw=="], + + "@ai-sdk/cerebras/@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], "@ai-sdk/cerebras/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], + "@ai-sdk/cohere/@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], + "@ai-sdk/cohere/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], "@ai-sdk/deepgram/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="], "@ai-sdk/deepgram/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.45", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8", "undici": "^5.29.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-7u5B/E2uZmU65SlJhhQGFHZwRCN0xOz4HHtFc4sEGV9PHbX3fGiEiZBpc/SABay1dGeJgK3VD60rvLGoWdWPXA=="], + "@ai-sdk/deepinfra/@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], + "@ai-sdk/deepinfra/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], "@ai-sdk/deepseek/@ai-sdk/provider": ["@ai-sdk/provider@3.0.14", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-5X1k57JBJ4H7H1QjX7CnJYAB1I19r/trVZTMcSms7/kLNZ8RaU4Nt2agcwZzv82Hfx6Q7/TOLU7agAKeFfc8cA=="], - "@ai-sdk/deepseek/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.38", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-/HHGmtKllqjg1OLc023v9w9kK3laW7Z6TzfZukYQWCsGBbzB9p60zTvvpXFVcs44NZBVXL3viOa1HRKUbeee8g=="], + "@ai-sdk/deepseek/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.40", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OL5IrpUm9Y8Dwy+w/vvFwPotS6m52O9W0op2oXgXdCROMJIBalBI0oro6OIBYkPxvm5Xg02GSkoQN25RlR0bnw=="], "@ai-sdk/elevenlabs/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="], @@ -5697,21 +5692,37 @@ "@ai-sdk/google-vertex/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.45", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8", "undici": "^5.29.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-7u5B/E2uZmU65SlJhhQGFHZwRCN0xOz4HHtFc4sEGV9PHbX3fGiEiZBpc/SABay1dGeJgK3VD60rvLGoWdWPXA=="], + "@ai-sdk/groq/@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], + "@ai-sdk/groq/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], "@ai-sdk/mistral/@ai-sdk/provider": ["@ai-sdk/provider@3.0.14", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-5X1k57JBJ4H7H1QjX7CnJYAB1I19r/trVZTMcSms7/kLNZ8RaU4Nt2agcwZzv82Hfx6Q7/TOLU7agAKeFfc8cA=="], "@ai-sdk/mistral/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.40", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OL5IrpUm9Y8Dwy+w/vvFwPotS6m52O9W0op2oXgXdCROMJIBalBI0oro6OIBYkPxvm5Xg02GSkoQN25RlR0bnw=="], + "@ai-sdk/openai/@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], + "@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], + "@ai-sdk/openai-compatible/@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], + "@ai-sdk/openai-compatible/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], + "@ai-sdk/perplexity/@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], + "@ai-sdk/perplexity/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], "@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], - "@ai-sdk/togetherai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], + "@ai-sdk/provider-utils/undici": ["undici@6.28.0", "", {}, "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA=="], + + "@ai-sdk/togetherai/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.62", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.40" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-lRe54zvyIS1a60N8UVhnwKZRI5I+GSV8uhKkPpId+aiKO7z7UgSbNqFmXkBBMD3yc9UrLnQnATV2EQyXNhzEkA=="], + + "@ai-sdk/togetherai/@ai-sdk/provider": ["@ai-sdk/provider@3.0.14", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-5X1k57JBJ4H7H1QjX7CnJYAB1I19r/trVZTMcSms7/kLNZ8RaU4Nt2agcwZzv82Hfx6Q7/TOLU7agAKeFfc8cA=="], + + "@ai-sdk/togetherai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.40", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OL5IrpUm9Y8Dwy+w/vvFwPotS6m52O9W0op2oXgXdCROMJIBalBI0oro6OIBYkPxvm5Xg02GSkoQN25RlR0bnw=="], + + "@ai-sdk/vercel/@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], "@ai-sdk/vercel/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], @@ -6025,7 +6036,7 @@ "@opencode-ai/app/@opencode-ai/client": ["@opencode-ai/client@vendor/opencode-ai-client-1.17.13-v2.tgz", {}, "sha512-332kgNifvpQOF9e3UA+pIa5xPrMhLaQkUiNiO+meS0Ba9HjSE6hfsWnEojMkD0DPSLqPP6rCF1dDoF7U0Y0OCQ=="], - "@opencode-ai/core/@ai-sdk/openai": ["@ai-sdk/openai@3.0.84", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.38" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-cmgbeJL0bbY0yTJH4/AdmP5E7MjWRL9G8UdhIi0JlV/So03o82ORJofW8OzwCZPTORVQblFbpZXYGDcUd9NdUQ=="], + "@opencode-ai/core/@ai-sdk/openai": ["@ai-sdk/openai@3.0.88", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.40" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-6M4+bxK/UMijDYK2ia1hCKYma1iajFYxHDlhbinFUdhH2WbFsjoZRMpSjEMlTOBptqmh2J1JclKnprGulF8WwQ=="], "@opencode-ai/core/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="], @@ -6039,6 +6050,8 @@ "@opencode-ai/llm/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], + "@opencode-ai/plugin/@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], + "@opencode-ai/script/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], "@opencode-ai/session-ui/@opencode-ai/client": ["@opencode-ai/client@../app/vendor/opencode-ai-client-1.17.13-v2.tgz", {}, "sha512-332kgNifvpQOF9e3UA+pIa5xPrMhLaQkUiNiO+meS0Ba9HjSE6hfsWnEojMkD0DPSLqPP6rCF1dDoF7U0Y0OCQ=="], @@ -6121,10 +6134,6 @@ "@solidjs/start/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=="], - "@standard-community/standard-json/effect": ["effect@4.0.0-beta.74", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.8.0", "find-my-way-ts": "^0.1.6", "ini": "^7.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.1", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^14.0.0", "yaml": "^2.9.0" } }, "sha512-Yx+Kh12U+i2FmjwEfKs+ePFmpMd43RPD1oGqc/VraSS9bYzvF0Ff3PojwEFEVEewp8xc92Uxu28gTspU4qyvHA=="], - - "@standard-community/standard-openapi/effect": ["effect@4.0.0-beta.74", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.8.0", "find-my-way-ts": "^0.1.6", "ini": "^7.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.1", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^14.0.0", "yaml": "^2.9.0" } }, "sha512-Yx+Kh12U+i2FmjwEfKs+ePFmpMd43RPD1oGqc/VraSS9bYzvF0Ff3PojwEFEVEewp8xc92Uxu28gTspU4qyvHA=="], - "@storybook/csf-plugin/unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="], "@tailwindcss/oxide/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], @@ -6153,10 +6162,6 @@ "@types/plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], - "@vitest/coverage-v8/@vitest/utils": ["@vitest/utils@4.1.8", "", { "dependencies": { "@vitest/pretty-format": "4.1.8", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg=="], - - "@vitest/coverage-v8/magicast": ["magicast@0.5.3", "", { "dependencies": { "@babel/parser": "^7.29.3", "@babel/types": "^7.29.0", "source-map-js": "^1.2.1" } }, "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw=="], - "@vitest/expect/@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="], "@vitest/expect/tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="], @@ -6165,12 +6170,24 @@ "@vscode/emmet-helper/jsonc-parser": ["jsonc-parser@2.3.1", "", {}, "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg=="], + "accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "ai/@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.104", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZKX5n74io8VIRlhIMSLWVlvT3sXC8Z7cZ9GHuWBWZDVi96+62AIsWuLGvMfcBA1STYuSoDrp6rIziZmvrTq0TA=="], + + "ai/@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], + + "ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.23", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-z8GlDaCmRSDlqkMF2f4/RFgWxdarvIbyuk+m6WXT1LYgsnGiXRJGTD2Z1+SDl3LqtFuRtGX1aghYvQLoHL/9pg=="], + "ai-gateway-provider/@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@4.0.153", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.110", "@ai-sdk/openai": "3.0.96", "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.45", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iEXrLgWylCHJmznqlKLU3CqRh8UWibv+illrwmsk136FVBBvyXiGnpQrI1pGWCScVLQjBQSFQu7GJDkUEomf/A=="], + "ai-gateway-provider/@ai-sdk/azure": ["@ai-sdk/azure@3.0.88", "", { "dependencies": { "@ai-sdk/deepseek": "2.0.47", "@ai-sdk/openai": "3.0.84", "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.38" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-RRjZkB1lYplh8dpBarnvkl1j7sYLHsyXua7erL3oNcMK7fHcl4bPO5C7iQhD1O/DqD/zCceDifnege1s+8yEvw=="], + "ai-gateway-provider/@ai-sdk/cerebras": ["@ai-sdk/cerebras@2.0.60", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.54", "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.33" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Rnok3cThg6awBwaDSyiZpgRpbV7pqxGYrA89LODCo5cuEHeP2h0AM0lLHP7zIkclAdXfOm4wldKi/S2T/DGCOw=="], "ai-gateway-provider/@ai-sdk/cohere": ["@ai-sdk/cohere@3.0.54", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.45" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-cXLjIsSzUriPHe704IH6d+ipJ/OvczTB700p9Zma7DPgQzvxG/diyr8q/2LEsbTRiTopiKhky8dn1PJNQcJToQ=="], + "ai-gateway-provider/@ai-sdk/deepseek": ["@ai-sdk/deepseek@2.0.47", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.38" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MzcQ321JO8OY+TVLFI81A7cIIuoeLLxrLCDD+8C1E3Ro6UFyfMtRXo9bw9OhTMRSDMo6hgSDOo4Fekz8aJtQYQ=="], + "ai-gateway-provider/@ai-sdk/google": ["@ai-sdk/google@3.0.108", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.45" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kwvYpRNghqt0VRKE7Hx1UWZQCUJJFqUITj24baxy+ApS0Hru0PkBJHD75a36Wc+e6e+wHcKR2MconTeJiBZigA=="], "ai-gateway-provider/@ai-sdk/groq": ["@ai-sdk/groq@3.0.59", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.45" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-X4h60TGq4pIOXPsthatUr+bfTaYCaKGX597hG9JgcueEl4+nboCdw99ixjFKGkvYlBJwLCCfI957EmGA2QlF0w=="], @@ -6203,8 +6220,6 @@ "archiver-utils/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], - "ast-v8-to-istanbul/js-tokens": ["js-tokens@10.0.0", "", {}, "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q=="], - "astro/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="], "astro/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], @@ -6291,8 +6306,6 @@ "electron-winstaller/fs-extra": ["fs-extra@7.0.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="], - "encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], - "engine.io-client/ws": ["ws@8.20.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w=="], "esast-util-from-js/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], @@ -6337,8 +6350,6 @@ "iconv-corefoundation/node-addon-api": ["node-addon-api@1.7.2", "", {}, "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg=="], - "istanbul-reports/html-escaper": ["html-escaper@2.0.2", "", {}, "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="], - "js-beautify/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], "js-beautify/nopt": ["nopt@7.2.1", "", { "dependencies": { "abbrev": "^2.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w=="], @@ -6351,6 +6362,8 @@ "lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + "make-fetch-happen/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], + "matcher/escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], "md-to-react-email/marked": ["marked@7.0.4", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ=="], @@ -6391,7 +6404,7 @@ "opencode/@ai-sdk/cerebras": ["@ai-sdk/cerebras@2.0.60", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.54", "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.33" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Rnok3cThg6awBwaDSyiZpgRpbV7pqxGYrA89LODCo5cuEHeP2h0AM0lLHP7zIkclAdXfOm4wldKi/S2T/DGCOw=="], - "opencode/@ai-sdk/openai": ["@ai-sdk/openai@3.0.84", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.38" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-cmgbeJL0bbY0yTJH4/AdmP5E7MjWRL9G8UdhIi0JlV/So03o82ORJofW8OzwCZPTORVQblFbpZXYGDcUd9NdUQ=="], + "opencode/@ai-sdk/openai": ["@ai-sdk/openai@3.0.88", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.40" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-6M4+bxK/UMijDYK2ia1hCKYma1iajFYxHDlhbinFUdhH2WbFsjoZRMpSjEMlTOBptqmh2J1JclKnprGulF8WwQ=="], "opencode/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="], @@ -6559,6 +6572,8 @@ "@actions/github/@octokit/plugin-rest-endpoint-methods/@octokit/types": ["@octokit/types@12.6.0", "", { "dependencies": { "@octokit/openapi-types": "^20.0.0" } }, "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw=="], + "@ai-sdk/alibaba/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils/undici": ["undici@6.28.0", "", {}, "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA=="], @@ -6883,7 +6898,11 @@ "@opencode-ai/core/@ai-sdk/openai/@ai-sdk/provider": ["@ai-sdk/provider@3.0.14", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-5X1k57JBJ4H7H1QjX7CnJYAB1I19r/trVZTMcSms7/kLNZ8RaU4Nt2agcwZzv82Hfx6Q7/TOLU7agAKeFfc8cA=="], - "@opencode-ai/core/@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.38", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-/HHGmtKllqjg1OLc023v9w9kK3laW7Z6TzfZukYQWCsGBbzB9p60zTvvpXFVcs44NZBVXL3viOa1HRKUbeee8g=="], + "@opencode-ai/core/@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.40", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OL5IrpUm9Y8Dwy+w/vvFwPotS6m52O9W0op2oXgXdCROMJIBalBI0oro6OIBYkPxvm5Xg02GSkoQN25RlR0bnw=="], + + "@opencode-ai/core/@ai-sdk/openai-compatible/@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], + + "@opencode-ai/core/@ai-sdk/openai-compatible/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.23", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-z8GlDaCmRSDlqkMF2f4/RFgWxdarvIbyuk+m6WXT1LYgsnGiXRJGTD2Z1+SDl3LqtFuRtGX1aghYvQLoHL/9pg=="], "@opencode-ai/desktop/@actions/artifact/@actions/http-client": ["@actions/http-client@2.2.3", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA=="], @@ -6955,20 +6974,16 @@ "@solidjs/start/shiki/@shikijs/types": ["@shikijs/types@1.29.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw=="], - "@standard-community/standard-json/effect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], - - "@standard-community/standard-openapi/effect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], - "@storybook/csf-plugin/unplugin/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], "@storybook/csf-plugin/unplugin/webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="], - "@vitest/coverage-v8/@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@4.1.8", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA=="], - "@vitest/expect/@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="], + "accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + "ai-gateway-provider/@ai-sdk/amazon-bedrock/@ai-sdk/openai": ["@ai-sdk/openai@3.0.96", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.45" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Pex8vOj1y05j7jtBS39cJJRDjJbMIyCY9+01cSIp1hwEJTKImrFejMgsAazMWXSi/HU+B9ZE6ElftCOwvg4mmQ=="], "ai-gateway-provider/@ai-sdk/amazon-bedrock/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="], @@ -6979,6 +6994,10 @@ "ai-gateway-provider/@ai-sdk/amazon-bedrock/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], + "ai-gateway-provider/@ai-sdk/azure/@ai-sdk/provider": ["@ai-sdk/provider@3.0.14", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-5X1k57JBJ4H7H1QjX7CnJYAB1I19r/trVZTMcSms7/kLNZ8RaU4Nt2agcwZzv82Hfx6Q7/TOLU7agAKeFfc8cA=="], + + "ai-gateway-provider/@ai-sdk/azure/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.38", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-/HHGmtKllqjg1OLc023v9w9kK3laW7Z6TzfZukYQWCsGBbzB9p60zTvvpXFVcs44NZBVXL3viOa1HRKUbeee8g=="], + "ai-gateway-provider/@ai-sdk/cerebras/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.54", "", { "dependencies": { "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.33" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OyXt0zK8y2/ZIyWlbxTv2r1M7AK227S+Gl4BYOEF42q0wz1n5m4fwR8L4Fy/MQ4Ho6xje47MPsFcRdIqIyP6Rw=="], "ai-gateway-provider/@ai-sdk/cerebras/@ai-sdk/provider": ["@ai-sdk/provider@3.0.12", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-sj9DWTJ2Ze0WR9qsiOPqoqzNx3OxL6iMxHImbhvoe9qOspekbzxNDMiJ4TIGfYHYh9w4OmBjz3prvqhzTi96+Q=="], @@ -6989,6 +7008,10 @@ "ai-gateway-provider/@ai-sdk/cohere/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.45", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8", "undici": "^5.29.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-7u5B/E2uZmU65SlJhhQGFHZwRCN0xOz4HHtFc4sEGV9PHbX3fGiEiZBpc/SABay1dGeJgK3VD60rvLGoWdWPXA=="], + "ai-gateway-provider/@ai-sdk/deepseek/@ai-sdk/provider": ["@ai-sdk/provider@3.0.14", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-5X1k57JBJ4H7H1QjX7CnJYAB1I19r/trVZTMcSms7/kLNZ8RaU4Nt2agcwZzv82Hfx6Q7/TOLU7agAKeFfc8cA=="], + + "ai-gateway-provider/@ai-sdk/deepseek/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.38", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-/HHGmtKllqjg1OLc023v9w9kK3laW7Z6TzfZukYQWCsGBbzB9p60zTvvpXFVcs44NZBVXL3viOa1HRKUbeee8g=="], + "ai-gateway-provider/@ai-sdk/google/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="], "ai-gateway-provider/@ai-sdk/google/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.45", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8", "undici": "^5.29.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-7u5B/E2uZmU65SlJhhQGFHZwRCN0xOz4HHtFc4sEGV9PHbX3fGiEiZBpc/SABay1dGeJgK3VD60rvLGoWdWPXA=="], @@ -7005,6 +7028,8 @@ "ai-gateway-provider/@ai-sdk/perplexity/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.45", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8", "undici": "^5.29.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-7u5B/E2uZmU65SlJhhQGFHZwRCN0xOz4HHtFc4sEGV9PHbX3fGiEiZBpc/SABay1dGeJgK3VD60rvLGoWdWPXA=="], + "ai/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "ajv-keywords/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], "ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -7151,7 +7176,11 @@ "opencode/@ai-sdk/openai/@ai-sdk/provider": ["@ai-sdk/provider@3.0.14", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-5X1k57JBJ4H7H1QjX7CnJYAB1I19r/trVZTMcSms7/kLNZ8RaU4Nt2agcwZzv82Hfx6Q7/TOLU7agAKeFfc8cA=="], - "opencode/@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.38", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-/HHGmtKllqjg1OLc023v9w9kK3laW7Z6TzfZukYQWCsGBbzB9p60zTvvpXFVcs44NZBVXL3viOa1HRKUbeee8g=="], + "opencode/@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.40", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OL5IrpUm9Y8Dwy+w/vvFwPotS6m52O9W0op2oXgXdCROMJIBalBI0oro6OIBYkPxvm5Xg02GSkoQN25RlR0bnw=="], + + "opencode/@ai-sdk/openai-compatible/@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], + + "opencode/@ai-sdk/openai-compatible/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.23", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-z8GlDaCmRSDlqkMF2f4/RFgWxdarvIbyuk+m6WXT1LYgsnGiXRJGTD2Z1+SDl3LqtFuRtGX1aghYvQLoHL/9pg=="], "p-locate/p-limit/yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], @@ -7393,6 +7422,8 @@ "@octokit/rest/@octokit/core/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], + "@opencode-ai/core/@ai-sdk/openai-compatible/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "@opencode-ai/core/@ai-sdk/openai/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "@opencode-ai/desktop/@actions/artifact/@actions/http-client/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], @@ -7405,8 +7436,6 @@ "@slack/bolt/express/accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "@slack/bolt/express/accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], - "@slack/bolt/express/body-parser/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], "@slack/bolt/express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], @@ -7425,12 +7454,16 @@ "ai-gateway-provider/@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], + "ai-gateway-provider/@ai-sdk/azure/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "ai-gateway-provider/@ai-sdk/cerebras/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "ai-gateway-provider/@ai-sdk/cohere/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "ai-gateway-provider/@ai-sdk/cohere/@ai-sdk/provider-utils/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], + "ai-gateway-provider/@ai-sdk/deepseek/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "ai-gateway-provider/@ai-sdk/google/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "ai-gateway-provider/@ai-sdk/google/@ai-sdk/provider-utils/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], @@ -7515,6 +7548,8 @@ "opencode/@ai-sdk/cerebras/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "opencode/@ai-sdk/openai-compatible/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "opencode/@ai-sdk/openai/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "pkg-dir/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], diff --git a/docs/fork/web-audit.md b/docs/fork/web-audit.md deleted file mode 100644 index 9c4e4a9ea2fc..000000000000 --- a/docs/fork/web-audit.md +++ /dev/null @@ -1,437 +0,0 @@ -# Fork web compatibility audit - -Updated: 2026-09-05. - -## Release decision - -**Merge authorized with known follow-ups.** On 2026-09-05 the repository owner -explicitly requested committing and pushing every current improvement and merging -production PR #7 and development PR #8, with remaining issues handled in follow-up -PRs. This supersedes the earlier draft/release hold. It does not mean the full -browser suite or hosted CI is green. The checkpoint below records the evidence -and unresolved work without weakening or skipping failing tests. - -The owner also confirmed that the CPU was throttled during the slower benchmark. -Those timings are not comparable to the earlier unthrottled baseline and are not -established as a code-induced performance regression. - -Integrated upstream remains `70b4ca8c181e4c1ac6d8993b86249d824487ec65`; -newer upstream work is explicitly tracked below. No finite audit establishes that -the entire fork is bug-free. - -The deployed service on ports 4096/14096 and its binary were not changed. Tests -used separate worktrees, loopback servers, synthetic sessions and isolated XDG -data. Real-server smoke checks were unauthenticated; they do not establish -Basic-auth deployment parity. The replacement transport has a separate unit -test asserting Basic-auth headers with dummy credentials. - -## Comparison boundary - -| Ref | Commit | -| ------------------------------------ | ------------------------------------------ | -| Fork production baseline | `c94eb6133eca258cb06cc30d159aae7a76519d1b` | -| Fork development baseline | `722450048f` | -| Initial upstream production | `20a7743876` | -| Initial upstream development | `79903a4cf7` | -| Upstream integrated in both branches | `70b4ca8c181e4c1ac6d8993b86249d824487ec65` | - -The initial production delta was 510 files, 38,512 additions / 7,297 deletions. -The latest upstream merge did not change app/session-ui runtime source relative -to the initial upstream production snapshot. It did bring release, provider and -console changes, so both integration branches received full unit/type validation. - -Fork-heavy boundaries remain the current-session model/reducer, timeline -presentation, prompt submit path, session queue, model persistence and shared -message-part rendering. These are intentional features, not candidates for -wholesale upstream replacement. App code still composes a pinned promise client, -a separate pinned current-session client, generated legacy SDK, and compatibility -stores. Regenerating the workspace client alone does not update the pinned clients. - -### Functional comparison - -Pristine latest upstream passed all 10 selected Chromium tests: reasoning-selector -visibility, eight reasoning/timeline profiles, and review-state persistence. -The fork passes those corresponding contracts with its native-session fixtures, -plus its additional queue/replacement/pending/model-selection regressions. - -An attempted identical-fixture comparison was invalid: fork-only payload fields -failed upstream schema validation and the upstream UI did not subscribe to the -fork's native session-event endpoint. Those failures are **not** counted as -upstream product bugs. Compare observable contracts using each protocol's valid -fixtures; do not silently rewrite either runtime to fit the other's mocks. - -## Reproduced defects and fixes - -### 1. Admitted steering disappeared after reload - -Admission is durable but transcript promotion occurs later at a runner boundary. -The web snapshot lacked pending admissions; replay starts at the snapshot's -watermark, so already-admitted input could not be reconstructed from later events. - -The message endpoint now includes an optional pending-user projection, selected -from unpromoted, undiscarded steering rows. Queue inputs remain separate. The -current-session model hydrates that projection and ignores stale pending snapshots -that would resurrect discarded input. Neither this query nor stop promotes or -resumes input. New mapping logic is isolated in `pending-inputs.ts`. - -Evidence: database selection/interrupt tests, reducer stale-snapshot test, model -hydration test, cross-browser reload test, and an isolated real-server interrupt -followed by browser reload. Admitted text remained visible and Stop was absent -when execution was idle. - -### 2. Rollback editing disagreed with upstream revert semantics - -Upstream revert retains its boundary message. The fork web editor hides that -message and means to replace it. Pending admissions also are not projected -message boundaries. Passing an extra flag to the pinned promise client was not -sufficient: its encoder omitted the unknown field. - -Inclusive replacement is now explicit and opt-in. Default upstream behavior is -unchanged. Staging captures an admission cutoff without deleting input. Commit -removes the selected original and subsequent pre-cutoff steering, preserves -explicit pending queues, and preserves the replacement admitted after staging. -The runner still commits before promoting new input. The focused persistence -logic lives in `revert-replacement.ts`; `server-revert.ts` bridges only the opt-in -request through the generated SDK. Clients were regenerated by repository scripts. - -The current-session projection is also updated optimistically and refreshed after -commit. Rollback no longer continues after an interruption error; it restores the -draft and shows a request-failed notification. Both composer implementations send -the explicit replacement flag on Enter. - -Evidence: 106 runner/projector/replacement tests passed, including default upstream -boundary retention. The live API check staged a pending original, admitted an -edited replacement, committed, and returned only the edited pending message. -Cross-browser tests cover Enter replacement, retained queue, and interruption -failure. Multi-client concurrent stage/resume remains a coverage gap. - -### 3. Review metadata and diff routes drifted across clients - -Current-session protocol detection did not imply support for `/api/vcs`. The -isolated server returned UI HTML for that unsupported path, and bootstrap skipped -legacy branch metadata on V2. The fix reuses the existing VCS compatibility adapter -and loads branch metadata from the supported endpoint. No new parallel VCS -implementation was introduced. - -Evidence: transport tests assert `/vcs/diff`, working-to-git mode translation, -directory placement and returned content; bootstrap tests assert branch metadata; -review persistence passes in both browsers. Review-line fixtures were corrected -to observe the actual compatibility endpoint rather than a nonexistent V2 route. - -### 4. Switching models reset timeline scroll - -The recent-model resource used a suspending read. A selection changed recent -models and briefly detached the session subtree, resetting the same scroll node -to zero. Browser instrumentation confirmed removal/reinsertion under `main`, -rather than a new session or new scroll node. The resource code is shared with -upstream; this is not evidence that every upstream UI configuration exhibits it. - -A one-line read of the resource's latest value prevents that suspension without -restructuring the layout. All six Chromium/Firefox model-switch scroll regressions -pass, including variant/no-variant changes and unchanged composer dimensions. - -### 5. Test and CI drift obscured regressions - -Mocks dropped model variants, assigned obsolete release dates, ignored configured -agents, lacked context/pending snapshots, and left rename responses non-mutating. -Several tests imported a removed pagination helper or asserted legacy part IDs -against normalized native rendering. Other fixtures hardcoded the local server -port, defeating isolated-port runs. Corrected fixtures retain semantic assertions; -no failing tests were skipped or weakened to force a green result. - -Three HTTP API exerciser assertions expected raw project values while the declared -Effect API uses located envelopes. Assertions now validate location/project and -the nested data explicitly. Coverage/auth/effect runs each passed 236 scenarios, -with no missing or skipped route scenarios. - -Fork CI previously selected upstream-only Blacksmith runners. It now selects -GitHub-hosted runners on the fork, checks production as well as dev, and typechecks -the addressed browser fixtures. Scheduled upstream sync now runs validation before -pushing because its GITHUB_TOKEN push does not trigger normal push workflows. -Actionlint syntax validation passed; optional shellcheck still reports existing -SC2129 style findings in the sync script, not new syntax errors. - -### 6. Firefox could not open the tab context menu with Shift+F10 - -A focused tab received both keydown events but no native `contextmenu` event. -The Kobalte trigger handles `contextmenu` and pointer events, not these keyboard -keys. The tab now explicitly routes Shift+F10 and ContextMenu to that existing -trigger, anchored below the focused tab. The helper is isolated in the existing -fork tab-gesture module; editing/dragging guards stay at the integration point. -Preventing the default avoids duplicate native synthesis on other browsers. - -Evidence: repeated Firefox failure before the fix, keyboard-event instrumentation, -three new unit cases, and all 16 rename tests passing in Chromium/Firefox. The -keyboard assertion was not replaced with a pointer click or skipped. - -### 7. Context circle counted messages hidden by staged rollback - -The message prop fix resolved the always-zero circle, but a second discrepancy -remained: the detail screen selects context through the staged revert boundary; -the circle used the full context snapshot. Staging does not delete that snapshot. -The circle now reuses `selectSessionContextMessages`, the same existing helper as -the detail screen. This is one import and one targeted call-site integration. - -Evidence: a schema-validated browser fixture records 50,000 of 100,000 tokens before -rollback and 25,000 after rollback. The rollback circle failed at 50% before this -fix. All four Chromium/Firefox cases now assert the SVG's numeric progress, -tooltip token count, and detail-screen total/percentage against explicit values. - -## Validation record - -- Both latest-upstream integration branches: **30/30 typecheck tasks and 10/10 - full unit-test tasks passed**. Each core suite: 1,142 tests. Each opencode suite: - 3,650 tests. Latest app suite: 793 tests. Generated-client check passed. -- Focused fork browser run: **32/32 passed** across Chromium and Firefox; separate - model-switch scroll run: **6/6 passed**. -- Initial full browser run: **135 passed, 96 failed, 3 pre-existing skips**. - Latest full rerun: **178 passed, 55 failed, 3 pre-existing skips** (236 cases, - 6.3 minutes). This rerun includes keyboard/remote-fixture fixes and precedes the - final context-selection fix; the latter separately passed all four new cases. - Neither run is an all-green result. -- Rename tests: **16/16 passed** across browsers after correcting native rename - fixtures and keyboard menu activation. Remote settings/auto-accept tests: - **4/4 passed**, including unfocused parent/child sessions on a different server. - The actual current request query is `location[directory]`, not `directory`; - current replies are session-addressed and use `{ reply: "once" }`. -- CI is not green. Windows development jobs failed before tests during Bun 1.3.14 - patch installation (`ENOTEMPTY` for patched `@ai-sdk/openai-compatible`), even - with no restored cache. Linux development unit CI hit subprocess timeouts in - `run-process.test.ts`; local full runs passed. Production typechecking was - cancelled, not a demonstrated compiler error. These require investigation and - successful reruns; no timeouts or assertions have been weakened. -- Manual browser against isolated source backend: edited pending message visible, - original absent, no Stop while idle; Muse Spark 1.3 Free offered Default, - Minimal, Low, Medium, High and Xhigh reasoning choices. No paid inference used. -- Production tab-switch benchmark: both before/after runs passed. V2 median stable - times, milliseconds: - - | Scenario | Before | After | - | ------------------- | -----: | ----: | - | Review closed, cold | 136.2 | 142.8 | - | Review closed, hot | 103.7 | 115.1 | - | Review open, cold | 120.6 | 120.4 | - | Review open, hot | 112.6 | 113.4 | - - Five local samples per scenario, not a statistical performance guarantee. The - final after run includes latest integrated upstream, the recent-model fix, and - the context-selection fix. These samples include concurrent local browser work; - the increases are not established as code-induced regressions or dismissed as - harmless. Repeat isolated performance measurements before release. - No wrong-destination or review-host replacement samples were observed. - -## Historical full-suite failure inventory (before checkpoint) - -These are failing test cases, not 55 confirmed product bugs. Several fixtures still -send mutation arrays as one SSE event or assert obsolete part IDs. Repair invalid -fixtures without weakening observable behavior assertions; investigate failures -that remain against valid data. - -| Area | Cases | -| ---------------------------------- | ----: | -| Native timeline transport | 14 | -| Timeline projection | 6 | -| Smoke pagination/timeline | 6 | -| Collapse state | 4 | -| History-root transitions | 4 | -| Subagent navigation | 4 | -| Context resize | 3 | -| Lifecycle/retry | 3 | -| Request docks | 2 | -| Reducer projection | 2 | -| Shell outline | 2 | -| Todo navigation | 2 | -| New-project model-selection story | 2 | -| Review/terminal stacking (Firefox) | 1 | - -## Historical work plan (superseded by checkpoint backlog) - -1. [x] Correct remote settings fixtures and verify cross-server auto-accept, - including unfocused parent/child sessions. This was fixture protocol drift, - not evidence of a runtime permissions defect. -2. [x] Resolve Firefox keyboard context-menu opening while retaining the keyboard - assertion. Rename, tab close and focus restoration pass on both browsers. -3. Migrate remaining timeline transport fixtures to individual native events and - native normalized part identities. Audit actual render behavior for collapse, - retry, context resize, history root, comments, attachments and subagent cards. -4. Finish request-dock, todo, smoke pagination and new-project/model user-story - validation. All configured test ports must be honored. Extend e2e typechecking - to the remaining regression files; current coverage is intentionally enumerated, - not a claim that every e2e file typechecks. -5. Audit keyboard undo/redo interruption-error handling and compatibility-store - reads. Main rollback is fixed; other entrypoints must receive equivalent tests. - Add multi-client replacement/cutoff tests. Basic and staged-rollback context - usage browser parity is now covered; live usage updates remain to be audited. -6. Run the complete browser suite and final benchmark on both integration heads; - inspect Linux and Windows CI. Update the PR validation record with final results. -7. Re-fetch upstream, validate any additional commits, then merge both PRs and - verify upstream ancestry on dev and production. - Do not deploy or reinstall the user's running service as an incidental step. - -## Mergeability rule - -Keep fork behavior behind focused modules and optional protocol fields. Prefer -small call-site adapters over editing vendored client archives or broadly rewriting -upstream UI. Preserve upstream defaults. Every future sync must validate these -boundaries, not merely resolve textual merge conflicts. - -## Saved-work checkpoint — 2026-09-05 - -This is a reviewed **checkpoint with known unresolved issues**. The owner has -authorized merging it and deferring the remaining work to follow-up PRs. No runtime features were removed to make the upstream diff smaller. -The changes use existing adapters and optional call-site callbacks; they do not -replace the session architecture. The user's live service and installed binary -remain untouched. - -### Additional underlying fixes saved - -- **Stop before a provider turn:** interruption could succeed before any assistant - step existed, leaving no step-ended event to clear the composer's busy state. - After a successful interrupt, both composers now refresh the current session. - Queue draining is paused first. Admitted steering is neither deleted nor - resubmitted. The new browser case failed before this change and passes after it, - including reload. The submit test asserts pause → interrupt → refresh ordering. -- **Native user projection:** compatibility conversion now preserves native file - URIs, agent mentions and original typed payload parts, including synthetic - comment context. Native rich prompts no longer depend on lossy legacy fields. -- **Child-task navigation:** native task metadata uses `sessionID`, while legacy - cards read `sessionId`. The adapter supplies the alias without replacing an - existing legacy value, and reads native structured metadata. Child headings - resolve descriptions from the parent's cached parts, not the child-only current - message accessor. -- **Retry display:** the current-to-compatibility status bridge now includes retry - metadata and updates attempts even when the status tag has not changed. Native - retry → recovery → idle browser coverage asserts both attempts. -- **Supported shared endpoints:** V2 session detection no longer forces empty - todos or path metadata. The existing todo endpoint remains authoritative for - persisted tasks; live updates and forced refresh retain their existing behavior. - Path lookup retains an empty fallback only when unavailable on a V2 server. -- **Keyboard rollback integration:** Undo/Redo now receive current user messages, - including pending steering, and delegate to the same rollback/restore mutations - as the timeline. Completion is guarded against session navigation. Undo reaches - the correct pending draft in the new regression; the full Redo interaction is - still blocked by the failure below and is not claimed fixed end-to-end. -- **Provider discovery:** onboarding choices come from the integration catalogue, - separately from the connected-model catalogue. Missing/offline responses are - tolerated; models and connected/default selections are not invented. This fixes - the discovery boundary but exposes a remaining connection-dialog hydration - defect; the whole onboarding flow is still incomplete. -- **Replacement consistency:** two independent current-session clients converge - after a committed replacement. Persistence tests cover a steer exactly at the - admission cutoff, a later replacement, explicit queues, and an unrelated session. - -### Test-fixture and CI improvements saved - -Native timeline fixtures now send individual events with the correct aggregate -ID, durable sequence, normalized text/reasoning IDs and current endpoint envelopes. -Reconnect tests assert the durable `after` cursor. Pagination distinguishes the -current 100-message page from compatibility hydration. Browser assertions still -check behavior, ordering, geometry, caret restoration and error absence; failing -cases were not skipped or given relaxed assertions. Expanded e2e typechecking is -explicitly enumerated, not comprehensive coverage of every Playwright file. - -The shared Bun setup action now honors its caller's Node version, so the existing -Playwright Node 24.15 pin is no longer silently overwritten. Fork CI uses lower -concurrency; upstream workflow concurrency is retained. CLI tests cap concurrent -subprocess tests at two without increasing their timeouts. Windows fixtures use -portable paths and shell syntax, ripgrep is preinstalled, and Turbo forwards the -existing isolated-home/file-watcher environment into core tests. - -The earlier GitHub failures were **not established as quota exhaustion**: - -- Typecheck jobs exited 137 or were cancelled without TypeScript diagnostics. - Resource pressure is plausible, but OOM was not proven. -- Linux subprocess timeout failures reproduced locally with cold concurrent - compilation. Pinned Bun 1.3.14 with concurrency two passed all 14 CLI cases with - the same deadlines (49 assertions). -- Windows showed real portability/download issues as well as a distinct patched - Bun dependency installation `ENOTEMPTY` failure. The portability changes are - tested on Linux; a clean Windows pass is still required. A stock Windows smoke - VM was used for investigation, but its attempted install is not a passing result. - -### Checkpoint verification - -Commands below run from the named package directory, never root `bun test`. - -| Validation | Observed result | -| ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | -| App `bun run test` | 800 unit + 51 browser-environment unit tests passed; zero failures | -| App `bun typecheck` and `bun run typecheck:e2e` | Both passed | -| Core `bun test test/command.test.ts test/session-prompt.test.ts test/session-replacement.test.ts` | 38 passed, 100 assertions | -| Timeline fixture unit test | 4 passed, 8 assertions | -| Workflow `actionlint` (test and typecheck) | Passed | -| Full pinned-Bun Linux Turbo unit run before the final focused additions | 10/10 tasks passed, uncached, 14m43s; core 1,142 tests; opencode 3,627 pass / 22 skip / 1 todo | -| Seven timeline projection/lifecycle/geometry specs, Chromium + Firefox | 43 passed; 3 existing Firefox CDP skips | -| Stop, pending reload, rollback and native transport focused run | 24 passed, 2 failed; only command Undo/Redo failed | -| Recorded, rolled-back and live context usage | 6 passed across Chromium + Firefox | -| Fresh request/todo/child/review/onboarding/smoke run | 18 passed, 8 failed across Chromium + Firefox | - -These are separate runs with some overlapping cases, not an aggregate full-suite -pass. The fresh 26-case run confirms request-dock caret, todo lifecycle, child -navigation, prepend anchoring and cold-tab paint behavior. Its eight failures are -listed below. A final full browser run on both exact branch heads remains follow-up work. - -### Actionable backlog for follow-up PRs - -| ID / priority | Evidence and likely boundary | Required next step / exit criterion | -| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| WEB-01 / P1 | New-project OpenCode Go discovery succeeds, but selecting it throws `Cannot read properties of undefined (reading 'name')` in `ProviderConnection` / `MethodSelection`, before the API-key field appears (both browsers). `provider()` assumes that a new hook instance already has either integration choices or a connected provider. | Make connection rendering safe during catalogue hydration without inventing connected models. Add a delayed-catalogue regression and complete key submission, refresh and model selection in both browsers. | -| WEB-02 / P1 | Command Undo selects/stages the pending message correctly; the subsequent Ctrl+P for Redo never produces a dialog textbox in either browser. No error page in the clean repro. | Separate command-dialog/focus teardown from a runtime hotkey defect; retain real keyboard activation. Require stage, clear, empty draft and restored single message assertions to pass. | -| WEB-03 / P2 | Review/terminal stacking times out waiting for a tree to have positive height in both browsers in the fresh run. Native lifecycle events are now used. | Inspect layout readiness and fixture review mode before changing runtime. Verify tree/terminal geometry, scrolling, detail refresh and remount invariants, without fixed sleep inflation. | -| WEB-04 / P2 | Cached-tab smoke reports one removed first-paint plain text `` in both browsers; latest-message and bottom placement assertions already pass. Probe currently tracks every descendant, including `HighlightedText` leaves rebuilt during hydration. | Establish whether a user-visible row/part remount occurs. Preserve semantic row identity and first-frame assertions; distinguish incidental leaf updates from structural replacement with a dedicated repro rather than blindly relaxing zero-removal. | -| WEB-05 / P2 | Full-history smoke reaches its final error audit, then fails: Chromium logs a current-context transport error; Firefox logs a global event-stream failure. No forbidden text or error toast was observed. | Determine mock coverage/reconnect or cancellation logging versus a real transport failure; preserve the no-console-errors contract and full ordering checks. | -| CI-01 / P1 | Windows patched dependency install failed with `ENOTEMPTY`; clean Windows validation is not established. | Reproduce using pinned Bun in the stock smoke VM or hosted runner, resolve install failures, then run affected core/MCP/ripgrep/LSP/CLI suites and Windows browser gates. Do not call this quota without evidence. | -| CI-02 / P1 | Both old PR heads have red GitHub checks. Local Linux full tests pass, but that does not establish hosted or Windows parity. | Inspect new-head jobs and logs. Require compiler, unit and browser failures to be fixed; document decent local equivalents only for demonstrated infrastructure/config/quota problems. | -| SYNC-01 / P1 | Latest fetched upstream dev and production are `e2894562f8ba943d72172d10b727c24d5f650c16`; integration branches contain `70b4ca8c181e4c1ac6d8993b86249d824487ec65`. The extra commit changes console usage normalization/tier configuration, not the web session fixes. | Merge this and any later upstream changes into both integration branches with affected console validation; recheck ancestry before merge. This checkpoint does not claim latest-upstream completion. | -| RELEASE-01 / P1 | Owner-authorized merge accepts the documented failures; Basic-auth deployed-browser parity and final exact-head full browser validation remain outstanding. | Complete the backlog in follow-up PRs and rerun both branches. Reinstall/deploy separately when explicitly requested. | - -### Reproduction commands - -From `packages/app`, against the task-owned mock-test Vite server (currently -14449, backend request origin 14999): - -```sh -PLAYWRIGHT_BASE_URL=http://127.0.0.1:14449 PLAYWRIGHT_PORT=14449 \ -PLAYWRIGHT_SERVER_PORT=14999 PLAYWRIGHT_WORKERS=2 bun run test:e2e \ - e2e/regression/session-rollback-queue.spec.ts \ - e2e/regression/review-terminal-stacked.spec.ts \ - e2e/user-story/model-selection-flow.spec.ts \ - e2e/smoke/session-timeline.spec.ts -``` - -The tests install synthetic API routes; these ports are not the deployed service. -If no task server is listening, use the repository Playwright configuration's own -server lifecycle on an unused port. Never restart the user's service for this. - -Production benchmark (builds its own temporary preview; run without other test -workloads): - -```sh -PLAYWRIGHT_PORT=14448 PLAYWRIGHT_WORKERS=1 bun run test:e2e \ - --config e2e/performance/playwright.config.ts --project=chromium \ - e2e/performance/timeline/session-tab-switch-benchmark.spec.ts -``` - -### Checkpoint performance result — CPU-throttled comparison - -The final production-build benchmark passed its two structural test cases, but -**did not establish performance parity**. V2 median stable times (five samples per -scenario) increased relative to the earlier baseline: - -| Scenario | Earlier baseline (ms) | Checkpoint (ms) | -| ------------------- | --------------------: | --------------: | -| Review closed, cold | 136.2 | 406.0 | -| Review closed, hot | 103.7 | 314.0 | -| Review open, cold | 120.6 | 354.2 | -| Review open, hot | 112.6 | 324.0 | - -No wrong-destination or review-file-host replacement samples were observed. The -owner subsequently confirmed that CPU throttling caused the slower timings. -The focused browser run finished before benchmark sampling; its tail overlapped -the benchmark build startup. Because CPU conditions differed, these measurements -cannot establish either performance parity or a code-induced regression. - -**PERF-01 / P2 (follow-up):** rerun baseline and checkpoint alternately with matching -CPU throttling and machine load. Retain first-frame/latest-message and review-host -identity checks. Investigate code only if a slowdown reproduces under comparable -conditions; the throttled comparison is not a merge blocker. diff --git a/infra/console.ts b/infra/console.ts index 764807d978fb..630bb56fec7d 100644 --- a/infra/console.ts +++ b/infra/console.ts @@ -150,8 +150,9 @@ const zenLitePrice = new stripe.Price("ZenLitePrice", { }) const ZEN_LITE_PRICE = new sst.Linkable("ZEN_LITE_PRICE", { properties: { - product: zenLiteProduct.id, - price: zenLitePrice.id, + // Use existing Go resources in dev's checkout Stripe account. + product: $app.stage === "dev" ? "prod_U1tUscpmwtV2bG" : zenLiteProduct.id, + price: $app.stage === "dev" ? "price_1T3phhE7fOCwHSD4zS6w2NPy" : zenLitePrice.id, priceInr: 92900, firstMonth50Coupon: zenLiteCouponFirstMonth50.id, firstMonth100Coupon: zenLiteCouponFirstMonth100.id, @@ -244,6 +245,7 @@ const bucketNew = new sst.cloudflare.Bucket("ZenDataNew") const DISCORD_INCIDENT_WEBHOOK_URL = new sst.Secret("DISCORD_INCIDENT_WEBHOOK_URL") 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") +const ENTERPRISE_SALES_INBOX_EMAIL = new sst.Secret("ENTERPRISE_SALES_INBOX_EMAIL") const SALESFORCE_CLIENT_ID = new sst.Secret("SALESFORCE_CLIENT_ID") const SALESFORCE_CLIENT_SECRET = new sst.Secret("SALESFORCE_CLIENT_SECRET") @@ -273,6 +275,7 @@ new sst.cloudflare.x.SolidStart("Console", { EMAILOCTOPUS_API_KEY, AWS_SES_ACCESS_KEY_ID, AWS_SES_SECRET_ACCESS_KEY, + ENTERPRISE_SALES_INBOX_EMAIL, SALESFORCE_CLIENT_ID, SALESFORCE_CLIENT_SECRET, SALESFORCE_INSTANCE_URL, @@ -280,6 +283,7 @@ new sst.cloudflare.x.SolidStart("Console", { ZEN_LITE_PRICE, new sst.Secret("ZEN_LIMITS"), new sst.Secret("ZEN_SESSION_SECRET"), + new sst.Secret("CLOUDFLARE_ACCESS_CLIENT_ID"), ...ZEN_MODELS, ...($dev ? [ diff --git a/nix/hashes.json b/nix/hashes.json index b36141f400cf..87c47efe16c5 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,8 +1,8 @@ { "nodeModules": { - "x86_64-linux": "sha256-2kzFIn42mD7ZDu/+6lWctqjZ/lIVZZfjZhmF/ymhF54=", - "aarch64-linux": "sha256-4HlReGD3gYfyyfnY/FQ46Ov+g3ZGV3sBYQ9p1bS9YAY=", - "aarch64-darwin": "sha256-dkfCoH/sW9XBPZ7XhnUoE54TY1lcfNvZ5wQQLr7gKiQ=", - "x86_64-darwin": "sha256-32t1JEcibZ4OrornIgfWOGQA87FOXjrxrxlDrflh7Ss=" + "x86_64-linux": "sha256-5u7uXnkg2bDPgkYubLCE4tNMwO9jGjmA2Gh1Qtaq/Us=", + "aarch64-linux": "sha256-XNjoxsIwxR1Kh9s3sJYgvSgiz4zJHmgKj2OLUf4LBKU=", + "aarch64-darwin": "sha256-6BVFUUe4CUGa9baXHIaHodWmxFAUdiBPeXDAk20fDt8=", + "x86_64-darwin": "sha256-QdbSHVtAHZPcSLDiwCRh6VfnxoD4d/wIh9coVBM9HOY=" } } diff --git a/package.json b/package.json index 8d58ace1b453..a3f9544410da 100644 --- a/package.json +++ b/package.json @@ -162,6 +162,7 @@ "@ai-sdk/openai-compatible@2.0.41": "patches/@ai-sdk%2Fopenai-compatible@2.0.41.patch", "@ai-sdk/groq@3.0.31": "patches/@ai-sdk%2Fgroq@3.0.31.patch", "@ai-sdk/anthropic@3.0.111": "patches/@ai-sdk%2Fanthropic@3.0.111.patch", - "@ai-sdk/amazon-bedrock@4.0.166": "patches/@ai-sdk%2Famazon-bedrock@4.0.166.patch" + "@ai-sdk/amazon-bedrock@4.0.166": "patches/@ai-sdk%2Famazon-bedrock@4.0.166.patch", + "@ai-sdk/openai@3.0.88": "patches/@ai-sdk%2Fopenai@3.0.88.patch" } } diff --git a/packages/app/e2e/regression/fork-legacy-layout.spec.ts b/packages/app/e2e/regression/fork-legacy-layout.spec.ts new file mode 100644 index 000000000000..2c7f2d4eb2ec --- /dev/null +++ b/packages/app/e2e/regression/fork-legacy-layout.spec.ts @@ -0,0 +1,94 @@ +import { expect, test } from "@playwright/test" +import { base64Encode } from "@opencode-ai/core/util/encode" +import { assistantMessage, setupTimeline, userMessage, userText } from "../performance/timeline-stability/fixture" +import { mockOpenCodeServer } from "../utils/mock-server" + +const draftID = "draft_legacy_new_session" +const directory = "C:/OpenCode/LegacyNewSession" +const server = `http://${process.env.PLAYWRIGHT_SERVER_HOST ?? "127.0.0.1"}:${process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"}` + +// Keep historical layout coverage independent of the upstream retirement date. +test.beforeEach(async ({ page }) => { + await page.clock.setFixedTime(new Date(2026, 8, 1)) +}) + +test("redirects a draft to the legacy new-session route", async ({ page }) => { + await mockOpenCodeServer(page, { + directory, + project: { + id: "proj_legacy_new_session", + worktree: directory, + vcs: "git", + name: "legacy-new-session", + time: { created: 1700000000000, updated: 1700000000000 }, + sandboxes: [], + }, + provider: { all: [], connected: [], default: {} }, + sessions: [], + currentPageMessages: () => ({ items: [], throughSeq: 0 }), + }) + await page.addInitScript( + ({ directory, draftID, server }) => { + localStorage.setItem("settings.v3", JSON.stringify({ general: { newLayoutDesigns: false } })) + localStorage.setItem("app-version.v1", JSON.stringify({ version: "1.17.20" })) + localStorage.setItem( + "opencode.window.browser.dat:tabs", + JSON.stringify([{ type: "draft", draftID, server, directory }]), + ) + }, + { directory, draftID, server }, + ) + + await page.goto(`/new-session?draftId=${draftID}`) + + await expect(page).toHaveURL(`/${base64Encode(directory)}/session`) + await expect(page.locator("header[data-tauri-drag-region]")).toBeVisible() + await expect(page.locator('[data-component="prompt-input"]')).toBeVisible() +}) + +test("renders comment strips and historical diff summary overflow", async ({ page }) => { + const user = userMessage([ + userText("The user made the following comment regarding lines 4 through 8 of src/a.ts: Keep this stable", { + id: "prt_comment_only", + synthetic: true, + metadata: { + opencodeComment: { + path: "src/a.ts", + selection: { startLine: 4, startChar: 0, endLine: 8, endChar: 0 }, + comment: "Keep this stable", + }, + }, + }), + userText("Continue after the comment", { id: "prt_comment_visible" }), + ]) + const nextUser = userMessage(undefined, { id: "msg_2000_diff_next_user", created: 1700000010000 }) + const nextAssistant = assistantMessage([], { + id: "msg_2001_diff_next_assistant", + created: 1700000011000, + }) + await setupTimeline(page, { + messages: [ + user, + assistantMessage([], { snapshot: { diffs: Array.from({ length: 11 }, (_, index) => summaryDiff(index)) } }), + nextUser, + nextAssistant, + ], + settings: { newLayoutDesigns: false }, + }) + const scroller = page.locator(".scroll-view__viewport", { has: page.locator("[data-timeline-row]") }) + await scroller.evaluate((element) => (element.scrollTop = 0)) + + await expect(page.locator('[data-timeline-row="CommentStrip"]')).toBeVisible() + await expect(page.getByText("Keep this stable", { exact: true })).toBeVisible() + await expect(page.locator('[data-timeline-row="DiffSummary"]')).toBeVisible() + await expect(page.getByText(/show all/i)).toBeVisible() +}) + +function summaryDiff(index: number) { + return { + file: `src/diff-${index}.ts`, + additions: 1, + deletions: 1, + patch: `@@ -1 +1 @@\n-export const value = ${index}\n+export const value = ${index + 1}`, + } +} diff --git a/packages/app/e2e/regression/legacy-new-session.spec.ts b/packages/app/e2e/regression/legacy-new-session.spec.ts deleted file mode 100644 index bca3a5004015..000000000000 --- a/packages/app/e2e/regression/legacy-new-session.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { expect, test } from "@playwright/test" -import { base64Encode } from "@opencode-ai/core/util/encode" -import { mockOpenCodeServer } from "../utils/mock-server" - -const draftID = "draft_legacy_new_session" -const directory = "C:/OpenCode/LegacyNewSession" -const server = `http://${process.env.PLAYWRIGHT_SERVER_HOST ?? "127.0.0.1"}:${process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"}` - -test("redirects a draft to the legacy new-session route", async ({ page }) => { - await mockOpenCodeServer(page, { - directory, - project: { - id: "proj_legacy_new_session", - worktree: directory, - vcs: "git", - name: "legacy-new-session", - time: { created: 1700000000000, updated: 1700000000000 }, - sandboxes: [], - }, - provider: { all: [], connected: [], default: {} }, - sessions: [], - currentPageMessages: () => ({ items: [], throughSeq: 0 }), - }) - await page.addInitScript( - ({ directory, draftID, server }) => { - localStorage.setItem("settings.v3", JSON.stringify({ general: { newLayoutDesigns: false } })) - localStorage.setItem("app-version.v1", JSON.stringify({ version: "1.17.20" })) - localStorage.setItem( - "opencode.window.browser.dat:tabs", - JSON.stringify([{ type: "draft", draftID, server, directory }]), - ) - }, - { directory, draftID, server }, - ) - - await page.goto(`/new-session?draftId=${draftID}`) - - await expect(page).toHaveURL(`/${base64Encode(directory)}/session`) - await expect(page.locator("header[data-tauri-drag-region]")).toBeVisible() - await expect(page.locator('[data-component="prompt-input"]')).toBeVisible() -}) diff --git a/packages/app/e2e/regression/session-context-usage.spec.ts b/packages/app/e2e/regression/session-context-usage.spec.ts index 0461fc378597..aa61c5738c78 100644 --- a/packages/app/e2e/regression/session-context-usage.spec.ts +++ b/packages/app/e2e/regression/session-context-usage.spec.ts @@ -33,89 +33,98 @@ const messages = [0, 1].flatMap((index) = ]) Schema.decodeUnknownSync(Schema.Array(SessionMessage.Message))(messages, { onExcessProperty: "error" }) -for (const mode of ["recorded", "rollback", "live"] as const) { - test(`context circle and detail agree with ${mode} usage`, async ({ page }) => { - const reverted = mode === "rollback" - let settled = mode !== "live" - const transport = await installSseTransport(page, { - server: `http://127.0.0.1:${process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"}`, - path: `/api/session/${sessionID}/event`, - }) - await mockOpenCodeServer(page, { - directory, - project: { id: "proj_context_usage", worktree: directory, time: { created: 1, updated: 1 }, sandboxes: [] }, - provider: { - all: [ +for (const newLayoutDesigns of [false, true]) { + for (const mode of ["recorded", "rollback", "live"] as const) { + test(`context circle and detail agree with ${mode} usage (${newLayoutDesigns ? "v2" : "legacy"})`, async ({ + page, + }) => { + // Exercise the legacy layout before its upstream retirement date. + if (!newLayoutDesigns) await page.clock.setFixedTime(new Date(2026, 8, 1)) + await page.addInitScript((newLayoutDesigns) => { + localStorage.setItem("settings.v3", JSON.stringify({ general: { newLayoutDesigns } })) + }, newLayoutDesigns) + const reverted = mode === "rollback" + let settled = mode !== "live" + const transport = await installSseTransport(page, { + server: `http://127.0.0.1:${process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"}`, + path: `/api/session/${sessionID}/event`, + }) + await mockOpenCodeServer(page, { + directory, + project: { id: "proj_context_usage", worktree: directory, time: { created: 1, updated: 1 }, sandboxes: [] }, + provider: { + all: [ + { + id: "opencode", + name: "OpenCode", + models: { test: { id: "test", name: "Test", limit: { context: 100_000 } } }, + }, + ], + connected: ["opencode"], + default: model, + }, + sessions: [ { - id: "opencode", - name: "OpenCode", - models: { test: { id: "test", name: "Test", limit: { context: 100_000 } } }, + id: sessionID, + directory, + title: "Context usage regression", + cost: 2.5, + time: { created: 1, updated: 5 }, + ...(reverted ? { revert: { messageID: "msg_3_user", inclusive: true } } : {}), }, ], - connected: ["opencode"], - default: model, - }, - sessions: [ - { - id: sessionID, - directory, - title: "Context usage regression", - cost: 2.5, - time: { created: 1, updated: 5 }, - ...(reverted ? { revert: { messageID: "msg_3_user", inclusive: true } } : {}), - }, - ], - currentPageMessages: () => ({ - items: messages - .map((message) => - !settled && message.type === "assistant" && message.id === "msg_4_assistant" - ? { - ...message, - time: { created: 4 }, - cost: 0, - tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } }, - } - : message, + currentPageMessages: () => ({ + items: messages + .map((message) => + !settled && message.type === "assistant" && message.id === "msg_4_assistant" + ? { + ...message, + time: { created: 4 }, + cost: 0, + tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } }, + } + : message, + ) + .toReversed(), + throughSeq: 0, + }), + }) + await page.goto(`/${base64Encode(directory)}/session/${sessionID}`) + await expectSessionTitle(page, "Context usage regression") + const usage = page.getByRole("button", { name: "View context usage", exact: true }).first() + const percentage = reverted ? 25 : 50 + const expectPercentage = (value: number) => + expect + .poll(async () => + usage.locator('circle[data-slot$="-progress"]').evaluate((circle) => { + const total = Number(circle.getAttribute("stroke-dasharray")) + return Math.round(100 * (1 - Number(circle.getAttribute("stroke-dashoffset")) / total)) + }), ) - .toReversed(), - throughSeq: 0, - }), - }) - await page.goto(`/${base64Encode(directory)}/session/${sessionID}`) - await expectSessionTitle(page, "Context usage regression") - const usage = page.getByRole("button", { name: "View context usage", exact: true }).first() - const percentage = reverted ? 25 : 50 - const expectPercentage = (value: number) => - expect - .poll(async () => - usage.locator('circle[data-slot$="-progress"]').evaluate((circle) => { - const total = Number(circle.getAttribute("stroke-dasharray")) - return Math.round(100 * (1 - Number(circle.getAttribute("stroke-dashoffset")) / total)) + .toBe(value) + await expectPercentage(mode === "live" ? 25 : percentage) + if (mode === "live") { + settled = true + await transport.send( + event("session.next.step.ended", { + sessionID, + timestamp: 10, + assistantMessageID: "msg_4_assistant", + finish: "stop", + cost: 1.25, + tokens: { input: 40_000, output: 10_000, reasoning: 0, cache: { read: 0, write: 0 } }, }), ) - .toBe(value) - await expectPercentage(mode === "live" ? 25 : percentage) - if (mode === "live") { - settled = true - await transport.send( - event("session.next.step.ended", { - sessionID, - timestamp: 10, - assistantMessageID: "msg_4_assistant", - finish: "stop", - cost: 1.25, - tokens: { input: 40_000, output: 10_000, reasoning: 0, cache: { read: 0, write: 0 } }, - }), + await expectPercentage(50) + } + await usage.hover() + await expect(page.getByRole("tooltip")).toContainText(`${percentage}%`) + await expect(page.getByRole("tooltip")).toContainText((percentage * 1_000).toLocaleString("en-US")) + await usage.click() + await expect(page.getByText("Total Tokens", { exact: true }).locator("..")).toContainText( + (percentage * 1_000).toLocaleString("en-US"), ) - await expectPercentage(50) - } - await usage.hover() - await expect(page.getByRole("tooltip")).toContainText(`${percentage}%`) - await expect(page.getByRole("tooltip")).toContainText((percentage * 1_000).toLocaleString("en-US")) - await usage.click() - await expect(page.getByText("Total Tokens", { exact: true }).locator("..")).toContainText( - (percentage * 1_000).toLocaleString("en-US"), - ) - await expect(page.getByText("Usage", { exact: true }).last().locator("..")).toContainText(`${percentage}%`) - }) + await expect(page.getByText("Usage", { exact: true }).last().locator("..")).toContainText(`${percentage}%`) + }) + } } diff --git a/packages/app/e2e/regression/session-rollback-queue.spec.ts b/packages/app/e2e/regression/session-rollback-queue.spec.ts index 80880719e8cc..0935d7e586b2 100644 --- a/packages/app/e2e/regression/session-rollback-queue.spec.ts +++ b/packages/app/e2e/regression/session-rollback-queue.spec.ts @@ -181,11 +181,15 @@ test("command undo and redo use the current pending input and replacement draft" await page.goto(`/${base64Encode(directory)}/session/${sessionID}`) await expectSessionTitle(page, session.title) await expect(page.getByText("second user prompt", { exact: true })).toHaveCount(1) + await page.clock.install() const select = async (command: string) => { await page.keyboard.press("Control+p") const dialog = page.getByRole("dialog") await dialog.getByRole("textbox").fill(command) await dialog.getByText(command, { exact: true }).click() + // Dialog portals disappear before the 100ms close timer releases the command lock. + await page.clock.runFor(150) + await expect(page.locator("[data-dialog-layer]")).toHaveCount(0) } const input = page.locator('[data-component="prompt-input"]') await select("Undo") diff --git a/packages/app/e2e/regression/session-timeline-projection.spec.ts b/packages/app/e2e/regression/session-timeline-projection.spec.ts index 9f580f2d45e0..3906a822201c 100644 --- a/packages/app/e2e/regression/session-timeline-projection.spec.ts +++ b/packages/app/e2e/regression/session-timeline-projection.spec.ts @@ -115,7 +115,7 @@ test.describe("session timeline projection", () => { await expect(page.locator('[data-timeline-row="TurnGap"]')).toBeVisible() }) - test("renders comment strips and historical diff summary overflow", async ({ page }) => { + test("renders inline comments and historical diff summary overflow", async ({ page }) => { const user = userMessage([ userText("The user made the following comment regarding lines 4 through 8 of src/a.ts: Keep this stable", { id: "prt_comment_only", @@ -142,12 +142,10 @@ test.describe("session timeline projection", () => { nextUser, nextAssistant, ], - settings: { newLayoutDesigns: false }, }) const scroller = page.locator(".scroll-view__viewport", { has: page.locator("[data-timeline-row]") }) await scroller.evaluate((element) => (element.scrollTop = 0)) - await expect(page.locator('[data-timeline-row="CommentStrip"]')).toBeVisible() await expect(page.getByText("Keep this stable", { exact: true })).toBeVisible() await expect(page.locator('[data-timeline-row="DiffSummary"]')).toBeVisible() await expect(page.getByText(/show all/i)).toBeVisible() diff --git a/packages/app/e2e/smoke/session-timeline.spec.ts b/packages/app/e2e/smoke/session-timeline.spec.ts index b1410cf4c7e7..f886f907e674 100644 --- a/packages/app/e2e/smoke/session-timeline.spec.ts +++ b/packages/app/e2e/smoke/session-timeline.spec.ts @@ -3,7 +3,7 @@ import { base64Encode } from "@opencode-ai/core/util/encode" import { currentPageMessages, fixture } from "./session-timeline.fixture" import { trackPageErrors, expectNoSmokeErrors } from "../utils/errors" import { mockOpenCodeServer } from "../utils/mock-server" -import { APP_READY_TIMEOUT, expectAppVisible, expectSessionTitle } from "../utils/waits" +import { expectAppVisible, expectSessionTitle } from "../utils/waits" import { expectAtBottom, scrollToBottom } from "../utils/scroll" const forbiddenText = ["Load details", "Show earlier steps"] @@ -383,9 +383,6 @@ test.describe("smoke: session timeline", () => { }) await configureSmokePage(page, fixture.directory) - await selectHomeProject(page, fixture.project.name) - await navigateToSession(page, fixture.directory, fixture.sourceID, fixture.expected.sourceTitle) - await expectSessionReady(page) await navigateToSession(page, fixture.directory, fixture.targetID, fixture.expected.targetTitle) const expectedPartIDs = fixture.expected.targetPartIDs const expectedMessageIDs = fixture.expected.targetMessageIDs @@ -763,18 +760,6 @@ function expectCompleteScroll( expect(expectedPartIDs.length).toBe(331) } -async function selectHomeProject(page: Page, projectName: string) { - await page.goto("/") - const row = page - .locator('[data-component="home-project-row"]') - .filter({ hasText: new RegExp(projectName, "i") }) - .first() - await expectAppVisible(row) - await row.click() - await expect(row).toHaveAttribute("data-selected", "", { timeout: APP_READY_TIMEOUT }) - await expect(page).toHaveURL(/\/$/) -} - async function navigateToSession(page: Page, directory: string, sessionId: string, expectedTitle: string) { await page.goto(`/${base64Encode(directory)}/session/${sessionId}`) await expectSessionTitle(page, expectedTitle) diff --git a/packages/app/e2e/user-story/model-selection-flow.spec.ts b/packages/app/e2e/user-story/model-selection-flow.spec.ts index 76581a5587e9..10a78242d455 100644 --- a/packages/app/e2e/user-story/model-selection-flow.spec.ts +++ b/packages/app/e2e/user-story/model-selection-flow.spec.ts @@ -5,7 +5,12 @@ import { expectAppVisible } from "../utils/waits" const directory = "C:/OpenCode/NewProject" test("creates a session in a new project, connects OpenCode Go, and selects its model", async ({ page }) => { + const errors: string[] = [] + page.on("pageerror", (error) => errors.push(error.message)) let connectedGo = false + let delayCatalogue = false + const catalogue = Promise.withResolvers() + const requested = Promise.withResolvers() const connections: Array<{ integrationID: string; body: unknown }> = [] await mockOpenCodeServer(page, { @@ -61,8 +66,12 @@ test("creates a session in a new project, connects OpenCode Go, and selects its }) await page.route( (url) => url.pathname === "/api/integration", - (route) => - route.fulfill({ + async (route) => { + if (delayCatalogue) { + requested.resolve() + await catalogue.promise + } + return route.fulfill({ contentType: "application/json", body: JSON.stringify({ location: { directory }, @@ -71,7 +80,8 @@ test("creates a session in a new project, connects OpenCode Go, and selects its { id: "opencode-go", name: "OpenCode Go", methods: [{ type: "key" }], connections: [] }, ], }), - }), + }) + }, ) await page.addInitScript(() => { localStorage.setItem("settings.v3", JSON.stringify({ general: { newLayoutDesigns: true } })) @@ -91,8 +101,12 @@ test("creates a session in a new project, connects OpenCode Go, and selects its await modelControl.click() await expect(page.locator('[data-section="free-models"]')).toContainText("Free models provided by OpenCode") + delayCatalogue = true await page.locator('[data-provider-id="opencode-go"]').click() + await requested.promise + expect(errors).toEqual([]) await page.locator('[data-input="provider-api-key"]').fill("mock-go-api-key") + catalogue.resolve() await page.locator('[data-action="provider-connect-submit"]').click() await expect(page.locator('[data-component="dialog-v2"]')).toHaveCount(0) expect(connections).toEqual([{ integrationID: "opencode-go", body: { key: "mock-go-api-key" } }]) @@ -104,4 +118,5 @@ test("creates a session in a new project, connects OpenCode Go, and selects its await goModel.click() await expect(modelControl).toContainText("Go Model 1") + expect(errors).toEqual([]) }) diff --git a/packages/app/package.json b/packages/app/package.json index 6fd397b02790..1b9db03d26eb 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "1.18.29", + "version": "1.18.32", "description": "", "type": "module", "exports": { diff --git a/packages/app/src/components/dialog-connect-provider.tsx b/packages/app/src/components/dialog-connect-provider.tsx index 1081310e5f21..5a7c1d2bcd8f 100644 --- a/packages/app/src/components/dialog-connect-provider.tsx +++ b/packages/app/src/components/dialog-connect-provider.tsx @@ -408,7 +408,9 @@ function ProviderConnection(props: { }) const provider = createMemo( - () => providers.all().get(props.provider) ?? serverSync().data.provider.all.get(props.provider)!, + () => + providers.all().get(props.provider) ?? + serverSync().data.provider.all.get(props.provider) ?? { id: props.provider, name: props.provider }, ) const fallback = createMemo(() => [ { diff --git a/packages/app/src/components/file-tree-v2.tsx b/packages/app/src/components/file-tree-v2.tsx index 15218a7cd14a..0983cf93ba41 100644 --- a/packages/app/src/components/file-tree-v2.tsx +++ b/packages/app/src/components/file-tree-v2.tsx @@ -23,7 +23,7 @@ import { normalizeFileTreeV2Path, type FileTreeV2Node, } from "@/components/file-tree-v2-model" -import { virtualScrollElement } from "@/components/virtual-scroll-element" +import { createVirtualScrollElement } from "@/components/virtual-scroll-element" export type { Kind } from "@/components/file-tree" @@ -142,12 +142,13 @@ export default function FileTreeV2(props: { return flattenFileTreeV2(model()!, expanded) }) const [root, setRoot] = createSignal() + const scrollElement = createVirtualScrollElement(root) const [focused, setFocused] = createSignal() const virtualizer = createVirtualizer({ get count() { return rows().length }, - getScrollElement: () => virtualScrollElement(root()), + getScrollElement: scrollElement, initialRect: { width: 0, height: 600 }, estimateSize: () => 28, gap: 2, diff --git a/packages/app/src/components/session-context-usage.tsx b/packages/app/src/components/session-context-usage.tsx index 4f970032b862..66cf2eec0f35 100644 --- a/packages/app/src/components/session-context-usage.tsx +++ b/packages/app/src/components/session-context-usage.tsx @@ -1,4 +1,4 @@ -import { Match, Show, Switch, createMemo, type ComponentProps, type JSX } from "solid-js" +import { Match, Show, Switch, batch, createMemo, type ComponentProps, type JSX } from "solid-js" import { ProgressCircle } from "@opencode-ai/ui/progress-circle" import { ProgressCircleV2 } from "@opencode-ai/ui/v2/progress-circle-v2" import { Button } from "@opencode-ai/ui/button" @@ -41,10 +41,12 @@ function openSessionContext(args: { layout: ReturnType tabs: ReturnType["tabs"]> }) { - args.view.reviewPanel.open(args.view.reviewPanel.opened() ? "other" : "context-button") - if (args.layout.fileTree.opened() && args.layout.fileTree.tab() !== "all") args.layout.fileTree.setTab("all") - void args.tabs.open("context") - args.tabs.setActive("context") + batch(() => { + args.view.reviewPanel.open(args.view.reviewPanel.opened() ? "other" : "context-button") + if (args.layout.fileTree.opened() && args.layout.fileTree.tab() !== "all") args.layout.fileTree.setTab("all") + void args.tabs.open("context") + args.tabs.setActive("context") + }) } export function SessionContextUsage(props: SessionContextUsageProps) { diff --git a/packages/app/src/components/virtual-scroll-element.test.ts b/packages/app/src/components/virtual-scroll-element.test.ts index 20c25a8561a0..984831b4e746 100644 --- a/packages/app/src/components/virtual-scroll-element.test.ts +++ b/packages/app/src/components/virtual-scroll-element.test.ts @@ -1,5 +1,5 @@ import { expect, test } from "bun:test" -import { virtualScrollElement } from "./virtual-scroll-element" +import { observeVirtualScrollElement, virtualScrollElement } from "./virtual-scroll-element" test("resolves the connected viewport that owns the virtual root", () => { const stale = document.createElement("div") @@ -16,3 +16,33 @@ test("resolves the connected viewport that owns the virtual root", () => { viewport.remove() expect(virtualScrollElement(root)).toBeNull() }) + +test("tracks late mounting, cached-panel reparenting, and disconnection", async () => { + const first = document.createElement("div") + const second = document.createElement("div") + first.className = second.className = "scroll-view__viewport" + const root = document.createElement("div") + first.append(root) + const updates: Array = [] + const dispose = observeVirtualScrollElement(root, (element) => updates.push(element)) + try { + expect(updates).toEqual([null]) + document.body.append(first, second) + await new Promise((resolve) => setTimeout(resolve, 0)) + expect(updates.at(-1)).toBe(first) + second.append(root) + await new Promise((resolve) => setTimeout(resolve, 0)) + expect(updates.at(-1)).toBe(second) + root.remove() + await new Promise((resolve) => setTimeout(resolve, 0)) + expect(updates).toEqual([null, first, second, null]) + dispose() + first.append(root) + await new Promise((resolve) => setTimeout(resolve, 0)) + expect(updates).toHaveLength(4) + } finally { + dispose() + first.remove() + second.remove() + } +}) diff --git a/packages/app/src/components/virtual-scroll-element.ts b/packages/app/src/components/virtual-scroll-element.ts index 8708781d86a7..677de1886373 100644 --- a/packages/app/src/components/virtual-scroll-element.ts +++ b/packages/app/src/components/virtual-scroll-element.ts @@ -1,4 +1,30 @@ +import { createEffect, createSignal, onCleanup, type Accessor } from "solid-js" + export function virtualScrollElement(root: HTMLElement | undefined) { if (!root?.isConnected) return null return root.closest(".scroll-view__viewport") } + +export function observeVirtualScrollElement(root: HTMLElement, update: (element: HTMLDivElement | null) => void) { + let current = virtualScrollElement(root) + update(current) + // Cached panels can mount or move after Solid's onMount without changing their props. + const observer = new MutationObserver(() => { + const next = virtualScrollElement(root) + if (next === current) return + current = next + update(next) + }) + observer.observe(root.ownerDocument, { childList: true, subtree: true }) + return () => observer.disconnect() +} + +export function createVirtualScrollElement(root: Accessor) { + const [element, setElement] = createSignal(null) + createEffect(() => { + const current = root() + setElement(null) + if (current) onCleanup(observeVirtualScrollElement(current, setElement)) + }) + return element +} diff --git a/packages/app/src/hooks/use-providers.ts b/packages/app/src/hooks/use-providers.ts index 36c0407923d6..b87af5c27e44 100644 --- a/packages/app/src/hooks/use-providers.ts +++ b/packages/app/src/hooks/use-providers.ts @@ -50,7 +50,8 @@ export function useProviders(directory: Accessor) { } const all = createMemo(() => { - const value = choices.latest + // Optional connection choices must not suspend the session while a picker mounts. + const value = choices.state === "ready" || choices.state === "refreshing" ? choices.latest : undefined return mergeProviderChoices( providers().all, value?.server === serverSDK() && value.directory === dir() ? value.items : [], diff --git a/packages/app/src/i18n/desktop-native.test.ts b/packages/app/src/i18n/desktop-native.test.ts index 6fc8660cced5..17a81817a7ee 100644 --- a/packages/app/src/i18n/desktop-native.test.ts +++ b/packages/app/src/i18n/desktop-native.test.ts @@ -147,5 +147,5 @@ describe("desktop native ICU data", () => { expect(() => new Intl.DisplayNames(tag, { type: "language" }), `${locale} names`).not.toThrow() expect(() => new Intl.Segmenter(tag), `${locale} segmenter`).not.toThrow() } - }) + }, 30_000) }) diff --git a/packages/app/src/pages/session/v2/session-file-list-v2.tsx b/packages/app/src/pages/session/v2/session-file-list-v2.tsx index 16cac2a45d66..472470072d54 100644 --- a/packages/app/src/pages/session/v2/session-file-list-v2.tsx +++ b/packages/app/src/pages/session/v2/session-file-list-v2.tsx @@ -5,7 +5,7 @@ import { createEffect, createMemo, createSignal, For, Show } from "solid-js" import { kindChange, kindLabel, type Kind } from "@/components/file-tree-v2" import { normalizePath } from "@/pages/session/v2/review-diff-kinds" import { createVirtualizer, defaultRangeExtractor } from "@tanstack/solid-virtual" -import { virtualScrollElement } from "@/components/virtual-scroll-element" +import { createVirtualScrollElement } from "@/components/virtual-scroll-element" // Drives the highlight/selection of the flat search-result list from the filter // input's keyboard events. @@ -53,12 +53,13 @@ export function SessionFileListV2(props: { const highlighted = () => normalizePath(props.highlighted ?? "") const normalized = createMemo(() => props.files.map(normalizePath)) const [root, setRoot] = createSignal() + const scrollElement = createVirtualScrollElement(root) const [focused, setFocused] = createSignal() const virtualizer = createVirtualizer({ get count() { return props.files.length }, - getScrollElement: () => virtualScrollElement(root()), + getScrollElement: scrollElement, initialRect: { width: 0, height: 600 }, estimateSize: () => 28, gap: 2, diff --git a/packages/app/src/utils/session-message.test.ts b/packages/app/src/utils/session-message.test.ts index 1e4aea53e18b..e50a6de6f6ad 100644 --- a/packages/app/src/utils/session-message.test.ts +++ b/packages/app/src/utils/session-message.test.ts @@ -96,6 +96,32 @@ describe("normalizeSessionMessages", () => { ]) }) + test("keeps admitted model metadata authoritative across a provider switch", () => { + const payload = { + version: 1, + agent: "plan", + model: { providerID: "anthropic", modelID: "sonnet", variant: "high" }, + parts: [{ type: "text", text: "Admitted prompt" }], + } + const result = normalizeCurrentSessionMessages("ses_1", [ + decodeCurrentMessage({ id: "msg_user", type: "user", text: "Admitted prompt", payload, time: { created: 1 } }), + decodeCurrentMessage({ + id: "msg_assistant", + type: "assistant", + agent: "build", + model: { providerID: "openai", id: "gpt" }, + content: [], + time: { created: 2, completed: 3 }, + }), + decodeCurrentMessage({ id: "msg_pending", type: "user", text: "Next prompt", payload, time: { created: 4 } }), + ]) + expect(result.messages).toMatchObject([ + { id: "msg_user", agent: payload.agent, model: payload.model }, + { id: "msg_assistant", agent: "build", providerID: "openai", modelID: "gpt" }, + { id: "msg_pending", agent: payload.agent, model: payload.model }, + ]) + }) + test("preserves current user attachments and payload comments in the compatibility projection", () => { const text = "Use @explore with @src/a.ts" const parts = [ @@ -138,6 +164,7 @@ describe("normalizeSessionMessages", () => { payload: { version: 1, agent: "build", model: { providerID: "provider", modelID: "model" }, parts }, }), ]) + expect(result.messages[0]).toMatchObject({ agent: "build", model: { providerID: "provider", modelID: "model" } }) expect(result.parts.get("msg_rich")).toMatchObject(parts) expect( result.parts.get("msg_rich")?.every((part) => part.sessionID === "ses_1" && part.messageID === "msg_rich"), diff --git a/packages/app/src/utils/session-message.ts b/packages/app/src/utils/session-message.ts index c3b1cd8905af..ad58e57f96d3 100644 --- a/packages/app/src/utils/session-message.ts +++ b/packages/app/src/utils/session-message.ts @@ -25,6 +25,8 @@ type PreparedAssistant = SessionMessageAssistant & { snapshot?: { diffs?: SnapshotFileDiff[] } } +type PreparedUser = SessionMessageUser & { payload?: Extract["payload"] } + const emptyTokens = { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } } const emptyModel: { id: string; providerID: string; variant?: string } = { id: "", providerID: "" } const decodeToolInput = Schema.decodeUnknownOption(Schema.UnknownFromJsonString) @@ -145,6 +147,7 @@ export function normalizeSessionMessages(sessionID: string, source: readonly Ses let agent = "" let model = emptyModel let parentID: string | undefined + let parentHasPayload = false source.forEach((message) => { if (message.type === "agent-switched") { @@ -156,12 +159,19 @@ export function normalizeSessionMessages(sessionID: string, source: readonly Ses return } if (message.type === "user") { + const payload = (message as PreparedUser).payload + parentHasPayload = !!payload + if (payload) { + agent = payload.agent + model = { providerID: payload.model.providerID, id: payload.model.modelID, variant: payload.model.variant } + } parentID = message.id messages.push(userMessage(sessionID, message, agent, model)) parts.set(message.id, userParts(sessionID, message)) return } if (message.type === "synthetic" && message.description?.trim()) { + parentHasPayload = false parentID = message.id messages.push({ id: message.id, @@ -187,11 +197,13 @@ export function normalizeSessionMessages(sessionID: string, source: readonly Ses if (!parentID) return const parent = messages.findLast((item) => item.id === parentID) if (parent?.role === "user") { - parent.agent = message.agent - parent.model = { - providerID: message.model.providerID, - modelID: message.model.id, - variant: message.model.variant, + if (!parentHasPayload) { + parent.agent = message.agent + parent.model = { + providerID: message.model.providerID, + modelID: message.model.id, + variant: message.model.variant, + } } const diffs = (message as PreparedAssistant).snapshot?.diffs if (diffs) parent.summary = { diffs } @@ -298,10 +310,7 @@ function userMessage( } } -function userParts( - sessionID: string, - message: SessionMessageUser & { payload?: Extract["payload"] }, -): Part[] { +function userParts(sessionID: string, message: PreparedUser): Part[] { if (message.payload) { const ordinals = { text: 0, file: 0, agent: 0, subtask: 0 } return message.payload.parts.map((part) => ({ diff --git a/packages/cli/package.json b/packages/cli/package.json index dc70e71ef439..4c51214028dc 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/cli", - "version": "1.18.29", + "version": "1.18.32", "type": "module", "license": "MIT", "bin": { diff --git a/packages/codemode/package.json b/packages/codemode/package.json index 66f983ad82c9..0c699730d4ec 100644 --- a/packages/codemode/package.json +++ b/packages/codemode/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/codemode", - "version": "1.18.29", + "version": "1.18.32", "description": "Effect-native confined code execution over schema-described tools", "private": true, "type": "module", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index f5d06e24d772..2d66b17a913f 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.18.29", + "version": "1.18.32", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/console/app/src/component/go-models.ts b/packages/console/app/src/component/go-models.ts new file mode 100644 index 000000000000..77ca6fadd5b4 --- /dev/null +++ b/packages/console/app/src/component/go-models.ts @@ -0,0 +1,63 @@ +// Requests are per 5 hours; allowances are monthly usage at official API prices. +export const goModels = [ + { id: "kimi-k3", name: "Kimi K3", requests: 110, allowance: 15, featured: true }, + { id: "qwen3.8-max", name: "Qwen3.8 Max", requests: 160, allowance: 15 }, + { id: "grok-4.7", name: "Grok 4.7", requests: 169, allowance: 15 }, + { id: "grok-4.6", name: "Grok 4.6", requests: 169, allowance: 15 }, + { id: "qwen3.7-max", name: "Qwen3.7 Max", requests: 170, allowance: 30 }, + { id: "glm-5.3", name: "GLM-5.3", requests: 220, allowance: 15 }, + { id: "glm-5.2", name: "GLM-5.2", requests: 880, allowance: 60 }, + { id: "glm-5.1", name: "GLM-5.1", requests: 880, allowance: 60 }, + { id: "deepseek-v4-pro", name: "DeepSeek V4 Pro", requests: 1050, allowance: 15 }, + { id: "kimi-k2.6", name: "Kimi K2.6", requests: 1150, allowance: 60 }, + { id: "kimi-k2.7-code", name: "Kimi K2.7 Code", requests: 1350, allowance: 60, featured: true }, + { id: "hy4-preview", name: "Hy4 preview", requests: 1350, allowance: 30 }, + { id: "gpt-5.6-luna", name: "GPT 5.6 Luna", requests: 2050, allowance: 15, featured: true }, + { id: "minimax-m3", name: "MiniMax M3", requests: 3200, allowance: 60, featured: true }, + { id: "mimo-v2.6-pro", name: "MiMo-V2.6-Pro", requests: 3250, allowance: 15, fresh: true }, + { id: "mimo-v2.5-pro", name: "MiMo-V2.5-Pro", requests: 3250, allowance: 15 }, + { id: "qwen3.6-plus", name: "Qwen3.6 Plus", requests: 3300, allowance: 60 }, + { id: "minimax-m2.7", name: "MiniMax M2.7", requests: 3400, allowance: 60 }, + { id: "deepseek-v4-flash-vision-exp", name: "DeepSeek V4 Flash Vision Exp", requests: 6500, allowance: 15 }, + { id: "qwen3.7-plus", name: "Qwen3.7 Plus", requests: 4300, allowance: 60, featured: true }, + { id: "hy3", name: "Hy3", requests: 4300, allowance: 60 }, + { id: "qwen3.8-flash", name: "Qwen3.8 Flash", requests: 5400, allowance: 30 }, + { id: "glm-5.3-flash", name: "GLM-5.3-Flash", requests: 6320, allowance: 60, featured: true }, + { id: "deepseek-v4-flash", name: "DeepSeek V4 Flash", requests: 13000, allowance: 30, featured: true }, + { + id: "deepseek-flash", + name: "DeepSeek V4.1 Flash", + requests: 26000, + baseRequests: 6500, + allowance: 60, + baseAllowance: 15, + bonus: 4, + featured: true, + fresh: true, + }, + { id: "longcat-2.0", name: "LongCat-2.0", requests: 11400, allowance: 60 }, + { + id: "mimo-v2.6-flash", + name: "MiMo-V2.6-Flash", + requests: 30100, + allowance: 60, + featured: true, + fresh: true, + }, + { id: "mimo-v2.5", name: "MiMo-V2.5", requests: 30100, allowance: 60 }, + { + id: "muse-spark-1.3-contributor", + name: "Muse Spark 1.3 Contributor", + requests: 45300, + allowance: 60, + featured: true, + regions: true, + }, + { + id: "muse-spark-1.2-contributor", + name: "Muse Spark 1.2 Contributor", + requests: 45300, + allowance: 60, + regions: true, + }, +].sort((a, b) => a.requests - b.requests) diff --git a/packages/console/app/src/component/header.tsx b/packages/console/app/src/component/header.tsx index a0e5ffc0cabe..dc157484b96c 100644 --- a/packages/console/app/src/component/header.tsx +++ b/packages/console/app/src/component/header.tsx @@ -143,12 +143,12 @@ export function Header(props: { zen?: boolean; go?: boolean; hideGetStarted?: bo