Compare commits

..

1 Commits

Author SHA1 Message Date
opencode 02546dfc2e release: v1.18.17 2026-08-12 20:24:50 +00:00
145 changed files with 633 additions and 8529 deletions
+37
View File
@@ -0,0 +1,37 @@
name: beta
on:
workflow_dispatch:
schedule:
- cron: "0 * * * *"
jobs:
sync:
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
fetch-depth: 0
- name: Setup Bun
uses: ./.github/actions/setup-bun
- name: Setup Git Committer
id: 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: Install OpenCode
run: bun i -g opencode-ai
- name: Sync beta branch
env:
GH_TOKEN: ${{ steps.setup-git-committer.outputs.token }}
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
run: bun script/beta.ts
+69 -116
View File
@@ -29,7 +29,7 @@
},
"packages/app": {
"name": "@opencode-ai/app",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@corvu/drawer": "catalog:",
"@dnd-kit/abstract": "0.5.0",
@@ -96,7 +96,7 @@
},
"packages/cli": {
"name": "@opencode-ai/cli",
"version": "1.18.18",
"version": "1.18.17",
"bin": {
"lildax": "./bin/lildax.cjs",
},
@@ -144,7 +144,7 @@
},
"packages/codemode": {
"name": "@opencode-ai/codemode",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"acorn": "8.15.0",
"effect": "catalog:",
@@ -158,7 +158,7 @@
},
"packages/console/app": {
"name": "@opencode-ai/console-app",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@cloudflare/vite-plugin": "1.15.2",
"@ibm/plex": "6.4.1",
@@ -194,7 +194,7 @@
},
"packages/console/core": {
"name": "@opencode-ai/console-core",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@aws-sdk/client-sts": "3.782.0",
"@jsx-email/render": "1.1.1",
@@ -221,7 +221,7 @@
},
"packages/console/function": {
"name": "@opencode-ai/console-function",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@ai-sdk/anthropic": "3.0.82",
"@ai-sdk/openai": "3.0.48",
@@ -243,7 +243,7 @@
},
"packages/console/mail": {
"name": "@opencode-ai/console-mail",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@jsx-email/all": "2.2.3",
"@jsx-email/cli": "1.4.3",
@@ -267,7 +267,7 @@
},
"packages/console/support": {
"name": "@opencode-ai/console-support",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@cloudflare/vite-plugin": "1.15.2",
"@opencode-ai/console-core": "workspace:*",
@@ -287,7 +287,7 @@
},
"packages/core": {
"name": "@opencode-ai/core",
"version": "1.18.18",
"version": "1.18.17",
"bin": {
"opencode": "./bin/opencode",
},
@@ -301,7 +301,7 @@
"@ai-sdk/deepinfra": "2.0.41",
"@ai-sdk/gateway": "3.0.104",
"@ai-sdk/google": "3.0.73",
"@ai-sdk/google-vertex": "4.0.181",
"@ai-sdk/google-vertex": "4.0.128",
"@ai-sdk/groq": "3.0.31",
"@ai-sdk/mistral": "3.0.51",
"@ai-sdk/openai": "3.0.84",
@@ -332,7 +332,7 @@
"@opentelemetry/sdk-trace-base": "2.6.1",
"@parcel/watcher": "2.5.1",
"@silvia-odwyer/photon-node": "0.3.4",
"ai-gateway-provider": "3.2.0",
"ai-gateway-provider": "3.1.2",
"bun-pty": "0.4.8",
"cross-spawn": "catalog:",
"diff": "catalog:",
@@ -381,7 +381,7 @@
},
"packages/desktop": {
"name": "@opencode-ai/desktop",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@zip.js/zip.js": "2.7.62",
"drizzle-orm": "catalog:",
@@ -435,7 +435,7 @@
},
"packages/effect-drizzle-sqlite": {
"name": "@opencode-ai/effect-drizzle-sqlite",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"drizzle-orm": "catalog:",
"effect": "catalog:",
@@ -449,7 +449,7 @@
},
"packages/effect-sqlite-node": {
"name": "@opencode-ai/effect-sqlite-node",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"effect": "catalog:",
},
@@ -461,7 +461,7 @@
},
"packages/enterprise": {
"name": "@opencode-ai/enterprise",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@hono/standard-validator": "catalog:",
"@opencode-ai/core": "workspace:*",
@@ -493,7 +493,7 @@
},
"packages/function": {
"name": "@opencode-ai/function",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@octokit/auth-app": "8.0.1",
"@octokit/rest": "catalog:",
@@ -509,7 +509,7 @@
},
"packages/http-recorder": {
"name": "@opencode-ai/http-recorder",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@effect/platform-node": "4.0.0-beta.83",
"@effect/platform-node-shared": "4.0.0-beta.83",
@@ -540,7 +540,7 @@
},
"packages/llm": {
"name": "@opencode-ai/llm",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@opencode-ai/schema": "workspace:*",
"@smithy/eventstream-codec": "4.2.14",
@@ -559,7 +559,7 @@
},
"packages/opencode": {
"name": "opencode",
"version": "1.18.18",
"version": "1.18.17",
"bin": {
"opencode": "./bin/opencode",
},
@@ -576,7 +576,7 @@
"@ai-sdk/deepinfra": "2.0.41",
"@ai-sdk/gateway": "3.0.104",
"@ai-sdk/google": "3.0.73",
"@ai-sdk/google-vertex": "4.0.181",
"@ai-sdk/google-vertex": "4.0.128",
"@ai-sdk/groq": "3.0.31",
"@ai-sdk/mistral": "3.0.51",
"@ai-sdk/openai": "3.0.84",
@@ -623,7 +623,7 @@
"@types/ws": "8.18.1",
"@zip.js/zip.js": "2.7.62",
"ai": "catalog:",
"ai-gateway-provider": "3.2.0",
"ai-gateway-provider": "3.1.2",
"bonjour-service": "1.3.0",
"chokidar": "4.0.3",
"cross-spawn": "catalog:",
@@ -690,7 +690,7 @@
},
"packages/plugin": {
"name": "@opencode-ai/plugin",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@ai-sdk/provider": "3.0.8",
"@opencode-ai/sdk": "workspace:*",
@@ -766,7 +766,7 @@
},
"packages/sdk/js": {
"name": "@opencode-ai/sdk",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"cross-spawn": "catalog:",
},
@@ -781,7 +781,7 @@
},
"packages/server": {
"name": "@opencode-ai/server",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@opencode-ai/core": "workspace:*",
"@opencode-ai/protocol": "workspace:*",
@@ -796,7 +796,7 @@
},
"packages/session-ui": {
"name": "@opencode-ai/session-ui",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@kobalte/core": "catalog:",
"@opencode-ai/client": "file:../app/vendor/opencode-ai-client-1.17.13-v2.tgz",
@@ -836,7 +836,7 @@
},
"packages/slack": {
"name": "@opencode-ai/slack",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@opencode-ai/sdk": "workspace:*",
"@slack/bolt": "^3.17.1",
@@ -849,7 +849,7 @@
},
"packages/stats/app": {
"name": "@opencode-ai/stats-app",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@ibm/plex": "6.4.1",
"@kobalte/core": "catalog:",
@@ -883,7 +883,7 @@
},
"packages/stats/core": {
"name": "@opencode-ai/stats-core",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@aws-sdk/client-athena": "3.933.0",
"@planetscale/database": "1.19.0",
@@ -902,7 +902,7 @@
},
"packages/stats/server": {
"name": "@opencode-ai/stats-server",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@aws-sdk/client-firehose": "3.933.0",
"@effect/platform-node": "catalog:",
@@ -944,7 +944,7 @@
},
"packages/tui": {
"name": "@opencode-ai/tui",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@opencode-ai/core": "workspace:*",
"@opencode-ai/plugin": "workspace:*",
@@ -971,7 +971,7 @@
},
"packages/ui": {
"name": "@opencode-ai/ui",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@kobalte/core": "catalog:",
"@pierre/diffs": "catalog:",
@@ -1022,7 +1022,7 @@
},
"packages/web": {
"name": "@opencode-ai/web",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@astrojs/cloudflare": "12.6.3",
"@astrojs/markdown-remark": "6.3.1",
@@ -1075,7 +1075,6 @@
"@silvia-odwyer/photon-node@0.3.4": "patches/@silvia-odwyer%2Fphoton-node@0.3.4.patch",
"@npmcli/agent@4.0.2": "patches/@npmcli%2Fagent@4.0.2.patch",
"solid-js@1.9.10": "patches/solid-js@1.9.10.patch",
"@ai-sdk/groq@3.0.31": "patches/@ai-sdk%2Fgroq@3.0.31.patch",
"@ai-sdk/google@3.0.73": "patches/@ai-sdk%2Fgoogle@3.0.73.patch",
"pacote@21.5.0": "patches/pacote@21.5.0.patch",
"@dnd-kit/dom@0.5.0": "patches/@dnd-kit%2Fdom@0.5.0.patch",
@@ -1183,21 +1182,21 @@
"@ai-sdk/cohere": ["@ai-sdk/cohere@3.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OqcCq2PiFY1dbK/0Ck45KuvE8jfdxRuuAE9Y5w46dAk6U+9vPOeg1CDcmR+ncqmrYrhRl3nmyDttyDahyjCzAw=="],
"@ai-sdk/deepgram": ["@ai-sdk/deepgram@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-DPoKiCXDwzopJI/pHcZnXaycZ5qqCL4xCWcfsb1s8M8OUPchK2GUHcCXt6v056fAqtKWLF/hrW+RcHFFY0qyHQ=="],
"@ai-sdk/deepgram": ["@ai-sdk/deepgram@2.0.33", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-VscTV68g6sXRY4O1yl72/O8y6+tBDvSQax6bqX06hRKWBGxsJ8Jr3LZsNmZnK9Od5Icx565ijK0QgrlNaN4TdQ=="],
"@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/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/elevenlabs": ["@ai-sdk/elevenlabs@2.0.33", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-EtvsWfGrqx3OhzJdoi82qH+4yzEPPKZr2utyQ+w8cHKoFeg0+8Lou9Z3uixy73WEwz8Z1+AR8QT9fZ64AWGYPA=="],
"@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/fireworks": ["@ai-sdk/fireworks@2.0.53", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.48", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-HjeiGsdxSzrCkOf2l2V+K+opzlqxBtduBq6BCiohAdgQk2KdZmI/67SMkBM6Kdze/BjUXiZlv0d7zNICPhxVDA=="],
"@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/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=="],
"@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@4.0.181", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.110", "@ai-sdk/google": "3.0.108", "@ai-sdk/openai-compatible": "2.0.67", "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.45", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-57b5Qor8V53vubkxCj09tbHWpzpCLUbzmll2FwShuLvyEAsCH6mh3sAowDhiwUWPXnLzU+rC3RVMKCPscqICcg=="],
"@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@4.0.128", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.77", "@ai-sdk/google": "3.0.73", "@ai-sdk/openai-compatible": "2.0.47", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-jK8fixb4km2yfgvb9DUFQRpV/jiDB0v9gyxHoHfPydaQvz+CpAz8DTt1quyaM+Wg9G2R8Zo68CYmHbIkUqW2AA=="],
"@ai-sdk/groq": ["@ai-sdk/groq@3.0.31", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-XbbugpnFmXGu2TlXiq8KUJskP6/VVbuFcnFIGDzDIB/Chg6XHsNnqrTF80Zxkh0Pd3+NvbM+2Uqrtsndk6bDAg=="],
@@ -3063,7 +3062,7 @@
"ai": ["ai@6.0.168", "", { "dependencies": { "@ai-sdk/gateway": "3.0.104", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-2HqCJuO+1V2aV7vfYs5LFEUfxbkGX+5oa54q/gCCTL7KLTdbxcCu5D7TdLA5kwsrs3Szgjah9q6D9tpjHM3hUQ=="],
"ai-gateway-provider": ["ai-gateway-provider@3.2.0", "", { "optionalDependencies": { "@ai-sdk/amazon-bedrock": "^4.0.117", "@ai-sdk/anthropic": "^3.0.84", "@ai-sdk/azure": "^3.0.74", "@ai-sdk/cerebras": "^2.0.56", "@ai-sdk/cohere": "^3.0.38", "@ai-sdk/deepgram": "^2.0.35", "@ai-sdk/deepseek": "^2.0.38", "@ai-sdk/elevenlabs": "^2.0.35", "@ai-sdk/fireworks": "^2.0.56", "@ai-sdk/google": "^3.0.82", "@ai-sdk/google-vertex": "^4.0.145", "@ai-sdk/groq": "^3.0.41", "@ai-sdk/mistral": "^3.0.39", "@ai-sdk/openai": "^3.0.71", "@ai-sdk/perplexity": "^3.0.35", "@ai-sdk/xai": "^3.0.95", "@openrouter/ai-sdk-provider": "^2.10.0" }, "peerDependencies": { "@ai-sdk/openai-compatible": "^2.0.0", "@ai-sdk/provider": "^3.0.0", "@ai-sdk/provider-utils": "^4.0.0", "ai": "^6.0.0" } }, "sha512-IGSV96IqAfiZd20CWSMVQk5sVeLcJR2uQcoWLB8GdkxyvQrsU3x4U0o1Ok6bfVJug7SrlX6I8ibz9cHIkUyRtg=="],
"ai-gateway-provider": ["ai-gateway-provider@3.1.2", "", { "optionalDependencies": { "@ai-sdk/amazon-bedrock": "^4.0.62", "@ai-sdk/anthropic": "^3.0.46", "@ai-sdk/azure": "^3.0.31", "@ai-sdk/cerebras": "^2.0.34", "@ai-sdk/cohere": "^3.0.21", "@ai-sdk/deepgram": "^2.0.20", "@ai-sdk/deepseek": "^2.0.20", "@ai-sdk/elevenlabs": "^2.0.20", "@ai-sdk/fireworks": "^2.0.34", "@ai-sdk/google": "^3.0.30", "@ai-sdk/google-vertex": "^4.0.61", "@ai-sdk/groq": "^3.0.24", "@ai-sdk/mistral": "^3.0.20", "@ai-sdk/openai": "^3.0.30", "@ai-sdk/perplexity": "^3.0.19", "@ai-sdk/xai": "^3.0.57", "@openrouter/ai-sdk-provider": "^2.2.3" }, "peerDependencies": { "@ai-sdk/openai-compatible": "^2.0.0", "@ai-sdk/provider": "^3.0.0", "@ai-sdk/provider-utils": "^4.0.0", "ai": "^6.0.0" } }, "sha512-krGNnJSoO/gJ7Hbe5nQDlsBpDUGIBGtMQTRUaW7s1MylsfvLduba0TLWzQaGtOmNRkP0pGhtGlwsnS6FNQMlyw=="],
"ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="],
@@ -5667,9 +5666,9 @@
"@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": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="],
"@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/deepgram/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="],
"@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=="],
@@ -5677,29 +5676,27 @@
"@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/elevenlabs/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="],
"@ai-sdk/elevenlabs/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="],
"@ai-sdk/elevenlabs/@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/elevenlabs/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="],
"@ai-sdk/fireworks/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.67", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.45" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-glcEJC2mBXJKj7joFI0fRhcbdDYKTBgXMPcT6Vcnlym67tTzuNG9pFx3zblxVv8TdOxhojJja5zGG19yeGJxuA=="],
"@ai-sdk/fireworks/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.48", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-z9MC6M4Oh/yUY/F/eszOtO8wc2nMz99XmZQKd2gWTtyIfe716xTfrKe3aYZKg20NZDtyjqPPKPSR+wqz7q1T7Q=="],
"@ai-sdk/fireworks/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="],
"@ai-sdk/fireworks/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="],
"@ai-sdk/fireworks/@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/fireworks/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="],
"@ai-sdk/google/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="],
"@ai-sdk/google/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="],
"@ai-sdk/google-vertex/@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.110", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.45" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-rNkamQCeAUOUGr5Npg5pXZyYFH4fS1U6Mbdy3dF/NNBEI3D2Chc/ruRrwNegP0gfpX3cllP3O4jSibGBbWPZ7A=="],
"@ai-sdk/google-vertex/@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.77", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ML8C2M1YvPA1ulEx4TiyF0k1xvC2ikEiPBIC1PPQ0a5xELUGrO2lAaEzsTEoJ+eCeDd8PSBuFJjs+r+9yIwQXA=="],
"@ai-sdk/google-vertex/@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-sdk/google-vertex/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.47", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Enm5UlL0zUCrW3792opk5h7hRWxZOZzDe6eQYVFqX9LUOGGCe1h8MZWAGim765nwzgnjlpeYOsuzZmLtRsTPlg=="],
"@ai-sdk/google-vertex/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.67", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.45" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-glcEJC2mBXJKj7joFI0fRhcbdDYKTBgXMPcT6Vcnlym67tTzuNG9pFx3zblxVv8TdOxhojJja5zGG19yeGJxuA=="],
"@ai-sdk/google-vertex/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="],
"@ai-sdk/google-vertex/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="],
"@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/google-vertex/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="],
"@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=="],
@@ -6173,23 +6170,21 @@
"accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
"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/amazon-bedrock": ["@ai-sdk/amazon-bedrock@4.0.107", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.78", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "@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-8nT08pGPy25rleJNk56ep00UHK6kCtCmu+ZNqVVSSPDieADlIZqcaN1iRXAFBoCH0Fb9F6C2EjFDaySdsargfQ=="],
"ai-gateway-provider/@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.110", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.45" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-rNkamQCeAUOUGr5Npg5pXZyYFH4fS1U6Mbdy3dF/NNBEI3D2Chc/ruRrwNegP0gfpX3cllP3O4jSibGBbWPZ7A=="],
"ai-gateway-provider/@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.78", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-0OY12G20cUt6iU6htpEA1491Oz++NVxZxlmWGX4B7rSbeZ5pnDmOu6YtW9BKzdZlNx5Gn23i6WMxyZFoMKNcgA=="],
"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/azure": ["@ai-sdk/azure@3.0.49", "", { "dependencies": { "@ai-sdk/openai": "3.0.48", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-wskgAL+OmrHG7by/iWIxEBQCEdc1mDudha/UZav46i0auzdFfsDB/k2rXZaC4/3nWSgMZkxr0W3ncyouEGX/eg=="],
"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.35", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-9DhYurbAvcurOEGN6u2myYDybrrzGfcrkG8hwmFjwTrePW6KCMggm0YxP7e8RkLYcQKqCEMgFlyEB4BM6EmiKg=="],
"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/mistral": ["@ai-sdk/mistral@3.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZXe7nZQgliDdjz5ufH5RKpHWxbN72AzmzzKGbF/z+0K9GN5tUCnftrQRvTRFHA5jAzTapcm2BEevmGLVbMkW+A=="],
"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=="],
"ai-gateway-provider/@ai-sdk/openai": ["@ai-sdk/openai@3.0.53", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Wld+Rbc05KaUn08uBt06eEuwcgalcIFtIl32Yp+GxuZXUQwOb6YeAuq+C6da4ch6BurFoqEaLemJVwjBb7x+PQ=="],
"ai-gateway-provider/@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-gateway-provider/@ai-sdk/xai": ["@ai-sdk/xai@3.0.82", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.41", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-A0VFMufnVf4wODcT3SPQUUzvYXiIO1VhFuXj9r6z/vP4rlo+QRDPw3WSTchcz93ROQWSfBE3I6Szqz342OHi5w=="],
"ai-gateway-provider/@ai-sdk/perplexity": ["@ai-sdk/perplexity@3.0.53", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.45" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bL3SWrPltTuxVNg/bZ5APbJLVe0+BIU+BYAbT8Yo0eSAZ5eMTImN2murQHZa08Wi8lUMm8MNolaYBQkb0JDbFw=="],
"ai-gateway-provider/@openrouter/ai-sdk-provider": ["@openrouter/ai-sdk-provider@2.10.0", "", { "peerDependencies": { "ai": "^6.0.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-FMsAEjLUt5pWuRE2LDC/LCvVrFjLlrEzUITH5+5SZtfq7KZ2wrOHjQVxzz92sju8S9ltpzW87CLW8/b0oBXVCw=="],
"ai-gateway-provider/@openrouter/ai-sdk-provider": ["@openrouter/ai-sdk-provider@2.8.1", "", { "peerDependencies": { "ai": "^6.0.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Y6j3yivgoEUf/kutD/k5GX/mzZfioRFoSx0gbQ+mIOzMaH/vJv1rCkztiuvlLw5xRYQil7oxHUZvmSfXqOx1NQ=="],
"ajv-keywords/ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="],
@@ -6599,24 +6594,16 @@
"@ai-sdk/deepgram/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"@ai-sdk/deepgram/@ai-sdk/provider-utils/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="],
"@ai-sdk/deepinfra/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"@ai-sdk/deepseek/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"@ai-sdk/elevenlabs/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"@ai-sdk/elevenlabs/@ai-sdk/provider-utils/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="],
"@ai-sdk/fireworks/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"@ai-sdk/fireworks/@ai-sdk/provider-utils/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="],
"@ai-sdk/google-vertex/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"@ai-sdk/google-vertex/@ai-sdk/provider-utils/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="],
"@ai-sdk/google/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"@ai-sdk/groq/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
@@ -6989,45 +6976,29 @@
"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.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="],
"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=="],
"ai-gateway-provider/@ai-sdk/amazon-bedrock/@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/amazon-bedrock/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="],
"ai-gateway-provider/@ai-sdk/amazon-bedrock/@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.14", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.1", "@smithy/util-hex-encoding": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-erZq0nOIpzfeZdCyzZjdJb4nVSKLUmSkaQUVkRGQTXs30gyUGeKnrYEg+Xe1W5gE3aReS7IgsvANwVPxSzY6Pw=="],
"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/anthropic/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="],
"ai-gateway-provider/@ai-sdk/anthropic/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="],
"ai-gateway-provider/@ai-sdk/anthropic/@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/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="],
"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/azure/@ai-sdk/openai": ["@ai-sdk/openai@3.0.48", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ALmj/53EXpcRqMbGpPJPP4UOSWw0q4VGpnDo7YctvsynjkrKDmoneDG/1a7VQnSPYHnJp6tTRMf5ZdxZ5whulg=="],
"ai-gateway-provider/@ai-sdk/cerebras/@ai-sdk/provider": ["@ai-sdk/provider@3.0.12", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-sj9DWTJ2Ze0WR9qsiOPqoqzNx3OxL6iMxHImbhvoe9qOspekbzxNDMiJ4TIGfYHYh9w4OmBjz3prvqhzTi96+Q=="],
"ai-gateway-provider/@ai-sdk/azure/@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-gateway-provider/@ai-sdk/cerebras/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.33", "", { "dependencies": { "@ai-sdk/provider": "3.0.12", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-nJ0bAfegMAIJtrzMJtbzer1cS3nb7c7DsyU1S4nrPm7ZU0Mn6SBBZv5IGZZGTbpWTJwqKTSPeZJTXalbAxt1BA=="],
"ai-gateway-provider/@ai-sdk/deepseek/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="],
"ai-gateway-provider/@ai-sdk/cohere/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="],
"ai-gateway-provider/@ai-sdk/deepseek/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="],
"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/mistral/@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-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=="],
"ai-gateway-provider/@ai-sdk/groq/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="],
"ai-gateway-provider/@ai-sdk/groq/@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/openai/@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/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=="],
"ai-gateway-provider/@ai-sdk/perplexity/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="],
"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-gateway-provider/@ai-sdk/xai/@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=="],
"ajv-keywords/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
@@ -7447,31 +7418,13 @@
"ai-gateway-provider/@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"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/anthropic/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"ai-gateway-provider/@ai-sdk/anthropic/@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/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/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/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=="],
"ai-gateway-provider/@ai-sdk/groq/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"ai-gateway-provider/@ai-sdk/groq/@ai-sdk/provider-utils/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="],
"ai-gateway-provider/@ai-sdk/openai/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"ai-gateway-provider/@ai-sdk/perplexity/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"ai-gateway-provider/@ai-sdk/perplexity/@ai-sdk/provider-utils/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="],
"ai-gateway-provider/@ai-sdk/mistral/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
+4 -4
View File
@@ -1,8 +1,8 @@
{
"nodeModules": {
"x86_64-linux": "sha256-yQ8EIxxYkzlEWIMY/UiIR+7lbGBuizsoehMPZzFA65Y=",
"aarch64-linux": "sha256-JF9VVgnl5QUZ430fqb5Qu8y0kchYJ00LO3FbYcd0lBM=",
"aarch64-darwin": "sha256-f3Tu6eu463NWcHgr7dupfD/zUTh26bJ6N2vVXuEyi6c=",
"x86_64-darwin": "sha256-miv9Sv4KdhD0UIi2O5LVS1wQOfq29IV+9S+BvIzAvgo="
"x86_64-linux": "sha256-uduwrM143NDSc+tXsi4lVVfoMll2a3BDHRUjuO7GB68=",
"aarch64-linux": "sha256-6DUda78XdXY6DP86lIUkweSjys3iG4Y4mo1PiaNuXbg=",
"aarch64-darwin": "sha256-AkJwfLULLZVwwz+XU1QcFUZoIS7oVPCn+n/MXEaxrqE=",
"x86_64-darwin": "sha256-hAxKGdiITTxQ2uujQt6prNjo3NxGAMMeo+9HlMWK6GU="
}
}
+1 -2
View File
@@ -159,7 +159,6 @@
"@modelcontextprotocol/sdk@1.29.0": "patches/@modelcontextprotocol%2Fsdk@1.29.0.patch",
"effect@4.0.0-beta.83": "patches/effect@4.0.0-beta.83.patch",
"@tanstack/virtual-core@3.17.3": "patches/@tanstack%2Fvirtual-core@3.17.3.patch",
"@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/openai-compatible@2.0.41": "patches/@ai-sdk%2Fopenai-compatible@2.0.41.patch"
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/app",
"version": "1.18.18",
"version": "1.18.17",
"description": "",
"type": "module",
"exports": {
@@ -145,7 +145,7 @@ function ServerForm(props: ServerFormProps) {
type="text"
label={language.t("dialog.server.add.name")}
placeholder={language.t("dialog.server.add.namePlaceholder")}
defaultValue={props.name}
value={props.name}
disabled={props.busy}
onChange={props.onNameChange}
onKeyDown={keyDown}
@@ -155,7 +155,7 @@ function ServerForm(props: ServerFormProps) {
type="text"
label={language.t("dialog.server.add.username")}
placeholder={language.t("dialog.server.add.usernamePlaceholder")}
defaultValue={props.username}
value={props.username}
disabled={props.busy}
onChange={props.onUsernameChange}
onKeyDown={keyDown}
@@ -164,7 +164,7 @@ function ServerForm(props: ServerFormProps) {
type="password"
label={language.t("dialog.server.add.password")}
placeholder={language.t("dialog.server.add.passwordPlaceholder")}
defaultValue={props.password}
value={props.password}
disabled={props.busy}
onChange={props.onPasswordChange}
onKeyDown={keyDown}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/cli",
"version": "1.18.18",
"version": "1.18.17",
"type": "module",
"license": "MIT",
"bin": {
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/codemode",
"version": "1.18.18",
"version": "1.18.17",
"description": "Effect-native confined code execution over schema-described tools",
"private": true,
"type": "module",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-app",
"version": "1.18.18",
"version": "1.18.17",
"type": "module",
"license": "MIT",
"scripts": {
+1 -6
View File
@@ -252,6 +252,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "الاستثناءات التالية",
"go.title": "OpenCode Go | نماذج برمجة منخفضة التكلفة للجميع",
"go.banner.text": "يحصل DeepSeek V4 Flash على حدود استخدام مضاعفة لفترة محدودة",
"go.meta.description":
"يبدأ Go بسعر $5 للشهر الأول، ثم $10/شهر، مع حدود استخدام سخية ووصول موثوق إلى نماذج البرمجة الرائدة.",
"go.hero.title": "نماذج برمجة منخفضة التكلفة للجميع",
@@ -341,13 +342,10 @@ export const dict = {
"go.faq.a5.used": "مستخدَمة",
"go.faq.a5.notUsed": "غير مستخدَمة",
"go.faq.a5.noAgreement": "لا توجد اتفاقية",
"go.faq.a5.notZdr": "ليست ZDR",
"go.faq.a5.grokRetention":
"تعطّل ZDR ميزات API مهمة تعتمد على البيانات المخزنة، بما في ذلك Responses API ذات الحالة، وFiles and Collections، وBatch API.",
"go.faq.a5.gptRetention":
"تُنشأ سجلات مراقبة إساءة الاستخدام لكل استخدام لميزات API، ويُحتفظ بها لمدة تصل إلى 30 يومًا.",
"go.faq.a5.museRetention":
"أسعار توكنات مخفّضة للغاية مقابل منح الإذن باستخدام مطالباتك وإكمالات النموذج لتدريب نماذج Meta المستقبلية.",
"go.faq.a5.learnMore": "اعرف المزيد",
"go.faq.a5.deepseekRetention": "تُجدَّد اتفاقية ZDR شهريًا. الاتفاقية الحالية سارية حتى 31 أغسطس 2026.",
"go.faq.a5.beforeExceptions":
@@ -388,9 +386,6 @@ export const dict = {
"zen.api.error.modelDisabled": "النموذج معطل",
"zen.api.error.regionNotAllowed":
"لا يتوفر أحدث إصدار من هذا النموذج إلا مستضافًا في الصين، ويتطلب تفعيلًا صريحًا: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "هذا النموذج غير متاح في بلدك.",
"zen.api.error.trainingNotAllowed":
"يجمع هذا النموذج بيانات تُستخدم لتحسين جودته، ويتطلب موافقتك الصريحة: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"انتهى العرض المجاني لـ {{model}}. يمكنك مواصلة استخدام النموذج بالاشتراك في OpenCode Go - {{link}}",
+1 -6
View File
@@ -256,6 +256,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "seguintes exceções",
"go.title": "OpenCode Go | Modelos de codificação de baixo custo para todos",
"go.banner.text": "DeepSeek V4 Flash tem limites de uso 2x maiores por tempo limitado",
"go.meta.description":
"O Go começa em $5 no primeiro mês, depois $10/mês, com limites generosos de uso e acesso confiável aos principais modelos de codificação.",
"go.hero.title": "Modelos de codificação de baixo custo para todos",
@@ -348,13 +349,10 @@ export const dict = {
"go.faq.a5.used": "Usado",
"go.faq.a5.notUsed": "Não usado",
"go.faq.a5.noAgreement": "Sem acordo",
"go.faq.a5.notZdr": "Não é ZDR",
"go.faq.a5.grokRetention":
"O ZDR desativa recursos importantes da API que dependem de dados armazenados, incluindo a Responses API com estado, Files and Collections e a Batch API.",
"go.faq.a5.gptRetention":
"Logs de monitoramento de abuso são gerados para todo uso de recursos da API e retidos por até 30 dias.",
"go.faq.a5.museRetention":
"Preços de tokens com grandes descontos em troca da permissão para usar seus prompts e respostas geradas para treinar futuros modelos da Meta.",
"go.faq.a5.learnMore": "Saiba mais",
"go.faq.a5.deepseekRetention":
"O acordo de ZDR é renovado mensalmente. O acordo atual é válido até 31 de agosto de 2026.",
@@ -397,9 +395,6 @@ export const dict = {
"zen.api.error.modelDisabled": "O modelo está desabilitado",
"zen.api.error.regionNotAllowed":
"A versão mais recente deste modelo está disponível apenas com hospedagem na China e requer adesão explícita: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "Este modelo não está disponível no seu país.",
"zen.api.error.trainingNotAllowed":
"Este modelo coleta dados usados para melhorar sua qualidade e exige seu consentimento explícito: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"A promoção gratuita do {{model}} terminou. Você pode continuar usando o modelo assinando o OpenCode Go - {{link}}",
+1 -6
View File
@@ -254,6 +254,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "følgende undtagelser",
"go.title": "OpenCode Go | Kodningsmodeller til lav pris for alle",
"go.banner.text": "DeepSeek V4 Flash får fordoblet brugsgrænse i en begrænset periode",
"go.meta.description":
"Go starter ved $5 for den første måned, derefter $10/måned, med generøse brugsgrænser og pålidelig adgang til førende kodningsmodeller.",
"go.hero.title": "Kodningsmodeller til lav pris for alle",
@@ -345,13 +346,10 @@ export const dict = {
"go.faq.a5.used": "Brugt",
"go.faq.a5.notUsed": "Ikke brugt",
"go.faq.a5.noAgreement": "Ingen aftale",
"go.faq.a5.notZdr": "Ikke ZDR",
"go.faq.a5.grokRetention":
"ZDR deaktiverer vigtige API-funktioner, der afhænger af lagrede data, herunder den tilstandsbevarende Responses API, Files and Collections og Batch API.",
"go.faq.a5.gptRetention":
"Logfiler til overvågning af misbrug genereres ved al brug af API-funktioner og opbevares i op til 30 dage.",
"go.faq.a5.museRetention":
"Kraftigt nedsatte tokenpriser til gengæld for tilladelse til at bruge dine prompts og modelsvar til at træne fremtidige Meta-modeller.",
"go.faq.a5.learnMore": "Læs mere",
"go.faq.a5.deepseekRetention":
"ZDR-aftalen fornyes månedligt. Den nuværende aftale er gyldig til og med 31. august 2026.",
@@ -394,9 +392,6 @@ export const dict = {
"zen.api.error.modelDisabled": "Modellen er deaktiveret",
"zen.api.error.regionNotAllowed":
"Den nyeste version af denne model er kun tilgængelig som hostet i Kina og kræver, at du aktivt tilvælger den: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "Denne model er ikke tilgængelig i dit land.",
"zen.api.error.trainingNotAllowed":
"Denne model indsamler data, der bruges til at forbedre dens kvalitet, og kræver, at du aktivt tilvælger den: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"Den gratis kampagne for {{model}} er afsluttet. Du kan fortsætte med at bruge modellen ved at abonnere på OpenCode Go - {{link}}",
+1 -6
View File
@@ -256,6 +256,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "folgenden Ausnahmen",
"go.title": "OpenCode Go | Kostengünstige Coding-Modelle für alle",
"go.banner.text": "DeepSeek V4 Flash erhält für begrenzte Zeit 2x Nutzungslimits",
"go.meta.description":
"Go beginnt bei $5 für deinen ersten Monat, danach $10/Monat, mit großzügigen Nutzungslimits und zuverlässigem Zugang zu führenden Coding-Modellen.",
"go.hero.title": "Kostengünstige Coding-Modelle für alle",
@@ -347,13 +348,10 @@ export const dict = {
"go.faq.a5.used": "Verwendet",
"go.faq.a5.notUsed": "Nicht verwendet",
"go.faq.a5.noAgreement": "Keine Vereinbarung",
"go.faq.a5.notZdr": "Kein ZDR",
"go.faq.a5.grokRetention":
"ZDR deaktiviert wichtige API-Funktionen, die von gespeicherten Daten abhängen, einschließlich der zustandsbehafteten Responses API, Files and Collections und der Batch API.",
"go.faq.a5.gptRetention":
"Für die Nutzung aller API-Funktionen werden Protokolle zur Missbrauchsüberwachung erstellt und bis zu 30 Tage lang aufbewahrt.",
"go.faq.a5.museRetention":
"Stark vergünstigte Tokenpreise im Gegenzug für die Erlaubnis, deine Prompts und Vervollständigungen zum Trainieren zukünftiger Meta-Modelle zu verwenden.",
"go.faq.a5.learnMore": "Mehr erfahren",
"go.faq.a5.deepseekRetention":
"Die ZDR-Vereinbarung wird monatlich erneuert. Die aktuelle Vereinbarung gilt bis einschließlich 31. August 2026.",
@@ -396,9 +394,6 @@ export const dict = {
"zen.api.error.modelDisabled": "Modell ist deaktiviert",
"zen.api.error.regionNotAllowed":
"Die neueste Version dieses Modells ist nur verfügbar, wenn sie in China gehostet wird, und muss ausdrücklich aktiviert werden: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "Dieses Modell ist in deinem Land nicht verfügbar.",
"zen.api.error.trainingNotAllowed":
"Dieses Modell erfasst Daten, die zur Verbesserung seiner Qualität verwendet werden, und erfordert deine ausdrückliche Zustimmung: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"Die kostenlose Aktion für {{model}} ist beendet. Du kannst das Modell weiterhin nutzen, indem du OpenCode Go abonnierst - {{link}}",
+2 -8
View File
@@ -253,6 +253,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "following exceptions",
"go.title": "OpenCode Go | Low cost coding models for everyone",
"go.banner.text": "DeepSeek V4 Flash gets 2× usage limits for a limited time",
"go.meta.description":
"Go starts at $5 for your first month, then $10/month, with generous usage limits and reliable access to leading coding models.",
"go.hero.title": "Low cost coding models for everyone",
@@ -343,13 +344,10 @@ export const dict = {
"go.faq.a5.used": "Used",
"go.faq.a5.notUsed": "Not used",
"go.faq.a5.noAgreement": "No agreement",
"go.faq.a5.notZdr": "Not ZDR",
"go.faq.a5.grokRetention":
"ZDR disables important API features that depend on stored data, including the stateful Responses API, Files and Collections, and the Batch API.",
"go.faq.a5.gptRetention":
"Abuse monitoring logs are generated for all API feature usage and retained for up to 30 days.",
"go.faq.a5.museRetention":
"Heavily discounted token pricing in exchange for permission to use your prompts and completions to train future Meta models.",
"go.faq.a5.deepseekRetention":
"ZDR agreement is renewed monthly. The current agreement is valid through August 31, 2026.",
"go.faq.a5.learnMore": "Learn more",
@@ -393,9 +391,6 @@ export const dict = {
"zen.api.error.modelDisabled": "Model is disabled",
"zen.api.error.regionNotAllowed":
"The latest version of this model is only available hosted in China and requires explicit opt in: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "This model is not available in your country.",
"zen.api.error.trainingNotAllowed":
"This model collects data used to improve its quality and requires explicit opt in: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"Free promotion has ended for {{model}}. You can continue using the model by subscribing to OpenCode Go - {{link}}",
@@ -677,8 +672,7 @@ export const dict = {
'Select "OpenCode Go" as the provider in your opencode configuration to use Go models.',
"workspace.lite.providers.title": "Providers",
"workspace.lite.providers.description": "Control which providers are used for routing.",
"workspace.lite.providers.allowTraining": "Allow models that train on request data",
"workspace.lite.providers.useChina": "Allow models hosted in China",
"workspace.lite.providers.useChina": "Enable models hosted in China",
"workspace.lite.black.message":
"You're currently subscribed to OpenCode Black or on the waitlist. Please unsubscribe first if you'd like to switch to Go.",
"workspace.lite.other.message":
+1 -6
View File
@@ -257,6 +257,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "siguientes excepciones",
"go.title": "OpenCode Go | Modelos de programación de bajo coste para todos",
"go.banner.text": "DeepSeek V4 Flash tiene límites de uso 2x mayores por tiempo limitado",
"go.meta.description":
"Go comienza en $5 el primer mes, luego 10 $/mes, con límites de uso generosos y acceso fiable a modelos de programación líderes.",
"go.hero.title": "Modelos de programación de bajo coste para todos",
@@ -348,13 +349,10 @@ export const dict = {
"go.faq.a5.used": "Utilizado",
"go.faq.a5.notUsed": "No utilizado",
"go.faq.a5.noAgreement": "Sin acuerdo",
"go.faq.a5.notZdr": "Sin ZDR",
"go.faq.a5.grokRetention":
"ZDR deshabilita funciones importantes de la API que dependen de datos almacenados, incluidas la Responses API con estado, Files and Collections y la Batch API.",
"go.faq.a5.gptRetention":
"Se generan registros de supervisión de abusos para todo el uso de funciones de la API y se conservan durante un máximo de 30 días.",
"go.faq.a5.museRetention":
"Precios de tokens muy reducidos a cambio de permitir que tus prompts y las respuestas generadas se utilicen para entrenar futuros modelos de Meta.",
"go.faq.a5.learnMore": "Más información",
"go.faq.a5.deepseekRetention":
"El acuerdo de ZDR se renueva mensualmente. El acuerdo actual es válido hasta el 31 de agosto de 2026.",
@@ -397,9 +395,6 @@ export const dict = {
"zen.api.error.modelDisabled": "El modelo está deshabilitado",
"zen.api.error.regionNotAllowed":
"La versión más reciente de este modelo solo está disponible alojada en China y requiere una aceptación explícita: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "Este modelo no está disponible en tu país.",
"zen.api.error.trainingNotAllowed":
"Este modelo recopila datos que se utilizan para mejorar su calidad y requiere tu consentimiento explícito: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"La promoción gratuita de {{model}} ha finalizado. Puedes seguir usando el modelo suscribiéndote a OpenCode Go - {{link}}",
+1 -6
View File
@@ -258,6 +258,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "exceptions suivantes",
"go.title": "OpenCode Go | Modèles de code à faible coût pour tous",
"go.banner.text": "DeepSeek V4 Flash bénéficie de limites dutilisation 2x supérieures pour une durée limitée",
"go.meta.description":
"Go commence à $5 pour le premier mois, puis 10 $/mois, avec des limites d'utilisation généreuses et un accès fiable aux principaux modèles de codage.",
"go.hero.title": "Modèles de code à faible coût pour tous",
@@ -349,13 +350,10 @@ export const dict = {
"go.faq.a5.used": "Utilisé",
"go.faq.a5.notUsed": "Non utilisé",
"go.faq.a5.noAgreement": "Aucun accord",
"go.faq.a5.notZdr": "Pas de ZDR",
"go.faq.a5.grokRetention":
"Le ZDR désactive d'importantes fonctionnalités API qui dépendent des données stockées, notamment Responses API avec état, Files and Collections et Batch API.",
"go.faq.a5.gptRetention":
"Des journaux de surveillance des abus sont générés pour toute utilisation des fonctionnalités API et conservés pendant un maximum de 30 jours.",
"go.faq.a5.museRetention":
"Des tarifs de tokens fortement réduits en échange de lautorisation dutiliser vos prompts et vos complétions pour entraîner de futurs modèles Meta.",
"go.faq.a5.learnMore": "En savoir plus",
"go.faq.a5.deepseekRetention":
"Laccord ZDR est renouvelé chaque mois. Laccord actuel est valable jusquau 31 août 2026.",
@@ -398,9 +396,6 @@ export const dict = {
"zen.api.error.modelDisabled": "Le modèle est désactivé",
"zen.api.error.regionNotAllowed":
"La dernière version de ce modèle est uniquement disponible avec un hébergement en Chine et nécessite votre consentement explicite : {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "Ce modèle nest pas disponible dans votre pays.",
"zen.api.error.trainingNotAllowed":
"Ce modèle collecte des données utilisées pour améliorer sa qualité et nécessite votre consentement explicite : {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"La promotion gratuite de {{model}} est terminée. Vous pouvez continuer à utiliser le modèle en vous abonnant à OpenCode Go - {{link}}",
+1 -6
View File
@@ -254,6 +254,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "seguenti eccezioni",
"go.title": "OpenCode Go | Modelli di coding a basso costo per tutti",
"go.banner.text": "DeepSeek V4 Flash offre limiti di utilizzo 2x superiori per un periodo limitato",
"go.meta.description":
"Go inizia a $5 per il primo mese, poi $10/mese, con limiti di utilizzo generosi e un accesso affidabile ai principali modelli di coding.",
"go.hero.title": "Modelli di coding a basso costo per tutti",
@@ -344,7 +345,6 @@ export const dict = {
"go.faq.a5.used": "Utilizzato",
"go.faq.a5.notUsed": "Non utilizzato",
"go.faq.a5.noAgreement": "Nessun accordo",
"go.faq.a5.notZdr": "Non ZDR",
"go.faq.a5.grokRetention":
"ZDR disabilita importanti funzionalità API che dipendono dai dati archiviati, tra cui la Responses API con stato, Files and Collections e Batch API.",
"go.faq.a5.gptRetention":
@@ -352,8 +352,6 @@ export const dict = {
"go.faq.a5.learnMore": "Scopri di più",
"go.faq.a5.deepseekRetention":
"L'accordo ZDR viene rinnovato mensilmente. L'accordo attuale è valido fino al 31 agosto 2026.",
"go.faq.a5.museRetention":
"Prezzi dei token fortemente scontati in cambio dell'autorizzazione a utilizzare i tuoi prompt e completamenti per addestrare futuri modelli Meta.",
"go.faq.a5.beforeExceptions":
"I modelli Go sono ospitati negli Stati Uniti. I provider seguono una policy di zero-retention e non usano i tuoi dati per l'addestramento dei modelli, con le",
"go.faq.a5.exceptionsLink": "seguenti eccezioni",
@@ -393,9 +391,6 @@ export const dict = {
"zen.api.error.modelDisabled": "Il modello è disabilitato",
"zen.api.error.regionNotAllowed":
"La versione più recente di questo modello è disponibile solo con hosting in Cina e richiede un consenso esplicito: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "Questo modello non è disponibile nel tuo paese.",
"zen.api.error.trainingNotAllowed":
"Questo modello raccoglie dati utilizzati per migliorarne la qualità e richiede il tuo consenso esplicito: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"La promozione gratuita di {{model}} è terminata. Puoi continuare a usare il modello abbonandoti a OpenCode Go - {{link}}",
+1 -6
View File
@@ -253,6 +253,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "以下の例外",
"go.title": "OpenCode Go | すべての人のための低価格なコーディングモデル",
"go.banner.text": "DeepSeek V4 Flashの利用上限が期間限定で2倍に",
"go.meta.description":
"Goは最初の月$5、その後$10/月で、主要なコーディングモデルへのゆとりある利用上限と安定したアクセスを提供します。",
"go.hero.title": "すべての人のための低価格なコーディングモデル",
@@ -344,12 +345,9 @@ export const dict = {
"go.faq.a5.used": "使用あり",
"go.faq.a5.notUsed": "使用なし",
"go.faq.a5.noAgreement": "契約なし",
"go.faq.a5.notZdr": "ZDRではない",
"go.faq.a5.grokRetention":
"ZDRでは、保存データに依存する重要なAPI機能(ステートフルなResponses API、Files and Collections、Batch APIなど)が無効になります。",
"go.faq.a5.gptRetention": "不正使用監視ログはすべてのAPI機能の使用時に生成され、最大30日間保持されます。",
"go.faq.a5.museRetention":
"将来のMetaモデルのトレーニングにプロンプトと生成結果を使用する許可と引き換えに、トークン料金が大幅に割引されます。",
"go.faq.a5.learnMore": "詳しく見る",
"go.faq.a5.deepseekRetention": "ZDR契約は毎月更新されます。現在の契約は2026年8月31日まで有効です。",
"go.faq.a5.beforeExceptions":
@@ -392,9 +390,6 @@ export const dict = {
"zen.api.error.modelDisabled": "モデルが無効です",
"zen.api.error.regionNotAllowed":
"このモデルの最新バージョンは中国でのみホスト提供されており、利用するには明示的なオプトインが必要です: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "このモデルはお住まいの国では利用できません。",
"zen.api.error.trainingNotAllowed":
"このモデルは品質向上のためのデータを収集します。利用するには明示的な同意が必要です: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"{{model}} の無料プロモーションは終了しました。OpenCode Go を購読するとモデルを引き続き使用できます - {{link}}",
+1 -6
View File
@@ -250,6 +250,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "다음 예외",
"go.title": "OpenCode Go | 모두를 위한 저비용 코딩 모델",
"go.banner.text": "DeepSeek V4 Flash 사용 한도가 한시적으로 2배 확대됩니다",
"go.meta.description":
"Go는 첫 달 $5, 이후 $10/월로 시작하며, 넉넉한 사용 한도와 주요 코딩 모델에 대한 안정적인 액세스를 제공합니다.",
"go.hero.title": "모두를 위한 저비용 코딩 모델",
@@ -340,12 +341,9 @@ export const dict = {
"go.faq.a5.used": "사용됨",
"go.faq.a5.notUsed": "사용되지 않음",
"go.faq.a5.noAgreement": "합의 없음",
"go.faq.a5.notZdr": "ZDR 아님",
"go.faq.a5.grokRetention":
"ZDR은 저장된 데이터에 의존하는 중요한 API 기능(상태 저장형 Responses API, Files and Collections, Batch API 포함)을 비활성화합니다.",
"go.faq.a5.gptRetention": "모든 API 기능 사용에 대해 악용 모니터링 로그가 생성되며 최대 30일 동안 보존됩니다.",
"go.faq.a5.museRetention":
"향후 Meta 모델 학습에 사용자의 프롬프트와 생성 결과를 사용할 수 있도록 허용하는 대신 토큰 가격이 대폭 할인됩니다.",
"go.faq.a5.learnMore": "자세히 알아보기",
"go.faq.a5.deepseekRetention": "ZDR 계약은 매월 갱신됩니다. 현재 계약은 2026년 8월 31일까지 유효합니다.",
"go.faq.a5.beforeExceptions":
@@ -386,9 +384,6 @@ export const dict = {
"zen.api.error.modelDisabled": "모델이 비활성화되었습니다",
"zen.api.error.regionNotAllowed":
"이 모델의 최신 버전은 중국에서 호스팅되는 경우에만 사용할 수 있으며, 명시적으로 사용에 동의해야 합니다: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "이 모델은 거주 국가에서 사용할 수 없습니다.",
"zen.api.error.trainingNotAllowed":
"이 모델은 품질 개선에 사용되는 데이터를 수집하며, 사용하려면 명시적으로 동의해야 합니다: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"{{model}}의 무료 프로모션이 종료되었습니다. OpenCode Go를 구독하면 모델을 계속 사용할 수 있습니다 - {{link}}",
+1 -6
View File
@@ -254,6 +254,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "følgende unntak",
"go.title": "OpenCode Go | Rimelige kodemodeller for alle",
"go.banner.text": "DeepSeek V4 Flash får 2x bruksgrense i en begrenset periode",
"go.meta.description":
"Go starter på $5 for den første måneden, deretter $10/måned, med sjenerøse bruksgrenser og pålitelig tilgang til ledende kodemodeller.",
"go.hero.title": "Rimelige kodemodeller for alle",
@@ -345,7 +346,6 @@ export const dict = {
"go.faq.a5.used": "Brukes",
"go.faq.a5.notUsed": "Brukes ikke",
"go.faq.a5.noAgreement": "Ingen avtale",
"go.faq.a5.notZdr": "Ikke ZDR",
"go.faq.a5.grokRetention":
"ZDR deaktiverer viktige API-funksjoner som er avhengige av lagrede data, inkludert den tilstandsbaserte Responses API, Files and Collections og Batch API.",
"go.faq.a5.gptRetention":
@@ -353,8 +353,6 @@ export const dict = {
"go.faq.a5.learnMore": "Les mer",
"go.faq.a5.deepseekRetention":
"ZDR-avtalen fornyes månedlig. Den gjeldende avtalen er gyldig til og med 31. august 2026.",
"go.faq.a5.museRetention":
"Kraftig rabatterte tokenpriser i bytte mot tillatelse til å bruke ledetekstene og fullføringene dine til å trene fremtidige Meta-modeller.",
"go.faq.a5.beforeExceptions":
"Go-modeller hostes i USA. Leverandører følger en policy om null oppbevaring og bruker ikke dataene dine til modelltrening, med",
@@ -395,9 +393,6 @@ export const dict = {
"zen.api.error.modelDisabled": "Modellen er deaktivert",
"zen.api.error.regionNotAllowed":
"Den nyeste versjonen av denne modellen er bare tilgjengelig som en tjeneste driftet i Kina og krever at du uttrykkelig samtykker: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "Denne modellen er ikke tilgjengelig i landet ditt.",
"zen.api.error.trainingNotAllowed":
"Denne modellen samler inn data som brukes til å forbedre modellens kvalitet, og krever at du uttrykkelig samtykker: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"Den gratis kampanjen for {{model}} er avsluttet. Du kan fortsette å bruke modellen ved å abonnere på OpenCode Go - {{link}}",
+1 -6
View File
@@ -255,6 +255,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "następującymi wyjątkami",
"go.title": "OpenCode Go | Niskokosztowe modele do kodowania dla każdego",
"go.banner.text": "DeepSeek V4 Flash oferuje 2x wyższe limity użycia przez ograniczony czas",
"go.meta.description":
"Go kosztuje $5 za pierwszy miesiąc, a następnie $10/miesiąc, oferując hojne limity użycia i niezawodny dostęp do wiodących modeli do kodowania.",
"go.hero.title": "Niskokosztowe modele do kodowania dla każdego",
@@ -346,15 +347,12 @@ export const dict = {
"go.faq.a5.used": "Wykorzystywane",
"go.faq.a5.notUsed": "Niewykorzystywane",
"go.faq.a5.noAgreement": "Brak umowy",
"go.faq.a5.notZdr": "Nie ZDR",
"go.faq.a5.grokRetention":
"ZDR wyłącza ważne funkcje API zależne od przechowywanych danych, w tym stanowy Responses API, Files and Collections oraz Batch API.",
"go.faq.a5.gptRetention":
"Dzienniki monitorowania nadużyć są generowane dla każdego użycia funkcji API i przechowywane przez maksymalnie 30 dni.",
"go.faq.a5.learnMore": "Dowiedz się więcej",
"go.faq.a5.deepseekRetention": "Umowa ZDR jest odnawiana co miesiąc. Obecna umowa obowiązuje do 31 sierpnia 2026 r.",
"go.faq.a5.museRetention":
"Znacznie obniżone ceny tokenów w zamian za zgodę na wykorzystanie Twoich promptów i odpowiedzi do trenowania przyszłych modeli Meta.",
"go.faq.a5.beforeExceptions":
"Modele Go są hostowane w USA. Dostawcy stosują politykę zerowej retencji i nie używają Twoich danych do trenowania modeli, z",
@@ -395,9 +393,6 @@ export const dict = {
"zen.api.error.modelDisabled": "Model jest wyłączony",
"zen.api.error.regionNotAllowed":
"Najnowsza wersja tego modelu jest dostępna wyłącznie jako usługa hostowana w Chinach i wymaga jawnej zgody użytkownika: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "Ten model nie jest dostępny w Twoim kraju.",
"zen.api.error.trainingNotAllowed":
"Ten model zbiera dane wykorzystywane do poprawy jego jakości i wymaga wyraźnej zgody użytkownika: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"Bezpłatna promocja {{model}} dobiegła końca. Możesz dalej korzystać z modelu, subskrybując OpenCode Go - {{link}}",
+1 -6
View File
@@ -258,6 +258,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "следующими исключениями",
"go.title": "OpenCode Go | Недорогие модели для кодинга для всех",
"go.banner.text": "DeepSeek V4 Flash получает 2x лимиты использования на ограниченное время",
"go.meta.description":
"Go стоит $5 за первый месяц, затем $10/месяц и предлагает щедрые лимиты использования и надежный доступ к ведущим моделям для кодинга.",
"go.hero.title": "Недорогие модели для кодинга для всех",
@@ -350,7 +351,6 @@ export const dict = {
"go.faq.a5.used": "Используется",
"go.faq.a5.notUsed": "Не используется",
"go.faq.a5.noAgreement": "Нет соглашения",
"go.faq.a5.notZdr": "Не ZDR",
"go.faq.a5.grokRetention":
"ZDR отключает важные функции API, зависящие от сохраненных данных, включая Responses API с сохранением состояния, Files and Collections и Batch API.",
"go.faq.a5.gptRetention":
@@ -358,8 +358,6 @@ export const dict = {
"go.faq.a5.learnMore": "Подробнее",
"go.faq.a5.deepseekRetention":
"Соглашение ZDR продлевается ежемесячно. Текущее соглашение действует до 31 августа 2026 года.",
"go.faq.a5.museRetention":
"Значительно сниженная стоимость токенов в обмен на разрешение использовать ваши промпты и ответы для обучения будущих моделей Meta.",
"go.faq.a5.beforeExceptions":
"Модели Go размещены в США. Провайдеры следуют политике нулевого хранения и не используют ваши данные для обучения моделей, за",
@@ -400,9 +398,6 @@ export const dict = {
"zen.api.error.modelDisabled": "Модель отключена",
"zen.api.error.regionNotAllowed":
"Последняя версия этой модели размещена только в Китае. Чтобы использовать её, необходимо явно подтвердить согласие: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "Эта модель недоступна в вашей стране.",
"zen.api.error.trainingNotAllowed":
"Эта модель собирает данные, которые используются для улучшения её качества, и требует явного согласия: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"Бесплатная акция для {{model}} завершена. Вы можете продолжить использование модели, подписавшись на OpenCode Go - {{link}}",
+1 -6
View File
@@ -253,6 +253,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "ข้อยกเว้นดังนี้",
"go.title": "OpenCode Go | โมเดลเขียนโค้ดราคาประหยัดสำหรับทุกคน",
"go.banner.text": "DeepSeek V4 Flash เพิ่มโควตาการใช้งานเป็น 2 เท่าในช่วงเวลาจำกัด",
"go.meta.description":
"Go เริ่มต้นที่ $5 สำหรับเดือนแรก จากนั้น $10/เดือน พร้อมขีดจำกัดการใช้งานที่เอื้อเฟื้อและการเข้าถึงโมเดลเขียนโค้ดชั้นนำอย่างเชื่อถือได้",
"go.hero.title": "โมเดลเขียนโค้ดราคาประหยัดสำหรับทุกคน",
@@ -342,13 +343,10 @@ export const dict = {
"go.faq.a5.used": "นำไปใช้",
"go.faq.a5.notUsed": "ไม่นำไปใช้",
"go.faq.a5.noAgreement": "ไม่มีข้อตกลง",
"go.faq.a5.notZdr": "ไม่ใช่ ZDR",
"go.faq.a5.grokRetention":
"ZDR ปิดใช้งานฟีเจอร์ API สำคัญที่ต้องอาศัยข้อมูลที่จัดเก็บไว้ ซึ่งรวมถึง Responses API แบบมีสถานะ, Files and Collections และ Batch API",
"go.faq.a5.gptRetention":
"ระบบจะสร้างบันทึกการตรวจสอบการใช้งานในทางที่ผิดสำหรับการใช้งานฟีเจอร์ API ทั้งหมด และเก็บรักษาไว้นานสูงสุด 30 วัน",
"go.faq.a5.museRetention":
"ราคาของ token ลดลงอย่างมาก โดยแลกกับการอนุญาตให้นำพรอมต์และผลลัพธ์ที่สร้างขึ้นของคุณไปใช้ฝึกโมเดล Meta ในอนาคต",
"go.faq.a5.learnMore": "ดูข้อมูลเพิ่มเติม",
"go.faq.a5.deepseekRetention": "ข้อตกลง ZDR จะต่ออายุทุกเดือน ข้อตกลงปัจจุบันมีผลใช้ถึงวันที่ 31 สิงหาคม 2026",
@@ -390,9 +388,6 @@ export const dict = {
"zen.api.error.modelDisabled": "โมเดลถูกปิดใช้งาน",
"zen.api.error.regionNotAllowed":
"โมเดลเวอร์ชันล่าสุดนี้ให้บริการเฉพาะผ่านระบบที่โฮสต์ในประเทศจีน และต้องให้ความยินยอมอย่างชัดแจ้งก่อนใช้งาน: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "โมเดลนี้ไม่พร้อมให้บริการในประเทศของคุณ",
"zen.api.error.trainingNotAllowed":
"โมเดลนี้เก็บรวบรวมข้อมูลที่ใช้เพื่อปรับปรุงคุณภาพของโมเดล และต้องได้รับความยินยอมอย่างชัดแจ้งก่อนใช้งาน: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"โปรโมชันฟรีสำหรับ {{model}} สิ้นสุดแล้ว คุณสามารถใช้โมเดลต่อได้โดยสมัครสมาชิก OpenCode Go - {{link}}",
+1 -6
View File
@@ -256,6 +256,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "aşağıdaki istisnalar",
"go.title": "OpenCode Go | Herkes için düşük maliyetli kodlama modelleri",
"go.banner.text": "DeepSeek V4 Flash sınırlı bir süre için 2x kullanım limiti sunuyor",
"go.meta.description":
"Go ilk ay $5, sonrasında ayda 10$ fiyatıyla başlar; cömert kullanım limitleri ve önde gelen kodlama modellerine güvenilir erişim sunar.",
"go.hero.title": "Herkes için düşük maliyetli kodlama modelleri",
@@ -348,7 +349,6 @@ export const dict = {
"go.faq.a5.used": "Kullanılır",
"go.faq.a5.notUsed": "Kullanılmaz",
"go.faq.a5.noAgreement": "Anlaşma yok",
"go.faq.a5.notZdr": "ZDR değil",
"go.faq.a5.grokRetention":
"ZDR, durum bilgisi tutan Responses API, Files and Collections ve Batch API dahil olmak üzere saklanan verilere bağlı önemli API özelliklerini devre dışı bırakır.",
"go.faq.a5.gptRetention":
@@ -356,8 +356,6 @@ export const dict = {
"go.faq.a5.learnMore": "Daha fazla bilgi",
"go.faq.a5.deepseekRetention":
"ZDR anlaşması aylık olarak yenilenir. Mevcut anlaşma 31 Ağustos 2026 tarihine kadar geçerlidir.",
"go.faq.a5.museRetention":
"İstemlerinizi ve tamamlamalarınızı gelecekteki Meta modellerini eğitmek için kullanma izni karşılığında büyük ölçüde indirimli token fiyatları.",
"go.faq.a5.beforeExceptions":
"Go modelleri ABD'de barındırılmaktadır. Sağlayıcılar sıfır saklama politikası izler ve verilerinizi model eğitimi için kullanmaz; şu",
@@ -398,9 +396,6 @@ export const dict = {
"zen.api.error.modelDisabled": "Model devre dışı",
"zen.api.error.regionNotAllowed":
"Bu modelin en son sürümü yalnızca Çin'de barındırılıyor ve kullanabilmek için açıkça onay vermeniz gerekiyor: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "Bu model ülkenizde kullanılamıyor.",
"zen.api.error.trainingNotAllowed":
"Bu model, kalitesini artırmak için kullanılan verileri toplar. Modeli kullanabilmek için açıkça onay vermeniz gerekir: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"{{model}} için ücretsiz promosyon sona erdi. OpenCode Go'ya abone olarak modeli kullanmaya devam edebilirsiniz - {{link}}",
+1 -6
View File
@@ -255,6 +255,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "такими винятками",
"go.title": "OpenCode Go | Недорогі моделі кодування для всіх",
"go.banner.text": "DeepSeek V4 Flash отримує 2x ліміти використання протягом обмеженого часу",
"go.meta.description":
"Go починається від $5 за перший місяць, потім $10/місяць, зі щедрими лімітами використання та надійним доступом до провідних моделей для кодування.",
"go.hero.title": "Недорогі моделі кодування для всіх",
@@ -346,15 +347,12 @@ export const dict = {
"go.faq.a5.used": "Використовується",
"go.faq.a5.notUsed": "Не використовується",
"go.faq.a5.noAgreement": "Немає угоди",
"go.faq.a5.notZdr": "Не ZDR",
"go.faq.a5.grokRetention":
"ZDR вимикає важливі функції API, які залежать від збережених даних, зокрема Responses API зі збереженням стану, Files and Collections та Batch API.",
"go.faq.a5.gptRetention":
"Журнали моніторингу зловживань створюються для всіх випадків використання функцій API та зберігаються до 30 днів.",
"go.faq.a5.learnMore": "Докладніше",
"go.faq.a5.deepseekRetention": "Угода ZDR поновлюється щомісяця. Поточна угода дійсна до 31 серпня 2026 року.",
"go.faq.a5.museRetention":
"Значно знижені ціни на токени в обмін на дозвіл використовувати ваші промпти та відповіді для навчання майбутніх моделей Meta.",
"go.faq.a5.beforeExceptions":
"Моделі Go розміщені в США. Провайдери дотримуються політики нульового зберігання та не використовують ваші дані для навчання моделей, за",
@@ -394,9 +392,6 @@ export const dict = {
"zen.api.error.modelDisabled": "Модель вимкнено",
"zen.api.error.regionNotAllowed":
"Остання версія цієї моделі доступна лише на серверах у Китаї, і для її використання потрібно надати явну згоду: {{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "Ця модель недоступна у вашій країні.",
"zen.api.error.trainingNotAllowed":
"Ця модель збирає дані, які використовуються для покращення її якості; для її використання потрібна ваша явна згода: {{consoleGoUrl}}",
"zen.api.error.trialEnded":
"Безкоштовна акція для {{model}} закінчилася. Ви можете продовжити використання, підписавшись на OpenCode Go — {{link}}",
+1 -4
View File
@@ -244,6 +244,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "以下例外情况除外",
"go.title": "OpenCode Go | 人人可用的低成本编程模型",
"go.banner.text": "DeepSeek V4 Flash 限时享受 2 倍使用额度",
"go.meta.description": "Go 首月 $5,之后 $10/月,提供充裕的使用限额,并可可靠访问领先的编程模型。",
"go.hero.title": "人人可用的低成本编程模型",
"go.hero.body":
@@ -328,11 +329,9 @@ export const dict = {
"go.faq.a5.used": "使用",
"go.faq.a5.notUsed": "不使用",
"go.faq.a5.noAgreement": "无协议",
"go.faq.a5.notZdr": "非 ZDR",
"go.faq.a5.grokRetention":
"ZDR 会禁用依赖所存储数据的重要 API 功能,包括有状态的 Responses API、Files and Collections 和 Batch API。",
"go.faq.a5.gptRetention": "所有 API 功能的使用都会生成滥用监控日志,并最多保留 30 天。",
"go.faq.a5.museRetention": "以允许使用你的提示词和补全结果训练未来的 Meta 模型为交换,token 价格可获得大幅折扣。",
"go.faq.a5.learnMore": "了解更多",
"go.faq.a5.deepseekRetention": "ZDR 协议每月续签。当前协议有效期至 2026 年 8 月 31 日。",
"go.faq.a5.beforeExceptions": "Go 模型托管在美国。提供商遵循零留存政策,不使用您的数据进行模型训练,",
@@ -370,8 +369,6 @@ export const dict = {
"zen.api.error.userMonthlyLimitReached": "您已达到每月支出限额 ${{amount}}。请在此处管理您的限额:{{membersUrl}}",
"zen.api.error.modelDisabled": "模型已禁用",
"zen.api.error.regionNotAllowed": "该模型的最新版本仅在中国提供托管服务,需明确选择启用:{{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "该模型在你所在的国家或地区不可用。",
"zen.api.error.trainingNotAllowed": "该模型会收集用于提升其质量的数据,使用前需要你明确同意:{{consoleGoUrl}}",
"zen.api.error.trialEnded": "{{model}} 的限免活动已结束。您可以订阅 OpenCode Go 继续使用该模型 - {{link}}",
"black.meta.title": "OpenCode Black | 访问全球顶尖编程模型",
+1 -4
View File
@@ -244,6 +244,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "以下例外情況",
"go.title": "OpenCode Go | 低成本全民編碼模型",
"go.banner.text": "DeepSeek V4 Flash 限時享有 2 倍使用額度",
"go.meta.description": "Go 首月 $5,之後 $10/月,提供充裕的使用限額,並可穩定存取領先的編碼模型。",
"go.hero.title": "低成本全民編碼模型",
"go.hero.body":
@@ -328,11 +329,9 @@ export const dict = {
"go.faq.a5.used": "使用",
"go.faq.a5.notUsed": "不使用",
"go.faq.a5.noAgreement": "無協議",
"go.faq.a5.notZdr": "非 ZDR",
"go.faq.a5.grokRetention":
"ZDR 會停用依賴儲存資料的重要 API 功能,包括具狀態的 Responses API、Files and Collections 與 Batch API。",
"go.faq.a5.gptRetention": "所有 API 功能的使用都會產生濫用監控日誌,並保留最多 30 天。",
"go.faq.a5.museRetention": "以允許使用您的提示詞和生成結果來訓練未來的 Meta 模型為交換,token 價格可享大幅折扣。",
"go.faq.a5.learnMore": "了解更多",
"go.faq.a5.deepseekRetention": "ZDR 協議每月續簽。目前的協議有效至 2026 年 8 月 31 日。",
"go.faq.a5.beforeExceptions": "Go 模型託管在美國。供應商遵循零留存政策,不會將你的資料用於模型訓練,但有",
@@ -370,8 +369,6 @@ export const dict = {
"zen.api.error.userMonthlyLimitReached": "你已達到每月支出限額 ${{amount}}。請在此處管理你的限額:{{membersUrl}}",
"zen.api.error.modelDisabled": "模型已停用",
"zen.api.error.regionNotAllowed": "此模型的最新版本僅於中國託管,且需明確選擇啟用:{{consoleGoUrl}}",
"zen.api.error.countryNotAllowed": "此模型無法在你所在的國家或地區使用。",
"zen.api.error.trainingNotAllowed": "此模型會收集用於提升其品質的資料,使用前須經你明確同意:{{consoleGoUrl}}",
"zen.api.error.trialEnded": "{{model}} 的限免活动已結束。您可以訂閱 OpenCode Go 繼續使用該模型 - {{link}}",
"black.meta.title": "OpenCode Black | 存取全球最佳編碼模型",
@@ -1,74 +1,5 @@
const MUSE_SPARK_BLOCKED_COUNTRIES = new Set([
"AD",
"AF",
"AT",
"AU",
"BE",
"BG",
"BR",
"BY",
"CA",
"CH",
"CN",
"CU",
"CY",
"CZ",
"DE",
"DK",
"EE",
"EH",
"ER",
"ES",
"ET",
"FI",
"FR",
"GB",
"GR",
"HK",
"HR",
"HT",
"HU",
"IE",
"IQ",
"IR",
"IS",
"IT",
"KH",
"KP",
"KR",
"LI",
"LT",
"LU",
"LV",
"LY",
"MC",
"MM",
"MO",
"MT",
"NI",
"NL",
"NO",
"PK",
"PL",
"PT",
"RO",
"RU",
"SE",
"SI",
"SK",
"SM",
"SO",
"SY",
"VA",
"VE",
])
export function countryFromRequest(request: Request | undefined) {
if (!request) return undefined
const cloudflareRequest = request as Request & { cf?: { country?: string } }
return cloudflareRequest.cf?.country ?? request.headers.get("cf-ipcountry") ?? undefined
}
export function isModelCountryRestricted(model: string, country: string | undefined) {
return model === "muse-spark-1.2" && country !== undefined && MUSE_SPARK_BLOCKED_COUNTRIES.has(country.toUpperCase())
}
+17 -14
View File
@@ -25,7 +25,6 @@ const checkLoggedIn = query(async () => {
const models = [
{ name: "Grok 4.5", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention30" },
{ name: "GPT 5.6 Luna", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention30" },
{ name: "GLM-5.3", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
{ name: "GLM-5.2", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
{ name: "GLM-5.1", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
{ name: "Kimi K3", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
@@ -39,7 +38,6 @@ const models = [
{ name: "Qwen3.6 Plus", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
{ name: "MiniMax M3", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
{ name: "MiniMax M2.7", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
{ name: "Muse Spark 1.2", training: "go.faq.a5.used", retention: "go.faq.a5.notZdr" },
{ name: "DeepSeek V4 Pro", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
{ name: "DeepSeek V4 Flash", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
{ name: "Hy3", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
@@ -68,18 +66,24 @@ function LimitsGraph(props: { href: string }) {
const baseline = 100
const graph = [
{ id: "kimi-k3", name: "Kimi K3", req: 110, d: "50ms" },
{ id: "grok-4.5", name: "Grok 4.5", req: 120, d: "75ms" },
{ id: "grok-4.5", name: "Grok 4.5", req: 120, d: "50ms" },
{ id: "kimi-k3", name: "Kimi K3", req: 110, d: "75ms" },
{ id: "qwen3.8-max", name: "Qwen3.8 Max", req: 160, d: "90ms" },
{ id: "glm-5.2", name: "GLM-5.2", req: 880, d: "100ms" },
{ id: "deepseek-v4-pro", name: "DeepSeek V4 Pro", req: 1050, d: "150ms" },
{ id: "minimax-m3", name: "MiniMax M3", req: 3200, d: "210ms" },
{ id: "deepseek-v4-pro", name: "DeepSeek V4 Pro", req: 3450, d: "270ms" },
{ id: "gpt-5.6-luna", name: "GPT 5.6 Luna", req: 4100, baseReq: 2050, d: "290ms" },
{ id: "qwen3.7-plus", name: "Qwen3.7 Plus", req: 4300, d: "300ms" },
{ id: "hy3", name: "Hy3", req: 4300, d: "320ms" },
{ id: "deepseek-v4-flash", name: "DeepSeek V4 Flash", req: 7600, d: "330ms" },
{ id: "mimo-v2.5", name: "MiMo-V2.5", req: 30100, d: "340ms" },
{ id: "muse-spark-1.2", name: "Muse Spark 1.2", req: 45300, edge: true, d: "360ms" },
{
id: "deepseek-v4-flash",
name: "DeepSeek V4 Flash",
req: 63300,
baseReq: 31650,
edge: true,
d: "340ms",
},
]
const w = 1040
@@ -254,6 +258,12 @@ export default function Home() {
<div data-component="content">
<section data-component="hero">
<div data-component="desktop-app-banner">
<span data-slot="badge">{i18n.t("home.banner.badge")}</span>
<div data-slot="content">
<span data-slot="text">{i18n.t("go.banner.text")}</span>
</div>
</div>
<div data-slot="hero-copy">
<img data-slot="zen logo light" src={goLogoLight} alt="" />
<img data-slot="zen logo dark" src={goLogoDark} alt="" />
@@ -507,13 +517,6 @@ export default function Home() {
</a>
.
</p>
<p>
<strong>Muse Spark 1.2:</strong> {i18n.t("go.faq.a5.museRetention")}{" "}
<a href="https://dev.meta.ai/docs/pricing-rate-limits#contributor-tier">
{i18n.t("go.faq.a5.learnMore")}
</a>
.
</p>
<p>
<strong>DeepSeek V4 Flash:</strong> {i18n.t("go.faq.a5.deepseekRetention")}
</p>
@@ -106,7 +106,6 @@
[data-slot="setting-row"] {
margin-top: 0;
padding-block: var(--space-2);
}
}
@@ -39,7 +39,6 @@ export const queryLiteSubscription = query(async (workspaceID: string) => {
timeCreated: LiteTable.timeCreated,
lite: BillingTable.lite,
region: WorkspaceTable.region,
allowTraining: WorkspaceTable.allow_training,
})
.from(BillingTable)
.innerJoin(LiteTable, eq(LiteTable.workspaceID, BillingTable.workspaceID))
@@ -55,7 +54,6 @@ export const queryLiteSubscription = query(async (workspaceID: string) => {
return {
mine,
useBalance: row.lite?.useBalance ?? false,
allowTraining: row.allowTraining ?? false,
region:
row.region ?? (await Workspace.setDefaultRegion({ country: countryFromRequest(getRequestEvent()?.request) })),
rollingUsage: Subscription.analyzeRollingUsage({
@@ -156,24 +154,6 @@ const setGoProviderRouting = action(async (form: FormData) => {
)
}, "go.providerRouting.set")
const setGoAllowTraining = action(async (form: FormData) => {
"use server"
const workspaceID = form.get("workspaceID") as string | null
if (!workspaceID) return { error: formError.workspaceRequired }
const allowTraining = (form.get("allowTraining") as string | null) === "true"
return json(
await withActor(
() =>
Workspace.update({ allow_training: allowTraining })
.then(() => ({ error: undefined }))
.catch((e) => ({ error: e.message as string })),
workspaceID,
),
{ revalidate: queryLiteSubscription.key },
)
}, "go.allowTraining.set")
function LiteUsageItem(props: { label: string; usage: { usagePercent: number; resetInSec: number } }) {
const i18n = useI18n()
@@ -206,7 +186,6 @@ export function LiteSection(props: { lite: LiteSubscription | undefined }) {
const checkoutSubmission = useSubmission(createLiteCheckoutUrl)
const useBalanceSubmission = useSubmission(setLiteUseBalance)
const providerRoutingSubmission = useSubmission(setGoProviderRouting)
const allowTrainingSubmission = useSubmission(setGoAllowTraining)
const [store, setStore] = createStore({
loading: undefined as undefined | "session" | "checkout" | "alipay" | "upi",
showModal: false,
@@ -285,20 +264,6 @@ export function LiteSection(props: { lite: LiteSubscription | undefined }) {
<h3>{i18n.t("workspace.lite.providers.title")}</h3>
<p>{i18n.t("workspace.lite.providers.description")}</p>
</div>
<form action={setGoAllowTraining} method="post" data-slot="setting-row">
<p>{i18n.t("workspace.lite.providers.allowTraining")}</p>
<input type="hidden" name="workspaceID" value={params.id} />
<input type="hidden" name="allowTraining" value={sub().allowTraining ? "false" : "true"} />
<label data-slot="toggle-label">
<input
type="checkbox"
checked={sub().allowTraining}
disabled={allowTrainingSubmission.pending}
onChange={(e) => e.currentTarget.form?.requestSubmit()}
/>
<span></span>
</label>
</form>
<form action={setGoProviderRouting} method="post" data-slot="setting-row">
<p>{i18n.t("workspace.lite.providers.useChina")}</p>
<input type="hidden" name="workspaceID" value={params.id} />
@@ -341,7 +306,6 @@ export function LiteSection(props: { lite: LiteSubscription | undefined }) {
<ul data-slot="promo-models">
<li>Grok 4.5</li>
<li>GPT 5.6 Luna</li>
<li>GLM-5.3</li>
<li>GLM-5.2</li>
<li>GLM-5.1</li>
<li>Kimi K3</li>
@@ -4,7 +4,6 @@ export class MonthlyLimitError extends Error {}
export class UserLimitError extends Error {}
export class ModelError extends Error {}
export class RegionError extends Error {}
export class DataPolicyError extends Error {}
class LimitError extends Error {
retryAfter?: number
@@ -22,7 +22,6 @@ import {
UserLimitError,
ModelError,
RegionError,
DataPolicyError,
RateLimitError,
FreeUsageLimitError,
GoUsageLimitError,
@@ -52,7 +51,7 @@ import { createModelTpsLimiter } from "./modelTpsLimiter"
import { createProviderBudgetTracker } from "./providerBudgetTracker"
import { accumulateUsage, HOT_WORKSPACES } from "./usageBatcher"
import { Workspace } from "@opencode-ai/console-core/workspace.js"
import { countryFromRequest, isModelCountryRestricted } from "~/lib/request-country"
import { countryFromRequest } from "~/lib/request-country"
type ZenData = Awaited<ReturnType<typeof ZenData.list>>
type RetryOptions = {
@@ -122,8 +121,6 @@ export async function handler(
})
const zenData = ZenData.list(opts.modelList)
const modelInfo = validateModel(zenData, model)
const country = countryFromRequest(input.request)
if (isModelCountryRestricted(modelInfo.id, country)) throw new RegionError(t("zen.api.error.countryNotAllowed"))
const trialLimiter = createTrialLimiter(modelInfo.trialProvider, ip)
const trialProviders = await trialLimiter?.check()
const rateLimiter = modelInfo.allowAnonymous
@@ -131,18 +128,12 @@ export async function handler(
: createKeyRateLimiter(modelInfo.id, modelInfo.rateLimit, zenApiKey, input.request)
await rateLimiter?.check()
const authInfo = await authenticate(modelInfo, zenApiKey)
if (authInfo && opts.modelList === "lite" && modelInfo.id === "muse-spark-1.2" && !authInfo.allowTraining)
throw new DataPolicyError(
t("zen.api.error.trainingNotAllowed", {
consoleGoUrl: `https://opencode.ai/workspace/${authInfo.workspaceID}/go`,
}),
)
const allowedRegions = authInfo?.region
? authInfo.region
: await (async () => {
if (!authInfo) return
return Actor.provide("system", { workspaceID: authInfo.workspaceID }, () =>
Workspace.setDefaultRegion({ country }),
Workspace.setDefaultRegion({ country: countryFromRequest(input.request) }),
)
})()
if (
@@ -256,7 +247,7 @@ export async function handler(
headers.delete("host")
headers.delete("content-length")
headers.delete("x-opencode-request")
if (!isNewInference) headers.delete("x-opencode-session")
headers.delete("x-opencode-session")
headers.delete("x-opencode-project")
headers.delete("x-opencode-client")
return headers
@@ -486,7 +477,7 @@ export async function handler(
} catch {}
}
if (error instanceof RegionError || error instanceof DataPolicyError)
if (error instanceof RegionError)
return new Response(
JSON.stringify({
type: "error",
@@ -717,7 +708,6 @@ export async function handler(
workspace: {
id: WorkspaceTable.id,
region: WorkspaceTable.region,
allowTraining: WorkspaceTable.allow_training,
isBlocked: WorkspaceTable.is_blocked,
isFlaggedByAnthropic: WorkspaceTable.is_flagged_by_anthropic,
isFlaggedByOpenAI: WorkspaceTable.is_flagged_by_openai,
@@ -830,7 +820,6 @@ export async function handler(
apiKeyId: data.apiKey,
workspaceID: data.workspace.id,
region: data.workspace.region,
allowTraining: data.workspace.allowTraining ?? false,
billing: data.billing,
user: data.user,
black: data.black,
@@ -1043,14 +1032,11 @@ export async function handler(
const { inputTokens, outputTokens, reasoningTokens, cacheReadTokens, cacheWrite5mTokens, cacheWrite1hTokens } =
usageInfo
const hour = new Date().getUTCHours()
const modelCost =
modelInfo.costPeak && ((hour >= 1 && hour < 4) || (hour >= 6 && hour < 10))
? modelInfo.costPeak
: modelInfo.cost200K &&
inputTokens + (cacheReadTokens ?? 0) + (cacheWrite5mTokens ?? 0) + (cacheWrite1hTokens ?? 0) > 200_000
? modelInfo.cost200K
: modelInfo.cost
modelInfo.cost200K &&
inputTokens + (cacheReadTokens ?? 0) + (cacheWrite5mTokens ?? 0) + (cacheWrite1hTokens ?? 0) > 200_000
? modelInfo.cost200K
: modelInfo.cost
const inputCost = modelCost.input * inputTokens * 100
const outputCost = modelCost.output * outputTokens * 100
@@ -1 +0,0 @@
ALTER TABLE `workspace` ADD `allow_non_zdr` boolean;
File diff suppressed because it is too large Load Diff
@@ -1 +0,0 @@
ALTER TABLE `workspace` RENAME COLUMN `allow_non_zdr` TO `allow_training`;
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/console-core",
"version": "1.18.18",
"version": "1.18.17",
"private": true,
"type": "module",
"license": "MIT",
-1
View File
@@ -24,7 +24,6 @@ export namespace ZenData {
cost: ModelCostSchema,
costMultiplier: z.number().default(1),
cost200K: ModelCostSchema.optional(),
costPeak: ModelCostSchema.optional(),
allowAnonymous: z.boolean().optional(),
byokProvider: z.enum(["openai", "anthropic", "google"]).optional(),
stickyProvider: z.enum(["strict", "prefer"]).optional(),
@@ -53,7 +53,6 @@ export const BillingTable = mysqlTable(
...workspaceIndexes(table),
uniqueIndex("global_customer_id").on(table.customerID),
uniqueIndex("global_subscription_id").on(table.subscriptionID),
uniqueIndex("global_lite_subscription_id").on(table.liteSubscriptionID),
],
)
@@ -1,4 +1,4 @@
import { bigint, index, mysqlTable, primaryKey, uniqueIndex, varchar } from "drizzle-orm/mysql-core"
import { bigint, mysqlTable, primaryKey, uniqueIndex, varchar } from "drizzle-orm/mysql-core"
import { timestamps, ulid, utc, workspaceColumns } from "../drizzle/types"
import { workspaceIndexes } from "./workspace.sql"
@@ -31,5 +31,5 @@ export const ReferralRewardTable = mysqlTable(
amount: bigint("amount", { mode: "number" }).notNull(),
timeApplied: utc("time_applied"),
},
(table) => [primaryKey({ columns: [table.workspaceID, table.referralID] }), index("referral_id").on(table.referralID)],
(table) => [primaryKey({ columns: [table.workspaceID, table.referralID] })],
)
@@ -8,7 +8,6 @@ export const WorkspaceTable = mysqlTable(
slug: varchar("slug", { length: 255 }),
name: varchar("name", { length: 255 }).notNull(),
region: json("region").$type<("us" | "eu" | "sg" | "cn")[]>(),
allow_training: boolean(),
is_blocked: boolean(),
is_flagged_by_anthropic: boolean(),
is_flagged_by_openai: boolean(),
-2
View File
@@ -62,7 +62,6 @@ export namespace Workspace {
z.object({
name: z.string().min(1).max(255).optional(),
region: z.array(Region).min(1).optional(),
allow_training: z.boolean().optional(),
}),
async (input) => {
Actor.assertAdmin()
@@ -73,7 +72,6 @@ export namespace Workspace {
.set({
...("name" in input ? { name: input.name } : {}),
...("region" in input ? { region: input.region } : {}),
...("allow_training" in input ? { allow_training: input.allow_training } : {}),
})
.where(eq(WorkspaceTable.id, workspaceID)),
)
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-function",
"version": "1.18.18",
"version": "1.18.17",
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-mail",
"version": "1.18.18",
"version": "1.18.17",
"dependencies": {
"@jsx-email/all": "2.2.3",
"@jsx-email/cli": "1.4.3",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-support",
"version": "1.18.18",
"version": "1.18.17",
"type": "module",
"license": "MIT",
"scripts": {
+3 -3
View File
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "1.18.18",
"version": "1.18.17",
"name": "@opencode-ai/core",
"type": "module",
"license": "MIT",
@@ -70,7 +70,7 @@
"@ai-sdk/deepinfra": "2.0.41",
"@ai-sdk/gateway": "3.0.104",
"@ai-sdk/google": "3.0.73",
"@ai-sdk/google-vertex": "4.0.181",
"@ai-sdk/google-vertex": "4.0.128",
"@ai-sdk/groq": "3.0.31",
"@ai-sdk/mistral": "3.0.51",
"@ai-sdk/openai": "3.0.84",
@@ -101,7 +101,7 @@
"@parcel/watcher": "2.5.1",
"@silvia-odwyer/photon-node": "0.3.4",
"@openrouter/ai-sdk-provider": "2.9.0",
"ai-gateway-provider": "3.2.0",
"ai-gateway-provider": "3.1.2",
"bun-pty": "0.4.8",
"cross-spawn": "catalog:",
"diff": "catalog:",
@@ -24,15 +24,9 @@ export const CloudflareAIGatewayPlugin = define({
apiKey: config.apiKey,
options: gatewayOptions(evt.options, metadata),
} as any)
const unified = createUnified({ apiKey: config.apiKey })
evt.sdk = {
languageModel(modelID: string) {
// Workers AI is the only first-party provider whose upstream is Cloudflare itself, so it is
// the only one that should receive the Cloudflare token as its upstream Authorization header.
// The Unified API addresses Workers AI both with the explicit "workers-ai/" prefix and as
// bare "@cf/..." ids. Third-party providers must not receive the token; they rely on the
// gateway's stored/BYOK keys instead.
const isWorkersAi = modelID.startsWith("workers-ai/") || modelID.startsWith("@cf/")
const unified = createUnified(isWorkersAi ? { apiKey: config.apiKey } : {})
return gateway(unified(modelID))
},
}
@@ -13,7 +13,7 @@ import { ConfigProviderV1 } from "../../v1/config/provider"
import { ConfigProviderOptionsV1 } from "../../v1/config/provider-options"
import { ConfigV1 } from "../../v1/config/config"
const defaultServer = "https://opencode.ai/console"
const defaultServer = "https://console.opencode.ai"
const clientID = "opencode-cli"
const methodID = Integration.MethodID.make("device")
const RemoteResponse = Schema.Struct({ config: ConfigV1.Info })
@@ -40,7 +40,7 @@ already-loaded config until then.
| Scope | Path |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| Project config | `./opencode.json`, `./opencode.jsonc`, or `.opencode/opencode.json` (opencode walks up from the cwd to the worktree root) |
| Global config | `~/.config/opencode/opencode.json` or `~/.config/opencode/opencode.jsonc` (NOT `~/.opencode/`) |
| Global config | `~/.config/opencode/opencode.json` (NOT `~/.opencode/`) |
| Project agents | `.opencode/agent/<name>.md` or `.opencode/agents/<name>.md` |
| Global agents | `~/.config/opencode/agent(s)/<name>.md` |
| Project commands | `.opencode/command/<name>.md` or `.opencode/commands/<name>.md` |
+1 -4
View File
@@ -264,10 +264,7 @@ const layer = Layer.effect(
}),
line: match.line_number,
offset: match.absolute_offset,
text:
match.lines.text.length > 2_000
? match.lines.text.slice(0, 2_000).replace(/[\uD800-\uDBFF]$/, "") + "..."
: match.lines.text,
text: match.lines.text.length > 2_000 ? match.lines.text.slice(0, 2_000) + "..." : match.lines.text,
submatches: match.submatches.map((submatch) => ({
text: submatch.match.text,
start: submatch.start,
-1
View File
@@ -202,7 +202,6 @@ export const make = (dependencies: Dependencies) => {
.stream(
LLM.request({
model: input.model,
http: input.request.http,
messages: [Message.user(summaryPrompt)],
tools: [],
generation: { maxTokens: summaryOutput },
+3
View File
@@ -12,6 +12,7 @@ import { SessionMessage } from "./message"
import { SessionMessageUpdater } from "./message-updater"
import { SessionInput } from "./input"
import { WorkspaceV2 } from "../workspace"
import { SessionContextEpoch } from "./context-epoch"
import { MessageTable, PartTable, SessionInputTable, SessionMessageTable, SessionTable } from "./sql"
import type { DeepMutable } from "../schema"
@@ -252,6 +253,7 @@ const layer = Layer.effectDiscard(
.where(eq(SessionTable.id, event.data.sessionID))
.run()
.pipe(Effect.orDie)
yield* SessionContextEpoch.reset(db, event.data.sessionID)
}),
)
yield* events.project(SessionV1.Event.Deleted, (event) =>
@@ -447,6 +449,7 @@ const layer = Layer.effectDiscard(
.where(eq(SessionTable.id, event.data.sessionID))
.run()
.pipe(Effect.orDie)
yield* SessionContextEpoch.reset(db, event.data.sessionID)
}),
)
}),
-7
View File
@@ -204,13 +204,6 @@ const layer = Layer.effect(
const promptCacheKey = /^ses_[0-9a-f]{64}$/.test(session.id) ? session.id.slice(4) : session.id
const request = LLM.request({
model,
http: {
headers: {
"x-session-affinity": session.id,
"X-Session-Id": session.id,
...(session.parentID ? { "x-parent-session-id": session.parentID } : {}),
},
},
providerOptions: { openai: { promptCacheKey } },
system: [agent.info?.system, system.baseline]
.filter((part): part is string => part !== undefined && part.length > 0)
-28
View File
@@ -1,28 +0,0 @@
import { createGroq } from "@ai-sdk/groq"
import { expect, test } from "bun:test"
test("Groq passes through unknown reasoning effort", async () => {
let body: Record<string, unknown> | undefined
const mockFetch = Object.assign(
async (_input: Parameters<typeof fetch>[0], init?: RequestInit) => {
body = JSON.parse(String(init?.body))
return Response.json({
id: "response-1",
created: 0,
model: "openai/gpt-oss-120b",
object: "chat.completion",
choices: [{ index: 0, message: { role: "assistant", content: "Hello" }, finish_reason: "stop" }],
usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 },
})
},
{ preconnect: fetch.preconnect },
)
const model = createGroq({ apiKey: "test", fetch: mockFetch })("openai/gpt-oss-120b")
await model.doGenerate({
prompt: [{ role: "user", content: [{ type: "text", text: "Hello" }] }],
providerOptions: { groq: { reasoningEffort: "custom" } },
})
expect(body?.reasoning_effort).toBe("custom")
})
@@ -27,32 +27,6 @@ test("Mistral sends promptCacheKey as prompt_cache_key", async () => {
expect(body?.prompt_cache_key).toBe("session-123")
})
test("Mistral passes through unknown reasoning effort", async () => {
let body: Record<string, unknown> | undefined
const mockFetch = Object.assign(
async (_input: Parameters<typeof fetch>[0], init?: RequestInit) => {
body = JSON.parse(String(init?.body))
return Response.json({
id: "response-1",
created: 0,
model: "mistral-large-latest",
object: "chat.completion",
choices: [{ index: 0, message: { role: "assistant", content: "Hello" }, finish_reason: "stop" }],
usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 },
})
},
{ preconnect: fetch.preconnect },
)
const model = createMistral({ apiKey: "test", fetch: mockFetch })("mistral-large-latest")
await model.doGenerate({
prompt: [{ role: "user", content: [{ type: "text", text: "Hello" }] }],
providerOptions: { mistral: { reasoningEffort: "custom" } },
})
expect(body?.reasoning_effort).toBe("custom")
})
test("Mistral round-trips native reasoning in assistant history", async () => {
let body: { messages?: unknown[] } | undefined
const mockFetch = Object.assign(
@@ -30,56 +30,3 @@ test("xAI Responses sends promptCacheKey as prompt_cache_key", async () => {
expect(body?.prompt_cache_key).toBe("session-123")
})
test("xAI Responses passes through xhigh reasoning effort", async () => {
let body: Record<string, unknown> | undefined
const mockFetch = Object.assign(
async (_input: Parameters<typeof fetch>[0], init?: RequestInit) => {
body = JSON.parse(String(init?.body))
return Response.json({
id: "response-1",
created_at: 0,
model: "grok-4",
object: "response",
output: [],
usage: { input_tokens: 1, output_tokens: 0 },
status: "completed",
})
},
{ preconnect: fetch.preconnect },
)
const model = createXai({ apiKey: "test", fetch: mockFetch }).responses("grok-4")
await model.doGenerate({
prompt: [{ role: "user", content: [{ type: "text", text: "Hello" }] }],
providerOptions: { xai: { reasoningEffort: "xhigh" } },
})
expect(body?.reasoning).toEqual({ effort: "xhigh" })
})
test("xAI Chat passes through xhigh reasoning effort", async () => {
let body: Record<string, unknown> | undefined
const mockFetch = Object.assign(
async (_input: Parameters<typeof fetch>[0], init?: RequestInit) => {
body = JSON.parse(String(init?.body))
return Response.json({
id: "chat-1",
created: 0,
model: "grok-4",
object: "chat.completion",
choices: [{ index: 0, message: { role: "assistant", content: "Hello" }, finish_reason: "stop" }],
usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 },
})
},
{ preconnect: fetch.preconnect },
)
const model = createXai({ apiKey: "test", fetch: mockFetch }).chat("grok-4")
await model.doGenerate({
prompt: [{ role: "user", content: [{ type: "text", text: "Hello" }] }],
providerOptions: { xai: { reasoningEffort: "xhigh" } },
})
expect(body?.reasoning_effort).toBe("xhigh")
})
-20
View File
@@ -62,24 +62,4 @@ describe("Ripgrep", () => {
(tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
),
)
it.live("does not split surrogate pairs in oversized line previews", () =>
Effect.acquireUseRelease(
Effect.promise(() => tmpdir()),
(tmp) =>
Effect.gen(function* () {
yield* Effect.promise(() =>
fs.writeFile(path.join(tmp.path, "unicode.txt"), `needle${"x".repeat(1_993)}😀\n`),
)
const matches = yield* (yield* Ripgrep.Service).grep({
cwd: tmp.path,
pattern: "needle",
limit: 10,
})
expect(matches[0]?.text).toBe(`needle${"x".repeat(1_993)}...`)
}),
(tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
),
)
})
+1 -35
View File
@@ -1,6 +1,6 @@
import { describe, expect } from "bun:test"
import { DateTime, Effect, Schema } from "effect"
import { asc, eq, sql } from "drizzle-orm"
import { asc, eq } from "drizzle-orm"
import { Database } from "@opencode-ai/core/database/database"
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
@@ -22,7 +22,6 @@ import { SessionInput } from "@opencode-ai/core/session/input"
import { SessionInputTable, SessionMessageTable, SessionTable } from "@opencode-ai/core/session/sql"
import { testEffect } from "./lib/effect"
import { Snapshot } from "@opencode-ai/core/snapshot"
import { Location } from "@opencode-ai/core/location"
const it = testEffect(AppNodeBuilder.build(LayerNode.group([Database.node, EventV2.node, SessionProjector.node])))
const sessionsLayer = AppNodeBuilder.build(SessionV2.node, [[SessionExecution.node, SessionExecution.noopLayer]])
@@ -45,39 +44,6 @@ const assistantRow = (
}
describe("SessionProjector", () => {
it.effect("projects moved sessions without the transitional context epoch table", () =>
Effect.gen(function* () {
const { db } = yield* Database.Service
const events = yield* EventV2.Service
yield* db
.insert(ProjectTable)
.values({ id: Project.ID.global, worktree: AbsolutePath.make("/project"), sandboxes: [] })
.run()
yield* db
.insert(SessionTable)
.values({
id: sessionID,
project_id: Project.ID.global,
slug: "test",
directory: "/project",
title: "test",
version: "test",
})
.run()
yield* db.run(sql`DROP TABLE session_context_epoch`)
yield* events.publish(SessionEvent.Moved, {
sessionID,
timestamp: DateTime.makeUnsafe(1),
location: Location.Ref.make({ directory: AbsolutePath.make("/project/subdir") }),
})
expect(yield* db.select({ directory: SessionTable.directory }).from(SessionTable).get()).toEqual({
directory: "/project/subdir",
})
}),
)
it.effect("projects staged, cleared, and committed reverts", () =>
Effect.gen(function* () {
const db = (yield* Database.Service).db
+7 -47
View File
@@ -703,6 +703,13 @@ describe("SessionRunnerLLM", () => {
timestamp: DateTime.makeUnsafe(1),
location: Location.Ref.make({ directory: AbsolutePath.make("/moved") }),
})
expect(
yield* db
.select()
.from(SessionContextEpochTable)
.where(eq(SessionContextEpochTable.session_id, sessionID))
.get(),
).toBeUndefined()
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false })
const exit = yield* session.resume(sessionID).pipe(Effect.exit)
@@ -1101,16 +1108,6 @@ describe("SessionRunnerLLM", () => {
yield* session.resume(sessionID)
expect(requests).toHaveLength(2)
expect(requests.map((request) => request.http?.headers)).toEqual([
{
"x-session-affinity": sessionID,
"X-Session-Id": sessionID,
},
{
"x-session-affinity": sessionID,
"X-Session-Id": sessionID,
},
])
expect(userTexts(requests[0])[0]).toContain("## Objective")
expect(userTexts(requests[1])).toHaveLength(1)
expect(userTexts(requests[1])[0]).toContain("<summary>\n## Objective\n- Preserve the task\n</summary>")
@@ -2518,43 +2515,6 @@ describe("SessionRunnerLLM", () => {
}),
)
it.effect("adds session correlation headers to model requests", () =>
Effect.gen(function* () {
yield* setup
const session = yield* SessionV2.Service
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Run correlated request" }), resume: false })
requests.length = 0
yield* session.resume(sessionID)
expect(requests[0]?.http?.headers).toEqual({
"x-session-affinity": sessionID,
"X-Session-Id": sessionID,
})
}),
)
it.effect("adds the parent session header to child model requests", () =>
Effect.gen(function* () {
yield* setup
const session = yield* SessionV2.Service
const parentID = SessionV2.ID.make("ses_runner_parent")
const { db } = yield* Database.Service
yield* db
.update(SessionTable)
.set({ parent_id: parentID })
.where(eq(SessionTable.id, sessionID))
.run()
.pipe(Effect.orDie)
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Run child request" }), resume: false })
requests.length = 0
yield* session.resume(sessionID)
expect(requests[0]?.http?.headers?.["x-parent-session-id"]).toBe(parentID)
}),
)
it.effect("bounds 64-character session prompt cache keys", () =>
Effect.gen(function* () {
yield* setup
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@opencode-ai/desktop",
"private": true,
"version": "1.18.18",
"version": "1.18.17",
"type": "module",
"license": "MIT",
"homepage": "https://opencode.ai",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "1.18.18",
"version": "1.18.17",
"name": "@opencode-ai/effect-drizzle-sqlite",
"type": "module",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "1.18.18",
"version": "1.18.17",
"name": "@opencode-ai/effect-sqlite-node",
"type": "module",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/enterprise",
"version": "1.18.18",
"version": "1.18.17",
"private": true,
"type": "module",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/function",
"version": "1.18.18",
"version": "1.18.17",
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "1.18.18",
"version": "1.18.17",
"name": "@opencode-ai/http-recorder",
"description": "Record and replay Effect HTTP client traffic with deterministic cassettes",
"type": "module",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "1.18.18",
"version": "1.18.17",
"name": "@opencode-ai/llm",
"type": "module",
"license": "MIT",
+3 -3
View File
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "1.18.18",
"version": "1.18.17",
"name": "opencode",
"type": "module",
"license": "MIT",
@@ -64,7 +64,7 @@
"@ai-sdk/deepinfra": "2.0.41",
"@ai-sdk/gateway": "3.0.104",
"@ai-sdk/google": "3.0.73",
"@ai-sdk/google-vertex": "4.0.181",
"@ai-sdk/google-vertex": "4.0.128",
"@ai-sdk/groq": "3.0.31",
"@ai-sdk/mistral": "3.0.51",
"@ai-sdk/openai": "3.0.84",
@@ -111,7 +111,7 @@
"@types/ws": "8.18.1",
"@zip.js/zip.js": "2.7.62",
"ai": "catalog:",
"ai-gateway-provider": "3.2.0",
"ai-gateway-provider": "3.1.2",
"bonjour-service": "1.3.0",
"chokidar": "4.0.3",
"cross-spawn": "catalog:",
+1 -1
View File
@@ -15,7 +15,7 @@ const dim = (value: string) => UI.Style.TEXT_DIM + value + UI.Style.TEXT_NORMAL
const activeSuffix = (isActive: boolean) => (isActive ? dim(" (active)") : "")
export const defaultConsoleUrl = "https://opencode.ai/console"
export const defaultConsoleUrl = "https://console.opencode.ai"
export const formatAccountLabel = (account: { email: string; url: string }, isActive: boolean) =>
`${account.email} ${dim(account.url)}${activeSuffix(isActive)}`
@@ -714,7 +714,6 @@ const layer = Layer.effect(
})
const list = Effect.fn("Workspace.list")(function* (project: Project.Info) {
if (!flags.experimentalWorkspaces) return []
return (yield* db
.select()
.from(WorkspaceTable)
@@ -852,7 +851,6 @@ const layer = Layer.effect(
})
const startWorkspaceSyncing = Effect.fn("Workspace.startWorkspaceSyncing")(function* (projectID: ProjectV2.ID) {
if (!flags.experimentalWorkspaces) return
const rows = yield* db
.selectDistinct({ workspace: WorkspaceTable })
.from(WorkspaceTable)
@@ -61,5 +61,16 @@ export async function CloudflareAIGatewayAuthPlugin(_input: PluginInput): Promis
},
],
},
"chat.params": async (input, output) => {
if (input.model.providerID !== "cloudflare-ai-gateway") return
// The unified gateway routes through @ai-sdk/openai-compatible, which
// always emits max_tokens. OpenAI reasoning models (gpt-5.x, o-series)
// reject that field and require max_completion_tokens instead, and the
// compatible SDK has no way to rename it. Drop the cap so OpenAI falls
// back to the model's default output budget.
if (!input.model.api.id.toLowerCase().startsWith("openai/")) return
if (!input.model.capabilities.reasoning) return
output.maxOutputTokens = undefined
},
}
}
+13 -20
View File
@@ -37,12 +37,10 @@ function base64UrlEncode(buffer: ArrayBuffer): string {
export interface IdTokenClaims {
chatgpt_account_id?: string
chatgpt_compute_residency?: string
organizations?: Array<{ id: string }>
email?: string
"https://api.openai.com/auth"?: {
chatgpt_account_id?: string
chatgpt_compute_residency?: string
}
}
@@ -77,14 +75,6 @@ export function extractAccountId(tokens: TokenResponse): string | undefined {
return undefined
}
export function extractResidency(token: string): string | undefined {
const claims = parseJwtClaims(token)
const residency =
claims?.["https://api.openai.com/auth"]?.chatgpt_compute_residency ?? claims?.chatgpt_compute_residency
if (!residency || residency === "no_constraint") return undefined
return residency
}
function buildAuthorizeUrl(redirectUri: string, pkce: PkceCodes, state: string): string {
const params = new URLSearchParams({
response_type: "code",
@@ -309,11 +299,16 @@ export async function CodexAuthPlugin(input: PluginInput, options: CodexAuthPlug
output: 0,
cache: { read: 0, write: 0 },
},
limit:
model.id.includes("gpt-5.5") || model.id.includes("gpt-5.6")
limit: model.id.includes("gpt-5.5")
? {
context: 400_000,
input: 272_000,
output: 128_000,
}
: model.id.includes("gpt-5.6")
? {
context: 400_000,
input: 272_000,
context: 500_000,
input: 372_000,
output: 128_000,
}
: model.limit,
@@ -416,12 +411,10 @@ export async function CodexAuthPlugin(input: PluginInput, options: CodexAuthPlug
requestInput instanceof URL
? requestInput
: new URL(typeof requestInput === "string" ? requestInput : requestInput.url)
const rewrite = parsed.pathname.includes("/v1/responses") || parsed.pathname.includes("/chat/completions")
const url = rewrite ? new URL(codexApiEndpoint) : parsed
if (rewrite) {
const residency = extractResidency(currentAuth.access)
if (residency) headers.set("x-openai-internal-codex-residency", residency)
}
const url =
parsed.pathname.includes("/v1/responses") || parsed.pathname.includes("/chat/completions")
? new URL(codexApiEndpoint)
: parsed
const requestInit = {
...init,
@@ -110,11 +110,10 @@ export function createWebSocketFetch(options?: CreateWebSocketFetchOptions) {
invalidate(entry)
}
},
onConnectionInvalid: (_error, closeCode) => {
onConnectionInvalid: (error) => {
entry.busy = false
entry.lastUsedAt = Date.now()
if (closeCode === OpenAIWebSocket.MESSAGE_TOO_BIG_CLOSE_CODE) entry.fallback = true
else if (!entry.fallback) recordStreamFailure(entry)
if (!entry.fallback) recordStreamFailure(entry)
invalidate(entry)
resolveFirstEvent(false)
},
+4 -6
View File
@@ -9,7 +9,6 @@ import { ProxyEnv } from "@/util/proxy-env"
import { isRecord } from "@/util/record"
export const PROTOCOL_HEADER = "responses_websockets=2026-02-06"
export const MESSAGE_TOO_BIG_CLOSE_CODE = 1009
export interface ConnectResponsesWebSocketOptions {
url: string
@@ -27,7 +26,7 @@ export interface StreamResponsesWebSocketOptions {
onComplete?: (event: Record<string, unknown>) => void
onTerminal?: (event: Record<string, unknown>) => void
onRetryableTerminal?: (event: Record<string, unknown>) => Promise<WebSocket | undefined>
onConnectionInvalid?: (error: ProviderError.ResponseStreamError, closeCode?: number) => void
onConnectionInvalid?: (error: ProviderError.ResponseStreamError) => void
onAbort?: (error: Error) => void
}
@@ -163,11 +162,11 @@ export function streamResponsesWebSocket(options: StreamResponsesWebSocketOption
controller?.close()
}
function invalidate(error: ProviderError.ResponseStreamError, closeCode?: number) {
function invalidate(error: ProviderError.ResponseStreamError) {
if (completed) return
completed = true
cleanup()
options.onConnectionInvalid?.(error, closeCode)
options.onConnectionInvalid?.(error)
controller?.error(error)
}
@@ -275,7 +274,6 @@ export function streamResponsesWebSocket(options: StreamResponsesWebSocketOption
if (completed) return
invalidate(
new ProviderError.ResponseStreamError(closeMessage("WebSocket closed before response.completed", code, reason)),
code,
)
}
@@ -375,7 +373,7 @@ function abortError(signal: AbortSignal | undefined) {
function closeMessage(message: string, code: number, reason: Buffer) {
const details = [`code ${code}`]
if (code === MESSAGE_TOO_BIG_CLOSE_CODE) details.push("message too big")
if (code === 1009) details.push("message too big")
if (reason.length > 0) details.push(reason.toString())
return `${message} (${details.join(": ")})`
}
+5 -36
View File
@@ -800,10 +800,9 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
)
}
// Use official ai-gateway-provider package (v2.x for AI SDK v5 compatibility)
const { createAiGateway } = yield* Effect.promise(() => import("ai-gateway-provider"))
const { createUnified } = yield* Effect.promise(() => import("ai-gateway-provider/providers/unified"))
const { createOpenAI } = yield* Effect.promise(() => import("ai-gateway-provider/providers/openai"))
const { createAnthropic } = yield* Effect.promise(() => import("ai-gateway-provider/providers/anthropic"))
const metadata = iife(() => {
if (input.options?.metadata) return input.options.metadata
@@ -830,23 +829,12 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
apiKey: apiToken,
...(Object.values(opts).some((v) => v !== undefined) ? { options: opts } : {}),
})
const unified = createUnified({ apiKey: apiToken })
return {
autoload: true,
async getModel(_sdk: any, modelID: string, _options?: Record<string, any>) {
// Model IDs use Unified API format: provider/model (e.g., "anthropic/claude-sonnet-4-5").
// OpenAI and Anthropic ride their native passthrough routes so agents get the Responses
// and Messages APIs; new OpenAI models reject tools+reasoning_effort on chat completions.
// The passthrough wrappers inject a CF_TEMP_TOKEN sentinel that the gateway strips before
// dispatch, so upstream billing stays on the gateway (Unified Billing / stored BYOK).
if (modelID.startsWith("openai/")) return aigateway(createOpenAI()(modelID.slice("openai/".length)))
if (modelID.startsWith("anthropic/")) return aigateway(createAnthropic()(modelID.slice("anthropic/".length)))
// Workers AI is the only first-party provider whose upstream is Cloudflare itself, so it is
// the only one that should receive the Cloudflare token as its upstream Authorization header.
// The Unified API addresses Workers AI both with the explicit "workers-ai/" prefix and as
// bare "@cf/..." ids. Third-party providers must not receive the token; they rely on the
// gateway's stored/BYOK keys instead.
const isWorkersAi = modelID.startsWith("workers-ai/") || modelID.startsWith("@cf/")
const unified = createUnified(isWorkersAi ? { apiKey: apiToken } : {})
// Model IDs use Unified API format: provider/model (e.g., "anthropic/claude-sonnet-4-5")
return aigateway(unified(modelID))
},
options: {},
@@ -1221,17 +1209,6 @@ function cost(c: ModelsDev.Model["cost"]): Model["cost"] {
return result
}
// Cloudflare AI Gateway routes OpenAI and Anthropic models through their native
// passthrough SDKs (Responses / Messages APIs). Resolving the native npm before
// variants are computed makes reasoning variants produce payloads the native
// SDKs understand (e.g. anthropic `effort` instead of compat `reasoningEffort`).
function cloudflareGatewayNpm(providerID: string, modelID: string) {
if (providerID !== "cloudflare-ai-gateway") return undefined
if (modelID.startsWith("openai/")) return "@ai-sdk/openai"
if (modelID.startsWith("anthropic/")) return "@ai-sdk/anthropic"
return undefined
}
function fromModelsDevModel(provider: ModelsDev.Provider, model: ModelsDev.Model): Model {
const base: Model = {
id: ModelV2.ID.make(model.id),
@@ -1241,11 +1218,7 @@ function fromModelsDevModel(provider: ModelsDev.Provider, model: ModelsDev.Model
api: {
id: model.id,
url: model.provider?.api ?? provider.api ?? "",
npm:
cloudflareGatewayNpm(provider.id, model.id) ??
model.provider?.npm ??
provider.npm ??
"@ai-sdk/openai-compatible",
npm: model.provider?.npm ?? provider.npm ?? "@ai-sdk/openai-compatible",
},
status: model.status ?? "active",
headers: {},
@@ -1467,9 +1440,6 @@ const layer = Layer.effect(
model.provider?.npm ??
provider.npm ??
existingModel?.api.npm ??
// Config-defined gateway models bypass fromModelsDevModel, so resolve the
// native passthrough npm here before falling back to the catalog default.
cloudflareGatewayNpm(providerID, apiID) ??
modelsDev[providerID]?.npm ??
"@ai-sdk/openai-compatible"
const name = iife(() => {
@@ -1649,7 +1619,6 @@ const layer = Layer.effect(
for (const [modelID, model] of Object.entries(provider.models)) {
model.api.id = model.api.id ?? model.id ?? modelID
if (
// These chat aliases are invalid for the special handling in the
// built-in providers below, but custom providers may support them.
@@ -528,6 +528,7 @@ const GEMINI_MODELS_WITH_SAMPLING_DEFAULTS = [
export function temperature(model: Provider.Model) {
const id = model.api.id.toLowerCase()
if (id.includes("north-mini-code")) return 1.0
if (id.includes("qwen")) return 0.55
if (id.includes("claude")) return undefined
if (id.includes("gemini"))
return GEMINI_MODELS_WITH_SAMPLING_DEFAULTS.some((model) => model.test(id)) ? 1.0 : undefined
@@ -546,6 +547,7 @@ export function temperature(model: Provider.Model) {
export function topP(model: Provider.Model) {
const id = model.api.id.toLowerCase()
if (id.includes("qwen")) return 1
if (id.includes("gemini"))
return GEMINI_MODELS_WITH_SAMPLING_DEFAULTS.some((model) => model.test(id)) ? 0.95 : undefined
if (["minimax-m2", "kimi-k2.5", "kimi-k2p5", "kimi-k2-5"].some((s) => id.includes(s))) {
@@ -2,7 +2,6 @@ import { ProviderAuth } from "@/provider/auth"
import { Config } from "@/config/config"
import { ModelsDev } from "@opencode-ai/core/models-dev"
import { Provider } from "@/provider/provider"
import { Auth } from "@/auth"
import { mapValues } from "remeda"
import { Effect, Schema } from "effect"
@@ -37,7 +36,6 @@ export const providerHandlers = HttpApiBuilder.group(InstanceHttpApi, "provider"
const cfg = yield* Config.Service
const provider = yield* Provider.Service
const svc = yield* ProviderAuth.Service
const authStore = yield* Auth.Service
const list = Effect.fn("ProviderHttpApi.list")(function* () {
const config = yield* cfg.get()
@@ -49,7 +47,6 @@ export const providerHandlers = HttpApiBuilder.group(InstanceHttpApi, "provider"
if ((enabled ? enabled.has(key) : true) && !disabled.has(key)) filtered[key] = value
}
const connected = yield* provider.list()
const credentials = yield* authStore.all().pipe(Effect.orDie)
const providers = Object.assign(
mapValues(filtered, (item) => Provider.fromModelsDevProvider(item)),
connected,
@@ -57,7 +54,7 @@ export const providerHandlers = HttpApiBuilder.group(InstanceHttpApi, "provider"
return {
all: Object.values(providers).map(Provider.toPublicInfo),
default: Provider.defaultModelIDs(providers),
connected: Object.keys(providers).filter((id) => id in connected || credentials[id]),
connected: Object.keys(connected),
}
})
+9 -7
View File
@@ -336,8 +336,10 @@ export function plan(input: { slug: string; time: { created: number } }, instanc
}
export const getUsage = (input: { model: Provider.Model; usage: Usage; metadata?: ProviderMetadata }) => {
const finite = (value: number) => (Number.isFinite(value) ? value : 0)
const safe = (value: number) => Math.max(0, finite(value))
const safe = (value: number) => {
if (!Number.isFinite(value)) return 0
return Math.max(0, value)
}
const inputTokens = safe(input.usage.inputTokens ?? 0)
const outputTokens = safe(input.usage.outputTokens ?? 0)
const reasoningTokens = safe(input.usage.reasoningTokens ?? 0)
@@ -391,13 +393,13 @@ export const getUsage = (input: { model: Provider.Model; usage: Usage; metadata?
? new Decimal(totalNanoAiu).div(100_000_000_000).toNumber()
: safe(
new Decimal(0)
.add(new Decimal(tokens.input).mul(finite(costInfo?.input ?? 0)).div(1_000_000))
.add(new Decimal(tokens.output).mul(finite(costInfo?.output ?? 0)).div(1_000_000))
.add(new Decimal(tokens.cache.read).mul(finite(costInfo?.cache?.read ?? 0)).div(1_000_000))
.add(new Decimal(tokens.cache.write).mul(finite(costInfo?.cache?.write ?? 0)).div(1_000_000))
.add(new Decimal(tokens.input).mul(costInfo?.input ?? 0).div(1_000_000))
.add(new Decimal(tokens.output).mul(costInfo?.output ?? 0).div(1_000_000))
.add(new Decimal(tokens.cache.read).mul(costInfo?.cache?.read ?? 0).div(1_000_000))
.add(new Decimal(tokens.cache.write).mul(costInfo?.cache?.write ?? 0).div(1_000_000))
// TODO: update models.dev to have better pricing model, for now:
// charge reasoning tokens at the same rate as output tokens
.add(new Decimal(tokens.reasoning).mul(finite(costInfo?.output ?? 0)).div(1_000_000))
.add(new Decimal(tokens.reasoning).mul(costInfo?.output ?? 0).div(1_000_000))
.toNumber(),
),
tokens,
+1 -5
View File
@@ -40,11 +40,7 @@ export function provider(model: Provider.Model) {
if (model.api.id.includes("gemini-")) return [PROMPT_GEMINI]
if (model.api.id.includes("claude")) return [PROMPT_ANTHROPIC]
if (model.api.id.toLowerCase().includes("trinity")) return [PROMPT_TRINITY]
if (
model.api.id.toLowerCase().includes("kimi") ||
["kimi-for-coding", "moonshotai", "moonshotai-cn"].includes(model.providerID)
)
return [PROMPT_KIMI]
if (model.api.id.toLowerCase().includes("kimi")) return [PROMPT_KIMI]
return [PROMPT_DEFAULT]
}
+1 -6
View File
@@ -56,12 +56,7 @@ import { PermissionV1 } from "@opencode-ai/core/v1/permission"
import { McpCatalog } from "@/mcp/catalog"
export function webSearchEnabled(providerID: ProviderV2.ID, flags = { exa: false, parallel: false }) {
return (
providerID === ProviderV2.ID.opencode ||
providerID === ProviderV2.ID.make("opencode-go") ||
flags.exa ||
flags.parallel
)
return providerID === ProviderV2.ID.opencode || flags.exa || flags.parallel
}
type TaskDef = Tool.InferDef<typeof TaskTool>
+2 -2
View File
@@ -4,8 +4,8 @@ import stripAnsi from "strip-ansi"
import { defaultConsoleUrl, formatAccountLabel, formatOrgLine } from "../../src/cli/cmd/account"
describe("console account display", () => {
test("uses opencode.ai/console as the default login URL", () => {
expect(defaultConsoleUrl).toBe("https://opencode.ai/console")
test("uses console.opencode.ai as the default login URL", () => {
expect(defaultConsoleUrl).toBe("https://console.opencode.ai")
})
test("includes the account url in account labels", () => {
@@ -8,7 +8,6 @@ import { Effect, Exit, Fiber, Layer, Schema } from "effect"
import { HttpServer, HttpServerRequest, HttpServerResponse } from "effect/unstable/http"
import { eq } from "drizzle-orm"
import { GlobalBus, type GlobalEvent } from "@/bus/global"
import { Project } from "@/project/project"
import { Database } from "@opencode-ai/core/database/database"
import { ProjectV2 } from "@opencode-ai/core/project"
import { ProjectTable } from "@opencode-ai/core/project/sql"
@@ -134,9 +133,6 @@ const startWorkspaceSyncingWithFlag = (projectID: ProjectV2.ID, experimentalWork
Workspace.use.startWorkspaceSyncing(projectID).pipe(Effect.provide(workspaceLayer(experimentalWorkspaces))),
)
const listWithFlag = (project: Project.Info, experimentalWorkspaces: boolean) =>
Effect.runPromise(Workspace.use.list(project).pipe(Effect.provide(workspaceLayer(experimentalWorkspaces))))
function captureGlobalEvents() {
const events: GlobalEvent[] = []
const handler = (event: GlobalEvent) => events.push(event)
@@ -421,18 +417,6 @@ describe("workspace CRUD", () => {
{ git: true },
)
it.instance(
"list is disabled by the experimental workspace flag",
() =>
Effect.gen(function* () {
const instance = yield* requireInstance
yield* insertWorkspace(workspaceInfo(instance.project.id, "manual"))
expect(yield* Effect.promise(() => listWithFlag(instance.project, false))).toEqual([])
}),
{ git: true },
)
it.instance(
"create configures, persists, creates, starts local sync, and passes environment",
() =>
@@ -13,13 +13,56 @@ const pluginInput = {
$: {} as never,
}
test("registers the cloudflare-ai-gateway auth method", async () => {
function makeHookInput(overrides: { providerID?: string; apiId?: string; reasoning?: boolean }) {
return {
sessionID: "s",
agent: "a",
provider: {} as never,
message: {} as never,
model: {
providerID: overrides.providerID ?? "cloudflare-ai-gateway",
api: { id: overrides.apiId ?? "openai/gpt-5.2-codex", url: "", npm: "ai-gateway-provider" },
capabilities: {
reasoning: overrides.reasoning ?? true,
temperature: false,
attachment: true,
toolcall: true,
input: { text: true, audio: false, image: false, video: false, pdf: false },
output: { text: true, audio: false, image: false, video: false, pdf: false },
interleaved: false,
},
} as never,
}
}
function makeHookOutput() {
return { temperature: 0, topP: 1, topK: 0, maxOutputTokens: 32_000 as number | undefined, options: {} }
}
test("omits maxOutputTokens for openai reasoning models on cloudflare-ai-gateway", async () => {
const hooks = await CloudflareAIGatewayAuthPlugin(pluginInput)
expect(hooks.auth?.provider).toBe("cloudflare-ai-gateway")
expect(hooks.auth?.methods).toHaveLength(1)
const out = makeHookOutput()
await hooks["chat.params"]!(makeHookInput({ apiId: "openai/gpt-5.2-codex", reasoning: true }), out)
expect(out.maxOutputTokens).toBeUndefined()
})
test("no longer drops maxOutputTokens; OpenAI models ride the Responses API passthrough", async () => {
test("keeps maxOutputTokens for openai non-reasoning models", async () => {
const hooks = await CloudflareAIGatewayAuthPlugin(pluginInput)
expect(hooks["chat.params"]).toBeUndefined()
const out = makeHookOutput()
await hooks["chat.params"]!(makeHookInput({ apiId: "openai/gpt-4-turbo", reasoning: false }), out)
expect(out.maxOutputTokens).toBe(32_000)
})
test("keeps maxOutputTokens for non-openai reasoning models on cloudflare-ai-gateway", async () => {
const hooks = await CloudflareAIGatewayAuthPlugin(pluginInput)
const out = makeHookOutput()
await hooks["chat.params"]!(makeHookInput({ apiId: "anthropic/claude-sonnet-4-5", reasoning: true }), out)
expect(out.maxOutputTokens).toBe(32_000)
})
test("ignores non-cloudflare-ai-gateway providers", async () => {
const hooks = await CloudflareAIGatewayAuthPlugin(pluginInput)
const out = makeHookOutput()
await hooks["chat.params"]!(makeHookInput({ providerID: "openai", apiId: "gpt-5.2-codex", reasoning: true }), out)
expect(out.maxOutputTokens).toBe(32_000)
})
+8 -172
View File
@@ -1,13 +1,9 @@
import { describe, expect, test } from "bun:test"
import { createServer, type IncomingMessage } from "node:http"
import { type AddressInfo } from "node:net"
import { WebSocketServer } from "ws"
import {
CodexAuthPlugin,
parseJwtClaims,
extractAccountIdFromClaims,
extractAccountId,
extractResidency,
renderOAuthError,
type IdTokenClaims,
} from "../../src/plugin/openai/codex"
@@ -135,69 +131,6 @@ describe("plugin.codex", () => {
})
})
describe("extractResidency", () => {
test("extracts compute residency from the namespaced auth claims", () => {
expect(
extractResidency(
createTestJwt({
"https://api.openai.com/auth": { chatgpt_compute_residency: "eu" },
}),
),
).toBe("eu")
})
test("falls back to a root compute residency claim", () => {
expect(extractResidency(createTestJwt({ chatgpt_compute_residency: "us" }))).toBe("us")
})
test("supports compute residency values without maintaining a region list", () => {
expect(
extractResidency(
createTestJwt({
"https://api.openai.com/auth": { chatgpt_compute_residency: "ae" },
}),
),
).toBe("ae")
expect(
extractResidency(
createTestJwt({
"https://api.openai.com/auth": { chatgpt_compute_residency: "future-region_1" },
}),
),
).toBe("future-region_1")
})
test("ignores unconstrained and data residency values", () => {
expect(
extractResidency(
createTestJwt({
"https://api.openai.com/auth": { chatgpt_compute_residency: "no_constraint" },
}),
),
).toBeUndefined()
expect(
extractResidency(
createTestJwt({
"https://api.openai.com/auth": { chatgpt_data_residency: "gb" },
}),
),
).toBeUndefined()
expect(extractResidency(createTestJwt({ chatgpt_compute_residency: "" }))).toBeUndefined()
expect(extractResidency("not-a-jwt")).toBeUndefined()
})
test("prefers a namespaced unconstrained value over a root residency", () => {
expect(
extractResidency(
createTestJwt({
chatgpt_compute_residency: "eu",
"https://api.openai.com/auth": { chatgpt_compute_residency: "no_constraint" },
}),
),
).toBeUndefined()
})
})
test("installs websocket transport only when experimental websockets are enabled", async () => {
const disabled = await CodexAuthPlugin({} as never)
const enabled = await CodexAuthPlugin({} as never, { experimentalWebSockets: true })
@@ -216,73 +149,6 @@ describe("plugin.codex", () => {
await enabled.dispose?.()
})
test("sends token residency only to the ChatGPT Codex backend", async () => {
const requests: Array<{ path: string; residency: string | null }> = []
using server = Bun.serve({
port: 0,
fetch(request) {
requests.push({
path: new URL(request.url).pathname,
residency: request.headers.get("x-openai-internal-codex-residency"),
})
return new Response("{}")
},
})
const hooks = await CodexAuthPlugin({} as never, {
codexApiEndpoint: new URL("/backend-api/codex/responses", server.url).toString(),
})
const loaded = await hooks.auth!.loader!(
async () =>
({
type: "oauth",
refresh: "refresh",
access: createTestJwt({
"https://api.openai.com/auth": { chatgpt_compute_residency: "eu" },
}),
expires: Date.now() + 60_000,
}) as never,
{} as never,
)
await loaded.fetch!("https://api.openai.com/v1/responses")
await loaded.fetch!(new URL("/other", server.url))
expect(requests).toEqual([
{ path: "/backend-api/codex/responses", residency: "eu" },
{ path: "/other", residency: null },
])
})
test("sends token residency through the WebSocket transport", async () => {
await using server = await createCodexWebSocketServer()
const hooks = await CodexAuthPlugin({} as never, {
codexApiEndpoint: server.url,
experimentalWebSockets: true,
})
const loaded = await hooks.auth!.loader!(
async () =>
({
type: "oauth",
refresh: "refresh",
access: createTestJwt({
"https://api.openai.com/auth": { chatgpt_compute_residency: "eu" },
}),
expires: Date.now() + 60_000,
}) as never,
{} as never,
)
const response = await loaded.fetch!("https://api.openai.com/v1/responses", {
method: "POST",
headers: { "session-id": "session-1" },
body: JSON.stringify({ stream: true, input: "hi" }),
})
expect(await response.text()).toContain("data: [DONE]")
expect(server.headers()?.["x-openai-internal-codex-residency"]).toBe("eu")
await hooks.dispose?.()
})
test("filters unsupported modes and uses Codex context limits for OAuth GPT models", async () => {
const hooks = await CodexAuthPlugin({} as never)
const limit = { context: 1_050_000, input: 922_000, output: 128_000 }
@@ -315,9 +181,9 @@ describe("plugin.codex", () => {
expect(models["gpt-5.4"]?.limit).toEqual(limit)
expect(models["gpt-5.5"]?.limit).toEqual({ context: 400_000, input: 272_000, output: 128_000 })
expect(models["gpt-5.6-sol"]?.limit).toEqual({ context: 400_000, input: 272_000, output: 128_000 })
expect(models["gpt-5.6-terra"]?.limit).toEqual({ context: 400_000, input: 272_000, output: 128_000 })
expect(models["gpt-5.6-luna"]?.limit).toEqual({ context: 400_000, input: 272_000, output: 128_000 })
expect(models["gpt-5.6-sol"]?.limit).toEqual({ context: 500_000, input: 372_000, output: 128_000 })
expect(models["gpt-5.6-terra"]?.limit).toEqual({ context: 500_000, input: 372_000, output: 128_000 })
expect(models["gpt-5.6-luna"]?.limit).toEqual({ context: 500_000, input: 372_000, output: 128_000 })
expect(models["gpt-5.4-pro"]).toBeUndefined()
expect(models["gpt-5.7-pro"]).toBeDefined()
expect(models["gpt-5.6-sol-high"]).toBeDefined()
@@ -327,9 +193,6 @@ describe("plugin.codex", () => {
})
test("deduplicates concurrent Codex token refreshes", async () => {
const refreshedAccess = createTestJwt({
"https://api.openai.com/auth": { chatgpt_compute_residency: "eu" },
})
let auth = {
type: "oauth" as const,
refresh: "refresh-old",
@@ -344,7 +207,7 @@ describe("plugin.codex", () => {
resolveRefresh = resolve
})
let refreshRequests = 0
const apiRequests: { authorization: string | null; accountId: string | null; residency: string | null }[] = []
const apiRequests: { authorization: string | null; accountId: string | null }[] = []
using server = Bun.serve({
port: 0,
@@ -356,7 +219,7 @@ describe("plugin.codex", () => {
await refreshReady
return Response.json({
id_token: createTestJwt({ chatgpt_account_id: "acc-123" }),
access_token: refreshedAccess,
access_token: "access-new",
refresh_token: "refresh-new",
expires_in: 3600,
})
@@ -366,7 +229,6 @@ describe("plugin.codex", () => {
apiRequests.push({
authorization: request.headers.get("authorization"),
accountId: request.headers.get("ChatGPT-Account-Id"),
residency: request.headers.get("x-openai-internal-codex-residency"),
})
return new Response("{}", { status: 200 })
}
@@ -419,11 +281,11 @@ describe("plugin.codex", () => {
expect(refreshRequests).toBe(1)
expect(authUpdates).toHaveLength(1)
expect(authUpdates[0]?.body.refresh).toBe("refresh-new")
expect(authUpdates[0]?.body.access).toBe(refreshedAccess)
expect(authUpdates[0]?.body.access).toBe("access-new")
expect(authUpdates[0]?.body.accountId).toBe("acc-123")
expect(apiRequests).toEqual([
{ authorization: `Bearer ${refreshedAccess}`, accountId: "acc-123", residency: "eu" },
{ authorization: `Bearer ${refreshedAccess}`, accountId: "acc-123", residency: "eu" },
{ authorization: "Bearer access-new", accountId: "acc-123" },
{ authorization: "Bearer access-new", accountId: "acc-123" },
])
})
})
@@ -435,29 +297,3 @@ async function waitFor(predicate: () => boolean) {
await new Promise((resolve) => setTimeout(resolve, 1))
}
}
async function createCodexWebSocketServer() {
let headers: IncomingMessage["headers"] | undefined
const server = createServer()
const sockets = new WebSocketServer({ server })
sockets.on("connection", (socket, request) => {
headers = request.headers
socket.once("message", () => {
socket.send(JSON.stringify({ type: "response.completed", response: { id: "resp_123" } }))
})
})
await new Promise<void>((resolve, reject) => {
server.once("error", reject)
server.listen(0, "127.0.0.1", resolve)
})
const address = server.address() as AddressInfo
return {
url: `http://127.0.0.1:${address.port}/backend-api/codex/responses`,
headers: () => headers,
async [Symbol.asyncDispose]() {
for (const socket of sockets.clients) socket.terminate()
sockets.close()
server.close()
},
}
}
@@ -17,18 +17,13 @@ describe("plugin.openai.ws", () => {
const socket = await OpenAIWebSocket.connectResponsesWebSocket({
url: server.wsUrl,
headers: {
authorization: "Bearer test",
"content-length": "123",
"x-openai-internal-codex-residency": "eu",
},
headers: { authorization: "Bearer test", "content-length": "123" },
})
expect(OpenAIWebSocket.toWebSocketUrl("http://example.com/v1/responses")).toBe("ws://example.com/v1/responses")
expect(OpenAIWebSocket.toWebSocketUrl("https://example.com/v1/responses")).toBe("wss://example.com/v1/responses")
expect(headers?.authorization).toBe("Bearer test")
expect(headers?.["openai-beta"]).toBe(OpenAIWebSocket.PROTOCOL_HEADER)
expect(headers?.["x-openai-internal-codex-residency"]).toBe("eu")
expect(headers?.["content-length"]).toBeUndefined()
socket.terminate()
})
@@ -237,26 +232,6 @@ describe("plugin.openai.ws-pool", () => {
fetch.close()
})
test("falls back immediately to HTTP when a websocket request is too large", async () => {
let connections = 0
await using server = await createWebSocketServer((socket) => {
connections += 1
socket.once("message", () => socket.close(1009, "payload too large"))
})
const fetch = OpenAIWebSocketPool.createWebSocketFetch({
url: server.url,
})
const first = await fetch(server.url, streamRequest())
const second = await fetch(server.url, streamRequest())
expect(await first.text()).toBe("http")
expect(await second.text()).toBe("http")
expect(connections).toBe(1)
expect(server.httpRequests).toHaveLength(2)
fetch.close()
})
test("removes HTTP fallback when its session is deleted", async () => {
let websocketAttempts = 0
await using server = await createRejectingWebSocketServer(() => websocketAttempts++)
@@ -1,26 +1,22 @@
// End-to-end regression tests for opencode#24432 and opencode#32051/#32052.
// End-to-end regression test for opencode#24432.
//
// Routes through the actual ai-gateway-provider chain that provider.ts builds at
// runtime, with only the network boundary stubbed:
// - openai/* -> native OpenAI passthrough (Responses API)
// - anthropic/* -> native Anthropic passthrough (Messages API)
// - everything else -> unified /compat (openai-compatible chat completions)
// Asserts what actually lands in the envelope body Cloudflare AI Gateway
// forwards upstream, which is the only place these bugs were observable.
// Routes through the actual ai-gateway-provider + @ai-sdk/openai-compatible
// chain that provider.ts:811 builds at runtime, with only the network boundary
// stubbed. Asserts that `reasoning_effort` (and other provider options the
// transform emits) actually land in the body Cloudflare AI Gateway forwards
// upstream, which is the only place the bug was observable.
import { afterEach, beforeEach, describe, expect, test } from "bun:test"
import type { JSONValue } from "ai"
import { generateText } from "ai"
import { createAiGateway } from "ai-gateway-provider"
import { createUnified } from "ai-gateway-provider/providers/unified"
import { createOpenAI } from "ai-gateway-provider/providers/openai"
import { createAnthropic } from "ai-gateway-provider/providers/anthropic"
import { ProviderTransform } from "@/provider/transform"
import type * as Provider from "@/provider/provider"
import { ProviderV2 } from "@opencode-ai/core/provider"
import { ModelV2 } from "@opencode-ai/core/model"
type Captured = { url: string; outerBody: unknown; headers: Record<string, string> }
type Captured = { url: string; outerBody: unknown }
type ProviderOptions = Record<string, Record<string, JSONValue>>
const realFetch = globalThis.fetch
@@ -30,76 +26,24 @@ function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value)
}
// The gateway returns the upstream provider's response body verbatim, so the
// mock must answer in the wire format of the step's target provider.
function upstreamResponseBody(provider: string | undefined) {
if (provider === "openai")
return {
id: "resp_test",
object: "response",
created_at: 0,
model: "gpt-5.4",
status: "completed",
error: null,
incomplete_details: null,
output: [
{
type: "message",
role: "assistant",
id: "msg_1",
status: "completed",
content: [{ type: "output_text", text: "ok", annotations: [] }],
},
],
usage: {
input_tokens: 1,
input_tokens_details: { cached_tokens: 0 },
output_tokens: 1,
output_tokens_details: { reasoning_tokens: 0 },
total_tokens: 2,
},
}
if (provider === "anthropic")
return {
id: "msg_test",
type: "message",
role: "assistant",
model: "claude-sonnet-4-6",
content: [{ type: "text", text: "ok" }],
stop_reason: "end_turn",
stop_sequence: null,
usage: { input_tokens: 1, output_tokens: 1 },
}
return {
id: "chatcmpl-test",
object: "chat.completion",
created: 0,
model: "test",
choices: [{ index: 0, message: { role: "assistant", content: "ok" }, finish_reason: "stop" }],
usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 },
}
}
beforeEach(() => {
captured = null
const handle = async (input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]): Promise<Response> => {
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url
if (url.startsWith("https://gateway.ai.cloudflare.com/")) {
const bodyText = typeof init?.body === "string" ? init.body : ""
const outerBody = bodyText ? JSON.parse(bodyText) : null
captured = {
url,
outerBody,
headers: Object.fromEntries(new Headers(init?.headers).entries()),
}
const provider =
Array.isArray(outerBody) && isRecord(outerBody[0]) && typeof outerBody[0].provider === "string"
? outerBody[0].provider
: undefined
return new Response(JSON.stringify(upstreamResponseBody(provider)), {
status: 200,
headers: { "Content-Type": "application/json" },
})
captured = { url, outerBody: bodyText ? JSON.parse(bodyText) : null }
return new Response(
JSON.stringify({
id: "chatcmpl-test",
object: "chat.completion",
created: 0,
model: "openai/gpt-5.4",
choices: [{ index: 0, message: { role: "assistant", content: "ok" }, finish_reason: "stop" }],
usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 },
}),
{ status: 200, headers: { "Content-Type": "application/json" } },
)
}
return realFetch(input, init)
}
@@ -112,19 +56,11 @@ afterEach(() => {
globalThis.fetch = realFetch
})
// Mirrors the runtime npm rewrite in provider.ts: openai/anthropic models carry
// their native SDK package so transforms key provider options correctly.
const cfNpm = (apiId: string) => {
if (apiId.startsWith("openai/")) return "@ai-sdk/openai"
if (apiId.startsWith("anthropic/")) return "@ai-sdk/anthropic"
return "ai-gateway-provider"
}
const cfModel = (apiId: string, releaseDate = "2026-03-05"): Provider.Model => ({
id: ModelV2.ID.make(`cloudflare-ai-gateway/${apiId}`),
providerID: ProviderV2.ID.make("cloudflare-ai-gateway"),
name: apiId,
api: { id: apiId, url: "https://gateway.ai.cloudflare.com/v1/compat", npm: cfNpm(apiId) },
api: { id: apiId, url: "https://gateway.ai.cloudflare.com/v1/compat", npm: "ai-gateway-provider" },
capabilities: {
reasoning: true,
temperature: false,
@@ -144,165 +80,53 @@ const cfModel = (apiId: string, releaseDate = "2026-03-05"): Provider.Model => (
// ai-gateway-provider sends an array of step descriptors; each entry's `query`
// is the body forwarded to the upstream provider.
function firstStep(body: unknown): Record<string, unknown> | undefined {
function extractUpstreamQuery(body: unknown): Record<string, unknown> | undefined {
if (!Array.isArray(body) || body.length === 0) return undefined
const first = body[0]
return isRecord(first) ? first : undefined
}
function extractUpstreamQuery(body: unknown): Record<string, unknown> | undefined {
const query = firstStep(body)?.query
if (!isRecord(first)) return undefined
const query = first.query
return isRecord(query) ? query : undefined
}
// Each step descriptor also carries the `headers` forwarded to the upstream provider.
function extractUpstreamHeaders(body: unknown): Record<string, unknown> | undefined {
const headers = firstStep(body)?.headers
return isRecord(headers) ? headers : undefined
}
// Mirrors the runtime routing in provider.ts getModel.
function gatewayModel(apiId: string, gatewayToken = "test") {
const aigateway = createAiGateway({ accountId: "test", gateway: "test", apiKey: gatewayToken })
if (apiId.startsWith("openai/")) return aigateway(createOpenAI()(apiId.slice("openai/".length)))
if (apiId.startsWith("anthropic/")) return aigateway(createAnthropic()(apiId.slice("anthropic/".length)))
const isWorkersAi = apiId.startsWith("workers-ai/") || apiId.startsWith("@cf/")
const unified = createUnified(isWorkersAi ? { apiKey: gatewayToken } : {})
return aigateway(unified(apiId))
}
async function callThroughGateway(apiId: string, providerOptions: ProviderOptions, gatewayToken = "test") {
await generateText({ model: gatewayModel(apiId, gatewayToken), prompt: "hi", providerOptions })
async function callThroughGateway(apiId: string, providerOptions: ProviderOptions) {
const aigateway = createAiGateway({ accountId: "test", gateway: "test", apiKey: "test" })
const unified = createUnified()
await generateText({ model: aigateway(unified(apiId)), prompt: "hi", providerOptions })
return extractUpstreamQuery(captured?.outerBody)
}
describe("cf-ai-gateway routing", () => {
test("openai/* rides the native OpenAI passthrough on the Responses API", async () => {
await callThroughGateway("openai/gpt-5.4", {})
const step = firstStep(captured?.outerBody)
expect(step?.provider).toBe("openai")
expect(step?.endpoint).toBe("v1/responses")
const upstream = extractUpstreamQuery(captured?.outerBody)
expect(upstream?.model).toBe("gpt-5.4")
})
test("anthropic/* rides the native Anthropic passthrough on the Messages API", async () => {
await callThroughGateway("anthropic/claude-sonnet-4-6", {})
const step = firstStep(captured?.outerBody)
expect(step?.provider).toBe("anthropic")
expect(step?.endpoint).toBe("v1/messages")
const upstream = extractUpstreamQuery(captured?.outerBody)
expect(upstream?.model).toBe("claude-sonnet-4-6")
})
test("workers-ai models stay on the unified /compat route", async () => {
await callThroughGateway("workers-ai/@cf/moonshotai/kimi-k2.6", {})
const step = firstStep(captured?.outerBody)
expect(step?.provider).toBe("compat")
expect(step?.endpoint).toBe("chat/completions")
const upstream = extractUpstreamQuery(captured?.outerBody)
expect(upstream?.model).toBe("workers-ai/@cf/moonshotai/kimi-k2.6")
})
})
describe("cf-ai-gateway end-to-end (regression: #24432)", () => {
test("ProviderTransform.providerOptions output puts reasoning effort on the Responses wire", async () => {
// The full chain the runtime exercises for OpenAI models:
// transform.providerOptions() -> "openai" key (npm rewritten to @ai-sdk/openai)
// -> OpenAIResponsesLanguageModel emits body.reasoning.effort
test("ProviderTransform.providerOptions output puts reasoning_effort on the wire", async () => {
// The full chain the runtime exercises:
// transform.providerOptions() -> openaiCompatible key
// -> @ai-sdk/openai-compatible reads it as compatibleOptions
// -> emits body.reasoning_effort
// -> ai-gateway-provider wraps the body and forwards to gateway.ai.cloudflare.com
const opts = ProviderTransform.providerOptions(cfModel("openai/gpt-5.4"), { reasoningEffort: "xhigh" })
expect(Object.keys(opts)).toEqual(["openai"])
expect(opts.openai.reasoningEffort).toBe("xhigh")
expect(opts).toEqual({ openaiCompatible: { reasoningEffort: "xhigh" } })
const upstream = await callThroughGateway("openai/gpt-5.4", opts)
expect((upstream?.reasoning as Record<string, unknown> | undefined)?.effort).toBe("xhigh")
expect(upstream?.reasoning_effort).toBe("xhigh")
})
test("variants() output for openai/gpt-5.4 lands xhigh on the wire", async () => {
// fromModelsDevModel resolves the native npm before computing variants, so
// OpenAI models get full Responses-flavored payloads (summary + encrypted
// reasoning include for stateless multi-turn reasoning).
// The other half of the bug: workflow `variant: xhigh` flows through variants()
// and must reach the wire. variants() returns the providerOptions payload
// unwrapped; providerOptions() wraps it under the SDK key.
const variants = ProviderTransform.variants(cfModel("openai/gpt-5.4"))
expect(variants.xhigh).toEqual({
reasoningEffort: "xhigh",
reasoningSummary: "auto",
include: ["reasoning.encrypted_content"],
})
expect(variants.xhigh).toEqual({ reasoningEffort: "xhigh" })
const opts = ProviderTransform.providerOptions(cfModel("openai/gpt-5.4"), variants.xhigh)
const upstream = await callThroughGateway("openai/gpt-5.4", opts)
const reasoning = upstream?.reasoning as Record<string, unknown> | undefined
expect(reasoning?.effort).toBe("xhigh")
expect(reasoning?.summary).toBe("auto")
})
test("reasoning effort variants for anthropic models land as native adaptive thinking", async () => {
// Mirrors the runtime catalog path: models.dev reasoning_options -> reasoningVariants
// computed on the native @ai-sdk/anthropic npm -> adaptive thinking + output_config.effort.
const model = cfModel("anthropic/claude-sonnet-4-6")
const variants = ProviderTransform.reasoningVariants(
{ reasoning_options: [{ type: "effort", values: ["low", "medium", "high"] }] } as never,
model,
)
expect(variants?.high).toMatchObject({ effort: "high" })
const opts = ProviderTransform.providerOptions(model, variants!.high)
expect(Object.keys(opts)).toEqual(["anthropic"])
const upstream = await callThroughGateway("anthropic/claude-sonnet-4-6", opts)
expect((upstream?.thinking as Record<string, unknown> | undefined)?.type).toBe("adaptive")
expect((upstream?.output_config as Record<string, unknown> | undefined)?.effort).toBe("high")
})
test("reasoning_effort still reaches the /compat wire for workers-ai models", async () => {
const model = cfModel("workers-ai/@cf/moonshotai/kimi-k2.6")
const opts = ProviderTransform.providerOptions(model, { reasoningEffort: "high" })
expect(opts).toEqual({ openaiCompatible: { reasoningEffort: "high" } })
const upstream = await callThroughGateway("workers-ai/@cf/moonshotai/kimi-k2.6", opts)
expect(upstream?.reasoning_effort).toBe("high")
expect(upstream?.reasoning_effort).toBe("xhigh")
})
test("legacy buggy key 'cloudflare-ai-gateway' does NOT reach the wire (proves the bug)", async () => {
// Sanity: confirms the bug class. If a future change accidentally restores
// providerID-keyed providerOptions, this test fails before users notice.
const upstream = await callThroughGateway("workers-ai/@cf/moonshotai/kimi-k2.6", {
const upstream = await callThroughGateway("openai/gpt-5.4", {
"cloudflare-ai-gateway": { reasoningEffort: "high" },
})
expect(upstream?.reasoning_effort).toBeUndefined()
})
})
describe("cf-ai-gateway token scoping (regression: #32051/#32052)", () => {
test("openai passthrough does NOT forward the Cloudflare token upstream", async () => {
await callThroughGateway("openai/gpt-5.4", {}, "cf-gateway-secret")
expect(captured?.headers["cf-aig-authorization"]).toBe("Bearer cf-gateway-secret")
// Security invariant: the Cloudflare token must never become the upstream provider's Authorization.
expect(extractUpstreamHeaders(captured?.outerBody)?.["authorization"]).toBeUndefined()
expect(JSON.stringify(captured?.outerBody)).not.toContain("cf-gateway-secret")
})
test("anthropic passthrough does NOT forward the Cloudflare token upstream", async () => {
await callThroughGateway("anthropic/claude-sonnet-4-6", {}, "cf-gateway-secret")
expect(captured?.headers["cf-aig-authorization"]).toBe("Bearer cf-gateway-secret")
expect(extractUpstreamHeaders(captured?.outerBody)?.["x-api-key"]).toBeUndefined()
expect(JSON.stringify(captured?.outerBody)).not.toContain("cf-gateway-secret")
})
test("workers-ai models DO forward the Cloudflare token upstream", async () => {
await callThroughGateway("workers-ai/@cf/google/gemma-4-26b-a4b-it", {}, "cf-gateway-secret")
expect(captured?.headers["cf-aig-authorization"]).toBe("Bearer cf-gateway-secret")
expect(extractUpstreamHeaders(captured?.outerBody)?.["authorization"]).toBe("Bearer cf-gateway-secret")
})
test("bare @cf/ Workers AI models DO forward the Cloudflare token upstream", async () => {
await callThroughGateway("@cf/meta/llama-3.1-8b-instruct", {}, "cf-gateway-secret")
expect(captured?.headers["cf-aig-authorization"]).toBe("Bearer cf-gateway-secret")
expect(extractUpstreamHeaders(captured?.outerBody)?.["authorization"]).toBe("Bearer cf-gateway-secret")
})
})
@@ -3215,19 +3215,6 @@ describe("ProviderTransform.temperature - Cohere North", () => {
})
})
describe("ProviderTransform sampling defaults - Qwen", () => {
test.each(["Qwen3.8-27B", "qwen3-coder-30b-a3b-instruct"])('leaves sampling unset for "%s"', (id) => {
const model = {
id: `custom/${id}`,
api: { id },
} as any
expect(ProviderTransform.temperature(model)).toBeUndefined()
expect(ProviderTransform.topP(model)).toBeUndefined()
expect(ProviderTransform.topK(model)).toBeUndefined()
})
})
describe("ProviderTransform sampling defaults - Gemini", () => {
const model = (id: string) =>
({
@@ -1782,22 +1782,6 @@ describe("SessionNs.getUsage", () => {
expect(Number.isNaN(result.cost)).toBe(false)
})
test("ignores malformed cost fields", () => {
const model = createModel({
context: 100_000,
output: 32_000,
cost: { input: 3, output: 15, cache: { read: 0.3, write: 3.75 } },
})
Object.assign(model.cost, { input: {} })
const result = SessionNs.getUsage({
model,
usage: usage({ inputTokens: 1_000_000, outputTokens: 100_000, totalTokens: 1_100_000 }),
})
expect(result.cost).toBe(1.5)
})
test("calculates cost correctly", () => {
const model = createModel({
context: 100_000,
@@ -102,13 +102,6 @@ describe("session.system", () => {
}
})
test("selects the Kimi prompt for official provider model IDs", () => {
for (const providerID of ["kimi-for-coding", "moonshotai", "moonshotai-cn"]) {
const prompt = SystemPrompt.provider({ providerID, api: { id: "k3" } } as Provider.Model)[0]
expect(prompt).toContain("# Prompt and Tool Use")
}
})
it.effect("skills output is sorted by name and stable across calls", () =>
Effect.gen(function* () {
const prompt = yield* SystemPrompt.Service
@@ -37,9 +37,8 @@ describe("websearch provider", () => {
expect(selectWebSearchProvider(SESSION_ID, { exa: false, parallel: true })).toBe("parallel")
})
test("is enabled for OpenCode providers or explicit websearch provider flags", () => {
test("is only enabled for opencode or explicit websearch provider flags", () => {
expect(webSearchEnabled(ProviderV2.ID.opencode, { exa: false, parallel: false })).toBe(true)
expect(webSearchEnabled(ProviderV2.ID.make("opencode-go"), { exa: false, parallel: false })).toBe(true)
expect(webSearchEnabled(ProviderV2.ID.openai, { exa: false, parallel: false })).toBe(false)
expect(webSearchEnabled(ProviderV2.ID.openai, { exa: true, parallel: false })).toBe(true)
expect(webSearchEnabled(ProviderV2.ID.openai, { exa: false, parallel: true })).toBe(true)
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/plugin",
"version": "1.18.18",
"version": "1.18.17",
"type": "module",
"license": "MIT",
"scripts": {
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/sdk",
"version": "1.18.18",
"version": "1.18.17",
"type": "module",
"license": "MIT",
"scripts": {
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/server",
"version": "1.18.18",
"version": "1.18.17",
"private": true,
"type": "module",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/session-ui",
"version": "1.18.18",
"version": "1.18.17",
"private": true,
"type": "module",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/slack",
"version": "1.18.18",
"version": "1.18.17",
"type": "module",
"license": "MIT",
"scripts": {
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/stats-app",
"version": "1.18.18",
"version": "1.18.17",
"private": true,
"type": "module",
"license": "MIT",
@@ -241,7 +241,7 @@ export function Footer(props: {
{ href: "https://opencode.ai/discord", label: i18n.t("footer.community") },
{ href: "https://x.com/opencode", label: "X" },
{ href: githubLink.href, label: i18n.t("header.github") },
{ href: "https://www.youtube.com/@anomalyco", label: i18n.t("footer.youtube") },
{ href: "https://www.youtube.com/@anomaly-co", label: i18n.t("footer.youtube") },
]
const bridge = () =>
props.bridge === undefined
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/stats-core",
"version": "1.18.18",
"version": "1.18.17",
"private": true,
"type": "module",
"license": "MIT",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/stats-server",
"version": "1.18.18",
"version": "1.18.17",
"private": true,
"type": "module",
"license": "MIT",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/tui",
"version": "1.18.18",
"version": "1.18.17",
"private": true,
"type": "module",
"license": "MIT",

Some files were not shown because too many files have changed in this diff Show More