mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-24 23:01:34 -04:00
Compare commits
136 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ef72fe8f6 | |||
| 51070b6f59 | |||
| 18b4cb6819 | |||
| 0561bac189 | |||
| f4019cab3e | |||
| f8b4dd70ac | |||
| 611cc73d84 | |||
| 7cde8329bc | |||
| be15db5861 | |||
| 55f984126c | |||
| 2a6be0a03b | |||
| 2a36236132 | |||
| 105b398c2a | |||
| 9fa27bd41c | |||
| 6bb772215b | |||
| 03521003fa | |||
| 754bb7e390 | |||
| 4371298fff | |||
| 3f2e0e89ec | |||
| 4dbeeddc77 | |||
| 4161695885 | |||
| 7bbfe425f6 | |||
| f2a1d547f1 | |||
| b1ce938ebe | |||
| 03bba464d4 | |||
| 63a883a4f7 | |||
| b3bad6b581 | |||
| ca10088bdf | |||
| dd3f915956 | |||
| c11c41bd86 | |||
| fa117558ee | |||
| 17b47301ba | |||
| 3d31e4bcec | |||
| bb72277407 | |||
| 32c3637da0 | |||
| 9d466cd849 | |||
| e3bd6e0947 | |||
| dc13c6bb3d | |||
| 3a31c4ea80 | |||
| e00890c672 | |||
| 3a4c253969 | |||
| 34a83b27c3 | |||
| ff3ef6e3e6 | |||
| e2ec62d073 | |||
| bcf1103a8c | |||
| 9cb6fb6529 | |||
| 1b937c860b | |||
| ad0bb6d9a3 | |||
| 487d584402 | |||
| 57fa34f235 | |||
| 0af9dd61d2 | |||
| 8ecd4c21bf | |||
| 361a71ffad | |||
| fa8f17014c | |||
| 813e6f3cec | |||
| ba72a6ff2b | |||
| b6a1f95858 | |||
| f357e70779 | |||
| a9cac91d60 | |||
| 35fe5b7212 | |||
| 62cb3f77bd | |||
| e0b9e68a68 | |||
| 1e4c153aed | |||
| c9dc1a1b3d | |||
| 40282c1d4d | |||
| e11dbd0206 | |||
| 7b11ef5a5e | |||
| 2859603cbb | |||
| c313504c82 | |||
| e49772a8b4 | |||
| 08faeb3893 | |||
| 5e75e5e990 | |||
| 5cc5b622f0 | |||
| 11e8110f9e | |||
| 82dee24302 | |||
| ad192a59b5 | |||
| 71d08e94d5 | |||
| b155b15694 | |||
| d06bf487a5 | |||
| ccccd75328 | |||
| 03d65f36d3 | |||
| f4a89683da | |||
| f715478a13 | |||
| e0e9bd7d5f | |||
| 5ccb1e88e1 | |||
| be469f328c | |||
| fc80874f45 | |||
| 3d26b12251 | |||
| 1b77242d40 | |||
| 4c5960dc4b | |||
| e2505d434a | |||
| a466a357b6 | |||
| 6386e67949 | |||
| 16af134053 | |||
| d545d8fba5 | |||
| da4730e4a4 | |||
| 18fc3eea7c | |||
| 101ff6d1a2 | |||
| 20ad497bc8 | |||
| 1b18a50418 | |||
| 0a6397272c | |||
| 3477d28a87 | |||
| fb772e8a02 | |||
| 4e29e04f24 | |||
| fbcd4faa61 | |||
| da3ba63872 | |||
| e2a2bc301d | |||
| 72824fe65d | |||
| 64b4f7df4c | |||
| 7774461bbf | |||
| 8b65fa2ef6 | |||
| 0033bb3559 | |||
| ad905f8e6c | |||
| 9b0dd36cda | |||
| 4e81a0b73f | |||
| 32320409b1 | |||
| 040b856140 | |||
| 65c35977bd | |||
| 57075d8cdc | |||
| e14acea581 | |||
| 7af274a921 | |||
| a97fec8af5 | |||
| 2cba7e227d | |||
| 4d68d30b48 | |||
| 5a0e07efcf | |||
| cba6b5f2f7 | |||
| 1c965451b5 | |||
| a0f8dccbfe | |||
| fb8344f3c2 | |||
| 3fd77ae980 | |||
| 976c185172 | |||
| 4643e65ad6 | |||
| e23586af26 | |||
| 92d29ba4a3 | |||
| 886fd98f52 | |||
| 722e717e99 |
@@ -1,37 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
},
|
},
|
||||||
"packages/app": {
|
"packages/app": {
|
||||||
"name": "@opencode-ai/app",
|
"name": "@opencode-ai/app",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@corvu/drawer": "catalog:",
|
"@corvu/drawer": "catalog:",
|
||||||
"@dnd-kit/abstract": "0.5.0",
|
"@dnd-kit/abstract": "0.5.0",
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
},
|
},
|
||||||
"packages/cli": {
|
"packages/cli": {
|
||||||
"name": "@opencode-ai/cli",
|
"name": "@opencode-ai/cli",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"bin": {
|
"bin": {
|
||||||
"lildax": "./bin/lildax.cjs",
|
"lildax": "./bin/lildax.cjs",
|
||||||
},
|
},
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
},
|
},
|
||||||
"packages/codemode": {
|
"packages/codemode": {
|
||||||
"name": "@opencode-ai/codemode",
|
"name": "@opencode-ai/codemode",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"acorn": "8.15.0",
|
"acorn": "8.15.0",
|
||||||
"effect": "catalog:",
|
"effect": "catalog:",
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/app": {
|
"packages/console/app": {
|
||||||
"name": "@opencode-ai/console-app",
|
"name": "@opencode-ai/console-app",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cloudflare/vite-plugin": "1.15.2",
|
"@cloudflare/vite-plugin": "1.15.2",
|
||||||
"@ibm/plex": "6.4.1",
|
"@ibm/plex": "6.4.1",
|
||||||
@@ -194,7 +194,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/core": {
|
"packages/console/core": {
|
||||||
"name": "@opencode-ai/console-core",
|
"name": "@opencode-ai/console-core",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-sts": "3.782.0",
|
"@aws-sdk/client-sts": "3.782.0",
|
||||||
"@jsx-email/render": "1.1.1",
|
"@jsx-email/render": "1.1.1",
|
||||||
@@ -221,7 +221,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/function": {
|
"packages/console/function": {
|
||||||
"name": "@opencode-ai/console-function",
|
"name": "@opencode-ai/console-function",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/anthropic": "3.0.82",
|
"@ai-sdk/anthropic": "3.0.82",
|
||||||
"@ai-sdk/openai": "3.0.48",
|
"@ai-sdk/openai": "3.0.48",
|
||||||
@@ -243,7 +243,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/mail": {
|
"packages/console/mail": {
|
||||||
"name": "@opencode-ai/console-mail",
|
"name": "@opencode-ai/console-mail",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jsx-email/all": "2.2.3",
|
"@jsx-email/all": "2.2.3",
|
||||||
"@jsx-email/cli": "1.4.3",
|
"@jsx-email/cli": "1.4.3",
|
||||||
@@ -267,7 +267,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/support": {
|
"packages/console/support": {
|
||||||
"name": "@opencode-ai/console-support",
|
"name": "@opencode-ai/console-support",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cloudflare/vite-plugin": "1.15.2",
|
"@cloudflare/vite-plugin": "1.15.2",
|
||||||
"@opencode-ai/console-core": "workspace:*",
|
"@opencode-ai/console-core": "workspace:*",
|
||||||
@@ -287,13 +287,13 @@
|
|||||||
},
|
},
|
||||||
"packages/core": {
|
"packages/core": {
|
||||||
"name": "@opencode-ai/core",
|
"name": "@opencode-ai/core",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"bin": {
|
"bin": {
|
||||||
"opencode": "./bin/opencode",
|
"opencode": "./bin/opencode",
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/alibaba": "1.0.17",
|
"@ai-sdk/alibaba": "1.0.17",
|
||||||
"@ai-sdk/amazon-bedrock": "4.0.112",
|
"@ai-sdk/amazon-bedrock": "4.0.158",
|
||||||
"@ai-sdk/anthropic": "3.0.82",
|
"@ai-sdk/anthropic": "3.0.82",
|
||||||
"@ai-sdk/azure": "3.0.88",
|
"@ai-sdk/azure": "3.0.88",
|
||||||
"@ai-sdk/cerebras": "2.0.41",
|
"@ai-sdk/cerebras": "2.0.41",
|
||||||
@@ -301,7 +301,7 @@
|
|||||||
"@ai-sdk/deepinfra": "2.0.41",
|
"@ai-sdk/deepinfra": "2.0.41",
|
||||||
"@ai-sdk/gateway": "3.0.104",
|
"@ai-sdk/gateway": "3.0.104",
|
||||||
"@ai-sdk/google": "3.0.73",
|
"@ai-sdk/google": "3.0.73",
|
||||||
"@ai-sdk/google-vertex": "4.0.128",
|
"@ai-sdk/google-vertex": "4.0.181",
|
||||||
"@ai-sdk/groq": "3.0.31",
|
"@ai-sdk/groq": "3.0.31",
|
||||||
"@ai-sdk/mistral": "3.0.51",
|
"@ai-sdk/mistral": "3.0.51",
|
||||||
"@ai-sdk/openai": "3.0.84",
|
"@ai-sdk/openai": "3.0.84",
|
||||||
@@ -381,7 +381,7 @@
|
|||||||
},
|
},
|
||||||
"packages/desktop": {
|
"packages/desktop": {
|
||||||
"name": "@opencode-ai/desktop",
|
"name": "@opencode-ai/desktop",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@zip.js/zip.js": "2.7.62",
|
"@zip.js/zip.js": "2.7.62",
|
||||||
"drizzle-orm": "catalog:",
|
"drizzle-orm": "catalog:",
|
||||||
@@ -435,7 +435,7 @@
|
|||||||
},
|
},
|
||||||
"packages/effect-drizzle-sqlite": {
|
"packages/effect-drizzle-sqlite": {
|
||||||
"name": "@opencode-ai/effect-drizzle-sqlite",
|
"name": "@opencode-ai/effect-drizzle-sqlite",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"drizzle-orm": "catalog:",
|
"drizzle-orm": "catalog:",
|
||||||
"effect": "catalog:",
|
"effect": "catalog:",
|
||||||
@@ -449,7 +449,7 @@
|
|||||||
},
|
},
|
||||||
"packages/effect-sqlite-node": {
|
"packages/effect-sqlite-node": {
|
||||||
"name": "@opencode-ai/effect-sqlite-node",
|
"name": "@opencode-ai/effect-sqlite-node",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"effect": "catalog:",
|
"effect": "catalog:",
|
||||||
},
|
},
|
||||||
@@ -461,7 +461,7 @@
|
|||||||
},
|
},
|
||||||
"packages/enterprise": {
|
"packages/enterprise": {
|
||||||
"name": "@opencode-ai/enterprise",
|
"name": "@opencode-ai/enterprise",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hono/standard-validator": "catalog:",
|
"@hono/standard-validator": "catalog:",
|
||||||
"@opencode-ai/core": "workspace:*",
|
"@opencode-ai/core": "workspace:*",
|
||||||
@@ -493,7 +493,7 @@
|
|||||||
},
|
},
|
||||||
"packages/function": {
|
"packages/function": {
|
||||||
"name": "@opencode-ai/function",
|
"name": "@opencode-ai/function",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/auth-app": "8.0.1",
|
"@octokit/auth-app": "8.0.1",
|
||||||
"@octokit/rest": "catalog:",
|
"@octokit/rest": "catalog:",
|
||||||
@@ -509,7 +509,7 @@
|
|||||||
},
|
},
|
||||||
"packages/http-recorder": {
|
"packages/http-recorder": {
|
||||||
"name": "@opencode-ai/http-recorder",
|
"name": "@opencode-ai/http-recorder",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@effect/platform-node": "4.0.0-beta.83",
|
"@effect/platform-node": "4.0.0-beta.83",
|
||||||
"@effect/platform-node-shared": "4.0.0-beta.83",
|
"@effect/platform-node-shared": "4.0.0-beta.83",
|
||||||
@@ -540,7 +540,7 @@
|
|||||||
},
|
},
|
||||||
"packages/llm": {
|
"packages/llm": {
|
||||||
"name": "@opencode-ai/llm",
|
"name": "@opencode-ai/llm",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/schema": "workspace:*",
|
"@opencode-ai/schema": "workspace:*",
|
||||||
"@smithy/eventstream-codec": "4.2.14",
|
"@smithy/eventstream-codec": "4.2.14",
|
||||||
@@ -559,7 +559,7 @@
|
|||||||
},
|
},
|
||||||
"packages/opencode": {
|
"packages/opencode": {
|
||||||
"name": "opencode",
|
"name": "opencode",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"bin": {
|
"bin": {
|
||||||
"opencode": "./bin/opencode",
|
"opencode": "./bin/opencode",
|
||||||
},
|
},
|
||||||
@@ -568,7 +568,7 @@
|
|||||||
"@actions/github": "6.0.1",
|
"@actions/github": "6.0.1",
|
||||||
"@agentclientprotocol/sdk": "0.21.0",
|
"@agentclientprotocol/sdk": "0.21.0",
|
||||||
"@ai-sdk/alibaba": "1.0.17",
|
"@ai-sdk/alibaba": "1.0.17",
|
||||||
"@ai-sdk/amazon-bedrock": "4.0.112",
|
"@ai-sdk/amazon-bedrock": "4.0.158",
|
||||||
"@ai-sdk/anthropic": "3.0.82",
|
"@ai-sdk/anthropic": "3.0.82",
|
||||||
"@ai-sdk/azure": "3.0.88",
|
"@ai-sdk/azure": "3.0.88",
|
||||||
"@ai-sdk/cerebras": "2.0.60",
|
"@ai-sdk/cerebras": "2.0.60",
|
||||||
@@ -576,7 +576,7 @@
|
|||||||
"@ai-sdk/deepinfra": "2.0.41",
|
"@ai-sdk/deepinfra": "2.0.41",
|
||||||
"@ai-sdk/gateway": "3.0.104",
|
"@ai-sdk/gateway": "3.0.104",
|
||||||
"@ai-sdk/google": "3.0.73",
|
"@ai-sdk/google": "3.0.73",
|
||||||
"@ai-sdk/google-vertex": "4.0.128",
|
"@ai-sdk/google-vertex": "4.0.181",
|
||||||
"@ai-sdk/groq": "3.0.31",
|
"@ai-sdk/groq": "3.0.31",
|
||||||
"@ai-sdk/mistral": "3.0.51",
|
"@ai-sdk/mistral": "3.0.51",
|
||||||
"@ai-sdk/openai": "3.0.84",
|
"@ai-sdk/openai": "3.0.84",
|
||||||
@@ -690,7 +690,7 @@
|
|||||||
},
|
},
|
||||||
"packages/plugin": {
|
"packages/plugin": {
|
||||||
"name": "@opencode-ai/plugin",
|
"name": "@opencode-ai/plugin",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/provider": "3.0.8",
|
"@ai-sdk/provider": "3.0.8",
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
@@ -766,7 +766,7 @@
|
|||||||
},
|
},
|
||||||
"packages/sdk/js": {
|
"packages/sdk/js": {
|
||||||
"name": "@opencode-ai/sdk",
|
"name": "@opencode-ai/sdk",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cross-spawn": "catalog:",
|
"cross-spawn": "catalog:",
|
||||||
},
|
},
|
||||||
@@ -781,7 +781,7 @@
|
|||||||
},
|
},
|
||||||
"packages/server": {
|
"packages/server": {
|
||||||
"name": "@opencode-ai/server",
|
"name": "@opencode-ai/server",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/core": "workspace:*",
|
"@opencode-ai/core": "workspace:*",
|
||||||
"@opencode-ai/protocol": "workspace:*",
|
"@opencode-ai/protocol": "workspace:*",
|
||||||
@@ -796,7 +796,7 @@
|
|||||||
},
|
},
|
||||||
"packages/session-ui": {
|
"packages/session-ui": {
|
||||||
"name": "@opencode-ai/session-ui",
|
"name": "@opencode-ai/session-ui",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kobalte/core": "catalog:",
|
"@kobalte/core": "catalog:",
|
||||||
"@opencode-ai/client": "file:../app/vendor/opencode-ai-client-1.17.13-v2.tgz",
|
"@opencode-ai/client": "file:../app/vendor/opencode-ai-client-1.17.13-v2.tgz",
|
||||||
@@ -836,7 +836,7 @@
|
|||||||
},
|
},
|
||||||
"packages/slack": {
|
"packages/slack": {
|
||||||
"name": "@opencode-ai/slack",
|
"name": "@opencode-ai/slack",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
"@slack/bolt": "^3.17.1",
|
"@slack/bolt": "^3.17.1",
|
||||||
@@ -849,7 +849,7 @@
|
|||||||
},
|
},
|
||||||
"packages/stats/app": {
|
"packages/stats/app": {
|
||||||
"name": "@opencode-ai/stats-app",
|
"name": "@opencode-ai/stats-app",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ibm/plex": "6.4.1",
|
"@ibm/plex": "6.4.1",
|
||||||
"@kobalte/core": "catalog:",
|
"@kobalte/core": "catalog:",
|
||||||
@@ -883,7 +883,7 @@
|
|||||||
},
|
},
|
||||||
"packages/stats/core": {
|
"packages/stats/core": {
|
||||||
"name": "@opencode-ai/stats-core",
|
"name": "@opencode-ai/stats-core",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-athena": "3.933.0",
|
"@aws-sdk/client-athena": "3.933.0",
|
||||||
"@planetscale/database": "1.19.0",
|
"@planetscale/database": "1.19.0",
|
||||||
@@ -902,7 +902,7 @@
|
|||||||
},
|
},
|
||||||
"packages/stats/server": {
|
"packages/stats/server": {
|
||||||
"name": "@opencode-ai/stats-server",
|
"name": "@opencode-ai/stats-server",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-firehose": "3.933.0",
|
"@aws-sdk/client-firehose": "3.933.0",
|
||||||
"@effect/platform-node": "catalog:",
|
"@effect/platform-node": "catalog:",
|
||||||
@@ -944,7 +944,7 @@
|
|||||||
},
|
},
|
||||||
"packages/tui": {
|
"packages/tui": {
|
||||||
"name": "@opencode-ai/tui",
|
"name": "@opencode-ai/tui",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/core": "workspace:*",
|
"@opencode-ai/core": "workspace:*",
|
||||||
"@opencode-ai/plugin": "workspace:*",
|
"@opencode-ai/plugin": "workspace:*",
|
||||||
@@ -971,7 +971,7 @@
|
|||||||
},
|
},
|
||||||
"packages/ui": {
|
"packages/ui": {
|
||||||
"name": "@opencode-ai/ui",
|
"name": "@opencode-ai/ui",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kobalte/core": "catalog:",
|
"@kobalte/core": "catalog:",
|
||||||
"@pierre/diffs": "catalog:",
|
"@pierre/diffs": "catalog:",
|
||||||
@@ -1022,7 +1022,7 @@
|
|||||||
},
|
},
|
||||||
"packages/web": {
|
"packages/web": {
|
||||||
"name": "@opencode-ai/web",
|
"name": "@opencode-ai/web",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/cloudflare": "12.6.3",
|
"@astrojs/cloudflare": "12.6.3",
|
||||||
"@astrojs/markdown-remark": "6.3.1",
|
"@astrojs/markdown-remark": "6.3.1",
|
||||||
@@ -1173,7 +1173,7 @@
|
|||||||
|
|
||||||
"@ai-sdk/alibaba": ["@ai-sdk/alibaba@1.0.17", "", { "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-ZbE+U5bWz2JBc5DERLowx5+TKbjGBE93LqKZAWvuEn7HOSQMraxFMZuc0ST335QZJAyfBOzh7m1mPQ+y7EaaoA=="],
|
"@ai-sdk/alibaba": ["@ai-sdk/alibaba@1.0.17", "", { "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-ZbE+U5bWz2JBc5DERLowx5+TKbjGBE93LqKZAWvuEn7HOSQMraxFMZuc0ST335QZJAyfBOzh7m1mPQ+y7EaaoA=="],
|
||||||
|
|
||||||
"@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@4.0.112", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.81", "@ai-sdk/openai": "3.0.67", "@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-PsSh7a6qW+3kQXPs1kD4wDwuZby0t1PIaB6j/1aMKmPFJ5LxcIcULLMF/bjITLt5o/8lc0t6TXIwG0zlhH7uZw=="],
|
"@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@4.0.158", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.111", "@ai-sdk/openai": "3.0.98", "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.46", "@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-yZebHEszUzPLsK+Rq5sVZJkJj7EYDgY+Lz36IGf/RSkSC5LOMDbVKoQ55S8xNzJqVjUDqlWuZiQzg40HQslmCw=="],
|
||||||
|
|
||||||
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.82", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-WKKou2wbhGGYV8PSALAPyV2YY4nfCqCPkyBzYtJtDA9yCcIFwsbtkTNgg7bqtLCVzeEsY7wwxRoCWy+EMfrw/A=="],
|
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.82", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-WKKou2wbhGGYV8PSALAPyV2YY4nfCqCPkyBzYtJtDA9yCcIFwsbtkTNgg7bqtLCVzeEsY7wwxRoCWy+EMfrw/A=="],
|
||||||
|
|
||||||
@@ -1197,7 +1197,7 @@
|
|||||||
|
|
||||||
"@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": ["@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.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/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/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=="],
|
"@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=="],
|
||||||
|
|
||||||
@@ -5641,13 +5641,13 @@
|
|||||||
|
|
||||||
"@ai-sdk/alibaba/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="],
|
"@ai-sdk/alibaba/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="],
|
||||||
|
|
||||||
"@ai-sdk/amazon-bedrock/@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.81", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-B1JDd9Ugq9R5AgIaW3674lhGCMMYJcPUxnrZh8fzbGojgg4QvHFRv6eZahGQAUsmGHbcf74G9bdSBDLWQGY2GA=="],
|
"@ai-sdk/amazon-bedrock/@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.111", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.46" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-atgBW8jZPr/KuaKX5FvDIHuXBI8VCol6kVeoD4P0657+VXR73QsLogXQVN/Zt5FHtq9WzpdIZseCJiXPqkgwwA=="],
|
||||||
|
|
||||||
"@ai-sdk/amazon-bedrock/@ai-sdk/openai": ["@ai-sdk/openai@3.0.67", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-oAiGC9eWG7IgtdsdS74bOCnAAHarAfTJhWN9x5INwnWPekL802AvF+0I5DvLzIF1MIRmNw4N8mPSL/GUVbX9Mw=="],
|
"@ai-sdk/amazon-bedrock/@ai-sdk/openai": ["@ai-sdk/openai@3.0.98", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.46" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-nAvp8pVOUJ3znJHRzZs54Y7CJQSikOW1Ty7LTdtQT+/pgtAwqhuKd8oaXbiW2xQaYBdH2i8o9AcEpcUdXIyF+g=="],
|
||||||
|
|
||||||
"@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-sdk/amazon-bedrock/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="],
|
||||||
|
|
||||||
"@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-sdk/amazon-bedrock/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.46", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8", "undici": "^6.28.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-tEtld97plCFiYevsJuOkGkeuhQndeMWFBVrJS4AjnbD5AqrNSXRCe0p+BZ3Cju/sxDeeZ9ym3q9YUV8fASA7aQ=="],
|
||||||
|
|
||||||
"@ai-sdk/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-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=="],
|
||||||
|
|
||||||
@@ -5691,13 +5691,15 @@
|
|||||||
|
|
||||||
"@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/@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.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/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/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/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/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/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-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/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/groq/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="],
|
"@ai-sdk/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=="],
|
||||||
|
|
||||||
@@ -6181,8 +6183,6 @@
|
|||||||
|
|
||||||
"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/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/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-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/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.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/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=="],
|
||||||
@@ -6589,6 +6589,8 @@
|
|||||||
|
|
||||||
"@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
"@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||||
|
|
||||||
|
"@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils/undici": ["undici@6.28.0", "", {}, "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA=="],
|
||||||
|
|
||||||
"@ai-sdk/anthropic/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
"@ai-sdk/anthropic/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||||
|
|
||||||
"@ai-sdk/azure/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
"@ai-sdk/azure/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||||
@@ -6615,6 +6617,8 @@
|
|||||||
|
|
||||||
"@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/@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/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=="],
|
"@ai-sdk/groq/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||||
@@ -7015,12 +7019,6 @@
|
|||||||
|
|
||||||
"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/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/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-gateway-provider/@ai-sdk/google-vertex/@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-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-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": ["@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/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=="],
|
||||||
@@ -7463,10 +7461,6 @@
|
|||||||
|
|
||||||
"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/cohere/@ai-sdk/provider-utils/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="],
|
||||||
|
|
||||||
"ai-gateway-provider/@ai-sdk/google-vertex/@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-vertex/@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/@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/google/@ai-sdk/provider-utils/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="],
|
||||||
|
|||||||
+4
-4
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"nodeModules": {
|
"nodeModules": {
|
||||||
"x86_64-linux": "sha256-TNwKfqxD83UpZuCKN8FdEWN+CcQUP9CkCQSLGNqR/sA=",
|
"x86_64-linux": "sha256-Be1I6OG6UitofhcGu2BeNzevmoQXc4Or5r/NPzwtft4=",
|
||||||
"aarch64-linux": "sha256-qzvOJZzmq2QhlauElw8GwgQnCPHdhexI52L0md5zrxQ=",
|
"aarch64-linux": "sha256-O+d+26CQIjZ08Rn8Qm3IytdDqIMbPdhzaGOZeUKAvIU=",
|
||||||
"aarch64-darwin": "sha256-ZzoyLayOFfcYUAg35ZbZ2WapxDdd9IUWqy2xkxZH4QM=",
|
"aarch64-darwin": "sha256-ObS50y/oy6fM9wSGUL/wx6O0+fTWHC04mXJNd7w/2Z0=",
|
||||||
"x86_64-darwin": "sha256-maP/qLeaC3q8VcmNIPyIKlnplxFXJ7ULho3v21/16Mw="
|
"x86_64-darwin": "sha256-eoR7ZSyH62Fq2ZaW2b2QqU2FC97rYxTMeEe+djT0nto="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,39 @@ test("keeps the file-browser sidebar mounted when switching file tabs", async ({
|
|||||||
await expect.poll(() => viewport.evaluate((element) => element.scrollTop)).toBe(scrolled)
|
await expect.poll(() => viewport.evaluate((element) => element.scrollTop)).toBe(scrolled)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("keeps previous file search results visible while the next search loads", async ({ page }) => {
|
||||||
|
const searchPending = Promise.withResolvers<void>()
|
||||||
|
await setup(page, async ({ query }) => {
|
||||||
|
if (query === "file-0") return ["file-00.ts"]
|
||||||
|
if (query === "file-7") {
|
||||||
|
await searchPending.promise
|
||||||
|
return ["file-79.ts"]
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
})
|
||||||
|
|
||||||
|
await page.goto(`/server/${base64Encode(server)}/session/${sessionID}`)
|
||||||
|
await expectSessionTitle(page, title)
|
||||||
|
|
||||||
|
const panel = page.locator("#review-panel")
|
||||||
|
await panel.getByRole("button", { name: "Open file" }).click()
|
||||||
|
const filter = panel.getByRole("combobox", { name: "Filter files" })
|
||||||
|
await filter.fill("file-0")
|
||||||
|
await expect(panel.getByRole("option", { name: "file-00.ts" })).toBeVisible()
|
||||||
|
|
||||||
|
const nextSearch = page.waitForRequest((request) => {
|
||||||
|
const url = new URL(request.url())
|
||||||
|
return url.pathname === "/find/file" && url.searchParams.get("query") === "file-7"
|
||||||
|
})
|
||||||
|
await filter.fill("file-7")
|
||||||
|
await nextSearch
|
||||||
|
await expect(panel.getByRole("option", { name: "file-00.ts" })).toBeVisible()
|
||||||
|
|
||||||
|
searchPending.resolve()
|
||||||
|
await expect(panel.getByRole("option", { name: "file-79.ts" })).toBeVisible()
|
||||||
|
await expect(panel.getByRole("option", { name: "file-00.ts" })).toBeHidden()
|
||||||
|
})
|
||||||
|
|
||||||
type Probed = HTMLElement & { __e2eProbe?: string }
|
type Probed = HTMLElement & { __e2eProbe?: string }
|
||||||
|
|
||||||
async function writeProbe(page: Page) {
|
async function writeProbe(page: Page) {
|
||||||
@@ -74,7 +107,10 @@ async function readProbe(page: Page) {
|
|||||||
.evaluate((el) => (el as Probed).__e2eProbe)
|
.evaluate((el) => (el as Probed).__e2eProbe)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setup(page: Page) {
|
async function setup(
|
||||||
|
page: Page,
|
||||||
|
findFiles?: (input: { query: string; dirs?: string; limit?: number }) => unknown | Promise<unknown>,
|
||||||
|
) {
|
||||||
await mockOpenCodeServer(page, {
|
await mockOpenCodeServer(page, {
|
||||||
directory,
|
directory,
|
||||||
project: {
|
project: {
|
||||||
@@ -119,6 +155,7 @@ async function setup(page: Page) {
|
|||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
fileContent: (path) => ({ type: "text", content: `contents:${path}` }),
|
fileContent: (path) => ({ type: "text", content: `contents:${path}` }),
|
||||||
|
findFiles,
|
||||||
pageMessages: () => ({ items: [] }),
|
pageMessages: () => ({ items: [] }),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export interface MockServerConfig {
|
|||||||
questions?: unknown[] | (() => unknown[])
|
questions?: unknown[] | (() => unknown[])
|
||||||
fileList?: (path: string) => unknown | Promise<unknown>
|
fileList?: (path: string) => unknown | Promise<unknown>
|
||||||
fileContent?: (path: string) => unknown | Promise<unknown>
|
fileContent?: (path: string) => unknown | Promise<unknown>
|
||||||
findFiles?: (input: { query: string; dirs?: string; limit?: number }) => unknown
|
findFiles?: (input: { query: string; dirs?: string; limit?: number }) => unknown | Promise<unknown>
|
||||||
sessionStatus?: Record<string, unknown> | (() => Record<string, unknown>)
|
sessionStatus?: Record<string, unknown> | (() => Record<string, unknown>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/app",
|
"name": "@opencode-ai/app",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"description": "",
|
"description": "",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ function ModelSelectorPopoverV2View(props: {
|
|||||||
<For each={groups()}>
|
<For each={groups()}>
|
||||||
{(group) => (
|
{(group) => (
|
||||||
<MenuV2.Group>
|
<MenuV2.Group>
|
||||||
<MenuV2.GroupLabel class="gap-2 px-3">
|
<MenuV2.GroupLabel class="sticky top-0 z-10 gap-2 bg-v2-background-bg-layer-01 px-3">
|
||||||
<span class="min-w-0 truncate">{group.items[0].provider.name}</span>
|
<span class="min-w-0 truncate">{group.items[0].provider.name}</span>
|
||||||
</MenuV2.GroupLabel>
|
</MenuV2.GroupLabel>
|
||||||
<MenuV2.RadioGroup value={props.current()}>
|
<MenuV2.RadioGroup value={props.current()}>
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ function ServerForm(props: ServerFormProps) {
|
|||||||
type="text"
|
type="text"
|
||||||
label={language.t("dialog.server.add.name")}
|
label={language.t("dialog.server.add.name")}
|
||||||
placeholder={language.t("dialog.server.add.namePlaceholder")}
|
placeholder={language.t("dialog.server.add.namePlaceholder")}
|
||||||
value={props.name}
|
defaultValue={props.name}
|
||||||
disabled={props.busy}
|
disabled={props.busy}
|
||||||
onChange={props.onNameChange}
|
onChange={props.onNameChange}
|
||||||
onKeyDown={keyDown}
|
onKeyDown={keyDown}
|
||||||
@@ -155,7 +155,7 @@ function ServerForm(props: ServerFormProps) {
|
|||||||
type="text"
|
type="text"
|
||||||
label={language.t("dialog.server.add.username")}
|
label={language.t("dialog.server.add.username")}
|
||||||
placeholder={language.t("dialog.server.add.usernamePlaceholder")}
|
placeholder={language.t("dialog.server.add.usernamePlaceholder")}
|
||||||
value={props.username}
|
defaultValue={props.username}
|
||||||
disabled={props.busy}
|
disabled={props.busy}
|
||||||
onChange={props.onUsernameChange}
|
onChange={props.onUsernameChange}
|
||||||
onKeyDown={keyDown}
|
onKeyDown={keyDown}
|
||||||
@@ -164,7 +164,7 @@ function ServerForm(props: ServerFormProps) {
|
|||||||
type="password"
|
type="password"
|
||||||
label={language.t("dialog.server.add.password")}
|
label={language.t("dialog.server.add.password")}
|
||||||
placeholder={language.t("dialog.server.add.passwordPlaceholder")}
|
placeholder={language.t("dialog.server.add.passwordPlaceholder")}
|
||||||
value={props.password}
|
defaultValue={props.password}
|
||||||
disabled={props.busy}
|
disabled={props.busy}
|
||||||
onChange={props.onPasswordChange}
|
onChange={props.onPasswordChange}
|
||||||
onKeyDown={keyDown}
|
onKeyDown={keyDown}
|
||||||
|
|||||||
@@ -972,17 +972,6 @@ export default function LegacyLayout(props: ParentProps) {
|
|||||||
keybind: "shift+alt+arrowdown",
|
keybind: "shift+alt+arrowdown",
|
||||||
onSelect: () => navigateSessionByUnseen(1),
|
onSelect: () => navigateSessionByUnseen(1),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: "session.archive",
|
|
||||||
title: language.t("command.session.archive"),
|
|
||||||
category: language.t("command.category.session"),
|
|
||||||
keybind: "mod+shift+backspace",
|
|
||||||
disabled: !params.dir || !params.id,
|
|
||||||
onSelect: () => {
|
|
||||||
const session = currentSessions().find((s) => s.id === params.id)
|
|
||||||
if (session) void archiveSession(session)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: "workspace.new",
|
id: "workspace.new",
|
||||||
title: language.t("workspace.new"),
|
title: language.t("workspace.new"),
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { useNavigate } from "@solidjs/router"
|
||||||
|
import { produce } from "solid-js/store"
|
||||||
|
import { notifySessionTabsRemoved } from "@/components/titlebar-session-events"
|
||||||
|
import { useLanguage } from "@/context/language"
|
||||||
|
import { useSDK } from "@/context/sdk"
|
||||||
|
import { useSync } from "@/context/sync"
|
||||||
|
import { useTabs } from "@/context/tabs"
|
||||||
|
import { errorMessage } from "@/pages/layout/helpers"
|
||||||
|
import { useSessionKey } from "@/pages/session/session-layout"
|
||||||
|
import { legacySessionHref, requireServerKey, sessionHref } from "@/utils/session-route"
|
||||||
|
import { showToast } from "@/utils/toast"
|
||||||
|
|
||||||
|
export function useSessionArchive() {
|
||||||
|
const language = useLanguage()
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const sdk = useSDK()
|
||||||
|
const sync = useSync()
|
||||||
|
const tabs = useTabs()
|
||||||
|
const { params } = useSessionKey()
|
||||||
|
|
||||||
|
const navigateAfterRemoval = (sessionID: string, parentID?: string, nextSessionID?: string) => {
|
||||||
|
if (params.id !== sessionID) return
|
||||||
|
const href = (id: string) =>
|
||||||
|
params.serverKey ? sessionHref(requireServerKey(params.serverKey), id) : legacySessionHref(sdk().directory, id)
|
||||||
|
if (parentID) {
|
||||||
|
navigate(href(parentID))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (nextSessionID) {
|
||||||
|
navigate(href(nextSessionID))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (params.serverKey) {
|
||||||
|
tabs.newDraft({ server: requireServerKey(params.serverKey), directory: sdk().directory })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
navigate(`/${params.dir}/session`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const archive = async (sessionID: string) => {
|
||||||
|
const session = sync().session.get(sessionID)
|
||||||
|
if (!session) return
|
||||||
|
if ((await sdk().protocol) !== "v1") return
|
||||||
|
|
||||||
|
const sessions = sync().data.session ?? []
|
||||||
|
const index = sessions.findIndex((s) => s.id === sessionID)
|
||||||
|
const nextSession = index === -1 ? undefined : (sessions[index + 1] ?? sessions[index - 1])
|
||||||
|
|
||||||
|
await sdk()
|
||||||
|
.client.session.update({ sessionID, directory: sdk().directory, time: { archived: Date.now() } })
|
||||||
|
.then(() => {
|
||||||
|
sync().set(
|
||||||
|
produce((draft) => {
|
||||||
|
const index = draft.session.findIndex((s) => s.id === sessionID)
|
||||||
|
if (index !== -1) draft.session.splice(index, 1)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
sync().session.evict(sessionID)
|
||||||
|
navigateAfterRemoval(sessionID, session.parentID, nextSession?.id)
|
||||||
|
notifySessionTabsRemoved({ directory: sdk().directory, sessionIDs: [sessionID] })
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
showToast({
|
||||||
|
title: language.t("common.requestFailed"),
|
||||||
|
description: errorMessage(err, language.t("common.requestFailed")),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return { archive, navigateAfterRemoval }
|
||||||
|
}
|
||||||
@@ -63,10 +63,10 @@ import { SessionContextUsage } from "@/components/session-context-usage"
|
|||||||
import { useDialog } from "@opencode-ai/ui/context/dialog"
|
import { useDialog } from "@opencode-ai/ui/context/dialog"
|
||||||
import { useLanguage } from "@/context/language"
|
import { useLanguage } from "@/context/language"
|
||||||
import { useSessionKey } from "@/pages/session/session-layout"
|
import { useSessionKey } from "@/pages/session/session-layout"
|
||||||
|
import { useSessionArchive } from "@/pages/session/session-archive"
|
||||||
import { useServerSDK } from "@/context/server-sdk"
|
import { useServerSDK } from "@/context/server-sdk"
|
||||||
import { usePlatform } from "@/context/platform"
|
import { usePlatform } from "@/context/platform"
|
||||||
import { useSettings } from "@/context/settings"
|
import { useSettings } from "@/context/settings"
|
||||||
import { useTabs } from "@/context/tabs"
|
|
||||||
import { legacySessionHref, requireServerKey, sessionHref } from "@/utils/session-route"
|
import { legacySessionHref, requireServerKey, sessionHref } from "@/utils/session-route"
|
||||||
import { useSDK } from "@/context/sdk"
|
import { useSDK } from "@/context/sdk"
|
||||||
import { useSync } from "@/context/sync"
|
import { useSync } from "@/context/sync"
|
||||||
@@ -263,8 +263,8 @@ export function MessageTimeline(props: {
|
|||||||
const sdk = useSDK()
|
const sdk = useSDK()
|
||||||
const sync = useSync()
|
const sync = useSync()
|
||||||
const settings = useSettings()
|
const settings = useSettings()
|
||||||
const tabs = useTabs()
|
|
||||||
const dialog = useDialog()
|
const dialog = useDialog()
|
||||||
|
const sessionArchive = useSessionArchive()
|
||||||
const language = useLanguage()
|
const language = useLanguage()
|
||||||
const { params, sessionKey } = useSessionKey()
|
const { params, sessionKey } = useSessionKey()
|
||||||
const ownerSessionKey = sessionKey()
|
const ownerSessionKey = sessionKey()
|
||||||
@@ -790,25 +790,6 @@ export function MessageTimeline(props: {
|
|||||||
titleMutation.mutate({ id, title: next })
|
titleMutation.mutate({ id, title: next })
|
||||||
}
|
}
|
||||||
|
|
||||||
const navigateAfterSessionRemoval = (sessionID: string, parentID?: string, nextSessionID?: string) => {
|
|
||||||
if (params.id !== sessionID) return
|
|
||||||
const href = (id: string) =>
|
|
||||||
params.serverKey ? sessionHref(requireServerKey(params.serverKey), id) : legacySessionHref(sdk().directory, id)
|
|
||||||
if (parentID) {
|
|
||||||
navigate(href(parentID))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (nextSessionID) {
|
|
||||||
navigate(href(nextSessionID))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (params.serverKey) {
|
|
||||||
tabs.newDraft({ server: requireServerKey(params.serverKey), directory: sdk().directory })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
navigate(`/${params.dir}/session`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const exportSession = async (sessionID: string) => {
|
const exportSession = async (sessionID: string) => {
|
||||||
try {
|
try {
|
||||||
const data = await fetchSessionExport({
|
const data = await fetchSessionExport({
|
||||||
@@ -832,36 +813,6 @@ export function MessageTimeline(props: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const archiveSession = async (sessionID: string) => {
|
|
||||||
const session = sync().session.get(sessionID)
|
|
||||||
if (!session) return
|
|
||||||
if ((await sdk().protocol) !== "v1") return
|
|
||||||
|
|
||||||
const sessions = sync().data.session ?? []
|
|
||||||
const index = sessions.findIndex((s) => s.id === sessionID)
|
|
||||||
const nextSession = index === -1 ? undefined : (sessions[index + 1] ?? sessions[index - 1])
|
|
||||||
|
|
||||||
await sdk()
|
|
||||||
.client.session.update({ sessionID, directory: sdk().directory, time: { archived: Date.now() } })
|
|
||||||
.then(() => {
|
|
||||||
sync().set(
|
|
||||||
produce((draft) => {
|
|
||||||
const index = draft.session.findIndex((s) => s.id === sessionID)
|
|
||||||
if (index !== -1) draft.session.splice(index, 1)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
sync().session.evict(sessionID)
|
|
||||||
navigateAfterSessionRemoval(sessionID, session.parentID, nextSession?.id)
|
|
||||||
notifySessionTabsRemoved({ directory: sdk().directory, sessionIDs: [sessionID] })
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
showToast({
|
|
||||||
title: language.t("common.requestFailed"),
|
|
||||||
description: errorMessage(err),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteSession = async (sessionID: string) => {
|
const deleteSession = async (sessionID: string) => {
|
||||||
const session = sync().session.get(sessionID)
|
const session = sync().session.get(sessionID)
|
||||||
if (!session) return false
|
if (!session) return false
|
||||||
@@ -911,7 +862,7 @@ export function MessageTimeline(props: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
navigateAfterSessionRemoval(sessionID, session.parentID, nextSession?.id)
|
sessionArchive.navigateAfterRemoval(sessionID, session.parentID, nextSession?.id)
|
||||||
|
|
||||||
sync().set(
|
sync().set(
|
||||||
produce((draft) => {
|
produce((draft) => {
|
||||||
@@ -1593,7 +1544,7 @@ export function MessageTimeline(props: {
|
|||||||
<DropdownMenu.Item onSelect={() => exportSession(id)}>
|
<DropdownMenu.Item onSelect={() => exportSession(id)}>
|
||||||
<DropdownMenu.ItemLabel>{language.t("common.export")}</DropdownMenu.ItemLabel>
|
<DropdownMenu.ItemLabel>{language.t("common.export")}</DropdownMenu.ItemLabel>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<DropdownMenu.Item onSelect={() => void archiveSession(id)}>
|
<DropdownMenu.Item onSelect={() => void sessionArchive.archive(id)}>
|
||||||
<DropdownMenu.ItemLabel>{language.t("common.archive")}</DropdownMenu.ItemLabel>
|
<DropdownMenu.ItemLabel>{language.t("common.archive")}</DropdownMenu.ItemLabel>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<DropdownMenu.Separator />
|
<DropdownMenu.Separator />
|
||||||
@@ -1667,7 +1618,7 @@ export function MessageTimeline(props: {
|
|||||||
<MenuV2.Item onSelect={() => exportSession(id)}>
|
<MenuV2.Item onSelect={() => exportSession(id)}>
|
||||||
{language.t("common.export")}...
|
{language.t("common.export")}...
|
||||||
</MenuV2.Item>
|
</MenuV2.Item>
|
||||||
<MenuV2.Item onSelect={() => void archiveSession(id)}>
|
<MenuV2.Item onSelect={() => void sessionArchive.archive(id)}>
|
||||||
{language.t("common.archive")}
|
{language.t("common.archive")}
|
||||||
</MenuV2.Item>
|
</MenuV2.Item>
|
||||||
<MenuV2.Separator />
|
<MenuV2.Separator />
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { createSessionTabs } from "@/pages/session/helpers"
|
|||||||
import { extractPromptFromParts } from "@/utils/prompt"
|
import { extractPromptFromParts } from "@/utils/prompt"
|
||||||
import { Message, Part, UserMessage } from "@opencode-ai/sdk/v2"
|
import { Message, Part, UserMessage } from "@opencode-ai/sdk/v2"
|
||||||
import { useSessionLayout } from "@/pages/session/session-layout"
|
import { useSessionLayout } from "@/pages/session/session-layout"
|
||||||
|
import { useSessionArchive } from "@/pages/session/session-archive"
|
||||||
import { createSessionOwnership } from "./session-ownership"
|
import { createSessionOwnership } from "./session-ownership"
|
||||||
import { useLocal } from "@/context/local"
|
import { useLocal } from "@/context/local"
|
||||||
|
|
||||||
@@ -52,6 +53,7 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
|||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { params, sessionKey, tabs, view } = useSessionLayout()
|
const { params, sessionKey, tabs, view } = useSessionLayout()
|
||||||
const sessionOwnership = createSessionOwnership(sessionKey)
|
const sessionOwnership = createSessionOwnership(sessionKey)
|
||||||
|
const sessionArchive = useSessionArchive()
|
||||||
const openDialog = async <T,>(load: () => Promise<T>, show: (value: T) => void) => {
|
const openDialog = async <T,>(load: () => Promise<T>, show: (value: T) => void) => {
|
||||||
const owner = sessionOwnership.capture()
|
const owner = sessionOwnership.capture()
|
||||||
const value = await load()
|
const value = await load()
|
||||||
@@ -497,6 +499,16 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
|||||||
disabled: !params.id,
|
disabled: !params.id,
|
||||||
onSelect: exportSession,
|
onSelect: exportSession,
|
||||||
}),
|
}),
|
||||||
|
sessionCommand({
|
||||||
|
id: "session.archive",
|
||||||
|
title: language.t("command.session.archive"),
|
||||||
|
keybind: "mod+shift+backspace",
|
||||||
|
disabled: !params.id,
|
||||||
|
onSelect: () => {
|
||||||
|
const id = params.id
|
||||||
|
if (id) void sessionArchive.archive(id)
|
||||||
|
},
|
||||||
|
}),
|
||||||
]
|
]
|
||||||
|
|
||||||
const fileCmds = () => {
|
const fileCmds = () => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createMemo, createSignal, createUniqueId, Show } from "solid-js"
|
import { createMemo, createSignal, createUniqueId, Show } from "solid-js"
|
||||||
import { createQuery } from "@tanstack/solid-query"
|
import { createQuery, keepPreviousData } from "@tanstack/solid-query"
|
||||||
import { Icon } from "@opencode-ai/ui/icon"
|
import { Icon } from "@opencode-ai/ui/icon"
|
||||||
import { SessionFilePanelV2, SessionFilePanelV2Empty } from "@opencode-ai/session-ui/v2/session-file-panel-v2"
|
import { SessionFilePanelV2, SessionFilePanelV2Empty } from "@opencode-ai/session-ui/v2/session-file-panel-v2"
|
||||||
import { SessionReviewV2Sidebar } from "@opencode-ai/session-ui/v2/session-review-v2"
|
import { SessionReviewV2Sidebar } from "@opencode-ai/session-ui/v2/session-review-v2"
|
||||||
@@ -50,6 +50,7 @@ export function SessionFileBrowserTab(props: {
|
|||||||
queryKey: ["session-open-file", workspaceKey(), value] as const,
|
queryKey: ["session-open-file", workspaceKey(), value] as const,
|
||||||
enabled: value.length > 0,
|
enabled: value.length > 0,
|
||||||
queryFn: ({ signal }) => file.searchFiles(value, { limit: 200, signal }),
|
queryFn: ({ signal }) => file.searchFiles(value, { limit: 200, signal }),
|
||||||
|
placeholderData: keepPreviousData,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const files = createMemo(() => {
|
const files = createMemo(() => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/cli",
|
"name": "@opencode-ai/cli",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/codemode",
|
"name": "@opencode-ai/codemode",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"description": "Effect-native confined code execution over schema-described tools",
|
"description": "Effect-native confined code execution over schema-described tools",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/console-app",
|
"name": "@opencode-ai/console-app",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -252,9 +252,8 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "الاستثناءات التالية",
|
"zen.privacy.exceptionsLink": "الاستثناءات التالية",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | نماذج برمجة منخفضة التكلفة للجميع",
|
"go.title": "OpenCode Go | نماذج برمجة منخفضة التكلفة للجميع",
|
||||||
"go.banner.text": "يحصل DeepSeek V4 Flash على حدود استخدام مضاعفة لفترة محدودة",
|
"go.banner.text": "Ox Alpha Free متاح على Go لفترة محدودة",
|
||||||
"go.meta.description":
|
"go.meta.description": "يبلغ سعر Go $10/شهر، مع حدود استخدام سخية ووصول موثوق إلى نماذج البرمجة الرائدة.",
|
||||||
"يبدأ Go بسعر $5 للشهر الأول، ثم $10/شهر، مع حدود استخدام سخية ووصول موثوق إلى نماذج البرمجة الرائدة.",
|
|
||||||
"go.hero.title": "نماذج برمجة منخفضة التكلفة للجميع",
|
"go.hero.title": "نماذج برمجة منخفضة التكلفة للجميع",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"يجلب Go البرمجة الوكيلة للمبرمجين حول العالم. يوفر حدودًا سخية ووصولًا موثوقًا إلى أقوى النماذج مفتوحة المصدر، حتى تتمكن من البناء باستخدام وكلاء أقوياء دون القلق بشأن التكلفة أو التوفر.",
|
"يجلب Go البرمجة الوكيلة للمبرمجين حول العالم. يوفر حدودًا سخية ووصولًا موثوقًا إلى أقوى النماذج مفتوحة المصدر، حتى تتمكن من البناء باستخدام وكلاء أقوياء دون القلق بشأن التكلفة أو التوفر.",
|
||||||
@@ -263,13 +262,13 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "اشترك في Go",
|
"go.cta.text": "اشترك في Go",
|
||||||
"go.cta.price": "$10/شهر",
|
"go.cta.price": "$10/شهر",
|
||||||
"go.cta.promo": "$5 للشهر الأول",
|
"go.pricing.body": "استخدمه مع أي وكيل. $10/شهر. قم بزيادة الرصيد إذا لزم الأمر. الإلغاء في أي وقت.",
|
||||||
"go.pricing.body":
|
|
||||||
"استخدمه مع أي وكيل. $5 للشهر الأول، ثم $10/شهر. قم بزيادة الرصيد إذا لزم الأمر. الإلغاء في أي وقت.",
|
|
||||||
"go.graph.free": "مجاني",
|
"go.graph.free": "مجاني",
|
||||||
"go.graph.freePill": "Big Pickle ونماذج مجانية",
|
"go.graph.freePill": "Big Pickle ونماذج مجانية",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "الطلبات كل 5 ساعات",
|
"go.graph.label": "الطلبات كل 5 ساعات",
|
||||||
|
"go.graph.limitedRegions": "مناطق محدودة",
|
||||||
|
"go.graph.limitedTime": "لفترة محدودة",
|
||||||
"go.graph.usageLimits": "حدود الاستخدام",
|
"go.graph.usageLimits": "حدود الاستخدام",
|
||||||
"go.graph.aria": "الطلبات كل 5 ساعات: {{free}} مقابل {{go}}",
|
"go.graph.aria": "الطلبات كل 5 ساعات: {{free}} مقابل {{go}}",
|
||||||
|
|
||||||
@@ -296,20 +295,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "أتمنى لو كنت لا أزال في Nvidia.",
|
"go.testimonials.frank.quote": "أتمنى لو كنت لا أزال في Nvidia.",
|
||||||
"go.problem.title": "ما المشكلة التي يحلها Go؟",
|
"go.problem.title": "ما المشكلة التي يحلها Go؟",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"نحن نركز على تقديم تجربة OpenCode لأكبر عدد ممكن من الناس. OpenCode Go هو اشتراك منخفض التكلفة: $5 للشهر الأول، ثم $10/شهر. يوفر حدودا سخية ووصولا موثوقا إلى نماذج المصدر المفتوح الأكثر قدرة.",
|
"نحن نركز على تقديم تجربة OpenCode لأكبر عدد ممكن من الناس. OpenCode Go هو اشتراك منخفض التكلفة بسعر $10/شهر. يوفر حدودا سخية ووصولا موثوقا إلى نماذج المصدر المفتوح الأكثر قدرة.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "أسعار اشتراك منخفضة التكلفة",
|
"go.problem.item1": "أسعار اشتراك منخفضة التكلفة",
|
||||||
"go.problem.item2": "حدود سخية ووصول موثوق",
|
"go.problem.item2": "حدود سخية ووصول موثوق",
|
||||||
"go.problem.item3": "مصمم لأكبر عدد ممكن من المبرمجين",
|
"go.problem.item3": "مصمم لأكبر عدد ممكن من المبرمجين",
|
||||||
"go.problem.item4": "مجموعة منسقة من النماذج المختبرة للبرمجة الوكيلة",
|
"go.problem.item4": "مجموعة منسقة من النماذج المختبرة للبرمجة الوكيلة",
|
||||||
"go.how.title": "كيف يعمل Go",
|
"go.how.title": "كيف يعمل Go",
|
||||||
"go.how.body": "يبدأ Go من $5 للشهر الأول، ثم $10/شهر. يمكنك استخدامه مع OpenCode أو أي وكيل.",
|
"go.how.body": "يبلغ سعر Go $10/شهر. يمكنك استخدامه مع OpenCode أو أي وكيل.",
|
||||||
"go.how.step1.title": "أنشئ حسابًا",
|
"go.how.step1.title": "أنشئ حسابًا",
|
||||||
"go.how.step1.beforeLink": "اتبع",
|
"go.how.step1.beforeLink": "اتبع",
|
||||||
"go.how.step1.link": "تعليمات الإعداد",
|
"go.how.step1.link": "تعليمات الإعداد",
|
||||||
"go.how.step2.title": "اشترك في Go",
|
"go.how.step2.title": "اشترك في Go",
|
||||||
"go.how.step2.link": "$5 للشهر الأول",
|
"go.how.step2.link": "$10/شهر",
|
||||||
"go.how.step2.afterLink": "ثم $10/شهر مع حدود سخية",
|
"go.how.step2.afterLink": "مع حدود سخية",
|
||||||
"go.how.step3.title": "ابدأ البرمجة",
|
"go.how.step3.title": "ابدأ البرمجة",
|
||||||
"go.how.step3.body": "مع وصول موثوق لنماذج مفتوحة المصدر",
|
"go.how.step3.body": "مع وصول موثوق لنماذج مفتوحة المصدر",
|
||||||
"go.privacy.title": "خصوصيتك مهمة بالنسبة لنا",
|
"go.privacy.title": "خصوصيتك مهمة بالنسبة لنا",
|
||||||
@@ -325,11 +324,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "يتضمن Go النماذج المدرجة أدناه، مع حدود سخية وإتاحة موثوقة.",
|
"go.faq.a2": "يتضمن Go النماذج المدرجة أدناه، مع حدود سخية وإتاحة موثوقة.",
|
||||||
"go.faq.q3": "هل Go هو نفسه Zen؟",
|
"go.faq.q3": "هل Go هو نفسه Zen؟",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"لا. يعتمد Zen على الدفع حسب الاستخدام، بينما يبدأ Go بسعر $5 للشهر الأول، ثم $10/شهر، مع حدود سخية ووصول موثوق إلى مجموعة منسقة من النماذج.",
|
"لا. يعتمد Zen على الدفع حسب الاستخدام، بينما يبلغ سعر Go $10/شهر، مع حدود سخية ووصول موثوق إلى مجموعة منسقة من النماذج.",
|
||||||
"go.faq.q4": "كم تكلفة Go؟",
|
"go.faq.q4": "كم تكلفة Go؟",
|
||||||
"go.faq.a4.p1.beforePricing": "تكلفة Go",
|
"go.faq.a4.p1.beforePricing": "تكلفة Go",
|
||||||
"go.faq.a4.p1.pricingLink": "$5 للشهر الأول",
|
"go.faq.a4.p1.pricingLink": "$10/شهر",
|
||||||
"go.faq.a4.p1.afterPricing": "ثم $10/شهر مع حدود سخية.",
|
"go.faq.a4.p1.afterPricing": "مع حدود سخية.",
|
||||||
"go.faq.a4.p2.beforeAccount": "يمكنك إدارة اشتراكك في",
|
"go.faq.a4.p2.beforeAccount": "يمكنك إدارة اشتراكك في",
|
||||||
"go.faq.a4.p2.accountLink": "حسابك",
|
"go.faq.a4.p2.accountLink": "حسابك",
|
||||||
"go.faq.a4.p3": "ألغِ في أي وقت.",
|
"go.faq.a4.p3": "ألغِ في أي وقت.",
|
||||||
@@ -342,10 +341,13 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "مستخدَمة",
|
"go.faq.a5.used": "مستخدَمة",
|
||||||
"go.faq.a5.notUsed": "غير مستخدَمة",
|
"go.faq.a5.notUsed": "غير مستخدَمة",
|
||||||
"go.faq.a5.noAgreement": "لا توجد اتفاقية",
|
"go.faq.a5.noAgreement": "لا توجد اتفاقية",
|
||||||
|
"go.faq.a5.notZdr": "ليست ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"go.faq.a5.grokRetention":
|
||||||
"تعطّل ZDR ميزات API مهمة تعتمد على البيانات المخزنة، بما في ذلك Responses API ذات الحالة، وFiles and Collections، وBatch API.",
|
"تعطّل ZDR ميزات API مهمة تعتمد على البيانات المخزنة، بما في ذلك Responses API ذات الحالة، وFiles and Collections، وBatch API.",
|
||||||
"go.faq.a5.gptRetention":
|
"go.faq.a5.gptRetention":
|
||||||
"تُنشأ سجلات مراقبة إساءة الاستخدام لكل استخدام لميزات API، ويُحتفظ بها لمدة تصل إلى 30 يومًا.",
|
"تُنشأ سجلات مراقبة إساءة الاستخدام لكل استخدام لميزات API، ويُحتفظ بها لمدة تصل إلى 30 يومًا.",
|
||||||
|
"go.faq.a5.museRetention":
|
||||||
|
"أسعار توكنات مخفّضة للغاية مقابل منح الإذن باستخدام مطالباتك وإكمالات النموذج لتدريب نماذج Meta المستقبلية.",
|
||||||
"go.faq.a5.learnMore": "اعرف المزيد",
|
"go.faq.a5.learnMore": "اعرف المزيد",
|
||||||
"go.faq.a5.deepseekRetention": "تُجدَّد اتفاقية ZDR شهريًا. الاتفاقية الحالية سارية حتى 31 أغسطس 2026.",
|
"go.faq.a5.deepseekRetention": "تُجدَّد اتفاقية ZDR شهريًا. الاتفاقية الحالية سارية حتى 31 أغسطس 2026.",
|
||||||
"go.faq.a5.beforeExceptions":
|
"go.faq.a5.beforeExceptions":
|
||||||
@@ -386,6 +388,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "النموذج معطل",
|
"zen.api.error.modelDisabled": "النموذج معطل",
|
||||||
"zen.api.error.regionNotAllowed":
|
"zen.api.error.regionNotAllowed":
|
||||||
"لا يتوفر أحدث إصدار من هذا النموذج إلا مستضافًا في الصين، ويتطلب تفعيلًا صريحًا: {{consoleGoUrl}}",
|
"لا يتوفر أحدث إصدار من هذا النموذج إلا مستضافًا في الصين، ويتطلب تفعيلًا صريحًا: {{consoleGoUrl}}",
|
||||||
|
"zen.api.error.countryNotAllowed": "هذا النموذج غير متاح في بلدك.",
|
||||||
|
"zen.api.error.trainingNotAllowed":
|
||||||
|
"يجمع هذا النموذج بيانات تُستخدم لتحسين جودته، ويتطلب موافقتك الصريحة: {{consoleGoUrl}}",
|
||||||
"zen.api.error.trialEnded":
|
"zen.api.error.trialEnded":
|
||||||
"انتهى العرض المجاني لـ {{model}}. يمكنك مواصلة استخدام النموذج بالاشتراك في OpenCode Go - {{link}}",
|
"انتهى العرض المجاني لـ {{model}}. يمكنك مواصلة استخدام النموذج بالاشتراك في OpenCode Go - {{link}}",
|
||||||
|
|
||||||
@@ -665,14 +670,15 @@ export const dict = {
|
|||||||
'اختر "OpenCode Go" كمزود في إعدادات opencode الخاصة بك لاستخدام نماذج Go.',
|
'اختر "OpenCode Go" كمزود في إعدادات opencode الخاصة بك لاستخدام نماذج Go.',
|
||||||
"workspace.lite.providers.title": "المزودون",
|
"workspace.lite.providers.title": "المزودون",
|
||||||
"workspace.lite.providers.description": "تحكم في المزودين المستخدمين للتوجيه.",
|
"workspace.lite.providers.description": "تحكم في المزودين المستخدمين للتوجيه.",
|
||||||
|
"workspace.lite.providers.allowTraining": "السماح بالنماذج التي تتدرب على بيانات الطلبات",
|
||||||
"workspace.lite.providers.useChina": "تفعيل النماذج المستضافة في الصين",
|
"workspace.lite.providers.useChina": "تفعيل النماذج المستضافة في الصين",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"أنت مشترك حاليًا في OpenCode Black أو في قائمة الانتظار. يرجى إلغاء الاشتراك أولاً إذا كنت ترغب في التبديل إلى Go.",
|
"أنت مشترك حاليًا في OpenCode Black أو في قائمة الانتظار. يرجى إلغاء الاشتراك أولاً إذا كنت ترغب في التبديل إلى Go.",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"عضو آخر في مساحة العمل هذه مشترك بالفعل في OpenCode Go. يمكن لعضو واحد فقط لكل مساحة عمل الاشتراك.",
|
"عضو آخر في مساحة العمل هذه مشترك بالفعل في OpenCode Go. يمكن لعضو واحد فقط لكل مساحة عمل الاشتراك.",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"يبدأ OpenCode Go بسعر {{price}}، ثم $10/شهر، ويوفر وصولا موثوقا لنماذج البرمجة المفتوحة الشهيرة مع حدود استخدام سخية.",
|
"يبلغ سعر OpenCode Go {{price}}، ويوفر وصولا موثوقا لنماذج البرمجة المفتوحة الشهيرة مع حدود استخدام سخية.",
|
||||||
"workspace.lite.promo.price": "$5 للشهر الأول",
|
"workspace.lite.promo.price": "$10/شهر",
|
||||||
"workspace.lite.promo.modelsTitle": "ما يتضمنه",
|
"workspace.lite.promo.modelsTitle": "ما يتضمنه",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"صُممت الخطة بشكل أساسي للمستخدمين الدوليين، وتوفر وصولًا عالميًا مستقرًا. قد تتغير الأسعار وحدود الاستخدام بينما نتعلم من الاستخدام المبكر والملاحظات.",
|
"صُممت الخطة بشكل أساسي للمستخدمين الدوليين، وتوفر وصولًا عالميًا مستقرًا. قد تتغير الأسعار وحدود الاستخدام بينما نتعلم من الاستخدام المبكر والملاحظات.",
|
||||||
|
|||||||
@@ -256,9 +256,9 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "seguintes exceções",
|
"zen.privacy.exceptionsLink": "seguintes exceções",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | Modelos de codificação de baixo custo para todos",
|
"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.banner.text": "Ox Alpha Free está disponível no Go por tempo limitado",
|
||||||
"go.meta.description":
|
"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.",
|
"O Go custa $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",
|
"go.hero.title": "Modelos de codificação de baixo custo para todos",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"O Go traz a codificação com agentes para programadores em todo o mundo. Oferecendo limites generosos e acesso confiável aos modelos de código aberto mais capazes, para que você possa construir com agentes poderosos sem se preocupar com custos ou disponibilidade.",
|
"O Go traz a codificação com agentes para programadores em todo o mundo. Oferecendo limites generosos e acesso confiável aos modelos de código aberto mais capazes, para que você possa construir com agentes poderosos sem se preocupar com custos ou disponibilidade.",
|
||||||
@@ -267,13 +267,14 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "Assinar o Go",
|
"go.cta.text": "Assinar o Go",
|
||||||
"go.cta.price": "$10/mês",
|
"go.cta.price": "$10/mês",
|
||||||
"go.cta.promo": "$5 no primeiro mês",
|
|
||||||
"go.pricing.body":
|
"go.pricing.body":
|
||||||
"Use com qualquer agente. $5 no primeiro mês, depois $10/mês. Recarregue o crédito se necessário. Cancele a qualquer momento.",
|
"Use com qualquer agente. $10/mês. Recarregue o crédito se necessário. Cancele a qualquer momento.",
|
||||||
"go.graph.free": "Grátis",
|
"go.graph.free": "Grátis",
|
||||||
"go.graph.freePill": "Big Pickle e modelos gratuitos",
|
"go.graph.freePill": "Big Pickle e modelos gratuitos",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "Requisições por 5 horas",
|
"go.graph.label": "Requisições por 5 horas",
|
||||||
|
"go.graph.limitedRegions": "regiões limitadas",
|
||||||
|
"go.graph.limitedTime": "tempo limitado",
|
||||||
"go.graph.usageLimits": "Limites de uso",
|
"go.graph.usageLimits": "Limites de uso",
|
||||||
"go.graph.aria": "Requisições por 5h: {{free}} vs {{go}}",
|
"go.graph.aria": "Requisições por 5h: {{free}} vs {{go}}",
|
||||||
|
|
||||||
@@ -301,21 +302,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "Eu queria ainda estar na Nvidia.",
|
"go.testimonials.frank.quote": "Eu queria ainda estar na Nvidia.",
|
||||||
"go.problem.title": "Que problema o Go resolve?",
|
"go.problem.title": "Que problema o Go resolve?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"Estamos focados em levar a experiência do OpenCode para o maior número de pessoas possível. OpenCode Go é uma assinatura de baixo custo: $5 no primeiro mês, depois $10/mês. Oferece limites generosos e acesso confiável aos modelos open source mais capazes.",
|
"Estamos focados em levar a experiência do OpenCode para o maior número de pessoas possível. OpenCode Go é uma assinatura de baixo custo de $10/mês. Oferece limites generosos e acesso confiável aos modelos open source mais capazes.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "Preço de assinatura de baixo custo",
|
"go.problem.item1": "Preço de assinatura de baixo custo",
|
||||||
"go.problem.item2": "Limites generosos e acesso confiável",
|
"go.problem.item2": "Limites generosos e acesso confiável",
|
||||||
"go.problem.item3": "Feito para o maior número possível de programadores",
|
"go.problem.item3": "Feito para o maior número possível de programadores",
|
||||||
"go.problem.item4": "Uma seleção de modelos testados para codificação com agentes",
|
"go.problem.item4": "Uma seleção de modelos testados para codificação com agentes",
|
||||||
"go.how.title": "Como o Go funciona",
|
"go.how.title": "Como o Go funciona",
|
||||||
"go.how.body":
|
"go.how.body": "O Go custa $10/mês. Você pode usá-lo com o OpenCode ou qualquer agente.",
|
||||||
"O Go começa em $5 no primeiro mês, depois $10/mês. Você pode usá-lo com o OpenCode ou qualquer agente.",
|
|
||||||
"go.how.step1.title": "Crie uma conta",
|
"go.how.step1.title": "Crie uma conta",
|
||||||
"go.how.step1.beforeLink": "siga as",
|
"go.how.step1.beforeLink": "siga as",
|
||||||
"go.how.step1.link": "instruções de configuração",
|
"go.how.step1.link": "instruções de configuração",
|
||||||
"go.how.step2.title": "Assinar o Go",
|
"go.how.step2.title": "Assinar o Go",
|
||||||
"go.how.step2.link": "$5 no primeiro mês",
|
"go.how.step2.link": "$10/mês",
|
||||||
"go.how.step2.afterLink": "depois $10/mês com limites generosos",
|
"go.how.step2.afterLink": "com limites generosos",
|
||||||
"go.how.step3.title": "Comece a codificar",
|
"go.how.step3.title": "Comece a codificar",
|
||||||
"go.how.step3.body": "com acesso confiável a modelos de código aberto",
|
"go.how.step3.body": "com acesso confiável a modelos de código aberto",
|
||||||
"go.privacy.title": "Sua privacidade é importante para nós",
|
"go.privacy.title": "Sua privacidade é importante para nós",
|
||||||
@@ -332,11 +332,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "O Go inclui os modelos listados abaixo, com limites generosos e acesso confiável.",
|
"go.faq.a2": "O Go inclui os modelos listados abaixo, com limites generosos e acesso confiável.",
|
||||||
"go.faq.q3": "O Go é o mesmo que o Zen?",
|
"go.faq.q3": "O Go é o mesmo que o Zen?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"Não. Zen é pay-as-you-go, enquanto o Go começa em $5 no primeiro mês, depois $10/mês, com limites generosos e acesso confiável a uma seleção de modelos.",
|
"Não. Zen é pay-as-you-go, enquanto o Go custa $10/mês, com limites generosos e acesso confiável a uma seleção de modelos.",
|
||||||
"go.faq.q4": "Quanto custa o Go?",
|
"go.faq.q4": "Quanto custa o Go?",
|
||||||
"go.faq.a4.p1.beforePricing": "O Go custa",
|
"go.faq.a4.p1.beforePricing": "O Go custa",
|
||||||
"go.faq.a4.p1.pricingLink": "$5 no primeiro mês",
|
"go.faq.a4.p1.pricingLink": "$10/mês",
|
||||||
"go.faq.a4.p1.afterPricing": "depois $10/mês com limites generosos.",
|
"go.faq.a4.p1.afterPricing": "com limites generosos.",
|
||||||
"go.faq.a4.p2.beforeAccount": "Você pode gerenciar sua assinatura em sua",
|
"go.faq.a4.p2.beforeAccount": "Você pode gerenciar sua assinatura em sua",
|
||||||
"go.faq.a4.p2.accountLink": "conta",
|
"go.faq.a4.p2.accountLink": "conta",
|
||||||
"go.faq.a4.p3": "Cancele a qualquer momento.",
|
"go.faq.a4.p3": "Cancele a qualquer momento.",
|
||||||
@@ -349,10 +349,13 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "Usado",
|
"go.faq.a5.used": "Usado",
|
||||||
"go.faq.a5.notUsed": "Não usado",
|
"go.faq.a5.notUsed": "Não usado",
|
||||||
"go.faq.a5.noAgreement": "Sem acordo",
|
"go.faq.a5.noAgreement": "Sem acordo",
|
||||||
|
"go.faq.a5.notZdr": "Não é ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"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.",
|
"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":
|
"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.",
|
"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.learnMore": "Saiba mais",
|
||||||
"go.faq.a5.deepseekRetention":
|
"go.faq.a5.deepseekRetention":
|
||||||
"O acordo de ZDR é renovado mensalmente. O acordo atual é válido até 31 de agosto de 2026.",
|
"O acordo de ZDR é renovado mensalmente. O acordo atual é válido até 31 de agosto de 2026.",
|
||||||
@@ -395,6 +398,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "O modelo está desabilitado",
|
"zen.api.error.modelDisabled": "O modelo está desabilitado",
|
||||||
"zen.api.error.regionNotAllowed":
|
"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}}",
|
"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":
|
"zen.api.error.trialEnded":
|
||||||
"A promoção gratuita do {{model}} terminou. Você pode continuar usando o modelo assinando o OpenCode Go - {{link}}",
|
"A promoção gratuita do {{model}} terminou. Você pode continuar usando o modelo assinando o OpenCode Go - {{link}}",
|
||||||
|
|
||||||
@@ -676,14 +682,15 @@ export const dict = {
|
|||||||
'Selecione "OpenCode Go" como provedor na sua configuração do opencode para usar os modelos Go.',
|
'Selecione "OpenCode Go" como provedor na sua configuração do opencode para usar os modelos Go.',
|
||||||
"workspace.lite.providers.title": "Provedores",
|
"workspace.lite.providers.title": "Provedores",
|
||||||
"workspace.lite.providers.description": "Controle quais provedores são usados para roteamento.",
|
"workspace.lite.providers.description": "Controle quais provedores são usados para roteamento.",
|
||||||
|
"workspace.lite.providers.allowTraining": "Permitir modelos que usam dados de solicitações para treinamento",
|
||||||
"workspace.lite.providers.useChina": "Ativar modelos hospedados na China",
|
"workspace.lite.providers.useChina": "Ativar modelos hospedados na China",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"Você está atualmente inscrito no OpenCode Black ou na lista de espera. Por favor, cancele a assinatura primeiro se desejar mudar para o Go.",
|
"Você está atualmente inscrito no OpenCode Black ou na lista de espera. Por favor, cancele a assinatura primeiro se desejar mudar para o Go.",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"Outro membro neste workspace já assina o OpenCode Go. Apenas um membro por workspace pode assinar.",
|
"Outro membro neste workspace já assina o OpenCode Go. Apenas um membro por workspace pode assinar.",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"O OpenCode Go começa em {{price}}, depois $10/mês, e oferece acesso confiável a modelos de codificação abertos populares com limites de uso generosos.",
|
"O OpenCode Go custa {{price}} e oferece acesso confiável a modelos de codificação abertos populares com limites de uso generosos.",
|
||||||
"workspace.lite.promo.price": "$5 no primeiro mês",
|
"workspace.lite.promo.price": "$10/mês",
|
||||||
"workspace.lite.promo.modelsTitle": "O que está incluído",
|
"workspace.lite.promo.modelsTitle": "O que está incluído",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"O plano foi desenvolvido principalmente para usuários internacionais e oferece acesso global estável. Os preços e limites de uso podem mudar à medida que aprendemos com o uso inicial e o feedback recebido.",
|
"O plano foi desenvolvido principalmente para usuários internacionais e oferece acesso global estável. Os preços e limites de uso podem mudar à medida que aprendemos com o uso inicial e o feedback recebido.",
|
||||||
|
|||||||
@@ -254,9 +254,9 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "følgende undtagelser",
|
"zen.privacy.exceptionsLink": "følgende undtagelser",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | Kodningsmodeller til lav pris for alle",
|
"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.banner.text": "Ox Alpha Free er tilgængelig på Go i en begrænset periode",
|
||||||
"go.meta.description":
|
"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 koster $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",
|
"go.hero.title": "Kodningsmodeller til lav pris for alle",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go bringer agentisk kodning til programmører over hele verden. Med generøse grænser og pålidelig adgang til de mest kapable open source-modeller, så du kan bygge med kraftfulde agenter uden at bekymre dig om omkostninger eller tilgængelighed.",
|
"Go bringer agentisk kodning til programmører over hele verden. Med generøse grænser og pålidelig adgang til de mest kapable open source-modeller, så du kan bygge med kraftfulde agenter uden at bekymre dig om omkostninger eller tilgængelighed.",
|
||||||
@@ -265,13 +265,13 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "Abonner på Go",
|
"go.cta.text": "Abonner på Go",
|
||||||
"go.cta.price": "$10/måned",
|
"go.cta.price": "$10/måned",
|
||||||
"go.cta.promo": "$5 første måned",
|
"go.pricing.body": "Brug med enhver agent. $10/måned. Tank op med kredit efter behov. Afmeld når som helst.",
|
||||||
"go.pricing.body":
|
|
||||||
"Brug med enhver agent. $5 første måned, derefter $10/måned. Tank op med kredit efter behov. Afmeld når som helst.",
|
|
||||||
"go.graph.free": "Gratis",
|
"go.graph.free": "Gratis",
|
||||||
"go.graph.freePill": "Big Pickle og gratis modeller",
|
"go.graph.freePill": "Big Pickle og gratis modeller",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "Forespørgsler pr. 5 timer",
|
"go.graph.label": "Forespørgsler pr. 5 timer",
|
||||||
|
"go.graph.limitedRegions": "begrænsede regioner",
|
||||||
|
"go.graph.limitedTime": "begrænset periode",
|
||||||
"go.graph.usageLimits": "Brugsgrænser",
|
"go.graph.usageLimits": "Brugsgrænser",
|
||||||
"go.graph.aria": "Forespørgsler pr. 5t: {{free}} vs {{go}}",
|
"go.graph.aria": "Forespørgsler pr. 5t: {{free}} vs {{go}}",
|
||||||
|
|
||||||
@@ -298,21 +298,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "Jeg ville ønske, jeg stadig var hos Nvidia.",
|
"go.testimonials.frank.quote": "Jeg ville ønske, jeg stadig var hos Nvidia.",
|
||||||
"go.problem.title": "Hvilket problem løser Go?",
|
"go.problem.title": "Hvilket problem løser Go?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"Vi fokuserer på at bringe OpenCode-oplevelsen ud til så mange som muligt. OpenCode Go er et lavprisabonnement: $5 for den første måned, derefter $10/måned. Det giver generøse grænser og pålidelig adgang til de mest kapable open source-modeller.",
|
"Vi fokuserer på at bringe OpenCode-oplevelsen ud til så mange som muligt. OpenCode Go er et lavprisabonnement til $10/måned. Det giver generøse grænser og pålidelig adgang til de mest kapable open source-modeller.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "Lavpris abonnementspriser",
|
"go.problem.item1": "Lavpris abonnementspriser",
|
||||||
"go.problem.item2": "Generøse grænser og pålidelig adgang",
|
"go.problem.item2": "Generøse grænser og pålidelig adgang",
|
||||||
"go.problem.item3": "Bygget til så mange programmører som muligt",
|
"go.problem.item3": "Bygget til så mange programmører som muligt",
|
||||||
"go.problem.item4": "Et kurateret modeludvalg testet til agentisk kodning",
|
"go.problem.item4": "Et kurateret modeludvalg testet til agentisk kodning",
|
||||||
"go.how.title": "Hvordan Go virker",
|
"go.how.title": "Hvordan Go virker",
|
||||||
"go.how.body":
|
"go.how.body": "Go koster $10/måned. Du kan bruge det med OpenCode eller enhver agent.",
|
||||||
"Go starter ved $5 for den første måned, derefter $10/måned. Du kan bruge det med OpenCode eller enhver agent.",
|
|
||||||
"go.how.step1.title": "Opret en konto",
|
"go.how.step1.title": "Opret en konto",
|
||||||
"go.how.step1.beforeLink": "følg",
|
"go.how.step1.beforeLink": "følg",
|
||||||
"go.how.step1.link": "opsætningsinstruktionerne",
|
"go.how.step1.link": "opsætningsinstruktionerne",
|
||||||
"go.how.step2.title": "Abonner på Go",
|
"go.how.step2.title": "Abonner på Go",
|
||||||
"go.how.step2.link": "$5 første måned",
|
"go.how.step2.link": "$10/måned",
|
||||||
"go.how.step2.afterLink": "derefter $10/måned med generøse grænser",
|
"go.how.step2.afterLink": "med generøse grænser",
|
||||||
"go.how.step3.title": "Start kodning",
|
"go.how.step3.title": "Start kodning",
|
||||||
"go.how.step3.body": "med pålidelig adgang til open source-modeller",
|
"go.how.step3.body": "med pålidelig adgang til open source-modeller",
|
||||||
"go.privacy.title": "Dit privatliv er vigtigt for os",
|
"go.privacy.title": "Dit privatliv er vigtigt for os",
|
||||||
@@ -329,11 +328,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go inkluderer modellerne nedenfor med generøse grænser og pålidelig adgang.",
|
"go.faq.a2": "Go inkluderer modellerne nedenfor med generøse grænser og pålidelig adgang.",
|
||||||
"go.faq.q3": "Er Go det samme som Zen?",
|
"go.faq.q3": "Er Go det samme som Zen?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"Nej. Zen er pay-as-you-go, mens Go starter ved $5 for den første måned, derefter $10/måned, med generøse grænser og pålidelig adgang til et kurateret modeludvalg.",
|
"Nej. Zen er pay-as-you-go, mens Go koster $10/måned, med generøse grænser og pålidelig adgang til et kurateret modeludvalg.",
|
||||||
"go.faq.q4": "Hvad koster Go?",
|
"go.faq.q4": "Hvad koster Go?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go koster",
|
"go.faq.a4.p1.beforePricing": "Go koster",
|
||||||
"go.faq.a4.p1.pricingLink": "$5 første måned",
|
"go.faq.a4.p1.pricingLink": "$10/måned",
|
||||||
"go.faq.a4.p1.afterPricing": "derefter $10/måned med generøse grænser.",
|
"go.faq.a4.p1.afterPricing": "med generøse grænser.",
|
||||||
"go.faq.a4.p2.beforeAccount": "Du kan administrere dit abonnement i din",
|
"go.faq.a4.p2.beforeAccount": "Du kan administrere dit abonnement i din",
|
||||||
"go.faq.a4.p2.accountLink": "konto",
|
"go.faq.a4.p2.accountLink": "konto",
|
||||||
"go.faq.a4.p3": "Annuller til enhver tid.",
|
"go.faq.a4.p3": "Annuller til enhver tid.",
|
||||||
@@ -346,10 +345,13 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "Brugt",
|
"go.faq.a5.used": "Brugt",
|
||||||
"go.faq.a5.notUsed": "Ikke brugt",
|
"go.faq.a5.notUsed": "Ikke brugt",
|
||||||
"go.faq.a5.noAgreement": "Ingen aftale",
|
"go.faq.a5.noAgreement": "Ingen aftale",
|
||||||
|
"go.faq.a5.notZdr": "Ikke ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"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.",
|
"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":
|
"go.faq.a5.gptRetention":
|
||||||
"Logfiler til overvågning af misbrug genereres ved al brug af API-funktioner og opbevares i op til 30 dage.",
|
"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.learnMore": "Læs mere",
|
||||||
"go.faq.a5.deepseekRetention":
|
"go.faq.a5.deepseekRetention":
|
||||||
"ZDR-aftalen fornyes månedligt. Den nuværende aftale er gyldig til og med 31. august 2026.",
|
"ZDR-aftalen fornyes månedligt. Den nuværende aftale er gyldig til og med 31. august 2026.",
|
||||||
@@ -392,6 +394,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "Modellen er deaktiveret",
|
"zen.api.error.modelDisabled": "Modellen er deaktiveret",
|
||||||
"zen.api.error.regionNotAllowed":
|
"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}}",
|
"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":
|
"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}}",
|
"Den gratis kampagne for {{model}} er afsluttet. Du kan fortsætte med at bruge modellen ved at abonnere på OpenCode Go - {{link}}",
|
||||||
|
|
||||||
@@ -673,14 +678,15 @@ export const dict = {
|
|||||||
'Vælg "OpenCode Go" som udbyder i din opencode-konfiguration for at bruge Go-modeller.',
|
'Vælg "OpenCode Go" som udbyder i din opencode-konfiguration for at bruge Go-modeller.',
|
||||||
"workspace.lite.providers.title": "Udbydere",
|
"workspace.lite.providers.title": "Udbydere",
|
||||||
"workspace.lite.providers.description": "Styr, hvilke udbydere der bruges til routing.",
|
"workspace.lite.providers.description": "Styr, hvilke udbydere der bruges til routing.",
|
||||||
|
"workspace.lite.providers.allowTraining": "Tillad modeller, der træner på anmodningsdata",
|
||||||
"workspace.lite.providers.useChina": "Aktivér modeller hostet i Kina",
|
"workspace.lite.providers.useChina": "Aktivér modeller hostet i Kina",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"Du abonnerer i øjeblikket på OpenCode Black eller er på venteliste. Afmeld venligst først, hvis du vil skifte til Go.",
|
"Du abonnerer i øjeblikket på OpenCode Black eller er på venteliste. Afmeld venligst først, hvis du vil skifte til Go.",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"Et andet medlem i dette workspace abonnerer allerede på OpenCode Go. Kun ét medlem pr. workspace kan abonnere.",
|
"Et andet medlem i dette workspace abonnerer allerede på OpenCode Go. Kun ét medlem pr. workspace kan abonnere.",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go starter ved {{price}}, derefter $10/måned, og giver pålidelig adgang til populære åbne kodningsmodeller med generøse brugsgrænser.",
|
"OpenCode Go koster {{price}} og giver pålidelig adgang til populære åbne kodningsmodeller med generøse brugsgrænser.",
|
||||||
"workspace.lite.promo.price": "$5 for den første måned",
|
"workspace.lite.promo.price": "$10/måned",
|
||||||
"workspace.lite.promo.modelsTitle": "Hvad er inkluderet",
|
"workspace.lite.promo.modelsTitle": "Hvad er inkluderet",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"Planen er primært udviklet til internationale brugere og giver stabil adgang i hele verden. Priser og forbrugsgrænser kan ændre sig, efterhånden som vi lærer af de første brugserfaringer og tilbagemeldinger.",
|
"Planen er primært udviklet til internationale brugere og giver stabil adgang i hele verden. Priser og forbrugsgrænser kan ændre sig, efterhånden som vi lærer af de første brugserfaringer og tilbagemeldinger.",
|
||||||
|
|||||||
@@ -256,9 +256,9 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "folgenden Ausnahmen",
|
"zen.privacy.exceptionsLink": "folgenden Ausnahmen",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | Kostengünstige Coding-Modelle für alle",
|
"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.banner.text": "Ox Alpha Free ist für begrenzte Zeit auf Go verfügbar",
|
||||||
"go.meta.description":
|
"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 kostet $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",
|
"go.hero.title": "Kostengünstige Coding-Modelle für alle",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go bringt Agentic Coding zu Programmierern auf der ganzen Welt. Mit großzügigen Limits und zuverlässigem Zugang zu den leistungsfähigsten Open-Source-Modellen, damit du mit leistungsstarken Agenten entwickeln kannst, ohne dir Gedanken über Kosten oder Verfügbarkeit zu machen.",
|
"Go bringt Agentic Coding zu Programmierern auf der ganzen Welt. Mit großzügigen Limits und zuverlässigem Zugang zu den leistungsfähigsten Open-Source-Modellen, damit du mit leistungsstarken Agenten entwickeln kannst, ohne dir Gedanken über Kosten oder Verfügbarkeit zu machen.",
|
||||||
@@ -267,13 +267,13 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "Go abonnieren",
|
"go.cta.text": "Go abonnieren",
|
||||||
"go.cta.price": "$10/Monat",
|
"go.cta.price": "$10/Monat",
|
||||||
"go.cta.promo": "$5 im ersten Monat",
|
"go.pricing.body": "Mit jedem Agenten nutzbar. $10/Monat. Guthaben bei Bedarf aufladen. Jederzeit kündbar.",
|
||||||
"go.pricing.body":
|
|
||||||
"Mit jedem Agenten nutzbar. $5 im ersten Monat, danach $10/Monat. Guthaben bei Bedarf aufladen. Jederzeit kündbar.",
|
|
||||||
"go.graph.free": "Kostenlos",
|
"go.graph.free": "Kostenlos",
|
||||||
"go.graph.freePill": "Big Pickle und kostenlose Modelle",
|
"go.graph.freePill": "Big Pickle und kostenlose Modelle",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "Anfragen pro 5 Stunden",
|
"go.graph.label": "Anfragen pro 5 Stunden",
|
||||||
|
"go.graph.limitedRegions": "begrenzte Regionen",
|
||||||
|
"go.graph.limitedTime": "begrenzte Zeit",
|
||||||
"go.graph.usageLimits": "Nutzungslimits",
|
"go.graph.usageLimits": "Nutzungslimits",
|
||||||
"go.graph.aria": "Anfragen pro 5h: {{free}} vs {{go}}",
|
"go.graph.aria": "Anfragen pro 5h: {{free}} vs {{go}}",
|
||||||
|
|
||||||
@@ -300,21 +300,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "Ich wünschte, ich wäre noch bei Nvidia.",
|
"go.testimonials.frank.quote": "Ich wünschte, ich wäre noch bei Nvidia.",
|
||||||
"go.problem.title": "Welches Problem löst Go?",
|
"go.problem.title": "Welches Problem löst Go?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"Wir konzentrieren uns darauf, die OpenCode-Erfahrung so vielen Menschen wie möglich zugänglich zu machen. OpenCode Go ist ein kostengünstiges Abonnement: $5 im ersten Monat, danach $10/Monat. Es bietet großzügige Limits und zuverlässigen Zugang zu den leistungsfähigsten Open-Source-Modellen.",
|
"Wir konzentrieren uns darauf, die OpenCode-Erfahrung so vielen Menschen wie möglich zugänglich zu machen. OpenCode Go ist ein kostengünstiges Abonnement für $10/Monat. Es bietet großzügige Limits und zuverlässigen Zugang zu den leistungsfähigsten Open-Source-Modellen.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "Kostengünstiges Abonnement",
|
"go.problem.item1": "Kostengünstiges Abonnement",
|
||||||
"go.problem.item2": "Großzügige Limits und zuverlässiger Zugang",
|
"go.problem.item2": "Großzügige Limits und zuverlässiger Zugang",
|
||||||
"go.problem.item3": "Für so viele Programmierer wie möglich gebaut",
|
"go.problem.item3": "Für so viele Programmierer wie möglich gebaut",
|
||||||
"go.problem.item4": "Eine kuratierte, für Agentic Coding getestete Modellauswahl",
|
"go.problem.item4": "Eine kuratierte, für Agentic Coding getestete Modellauswahl",
|
||||||
"go.how.title": "Wie Go funktioniert",
|
"go.how.title": "Wie Go funktioniert",
|
||||||
"go.how.body":
|
"go.how.body": "Go kostet $10/Monat. Du kannst es mit OpenCode oder jedem Agenten nutzen.",
|
||||||
"Go beginnt bei $5 für den ersten Monat, danach $10/Monat. Du kannst es mit OpenCode oder jedem Agenten nutzen.",
|
|
||||||
"go.how.step1.title": "Konto erstellen",
|
"go.how.step1.title": "Konto erstellen",
|
||||||
"go.how.step1.beforeLink": "folge den",
|
"go.how.step1.beforeLink": "folge den",
|
||||||
"go.how.step1.link": "Einrichtungsanweisungen",
|
"go.how.step1.link": "Einrichtungsanweisungen",
|
||||||
"go.how.step2.title": "Go abonnieren",
|
"go.how.step2.title": "Go abonnieren",
|
||||||
"go.how.step2.link": "$5 im ersten Monat",
|
"go.how.step2.link": "$10/Monat",
|
||||||
"go.how.step2.afterLink": "danach $10/Monat mit großzügigen Limits",
|
"go.how.step2.afterLink": "mit großzügigen Limits",
|
||||||
"go.how.step3.title": "Loslegen mit Coding",
|
"go.how.step3.title": "Loslegen mit Coding",
|
||||||
"go.how.step3.body": "mit zuverlässigem Zugang zu Open-Source-Modellen",
|
"go.how.step3.body": "mit zuverlässigem Zugang zu Open-Source-Modellen",
|
||||||
"go.privacy.title": "Deine Privatsphäre ist uns wichtig",
|
"go.privacy.title": "Deine Privatsphäre ist uns wichtig",
|
||||||
@@ -331,11 +330,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go umfasst die unten aufgeführten Modelle mit großzügigen Limits und zuverlässigem Zugriff.",
|
"go.faq.a2": "Go umfasst die unten aufgeführten Modelle mit großzügigen Limits und zuverlässigem Zugriff.",
|
||||||
"go.faq.q3": "Ist Go dasselbe wie Zen?",
|
"go.faq.q3": "Ist Go dasselbe wie Zen?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"Nein. Zen ist Pay-as-you-go, während Go bei $5 für deinen ersten Monat beginnt, danach $10/Monat, mit großzügigen Limits und zuverlässigem Zugang zu einer kuratierten Modellauswahl.",
|
"Nein. Zen ist Pay-as-you-go, während Go $10/Monat kostet, mit großzügigen Limits und zuverlässigem Zugang zu einer kuratierten Modellauswahl.",
|
||||||
"go.faq.q4": "Wie viel kostet Go?",
|
"go.faq.q4": "Wie viel kostet Go?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go kostet",
|
"go.faq.a4.p1.beforePricing": "Go kostet",
|
||||||
"go.faq.a4.p1.pricingLink": "$5 im ersten Monat",
|
"go.faq.a4.p1.pricingLink": "$10/Monat",
|
||||||
"go.faq.a4.p1.afterPricing": "danach $10/Monat mit großzügigen Limits.",
|
"go.faq.a4.p1.afterPricing": "mit großzügigen Limits.",
|
||||||
"go.faq.a4.p2.beforeAccount": "Du kannst dein Abonnement in deinem",
|
"go.faq.a4.p2.beforeAccount": "Du kannst dein Abonnement in deinem",
|
||||||
"go.faq.a4.p2.accountLink": "Konto verwalten",
|
"go.faq.a4.p2.accountLink": "Konto verwalten",
|
||||||
"go.faq.a4.p3": "Jederzeit kündbar.",
|
"go.faq.a4.p3": "Jederzeit kündbar.",
|
||||||
@@ -348,10 +347,13 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "Verwendet",
|
"go.faq.a5.used": "Verwendet",
|
||||||
"go.faq.a5.notUsed": "Nicht verwendet",
|
"go.faq.a5.notUsed": "Nicht verwendet",
|
||||||
"go.faq.a5.noAgreement": "Keine Vereinbarung",
|
"go.faq.a5.noAgreement": "Keine Vereinbarung",
|
||||||
|
"go.faq.a5.notZdr": "Kein ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"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.",
|
"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":
|
"go.faq.a5.gptRetention":
|
||||||
"Für die Nutzung aller API-Funktionen werden Protokolle zur Missbrauchsüberwachung erstellt und bis zu 30 Tage lang aufbewahrt.",
|
"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.learnMore": "Mehr erfahren",
|
||||||
"go.faq.a5.deepseekRetention":
|
"go.faq.a5.deepseekRetention":
|
||||||
"Die ZDR-Vereinbarung wird monatlich erneuert. Die aktuelle Vereinbarung gilt bis einschließlich 31. August 2026.",
|
"Die ZDR-Vereinbarung wird monatlich erneuert. Die aktuelle Vereinbarung gilt bis einschließlich 31. August 2026.",
|
||||||
@@ -394,6 +396,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "Modell ist deaktiviert",
|
"zen.api.error.modelDisabled": "Modell ist deaktiviert",
|
||||||
"zen.api.error.regionNotAllowed":
|
"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}}",
|
"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":
|
"zen.api.error.trialEnded":
|
||||||
"Die kostenlose Aktion für {{model}} ist beendet. Du kannst das Modell weiterhin nutzen, indem du OpenCode Go abonnierst - {{link}}",
|
"Die kostenlose Aktion für {{model}} ist beendet. Du kannst das Modell weiterhin nutzen, indem du OpenCode Go abonnierst - {{link}}",
|
||||||
|
|
||||||
@@ -675,14 +680,15 @@ export const dict = {
|
|||||||
'Wähle "OpenCode Go" als Anbieter in deiner opencode-Konfiguration, um Go-Modelle zu verwenden.',
|
'Wähle "OpenCode Go" als Anbieter in deiner opencode-Konfiguration, um Go-Modelle zu verwenden.',
|
||||||
"workspace.lite.providers.title": "Anbieter",
|
"workspace.lite.providers.title": "Anbieter",
|
||||||
"workspace.lite.providers.description": "Steuere, welche Anbieter für das Routing verwendet werden.",
|
"workspace.lite.providers.description": "Steuere, welche Anbieter für das Routing verwendet werden.",
|
||||||
|
"workspace.lite.providers.allowTraining": "Modelle zulassen, die mit Anfragedaten trainieren",
|
||||||
"workspace.lite.providers.useChina": "In China gehostete Modelle aktivieren",
|
"workspace.lite.providers.useChina": "In China gehostete Modelle aktivieren",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"Du hast derzeit OpenCode Black abonniert oder stehst auf der Warteliste. Bitte kündige zuerst, wenn du zu Go wechseln möchtest.",
|
"Du hast derzeit OpenCode Black abonniert oder stehst auf der Warteliste. Bitte kündige zuerst, wenn du zu Go wechseln möchtest.",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"Ein anderes Mitglied in diesem Workspace hat OpenCode Go bereits abonniert. Nur ein Mitglied pro Workspace kann abonnieren.",
|
"Ein anderes Mitglied in diesem Workspace hat OpenCode Go bereits abonniert. Nur ein Mitglied pro Workspace kann abonnieren.",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go startet bei {{price}}, danach $10/Monat, und bietet zuverlässigen Zugang zu beliebten offenen Coding-Modellen mit großzügigen Nutzungslimits.",
|
"OpenCode Go kostet {{price}} und bietet zuverlässigen Zugang zu beliebten offenen Coding-Modellen mit großzügigen Nutzungslimits.",
|
||||||
"workspace.lite.promo.price": "$5 im ersten Monat",
|
"workspace.lite.promo.price": "$10/Monat",
|
||||||
"workspace.lite.promo.modelsTitle": "Was enthalten ist",
|
"workspace.lite.promo.modelsTitle": "Was enthalten ist",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"Der Plan richtet sich in erster Linie an internationale Nutzer und bietet stabilen weltweiten Zugriff. Preise und Nutzungslimits können sich ändern, wenn wir Erkenntnisse aus der ersten Nutzung und dem Feedback gewinnen.",
|
"Der Plan richtet sich in erster Linie an internationale Nutzer und bietet stabilen weltweiten Zugriff. Preise und Nutzungslimits können sich ändern, wenn wir Erkenntnisse aus der ersten Nutzung und dem Feedback gewinnen.",
|
||||||
|
|||||||
@@ -253,9 +253,8 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "following exceptions",
|
"zen.privacy.exceptionsLink": "following exceptions",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | Low cost coding models for everyone",
|
"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.banner.text": "Ox Alpha Free is available on Go for a limited time",
|
||||||
"go.meta.description":
|
"go.meta.description": "Go costs $10/month, with generous usage limits and reliable access to leading coding models.",
|
||||||
"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",
|
"go.hero.title": "Low cost coding models for everyone",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go brings agentic coding to programmers around the world. Offering generous limits and reliable access to the most capable open-source models, so you can build with powerful agents without worrying about cost or availability.",
|
"Go brings agentic coding to programmers around the world. Offering generous limits and reliable access to the most capable open-source models, so you can build with powerful agents without worrying about cost or availability.",
|
||||||
@@ -264,12 +263,13 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "Subscribe to Go",
|
"go.cta.text": "Subscribe to Go",
|
||||||
"go.cta.price": "$10/month",
|
"go.cta.price": "$10/month",
|
||||||
"go.cta.promo": "$5 first month",
|
"go.pricing.body": "Use with any agent. $10/month. Top up credit if needed. Cancel any time.",
|
||||||
"go.pricing.body": "Use with any agent. $5 first month, then $10/month. Top up credit if needed. Cancel any time.",
|
|
||||||
"go.graph.free": "Free",
|
"go.graph.free": "Free",
|
||||||
"go.graph.freePill": "Big Pickle and free models",
|
"go.graph.freePill": "Big Pickle and free models",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "Requests per 5 hour",
|
"go.graph.label": "Requests per 5 hour",
|
||||||
|
"go.graph.limitedRegions": "limited regions",
|
||||||
|
"go.graph.limitedTime": "limited time",
|
||||||
"go.graph.tick": "{{n}}x",
|
"go.graph.tick": "{{n}}x",
|
||||||
"go.graph.usageLimits": "Usage limits",
|
"go.graph.usageLimits": "Usage limits",
|
||||||
"go.graph.aria": "Requests per 5h: {{free}} vs {{go}}",
|
"go.graph.aria": "Requests per 5h: {{free}} vs {{go}}",
|
||||||
@@ -297,20 +297,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "I wish I was still at Nvidia.",
|
"go.testimonials.frank.quote": "I wish I was still at Nvidia.",
|
||||||
"go.problem.title": "What problem is Go solving?",
|
"go.problem.title": "What problem is Go solving?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"We're focused on bringing the OpenCode experience to as many people as possible. OpenCode Go is a low cost subscription: $5 for your first month, then $10/month. It provides generous limits and reliable access to the most capable open source models.",
|
"We're focused on bringing the OpenCode experience to as many people as possible. OpenCode Go is a low cost $10/month subscription. It provides generous limits and reliable access to the most capable open source models.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "Low cost subscription pricing",
|
"go.problem.item1": "Low cost subscription pricing",
|
||||||
"go.problem.item2": "Generous limits and reliable access",
|
"go.problem.item2": "Generous limits and reliable access",
|
||||||
"go.problem.item3": "Built for as many programmers as possible",
|
"go.problem.item3": "Built for as many programmers as possible",
|
||||||
"go.problem.item4": "A curated model lineup tested for agentic coding",
|
"go.problem.item4": "A curated model lineup tested for agentic coding",
|
||||||
"go.how.title": "How Go works",
|
"go.how.title": "How Go works",
|
||||||
"go.how.body": "Go starts at $5 for your first month, then $10/month. You can use it with OpenCode or any agent.",
|
"go.how.body": "Go costs $10/month. You can use it with OpenCode or any agent.",
|
||||||
"go.how.step1.title": "Create an account",
|
"go.how.step1.title": "Create an account",
|
||||||
"go.how.step1.beforeLink": "follow the",
|
"go.how.step1.beforeLink": "follow the",
|
||||||
"go.how.step1.link": "setup instructions",
|
"go.how.step1.link": "setup instructions",
|
||||||
"go.how.step2.title": "Subscribe to Go",
|
"go.how.step2.title": "Subscribe to Go",
|
||||||
"go.how.step2.link": "$5 first month",
|
"go.how.step2.link": "$10/month",
|
||||||
"go.how.step2.afterLink": "then $10/month with generous limits",
|
"go.how.step2.afterLink": "with generous limits",
|
||||||
"go.how.step3.title": "Start coding",
|
"go.how.step3.title": "Start coding",
|
||||||
"go.how.step3.body": "with reliable access to open-source models",
|
"go.how.step3.body": "with reliable access to open-source models",
|
||||||
"go.privacy.title": "Your privacy is important to us",
|
"go.privacy.title": "Your privacy is important to us",
|
||||||
@@ -327,11 +327,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go includes the models listed below, with generous limits and reliable access.",
|
"go.faq.a2": "Go includes the models listed below, with generous limits and reliable access.",
|
||||||
"go.faq.q3": "Is Go the same as Zen?",
|
"go.faq.q3": "Is Go the same as Zen?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"No. Zen is pay-as-you-go, while Go starts at $5 for your first month, then $10/month, with generous limits and reliable access to a curated model lineup.",
|
"No. Zen is pay-as-you-go, while Go costs $10/month, with generous limits and reliable access to a curated model lineup.",
|
||||||
"go.faq.q4": "How much does Go cost?",
|
"go.faq.q4": "How much does Go cost?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go costs",
|
"go.faq.a4.p1.beforePricing": "Go costs",
|
||||||
"go.faq.a4.p1.pricingLink": "$5 first month",
|
"go.faq.a4.p1.pricingLink": "$10/month",
|
||||||
"go.faq.a4.p1.afterPricing": "then $10/month with generous limits.",
|
"go.faq.a4.p1.afterPricing": "with generous limits.",
|
||||||
"go.faq.a4.p2.beforeAccount": "You can manage your subscription in your",
|
"go.faq.a4.p2.beforeAccount": "You can manage your subscription in your",
|
||||||
"go.faq.a4.p2.accountLink": "account",
|
"go.faq.a4.p2.accountLink": "account",
|
||||||
"go.faq.a4.p3": "Cancel any time.",
|
"go.faq.a4.p3": "Cancel any time.",
|
||||||
@@ -344,10 +344,13 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "Used",
|
"go.faq.a5.used": "Used",
|
||||||
"go.faq.a5.notUsed": "Not used",
|
"go.faq.a5.notUsed": "Not used",
|
||||||
"go.faq.a5.noAgreement": "No agreement",
|
"go.faq.a5.noAgreement": "No agreement",
|
||||||
|
"go.faq.a5.notZdr": "Not ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"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.",
|
"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":
|
"go.faq.a5.gptRetention":
|
||||||
"Abuse monitoring logs are generated for all API feature usage and retained for up to 30 days.",
|
"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":
|
"go.faq.a5.deepseekRetention":
|
||||||
"ZDR agreement is renewed monthly. The current agreement is valid through August 31, 2026.",
|
"ZDR agreement is renewed monthly. The current agreement is valid through August 31, 2026.",
|
||||||
"go.faq.a5.learnMore": "Learn more",
|
"go.faq.a5.learnMore": "Learn more",
|
||||||
@@ -391,6 +394,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "Model is disabled",
|
"zen.api.error.modelDisabled": "Model is disabled",
|
||||||
"zen.api.error.regionNotAllowed":
|
"zen.api.error.regionNotAllowed":
|
||||||
"The latest version of this model is only available hosted in China and requires explicit opt in: {{consoleGoUrl}}",
|
"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":
|
"zen.api.error.trialEnded":
|
||||||
"Free promotion has ended for {{model}}. You can continue using the model by subscribing to OpenCode Go - {{link}}",
|
"Free promotion has ended for {{model}}. You can continue using the model by subscribing to OpenCode Go - {{link}}",
|
||||||
|
|
||||||
@@ -672,14 +678,15 @@ export const dict = {
|
|||||||
'Select "OpenCode Go" as the provider in your opencode configuration to use Go models.',
|
'Select "OpenCode Go" as the provider in your opencode configuration to use Go models.',
|
||||||
"workspace.lite.providers.title": "Providers",
|
"workspace.lite.providers.title": "Providers",
|
||||||
"workspace.lite.providers.description": "Control which providers are used for routing.",
|
"workspace.lite.providers.description": "Control which providers are used for routing.",
|
||||||
"workspace.lite.providers.useChina": "Enable models hosted in China",
|
"workspace.lite.providers.allowTraining": "Allow models that train on request data",
|
||||||
|
"workspace.lite.providers.useChina": "Allow models hosted in China",
|
||||||
"workspace.lite.black.message":
|
"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.",
|
"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":
|
"workspace.lite.other.message":
|
||||||
"Another member in this workspace is already subscribed to OpenCode Go. Only one member per workspace can subscribe.",
|
"Another member in this workspace is already subscribed to OpenCode Go. Only one member per workspace can subscribe.",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go starts at {{price}}, then $10/month, and provides reliable access to popular open coding models with generous usage limits.",
|
"OpenCode Go costs {{price}} and provides reliable access to popular open coding models with generous usage limits.",
|
||||||
"workspace.lite.promo.price": "$5 for your first month",
|
"workspace.lite.promo.price": "$10/month",
|
||||||
"workspace.lite.promo.modelsTitle": "What's Included",
|
"workspace.lite.promo.modelsTitle": "What's Included",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"The plan is designed primarily for international users and provides stable global access. Pricing and usage limits may change as we learn from early usage and feedback.",
|
"The plan is designed primarily for international users and provides stable global access. Pricing and usage limits may change as we learn from early usage and feedback.",
|
||||||
|
|||||||
@@ -257,9 +257,9 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "siguientes excepciones",
|
"zen.privacy.exceptionsLink": "siguientes excepciones",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | Modelos de programación de bajo coste para todos",
|
"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.banner.text": "Ox Alpha Free está disponible en Go por tiempo limitado",
|
||||||
"go.meta.description":
|
"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 cuesta 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",
|
"go.hero.title": "Modelos de programación de bajo coste para todos",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go lleva la programación agéntica a programadores de todo el mundo. Ofrece límites generosos y acceso fiable a los modelos de código abierto más capaces, para que puedas crear con agentes potentes sin preocuparte por el coste o la disponibilidad.",
|
"Go lleva la programación agéntica a programadores de todo el mundo. Ofrece límites generosos y acceso fiable a los modelos de código abierto más capaces, para que puedas crear con agentes potentes sin preocuparte por el coste o la disponibilidad.",
|
||||||
@@ -268,13 +268,14 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "Suscribirse a Go",
|
"go.cta.text": "Suscribirse a Go",
|
||||||
"go.cta.price": "10 $/mes",
|
"go.cta.price": "10 $/mes",
|
||||||
"go.cta.promo": "$5 el primer mes",
|
|
||||||
"go.pricing.body":
|
"go.pricing.body":
|
||||||
"Úsalo con cualquier agente. $5 el primer mes, luego 10 $/mes. Recarga crédito si es necesario. Cancela en cualquier momento.",
|
"Úsalo con cualquier agente. 10 $/mes. Recarga crédito si es necesario. Cancela en cualquier momento.",
|
||||||
"go.graph.free": "Gratis",
|
"go.graph.free": "Gratis",
|
||||||
"go.graph.freePill": "Big Pickle y modelos gratuitos",
|
"go.graph.freePill": "Big Pickle y modelos gratuitos",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "Solicitudes por 5 horas",
|
"go.graph.label": "Solicitudes por 5 horas",
|
||||||
|
"go.graph.limitedRegions": "regiones limitadas",
|
||||||
|
"go.graph.limitedTime": "tiempo limitado",
|
||||||
"go.graph.usageLimits": "Límites de uso",
|
"go.graph.usageLimits": "Límites de uso",
|
||||||
"go.graph.aria": "Solicitudes por 5h: {{free}} vs {{go}}",
|
"go.graph.aria": "Solicitudes por 5h: {{free}} vs {{go}}",
|
||||||
|
|
||||||
@@ -302,20 +303,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "Ojalá siguiera en Nvidia.",
|
"go.testimonials.frank.quote": "Ojalá siguiera en Nvidia.",
|
||||||
"go.problem.title": "¿Qué problema resuelve Go?",
|
"go.problem.title": "¿Qué problema resuelve Go?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"Nos enfocamos en llevar la experiencia de OpenCode a tantas personas como sea posible. OpenCode Go es una suscripción de bajo coste: $5 el primer mes, luego 10 $/mes. Proporciona límites generosos y acceso fiable a los modelos de código abierto más capaces.",
|
"Nos enfocamos en llevar la experiencia de OpenCode a tantas personas como sea posible. OpenCode Go es una suscripción de bajo coste de 10 $/mes. Proporciona límites generosos y acceso fiable a los modelos de código abierto más capaces.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "Precios de suscripción de bajo coste",
|
"go.problem.item1": "Precios de suscripción de bajo coste",
|
||||||
"go.problem.item2": "Límites generosos y acceso fiable",
|
"go.problem.item2": "Límites generosos y acceso fiable",
|
||||||
"go.problem.item3": "Creado para tantos programadores como sea posible",
|
"go.problem.item3": "Creado para tantos programadores como sea posible",
|
||||||
"go.problem.item4": "Una selección de modelos probados para programación agéntica",
|
"go.problem.item4": "Una selección de modelos probados para programación agéntica",
|
||||||
"go.how.title": "Cómo funciona Go",
|
"go.how.title": "Cómo funciona Go",
|
||||||
"go.how.body": "Go comienza en $5 el primer mes, luego 10 $/mes. Puedes usarlo con OpenCode o cualquier agente.",
|
"go.how.body": "Go cuesta 10 $/mes. Puedes usarlo con OpenCode o cualquier agente.",
|
||||||
"go.how.step1.title": "Crear una cuenta",
|
"go.how.step1.title": "Crear una cuenta",
|
||||||
"go.how.step1.beforeLink": "sigue las",
|
"go.how.step1.beforeLink": "sigue las",
|
||||||
"go.how.step1.link": "instrucciones de configuración",
|
"go.how.step1.link": "instrucciones de configuración",
|
||||||
"go.how.step2.title": "Suscribirse a Go",
|
"go.how.step2.title": "Suscribirse a Go",
|
||||||
"go.how.step2.link": "$5 el primer mes",
|
"go.how.step2.link": "10 $/mes",
|
||||||
"go.how.step2.afterLink": "luego 10 $/mes con límites generosos",
|
"go.how.step2.afterLink": "con límites generosos",
|
||||||
"go.how.step3.title": "Empezar a programar",
|
"go.how.step3.title": "Empezar a programar",
|
||||||
"go.how.step3.body": "con acceso fiable a modelos de código abierto",
|
"go.how.step3.body": "con acceso fiable a modelos de código abierto",
|
||||||
"go.privacy.title": "Tu privacidad es importante para nosotros",
|
"go.privacy.title": "Tu privacidad es importante para nosotros",
|
||||||
@@ -332,11 +333,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go incluye los modelos que se indican abajo, con límites generosos y acceso confiable.",
|
"go.faq.a2": "Go incluye los modelos que se indican abajo, con límites generosos y acceso confiable.",
|
||||||
"go.faq.q3": "¿Es Go lo mismo que Zen?",
|
"go.faq.q3": "¿Es Go lo mismo que Zen?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"No. Zen es de pago por uso, mientras que Go comienza en $5 el primer mes, luego 10 $/mes, con límites generosos y acceso fiable a una selección de modelos.",
|
"No. Zen es de pago por uso, mientras que Go cuesta 10 $/mes, con límites generosos y acceso fiable a una selección de modelos.",
|
||||||
"go.faq.q4": "¿Cuánto cuesta Go?",
|
"go.faq.q4": "¿Cuánto cuesta Go?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go cuesta",
|
"go.faq.a4.p1.beforePricing": "Go cuesta",
|
||||||
"go.faq.a4.p1.pricingLink": "$5 el primer mes",
|
"go.faq.a4.p1.pricingLink": "10 $/mes",
|
||||||
"go.faq.a4.p1.afterPricing": "luego 10 $/mes con límites generosos.",
|
"go.faq.a4.p1.afterPricing": "con límites generosos.",
|
||||||
"go.faq.a4.p2.beforeAccount": "Puedes gestionar tu suscripción en tu",
|
"go.faq.a4.p2.beforeAccount": "Puedes gestionar tu suscripción en tu",
|
||||||
"go.faq.a4.p2.accountLink": "cuenta",
|
"go.faq.a4.p2.accountLink": "cuenta",
|
||||||
"go.faq.a4.p3": "Cancela en cualquier momento.",
|
"go.faq.a4.p3": "Cancela en cualquier momento.",
|
||||||
@@ -349,10 +350,13 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "Utilizado",
|
"go.faq.a5.used": "Utilizado",
|
||||||
"go.faq.a5.notUsed": "No utilizado",
|
"go.faq.a5.notUsed": "No utilizado",
|
||||||
"go.faq.a5.noAgreement": "Sin acuerdo",
|
"go.faq.a5.noAgreement": "Sin acuerdo",
|
||||||
|
"go.faq.a5.notZdr": "Sin ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"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.",
|
"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":
|
"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.",
|
"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.learnMore": "Más información",
|
||||||
"go.faq.a5.deepseekRetention":
|
"go.faq.a5.deepseekRetention":
|
||||||
"El acuerdo de ZDR se renueva mensualmente. El acuerdo actual es válido hasta el 31 de agosto de 2026.",
|
"El acuerdo de ZDR se renueva mensualmente. El acuerdo actual es válido hasta el 31 de agosto de 2026.",
|
||||||
@@ -395,6 +399,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "El modelo está deshabilitado",
|
"zen.api.error.modelDisabled": "El modelo está deshabilitado",
|
||||||
"zen.api.error.regionNotAllowed":
|
"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}}",
|
"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":
|
"zen.api.error.trialEnded":
|
||||||
"La promoción gratuita de {{model}} ha finalizado. Puedes seguir usando el modelo suscribiéndote a OpenCode Go - {{link}}",
|
"La promoción gratuita de {{model}} ha finalizado. Puedes seguir usando el modelo suscribiéndote a OpenCode Go - {{link}}",
|
||||||
|
|
||||||
@@ -676,14 +683,15 @@ export const dict = {
|
|||||||
'Selecciona "OpenCode Go" como proveedor en tu configuración de opencode para usar los modelos Go.',
|
'Selecciona "OpenCode Go" como proveedor en tu configuración de opencode para usar los modelos Go.',
|
||||||
"workspace.lite.providers.title": "Proveedores",
|
"workspace.lite.providers.title": "Proveedores",
|
||||||
"workspace.lite.providers.description": "Controla qué proveedores se usan para el enrutamiento.",
|
"workspace.lite.providers.description": "Controla qué proveedores se usan para el enrutamiento.",
|
||||||
|
"workspace.lite.providers.allowTraining": "Permitir modelos que se entrenan con los datos de las solicitudes",
|
||||||
"workspace.lite.providers.useChina": "Activar modelos alojados en China",
|
"workspace.lite.providers.useChina": "Activar modelos alojados en China",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"Actualmente estás suscrito a OpenCode Black o estás en la lista de espera. Por favor, cancela la suscripción primero si deseas cambiar a Go.",
|
"Actualmente estás suscrito a OpenCode Black o estás en la lista de espera. Por favor, cancela la suscripción primero si deseas cambiar a Go.",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"Otro miembro de este espacio de trabajo ya está suscrito a OpenCode Go. Solo un miembro por espacio de trabajo puede suscribirse.",
|
"Otro miembro de este espacio de trabajo ya está suscrito a OpenCode Go. Solo un miembro por espacio de trabajo puede suscribirse.",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go comienza en {{price}}, luego $10/mes, y ofrece acceso confiable a modelos de codificación abiertos populares con límites de uso generosos.",
|
"OpenCode Go cuesta {{price}} y ofrece acceso confiable a modelos de codificación abiertos populares con límites de uso generosos.",
|
||||||
"workspace.lite.promo.price": "$5 el primer mes",
|
"workspace.lite.promo.price": "$10/mes",
|
||||||
"workspace.lite.promo.modelsTitle": "Qué incluye",
|
"workspace.lite.promo.modelsTitle": "Qué incluye",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"El plan está diseñado principalmente para usuarios internacionales y ofrece un acceso global estable. Los precios y los límites de uso pueden cambiar a medida que aprendemos del uso inicial y de los comentarios recibidos.",
|
"El plan está diseñado principalmente para usuarios internacionales y ofrece un acceso global estable. Los precios y los límites de uso pueden cambiar a medida que aprendemos del uso inicial y de los comentarios recibidos.",
|
||||||
|
|||||||
@@ -258,9 +258,9 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "exceptions suivantes",
|
"zen.privacy.exceptionsLink": "exceptions suivantes",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | Modèles de code à faible coût pour tous",
|
"go.title": "OpenCode Go | Modèles de code à faible coût pour tous",
|
||||||
"go.banner.text": "DeepSeek V4 Flash bénéficie de limites d’utilisation 2x supérieures pour une durée limitée",
|
"go.banner.text": "Ox Alpha Free est disponible sur Go pour une durée limitée",
|
||||||
"go.meta.description":
|
"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 coûte 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",
|
"go.hero.title": "Modèles de code à faible coût pour tous",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go apporte le codage agentique aux programmeurs du monde entier. Offrant des limites généreuses et un accès fiable aux modèles open source les plus capables, pour que vous puissiez construire avec des agents puissants sans vous soucier du coût ou de la disponibilité.",
|
"Go apporte le codage agentique aux programmeurs du monde entier. Offrant des limites généreuses et un accès fiable aux modèles open source les plus capables, pour que vous puissiez construire avec des agents puissants sans vous soucier du coût ou de la disponibilité.",
|
||||||
@@ -269,13 +269,14 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "S'abonner à Go",
|
"go.cta.text": "S'abonner à Go",
|
||||||
"go.cta.price": "10 $/mois",
|
"go.cta.price": "10 $/mois",
|
||||||
"go.cta.promo": "$5 le premier mois",
|
|
||||||
"go.pricing.body":
|
"go.pricing.body":
|
||||||
"Utilisez-le avec n'importe quel agent. $5 le premier mois, puis 10 $/mois. Rechargez du crédit si nécessaire. Annulez à tout moment.",
|
"Utilisez-le avec n'importe quel agent. 10 $/mois. Rechargez du crédit si nécessaire. Annulez à tout moment.",
|
||||||
"go.graph.free": "Gratuit",
|
"go.graph.free": "Gratuit",
|
||||||
"go.graph.freePill": "Big Pickle et modèles gratuits",
|
"go.graph.freePill": "Big Pickle et modèles gratuits",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "Requêtes par tranche de 5 heures",
|
"go.graph.label": "Requêtes par tranche de 5 heures",
|
||||||
|
"go.graph.limitedRegions": "régions limitées",
|
||||||
|
"go.graph.limitedTime": "durée limitée",
|
||||||
"go.graph.usageLimits": "Limites d'utilisation",
|
"go.graph.usageLimits": "Limites d'utilisation",
|
||||||
"go.graph.aria": "Requêtes par 5h : {{free}} vs {{go}}",
|
"go.graph.aria": "Requêtes par 5h : {{free}} vs {{go}}",
|
||||||
|
|
||||||
@@ -302,21 +303,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "J'aimerais être encore chez Nvidia.",
|
"go.testimonials.frank.quote": "J'aimerais être encore chez Nvidia.",
|
||||||
"go.problem.title": "Quel problème Go résout-il ?",
|
"go.problem.title": "Quel problème Go résout-il ?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"Nous nous efforçons d'apporter l'expérience OpenCode au plus grand nombre. OpenCode Go est un abonnement à faible coût : $5 pour le premier mois, puis 10 $/mois. Il offre des limites généreuses et un accès fiable aux modèles open source les plus performants.",
|
"Nous nous efforçons d'apporter l'expérience OpenCode au plus grand nombre. OpenCode Go est un abonnement à faible coût de 10 $/mois. Il offre des limites généreuses et un accès fiable aux modèles open source les plus performants.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "Prix d'abonnement bas",
|
"go.problem.item1": "Prix d'abonnement bas",
|
||||||
"go.problem.item2": "Limites généreuses et accès fiable",
|
"go.problem.item2": "Limites généreuses et accès fiable",
|
||||||
"go.problem.item3": "Conçu pour autant de programmeurs que possible",
|
"go.problem.item3": "Conçu pour autant de programmeurs que possible",
|
||||||
"go.problem.item4": "Une sélection de modèles testés pour le codage agentique",
|
"go.problem.item4": "Une sélection de modèles testés pour le codage agentique",
|
||||||
"go.how.title": "Comment fonctionne Go",
|
"go.how.title": "Comment fonctionne Go",
|
||||||
"go.how.body":
|
"go.how.body": "Go coûte 10 $/mois. Vous pouvez l'utiliser avec OpenCode ou n'importe quel agent.",
|
||||||
"Go commence à $5 pour le premier mois, puis 10 $/mois. Vous pouvez l'utiliser avec OpenCode ou n'importe quel agent.",
|
|
||||||
"go.how.step1.title": "Créez un compte",
|
"go.how.step1.title": "Créez un compte",
|
||||||
"go.how.step1.beforeLink": "suivez les",
|
"go.how.step1.beforeLink": "suivez les",
|
||||||
"go.how.step1.link": "instructions de configuration",
|
"go.how.step1.link": "instructions de configuration",
|
||||||
"go.how.step2.title": "Abonnez-vous à Go",
|
"go.how.step2.title": "Abonnez-vous à Go",
|
||||||
"go.how.step2.link": "$5 le premier mois",
|
"go.how.step2.link": "10 $/mois",
|
||||||
"go.how.step2.afterLink": "puis 10 $/mois avec des limites généreuses",
|
"go.how.step2.afterLink": "avec des limites généreuses",
|
||||||
"go.how.step3.title": "Commencez à coder",
|
"go.how.step3.title": "Commencez à coder",
|
||||||
"go.how.step3.body": "avec un accès fiable aux modèles open source",
|
"go.how.step3.body": "avec un accès fiable aux modèles open source",
|
||||||
"go.privacy.title": "Votre vie privée est importante pour nous",
|
"go.privacy.title": "Votre vie privée est importante pour nous",
|
||||||
@@ -333,11 +333,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go inclut les modèles ci-dessous, avec des limites généreuses et un accès fiable.",
|
"go.faq.a2": "Go inclut les modèles ci-dessous, avec des limites généreuses et un accès fiable.",
|
||||||
"go.faq.q3": "Est-ce que Go est la même chose que Zen ?",
|
"go.faq.q3": "Est-ce que Go est la même chose que Zen ?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"Non. Zen est un paiement à l'utilisation, tandis que Go commence à $5 pour le premier mois, puis 10 $/mois, avec des limites généreuses et un accès fiable à une sélection de modèles.",
|
"Non. Zen est un paiement à l'utilisation, tandis que Go coûte 10 $/mois, avec des limites généreuses et un accès fiable à une sélection de modèles.",
|
||||||
"go.faq.q4": "Combien coûte Go ?",
|
"go.faq.q4": "Combien coûte Go ?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go coûte",
|
"go.faq.a4.p1.beforePricing": "Go coûte",
|
||||||
"go.faq.a4.p1.pricingLink": "$5 le premier mois",
|
"go.faq.a4.p1.pricingLink": "10 $/mois",
|
||||||
"go.faq.a4.p1.afterPricing": "puis 10 $/mois avec des limites généreuses.",
|
"go.faq.a4.p1.afterPricing": "avec des limites généreuses.",
|
||||||
"go.faq.a4.p2.beforeAccount": "Vous pouvez gérer votre abonnement dans votre",
|
"go.faq.a4.p2.beforeAccount": "Vous pouvez gérer votre abonnement dans votre",
|
||||||
"go.faq.a4.p2.accountLink": "compte",
|
"go.faq.a4.p2.accountLink": "compte",
|
||||||
"go.faq.a4.p3": "Annulez à tout moment.",
|
"go.faq.a4.p3": "Annulez à tout moment.",
|
||||||
@@ -350,10 +350,13 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "Utilisé",
|
"go.faq.a5.used": "Utilisé",
|
||||||
"go.faq.a5.notUsed": "Non utilisé",
|
"go.faq.a5.notUsed": "Non utilisé",
|
||||||
"go.faq.a5.noAgreement": "Aucun accord",
|
"go.faq.a5.noAgreement": "Aucun accord",
|
||||||
|
"go.faq.a5.notZdr": "Pas de ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"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.",
|
"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":
|
"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.",
|
"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 l’autorisation d’utiliser vos prompts et vos complétions pour entraîner de futurs modèles Meta.",
|
||||||
"go.faq.a5.learnMore": "En savoir plus",
|
"go.faq.a5.learnMore": "En savoir plus",
|
||||||
"go.faq.a5.deepseekRetention":
|
"go.faq.a5.deepseekRetention":
|
||||||
"L’accord ZDR est renouvelé chaque mois. L’accord actuel est valable jusqu’au 31 août 2026.",
|
"L’accord ZDR est renouvelé chaque mois. L’accord actuel est valable jusqu’au 31 août 2026.",
|
||||||
@@ -396,6 +399,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "Le modèle est désactivé",
|
"zen.api.error.modelDisabled": "Le modèle est désactivé",
|
||||||
"zen.api.error.regionNotAllowed":
|
"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}}",
|
"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 n’est 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":
|
"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}}",
|
"La promotion gratuite de {{model}} est terminée. Vous pouvez continuer à utiliser le modèle en vous abonnant à OpenCode Go - {{link}}",
|
||||||
|
|
||||||
@@ -683,14 +689,15 @@ export const dict = {
|
|||||||
'Sélectionnez "OpenCode Go" comme fournisseur dans votre configuration opencode pour utiliser les modèles Go.',
|
'Sélectionnez "OpenCode Go" comme fournisseur dans votre configuration opencode pour utiliser les modèles Go.',
|
||||||
"workspace.lite.providers.title": "Fournisseurs",
|
"workspace.lite.providers.title": "Fournisseurs",
|
||||||
"workspace.lite.providers.description": "Contrôlez les fournisseurs utilisés pour le routage.",
|
"workspace.lite.providers.description": "Contrôlez les fournisseurs utilisés pour le routage.",
|
||||||
|
"workspace.lite.providers.allowTraining": "Autoriser les modèles qui s’entraînent sur les données des requêtes",
|
||||||
"workspace.lite.providers.useChina": "Activer les modèles hébergés en Chine",
|
"workspace.lite.providers.useChina": "Activer les modèles hébergés en Chine",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"Vous êtes actuellement abonné à OpenCode Black ou sur liste d'attente. Veuillez d'abord vous désabonner si vous souhaitez passer à Go.",
|
"Vous êtes actuellement abonné à OpenCode Black ou sur liste d'attente. Veuillez d'abord vous désabonner si vous souhaitez passer à Go.",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"Un autre membre de cet espace de travail est déjà abonné à OpenCode Go. Un seul membre par espace de travail peut s'abonner.",
|
"Un autre membre de cet espace de travail est déjà abonné à OpenCode Go. Un seul membre par espace de travail peut s'abonner.",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go commence à {{price}}, puis 10 $/mois, et offre un accès fiable aux modèles de code ouverts populaires avec des limites d'utilisation généreuses.",
|
"OpenCode Go coûte {{price}} et offre un accès fiable aux modèles de code ouverts populaires avec des limites d'utilisation généreuses.",
|
||||||
"workspace.lite.promo.price": "$5 le premier mois",
|
"workspace.lite.promo.price": "10 $/mois",
|
||||||
"workspace.lite.promo.modelsTitle": "Ce qui est inclus",
|
"workspace.lite.promo.modelsTitle": "Ce qui est inclus",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"Ce forfait est principalement conçu pour les utilisateurs internationaux et offre un accès mondial stable. Les tarifs et les limites d'utilisation peuvent évoluer à mesure que nous tirons les enseignements des premières utilisations et des retours reçus.",
|
"Ce forfait est principalement conçu pour les utilisateurs internationaux et offre un accès mondial stable. Les tarifs et les limites d'utilisation peuvent évoluer à mesure que nous tirons les enseignements des premières utilisations et des retours reçus.",
|
||||||
|
|||||||
@@ -254,9 +254,9 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "seguenti eccezioni",
|
"zen.privacy.exceptionsLink": "seguenti eccezioni",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | Modelli di coding a basso costo per tutti",
|
"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.banner.text": "Ox Alpha Free è disponibile su Go per un periodo limitato",
|
||||||
"go.meta.description":
|
"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 costa $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",
|
"go.hero.title": "Modelli di coding a basso costo per tutti",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go porta il coding agentico ai programmatori di tutto il mondo. Offrendo limiti generosi e un accesso affidabile ai modelli open source più capaci, in modo da poter costruire con agenti potenti senza preoccuparsi dei costi o della disponibilità.",
|
"Go porta il coding agentico ai programmatori di tutto il mondo. Offrendo limiti generosi e un accesso affidabile ai modelli open source più capaci, in modo da poter costruire con agenti potenti senza preoccuparsi dei costi o della disponibilità.",
|
||||||
@@ -265,13 +265,14 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "Abbonati a Go",
|
"go.cta.text": "Abbonati a Go",
|
||||||
"go.cta.price": "$10/mese",
|
"go.cta.price": "$10/mese",
|
||||||
"go.cta.promo": "$5 il primo mese",
|
|
||||||
"go.pricing.body":
|
"go.pricing.body":
|
||||||
"Usalo con qualsiasi agente. $5 il primo mese, poi $10/mese. Ricarica il credito se necessario. Annulla in qualsiasi momento.",
|
"Usalo con qualsiasi agente. $10/mese. Ricarica il credito se necessario. Annulla in qualsiasi momento.",
|
||||||
"go.graph.free": "Gratis",
|
"go.graph.free": "Gratis",
|
||||||
"go.graph.freePill": "Big Pickle e modelli gratuiti",
|
"go.graph.freePill": "Big Pickle e modelli gratuiti",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "Richieste ogni 5 ore",
|
"go.graph.label": "Richieste ogni 5 ore",
|
||||||
|
"go.graph.limitedRegions": "regioni limitate",
|
||||||
|
"go.graph.limitedTime": "periodo limitato",
|
||||||
"go.graph.usageLimits": "Limiti di utilizzo",
|
"go.graph.usageLimits": "Limiti di utilizzo",
|
||||||
"go.graph.aria": "Richieste ogni 5h: {{free}} vs {{go}}",
|
"go.graph.aria": "Richieste ogni 5h: {{free}} vs {{go}}",
|
||||||
|
|
||||||
@@ -298,20 +299,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "Vorrei essere ancora a Nvidia.",
|
"go.testimonials.frank.quote": "Vorrei essere ancora a Nvidia.",
|
||||||
"go.problem.title": "Quale problema risolve Go?",
|
"go.problem.title": "Quale problema risolve Go?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"Ci concentriamo nel portare l'esperienza OpenCode a quante più persone possibile. OpenCode Go è un abbonamento a basso costo: $5 il primo mese, poi $10/mese. Offre limiti generosi e accesso affidabile ai modelli open source più capaci.",
|
"Ci concentriamo nel portare l'esperienza OpenCode a quante più persone possibile. OpenCode Go è un abbonamento a basso costo da $10/mese. Offre limiti generosi e accesso affidabile ai modelli open source più capaci.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "Prezzo di abbonamento a basso costo",
|
"go.problem.item1": "Prezzo di abbonamento a basso costo",
|
||||||
"go.problem.item2": "Limiti generosi e accesso affidabile",
|
"go.problem.item2": "Limiti generosi e accesso affidabile",
|
||||||
"go.problem.item3": "Costruito per il maggior numero possibile di programmatori",
|
"go.problem.item3": "Costruito per il maggior numero possibile di programmatori",
|
||||||
"go.problem.item4": "Una selezione curata di modelli testati per il coding agentico",
|
"go.problem.item4": "Una selezione curata di modelli testati per il coding agentico",
|
||||||
"go.how.title": "Come funziona Go",
|
"go.how.title": "Come funziona Go",
|
||||||
"go.how.body": "Go inizia a $5 per il primo mese, poi $10/mese. Puoi usarlo con OpenCode o qualsiasi agente.",
|
"go.how.body": "Go costa $10/mese. Puoi usarlo con OpenCode o qualsiasi agente.",
|
||||||
"go.how.step1.title": "Crea un account",
|
"go.how.step1.title": "Crea un account",
|
||||||
"go.how.step1.beforeLink": "segui le",
|
"go.how.step1.beforeLink": "segui le",
|
||||||
"go.how.step1.link": "istruzioni di configurazione",
|
"go.how.step1.link": "istruzioni di configurazione",
|
||||||
"go.how.step2.title": "Abbonati a Go",
|
"go.how.step2.title": "Abbonati a Go",
|
||||||
"go.how.step2.link": "$5 il primo mese",
|
"go.how.step2.link": "$10/mese",
|
||||||
"go.how.step2.afterLink": "poi $10/mese con limiti generosi",
|
"go.how.step2.afterLink": "con limiti generosi",
|
||||||
"go.how.step3.title": "Inizia a programmare",
|
"go.how.step3.title": "Inizia a programmare",
|
||||||
"go.how.step3.body": "con accesso affidabile ai modelli open source",
|
"go.how.step3.body": "con accesso affidabile ai modelli open source",
|
||||||
"go.privacy.title": "La tua privacy è importante per noi",
|
"go.privacy.title": "La tua privacy è importante per noi",
|
||||||
@@ -328,11 +329,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go include i modelli elencati di seguito, con limiti generosi e accesso affidabile.",
|
"go.faq.a2": "Go include i modelli elencati di seguito, con limiti generosi e accesso affidabile.",
|
||||||
"go.faq.q3": "Go è lo stesso di Zen?",
|
"go.faq.q3": "Go è lo stesso di Zen?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"No. Zen è a consumo, mentre Go inizia a $5 per il primo mese, poi $10/mese, con limiti generosi e un accesso affidabile a una selezione curata di modelli.",
|
"No. Zen è a consumo, mentre Go costa $10/mese, con limiti generosi e un accesso affidabile a una selezione curata di modelli.",
|
||||||
"go.faq.q4": "Quanto costa Go?",
|
"go.faq.q4": "Quanto costa Go?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go costa",
|
"go.faq.a4.p1.beforePricing": "Go costa",
|
||||||
"go.faq.a4.p1.pricingLink": "$5 il primo mese",
|
"go.faq.a4.p1.pricingLink": "$10/mese",
|
||||||
"go.faq.a4.p1.afterPricing": "poi $10/mese con limiti generosi.",
|
"go.faq.a4.p1.afterPricing": "con limiti generosi.",
|
||||||
"go.faq.a4.p2.beforeAccount": "Puoi gestire il tuo abbonamento nel tuo",
|
"go.faq.a4.p2.beforeAccount": "Puoi gestire il tuo abbonamento nel tuo",
|
||||||
"go.faq.a4.p2.accountLink": "account",
|
"go.faq.a4.p2.accountLink": "account",
|
||||||
"go.faq.a4.p3": "Annulla in qualsiasi momento.",
|
"go.faq.a4.p3": "Annulla in qualsiasi momento.",
|
||||||
@@ -345,6 +346,7 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "Utilizzato",
|
"go.faq.a5.used": "Utilizzato",
|
||||||
"go.faq.a5.notUsed": "Non utilizzato",
|
"go.faq.a5.notUsed": "Non utilizzato",
|
||||||
"go.faq.a5.noAgreement": "Nessun accordo",
|
"go.faq.a5.noAgreement": "Nessun accordo",
|
||||||
|
"go.faq.a5.notZdr": "Non ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"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.",
|
"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":
|
"go.faq.a5.gptRetention":
|
||||||
@@ -352,6 +354,8 @@ export const dict = {
|
|||||||
"go.faq.a5.learnMore": "Scopri di più",
|
"go.faq.a5.learnMore": "Scopri di più",
|
||||||
"go.faq.a5.deepseekRetention":
|
"go.faq.a5.deepseekRetention":
|
||||||
"L'accordo ZDR viene rinnovato mensilmente. L'accordo attuale è valido fino al 31 agosto 2026.",
|
"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":
|
"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",
|
"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",
|
"go.faq.a5.exceptionsLink": "seguenti eccezioni",
|
||||||
@@ -391,6 +395,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "Il modello è disabilitato",
|
"zen.api.error.modelDisabled": "Il modello è disabilitato",
|
||||||
"zen.api.error.regionNotAllowed":
|
"zen.api.error.regionNotAllowed":
|
||||||
"La versione più recente di questo modello è disponibile solo con hosting in Cina e richiede un consenso esplicito: {{consoleGoUrl}}",
|
"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":
|
"zen.api.error.trialEnded":
|
||||||
"La promozione gratuita di {{model}} è terminata. Puoi continuare a usare il modello abbonandoti a OpenCode Go - {{link}}",
|
"La promozione gratuita di {{model}} è terminata. Puoi continuare a usare il modello abbonandoti a OpenCode Go - {{link}}",
|
||||||
|
|
||||||
@@ -674,14 +681,15 @@ export const dict = {
|
|||||||
'Seleziona "OpenCode Go" come provider nella tua configurazione opencode per utilizzare i modelli Go.',
|
'Seleziona "OpenCode Go" come provider nella tua configurazione opencode per utilizzare i modelli Go.',
|
||||||
"workspace.lite.providers.title": "Provider",
|
"workspace.lite.providers.title": "Provider",
|
||||||
"workspace.lite.providers.description": "Controlla quali provider vengono usati per il routing.",
|
"workspace.lite.providers.description": "Controlla quali provider vengono usati per il routing.",
|
||||||
|
"workspace.lite.providers.allowTraining": "Consenti i modelli che si addestrano sui dati delle richieste",
|
||||||
"workspace.lite.providers.useChina": "Abilita modelli ospitati in Cina",
|
"workspace.lite.providers.useChina": "Abilita modelli ospitati in Cina",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"Attualmente sei abbonato a OpenCode Black o sei in lista d'attesa. Annulla l'iscrizione prima se desideri passare a Go.",
|
"Attualmente sei abbonato a OpenCode Black o sei in lista d'attesa. Annulla l'iscrizione prima se desideri passare a Go.",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"Un altro membro in questo workspace è già abbonato a OpenCode Go. Solo un membro per workspace può abbonarsi.",
|
"Un altro membro in questo workspace è già abbonato a OpenCode Go. Solo un membro per workspace può abbonarsi.",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go parte da {{price}}, poi $10/mese, e offre un accesso affidabile a popolari modelli di coding aperti con generosi limiti di utilizzo.",
|
"OpenCode Go costa {{price}} e offre un accesso affidabile a popolari modelli di coding aperti con generosi limiti di utilizzo.",
|
||||||
"workspace.lite.promo.price": "$5 il primo mese",
|
"workspace.lite.promo.price": "$10/mese",
|
||||||
"workspace.lite.promo.modelsTitle": "Cosa è incluso",
|
"workspace.lite.promo.modelsTitle": "Cosa è incluso",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"Il piano è pensato principalmente per gli utenti internazionali e offre un accesso globale stabile. I prezzi e i limiti di utilizzo potrebbero cambiare in base a quanto apprenderemo dall'utilizzo iniziale e dai feedback.",
|
"Il piano è pensato principalmente per gli utenti internazionali e offre un accesso globale stabile. I prezzi e i limiti di utilizzo potrebbero cambiare in base a quanto apprenderemo dall'utilizzo iniziale e dai feedback.",
|
||||||
|
|||||||
@@ -253,9 +253,9 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "以下の例外",
|
"zen.privacy.exceptionsLink": "以下の例外",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | すべての人のための低価格なコーディングモデル",
|
"go.title": "OpenCode Go | すべての人のための低価格なコーディングモデル",
|
||||||
"go.banner.text": "DeepSeek V4 Flashの利用上限が期間限定で2倍に",
|
"go.banner.text": "Ox Alpha Freeは期間限定でGoで利用できます",
|
||||||
"go.meta.description":
|
"go.meta.description":
|
||||||
"Goは最初の月$5、その後$10/月で、主要なコーディングモデルへのゆとりある利用上限と安定したアクセスを提供します。",
|
"Goは月額$10で、主要なコーディングモデルへのゆとりある利用上限と安定したアクセスを提供します。",
|
||||||
"go.hero.title": "すべての人のための低価格なコーディングモデル",
|
"go.hero.title": "すべての人のための低価格なコーディングモデル",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Goは、世界中のプログラマーにエージェント型コーディングをもたらします。最も高性能なオープンソースモデルへの十分な制限と安定したアクセスを提供し、コストや可用性を気にすることなく強力なエージェントで構築できます。",
|
"Goは、世界中のプログラマーにエージェント型コーディングをもたらします。最も高性能なオープンソースモデルへの十分な制限と安定したアクセスを提供し、コストや可用性を気にすることなく強力なエージェントで構築できます。",
|
||||||
@@ -264,13 +264,14 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "Goを購読する",
|
"go.cta.text": "Goを購読する",
|
||||||
"go.cta.price": "$10/月",
|
"go.cta.price": "$10/月",
|
||||||
"go.cta.promo": "初月 $5",
|
|
||||||
"go.pricing.body":
|
"go.pricing.body":
|
||||||
"どのエージェントでも使えます。最初の月$5、その後$10/月。必要に応じてクレジットを追加。いつでもキャンセルできます。",
|
"どのエージェントでも使えます。月額$10。必要に応じてクレジットを追加。いつでもキャンセルできます。",
|
||||||
"go.graph.free": "無料",
|
"go.graph.free": "無料",
|
||||||
"go.graph.freePill": "Big Pickleと無料モデル",
|
"go.graph.freePill": "Big Pickleと無料モデル",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "5時間あたりのリクエスト数",
|
"go.graph.label": "5時間あたりのリクエスト数",
|
||||||
|
"go.graph.limitedRegions": "一部の地域に限定",
|
||||||
|
"go.graph.limitedTime": "期間限定",
|
||||||
"go.graph.usageLimits": "利用制限",
|
"go.graph.usageLimits": "利用制限",
|
||||||
"go.graph.aria": "5時間あたりのリクエスト数: {{free}} 対 {{go}}",
|
"go.graph.aria": "5時間あたりのリクエスト数: {{free}} 対 {{go}}",
|
||||||
|
|
||||||
@@ -298,20 +299,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "まだNvidiaにいられたらよかったのに。",
|
"go.testimonials.frank.quote": "まだNvidiaにいられたらよかったのに。",
|
||||||
"go.problem.title": "Goはどのような問題を解決していますか?",
|
"go.problem.title": "Goはどのような問題を解決していますか?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"私たちはOpenCodeの体験をできるだけ多くの人に届けることに注力しています。OpenCode Goは低価格のサブスクリプションで、最初の月は$5、その後は$10/月です。ゆとりある上限と、最も高性能なオープンソースモデルへの信頼できるアクセスを提供します。",
|
"私たちはOpenCodeの体験をできるだけ多くの人に届けることに注力しています。OpenCode Goは月額$10の低価格なサブスクリプションです。ゆとりある上限と、最も高性能なオープンソースモデルへの信頼できるアクセスを提供します。",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "低価格なサブスクリプション料金",
|
"go.problem.item1": "低価格なサブスクリプション料金",
|
||||||
"go.problem.item2": "十分な制限と安定したアクセス",
|
"go.problem.item2": "十分な制限と安定したアクセス",
|
||||||
"go.problem.item3": "できるだけ多くのプログラマーのために構築",
|
"go.problem.item3": "できるだけ多くのプログラマーのために構築",
|
||||||
"go.problem.item4": "エージェント型コーディング向けにテストされた厳選モデルラインナップ",
|
"go.problem.item4": "エージェント型コーディング向けにテストされた厳選モデルラインナップ",
|
||||||
"go.how.title": "Goの仕組み",
|
"go.how.title": "Goの仕組み",
|
||||||
"go.how.body": "Goは最初の月$5、その後$10/月で始まります。OpenCodeまたは任意のエージェントで使えます。",
|
"go.how.body": "Goは月額$10です。OpenCodeまたは任意のエージェントで使えます。",
|
||||||
"go.how.step1.title": "アカウントを作成",
|
"go.how.step1.title": "アカウントを作成",
|
||||||
"go.how.step1.beforeLink": "",
|
"go.how.step1.beforeLink": "",
|
||||||
"go.how.step1.link": "セットアップ手順はこちら",
|
"go.how.step1.link": "セットアップ手順はこちら",
|
||||||
"go.how.step2.title": "Goを購読する",
|
"go.how.step2.title": "Goを購読する",
|
||||||
"go.how.step2.link": "最初の月$5",
|
"go.how.step2.link": "月額$10",
|
||||||
"go.how.step2.afterLink": "その後$10/月、ゆとりある上限付き",
|
"go.how.step2.afterLink": "ゆとりある上限付き",
|
||||||
"go.how.step3.title": "コーディングを開始",
|
"go.how.step3.title": "コーディングを開始",
|
||||||
"go.how.step3.body": "オープンソースモデルへの安定したアクセスで",
|
"go.how.step3.body": "オープンソースモデルへの安定したアクセスで",
|
||||||
"go.privacy.title": "あなたのプライバシーは私たちにとって重要です",
|
"go.privacy.title": "あなたのプライバシーは私たちにとって重要です",
|
||||||
@@ -328,11 +329,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go には、十分な利用上限と安定したアクセスを備えた、以下のモデルが含まれます。",
|
"go.faq.a2": "Go には、十分な利用上限と安定したアクセスを備えた、以下のモデルが含まれます。",
|
||||||
"go.faq.q3": "GoはZenと同じですか?",
|
"go.faq.q3": "GoはZenと同じですか?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"いいえ。Zenは従量課金制ですが、Goは最初の月$5、その後$10/月で、厳選されたモデルラインナップへのゆとりある上限と安定したアクセスを提供します。",
|
"いいえ。Zenは従量課金制ですが、Goは月額$10で、厳選されたモデルラインナップへのゆとりある上限と安定したアクセスを提供します。",
|
||||||
"go.faq.q4": "Goの料金は?",
|
"go.faq.q4": "Goの料金は?",
|
||||||
"go.faq.a4.p1.beforePricing": "Goは",
|
"go.faq.a4.p1.beforePricing": "Goは",
|
||||||
"go.faq.a4.p1.pricingLink": "最初の月$5",
|
"go.faq.a4.p1.pricingLink": "月額$10",
|
||||||
"go.faq.a4.p1.afterPricing": "その後$10/月、ゆとりある上限付き。",
|
"go.faq.a4.p1.afterPricing": "ゆとりある上限付き。",
|
||||||
"go.faq.a4.p2.beforeAccount": "管理画面:",
|
"go.faq.a4.p2.beforeAccount": "管理画面:",
|
||||||
"go.faq.a4.p2.accountLink": "アカウント",
|
"go.faq.a4.p2.accountLink": "アカウント",
|
||||||
"go.faq.a4.p3": "いつでもキャンセル可能です。",
|
"go.faq.a4.p3": "いつでもキャンセル可能です。",
|
||||||
@@ -345,9 +346,12 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "使用あり",
|
"go.faq.a5.used": "使用あり",
|
||||||
"go.faq.a5.notUsed": "使用なし",
|
"go.faq.a5.notUsed": "使用なし",
|
||||||
"go.faq.a5.noAgreement": "契約なし",
|
"go.faq.a5.noAgreement": "契約なし",
|
||||||
|
"go.faq.a5.notZdr": "ZDRではない",
|
||||||
"go.faq.a5.grokRetention":
|
"go.faq.a5.grokRetention":
|
||||||
"ZDRでは、保存データに依存する重要なAPI機能(ステートフルなResponses API、Files and Collections、Batch APIなど)が無効になります。",
|
"ZDRでは、保存データに依存する重要なAPI機能(ステートフルなResponses API、Files and Collections、Batch APIなど)が無効になります。",
|
||||||
"go.faq.a5.gptRetention": "不正使用監視ログはすべてのAPI機能の使用時に生成され、最大30日間保持されます。",
|
"go.faq.a5.gptRetention": "不正使用監視ログはすべてのAPI機能の使用時に生成され、最大30日間保持されます。",
|
||||||
|
"go.faq.a5.museRetention":
|
||||||
|
"将来のMetaモデルのトレーニングにプロンプトと生成結果を使用する許可と引き換えに、トークン料金が大幅に割引されます。",
|
||||||
"go.faq.a5.learnMore": "詳しく見る",
|
"go.faq.a5.learnMore": "詳しく見る",
|
||||||
"go.faq.a5.deepseekRetention": "ZDR契約は毎月更新されます。現在の契約は2026年8月31日まで有効です。",
|
"go.faq.a5.deepseekRetention": "ZDR契約は毎月更新されます。現在の契約は2026年8月31日まで有効です。",
|
||||||
"go.faq.a5.beforeExceptions":
|
"go.faq.a5.beforeExceptions":
|
||||||
@@ -390,6 +394,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "モデルが無効です",
|
"zen.api.error.modelDisabled": "モデルが無効です",
|
||||||
"zen.api.error.regionNotAllowed":
|
"zen.api.error.regionNotAllowed":
|
||||||
"このモデルの最新バージョンは中国でのみホスト提供されており、利用するには明示的なオプトインが必要です: {{consoleGoUrl}}",
|
"このモデルの最新バージョンは中国でのみホスト提供されており、利用するには明示的なオプトインが必要です: {{consoleGoUrl}}",
|
||||||
|
"zen.api.error.countryNotAllowed": "このモデルはお住まいの国では利用できません。",
|
||||||
|
"zen.api.error.trainingNotAllowed":
|
||||||
|
"このモデルは品質向上のためのデータを収集します。利用するには明示的な同意が必要です: {{consoleGoUrl}}",
|
||||||
"zen.api.error.trialEnded":
|
"zen.api.error.trialEnded":
|
||||||
"{{model}} の無料プロモーションは終了しました。OpenCode Go を購読するとモデルを引き続き使用できます - {{link}}",
|
"{{model}} の無料プロモーションは終了しました。OpenCode Go を購読するとモデルを引き続き使用できます - {{link}}",
|
||||||
|
|
||||||
@@ -672,14 +679,15 @@ export const dict = {
|
|||||||
"Go モデルを使用するには、opencode の設定で「OpenCode Go」をプロバイダーとして選択してください。",
|
"Go モデルを使用するには、opencode の設定で「OpenCode Go」をプロバイダーとして選択してください。",
|
||||||
"workspace.lite.providers.title": "プロバイダー",
|
"workspace.lite.providers.title": "プロバイダー",
|
||||||
"workspace.lite.providers.description": "ルーティングに使用するプロバイダーを管理します。",
|
"workspace.lite.providers.description": "ルーティングに使用するプロバイダーを管理します。",
|
||||||
|
"workspace.lite.providers.allowTraining": "リクエストデータを学習に使用するモデルを許可",
|
||||||
"workspace.lite.providers.useChina": "中国でホストされているモデルを有効にする",
|
"workspace.lite.providers.useChina": "中国でホストされているモデルを有効にする",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"現在 OpenCode Black を購読中、またはウェイティングリストに登録されています。Go に切り替える場合は、先に登録を解除してください。",
|
"現在 OpenCode Black を購読中、またはウェイティングリストに登録されています。Go に切り替える場合は、先に登録を解除してください。",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"このワークスペースの別のメンバーが既に OpenCode Go を購読しています。ワークスペースにつき1人のメンバーのみが購読できます。",
|
"このワークスペースの別のメンバーが既に OpenCode Go を購読しています。ワークスペースにつき1人のメンバーのみが購読できます。",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Goは{{price}}で始まり、その後は$10/月で、人気の高いオープンコーディングモデルへの安定したアクセスと余裕のある利用枠を提供します。",
|
"OpenCode Goは{{price}}で、人気の高いオープンコーディングモデルへの安定したアクセスと余裕のある利用枠を提供します。",
|
||||||
"workspace.lite.promo.price": "初月$5",
|
"workspace.lite.promo.price": "$10/月",
|
||||||
"workspace.lite.promo.modelsTitle": "含まれるもの",
|
"workspace.lite.promo.modelsTitle": "含まれるもの",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"このプランは主に海外のユーザー向けに設計されており、世界中から安定してご利用いただけます。料金と利用上限は、初期の利用状況やフィードバックを踏まえて変更される場合があります。",
|
"このプランは主に海外のユーザー向けに設計されており、世界中から安定してご利用いただけます。料金と利用上限は、初期の利用状況やフィードバックを踏まえて変更される場合があります。",
|
||||||
|
|||||||
@@ -250,9 +250,8 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "다음 예외",
|
"zen.privacy.exceptionsLink": "다음 예외",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | 모두를 위한 저비용 코딩 모델",
|
"go.title": "OpenCode Go | 모두를 위한 저비용 코딩 모델",
|
||||||
"go.banner.text": "DeepSeek V4 Flash 사용 한도가 한시적으로 2배 확대됩니다",
|
"go.banner.text": "Ox Alpha Free가 한정된 기간 동안 Go에서 제공됩니다",
|
||||||
"go.meta.description":
|
"go.meta.description": "Go는 월 $10이며, 넉넉한 사용 한도와 주요 코딩 모델에 대한 안정적인 액세스를 제공합니다.",
|
||||||
"Go는 첫 달 $5, 이후 $10/월로 시작하며, 넉넉한 사용 한도와 주요 코딩 모델에 대한 안정적인 액세스를 제공합니다.",
|
|
||||||
"go.hero.title": "모두를 위한 저비용 코딩 모델",
|
"go.hero.title": "모두를 위한 저비용 코딩 모델",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go는 전 세계 프로그래머들에게 에이전트 코딩을 제공합니다. 가장 유능한 오픈 소스 모델에 대한 넉넉한 한도와 안정적인 액세스를 제공하므로, 비용이나 가용성 걱정 없이 강력한 에이전트로 빌드할 수 있습니다.",
|
"Go는 전 세계 프로그래머들에게 에이전트 코딩을 제공합니다. 가장 유능한 오픈 소스 모델에 대한 넉넉한 한도와 안정적인 액세스를 제공하므로, 비용이나 가용성 걱정 없이 강력한 에이전트로 빌드할 수 있습니다.",
|
||||||
@@ -261,13 +260,14 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "Go 구독하기",
|
"go.cta.text": "Go 구독하기",
|
||||||
"go.cta.price": "$10/월",
|
"go.cta.price": "$10/월",
|
||||||
"go.cta.promo": "첫 달 $5",
|
|
||||||
"go.pricing.body":
|
"go.pricing.body":
|
||||||
"어떤 에이전트와도 사용할 수 있습니다. 첫 달 $5, 이후 $10/월. 필요하면 크레딧을 충전하세요. 언제든지 취소할 수 있습니다.",
|
"어떤 에이전트와도 사용할 수 있습니다. 월 $10. 필요하면 크레딧을 충전하세요. 언제든지 취소할 수 있습니다.",
|
||||||
"go.graph.free": "무료",
|
"go.graph.free": "무료",
|
||||||
"go.graph.freePill": "Big Pickle 및 무료 모델",
|
"go.graph.freePill": "Big Pickle 및 무료 모델",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "5시간당 요청 수",
|
"go.graph.label": "5시간당 요청 수",
|
||||||
|
"go.graph.limitedRegions": "일부 지역에서만 제공",
|
||||||
|
"go.graph.limitedTime": "한정된 기간",
|
||||||
"go.graph.usageLimits": "사용 한도",
|
"go.graph.usageLimits": "사용 한도",
|
||||||
"go.graph.aria": "5시간당 요청 수: {{free}} 대 {{go}}",
|
"go.graph.aria": "5시간당 요청 수: {{free}} 대 {{go}}",
|
||||||
|
|
||||||
@@ -295,20 +295,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "아직 Nvidia에 있었으면 좋았을 텐데요.",
|
"go.testimonials.frank.quote": "아직 Nvidia에 있었으면 좋았을 텐데요.",
|
||||||
"go.problem.title": "Go는 어떤 문제를 해결하나요?",
|
"go.problem.title": "Go는 어떤 문제를 해결하나요?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"우리는 가능한 많은 사람들에게 OpenCode 경험을 제공하는 데 집중하고 있습니다. OpenCode Go는 저렴한 구독 서비스로, 첫 달 $5, 이후 $10/월입니다. 넉넉한 한도와 가장 뛰어난 오픈 소스 모델에 대한 안정적인 액세스를 제공합니다.",
|
"우리는 가능한 많은 사람들에게 OpenCode 경험을 제공하는 데 집중하고 있습니다. OpenCode Go는 월 $10의 저렴한 구독 서비스입니다. 넉넉한 한도와 가장 뛰어난 오픈 소스 모델에 대한 안정적인 액세스를 제공합니다.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "저렴한 구독 가격",
|
"go.problem.item1": "저렴한 구독 가격",
|
||||||
"go.problem.item2": "넉넉한 한도와 안정적인 액세스",
|
"go.problem.item2": "넉넉한 한도와 안정적인 액세스",
|
||||||
"go.problem.item3": "가능한 한 많은 프로그래머를 위해 제작됨",
|
"go.problem.item3": "가능한 한 많은 프로그래머를 위해 제작됨",
|
||||||
"go.problem.item4": "에이전트 코딩용으로 테스트된 엄선된 모델 라인업",
|
"go.problem.item4": "에이전트 코딩용으로 테스트된 엄선된 모델 라인업",
|
||||||
"go.how.title": "Go 작동 방식",
|
"go.how.title": "Go 작동 방식",
|
||||||
"go.how.body": "Go는 첫 달 $5, 이후 $10/월로 시작합니다. OpenCode 또는 어떤 에이전트와도 함께 사용할 수 있습니다.",
|
"go.how.body": "Go는 월 $10입니다. OpenCode 또는 어떤 에이전트와도 함께 사용할 수 있습니다.",
|
||||||
"go.how.step1.title": "계정 생성",
|
"go.how.step1.title": "계정 생성",
|
||||||
"go.how.step1.beforeLink": "",
|
"go.how.step1.beforeLink": "",
|
||||||
"go.how.step1.link": "설정 지침을 따르세요",
|
"go.how.step1.link": "설정 지침을 따르세요",
|
||||||
"go.how.step2.title": "Go 구독",
|
"go.how.step2.title": "Go 구독",
|
||||||
"go.how.step2.link": "첫 달 $5",
|
"go.how.step2.link": "월 $10",
|
||||||
"go.how.step2.afterLink": "이후 $10/월, 넉넉한 한도 포함",
|
"go.how.step2.afterLink": "넉넉한 한도 포함",
|
||||||
"go.how.step3.title": "코딩 시작",
|
"go.how.step3.title": "코딩 시작",
|
||||||
"go.how.step3.body": "오픈 소스 모델에 대한 안정적인 액세스와 함께",
|
"go.how.step3.body": "오픈 소스 모델에 대한 안정적인 액세스와 함께",
|
||||||
"go.privacy.title": "귀하의 프라이버시는 우리에게 중요합니다",
|
"go.privacy.title": "귀하의 프라이버시는 우리에게 중요합니다",
|
||||||
@@ -324,11 +324,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go에는 넉넉한 한도와 안정적인 액세스를 제공하는 아래 모델이 포함됩니다.",
|
"go.faq.a2": "Go에는 넉넉한 한도와 안정적인 액세스를 제공하는 아래 모델이 포함됩니다.",
|
||||||
"go.faq.q3": "Go는 Zen과 같은가요?",
|
"go.faq.q3": "Go는 Zen과 같은가요?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"아니요. Zen은 종량제인 반면, Go는 첫 달 $5, 이후 $10/월로 시작하며, 엄선된 모델 라인업에 대한 넉넉한 한도와 안정적인 액세스를 제공합니다.",
|
"아니요. Zen은 종량제인 반면, Go는 월 $10이며, 엄선된 모델 라인업에 대한 넉넉한 한도와 안정적인 액세스를 제공합니다.",
|
||||||
"go.faq.q4": "Go 비용은 얼마인가요?",
|
"go.faq.q4": "Go 비용은 얼마인가요?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go 비용은",
|
"go.faq.a4.p1.beforePricing": "Go 비용은",
|
||||||
"go.faq.a4.p1.pricingLink": "첫 달 $5",
|
"go.faq.a4.p1.pricingLink": "월 $10",
|
||||||
"go.faq.a4.p1.afterPricing": "이후 $10/월, 넉넉한 한도 포함.",
|
"go.faq.a4.p1.afterPricing": "넉넉한 한도 포함.",
|
||||||
"go.faq.a4.p2.beforeAccount": "구독 관리는 다음에서 가능합니다:",
|
"go.faq.a4.p2.beforeAccount": "구독 관리는 다음에서 가능합니다:",
|
||||||
"go.faq.a4.p2.accountLink": "계정",
|
"go.faq.a4.p2.accountLink": "계정",
|
||||||
"go.faq.a4.p3": "언제든지 취소할 수 있습니다.",
|
"go.faq.a4.p3": "언제든지 취소할 수 있습니다.",
|
||||||
@@ -341,9 +341,12 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "사용됨",
|
"go.faq.a5.used": "사용됨",
|
||||||
"go.faq.a5.notUsed": "사용되지 않음",
|
"go.faq.a5.notUsed": "사용되지 않음",
|
||||||
"go.faq.a5.noAgreement": "합의 없음",
|
"go.faq.a5.noAgreement": "합의 없음",
|
||||||
|
"go.faq.a5.notZdr": "ZDR 아님",
|
||||||
"go.faq.a5.grokRetention":
|
"go.faq.a5.grokRetention":
|
||||||
"ZDR은 저장된 데이터에 의존하는 중요한 API 기능(상태 저장형 Responses API, Files and Collections, Batch API 포함)을 비활성화합니다.",
|
"ZDR은 저장된 데이터에 의존하는 중요한 API 기능(상태 저장형 Responses API, Files and Collections, Batch API 포함)을 비활성화합니다.",
|
||||||
"go.faq.a5.gptRetention": "모든 API 기능 사용에 대해 악용 모니터링 로그가 생성되며 최대 30일 동안 보존됩니다.",
|
"go.faq.a5.gptRetention": "모든 API 기능 사용에 대해 악용 모니터링 로그가 생성되며 최대 30일 동안 보존됩니다.",
|
||||||
|
"go.faq.a5.museRetention":
|
||||||
|
"향후 Meta 모델 학습에 사용자의 프롬프트와 생성 결과를 사용할 수 있도록 허용하는 대신 토큰 가격이 대폭 할인됩니다.",
|
||||||
"go.faq.a5.learnMore": "자세히 알아보기",
|
"go.faq.a5.learnMore": "자세히 알아보기",
|
||||||
"go.faq.a5.deepseekRetention": "ZDR 계약은 매월 갱신됩니다. 현재 계약은 2026년 8월 31일까지 유효합니다.",
|
"go.faq.a5.deepseekRetention": "ZDR 계약은 매월 갱신됩니다. 현재 계약은 2026년 8월 31일까지 유효합니다.",
|
||||||
"go.faq.a5.beforeExceptions":
|
"go.faq.a5.beforeExceptions":
|
||||||
@@ -384,6 +387,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "모델이 비활성화되었습니다",
|
"zen.api.error.modelDisabled": "모델이 비활성화되었습니다",
|
||||||
"zen.api.error.regionNotAllowed":
|
"zen.api.error.regionNotAllowed":
|
||||||
"이 모델의 최신 버전은 중국에서 호스팅되는 경우에만 사용할 수 있으며, 명시적으로 사용에 동의해야 합니다: {{consoleGoUrl}}",
|
"이 모델의 최신 버전은 중국에서 호스팅되는 경우에만 사용할 수 있으며, 명시적으로 사용에 동의해야 합니다: {{consoleGoUrl}}",
|
||||||
|
"zen.api.error.countryNotAllowed": "이 모델은 거주 국가에서 사용할 수 없습니다.",
|
||||||
|
"zen.api.error.trainingNotAllowed":
|
||||||
|
"이 모델은 품질 개선에 사용되는 데이터를 수집하며, 사용하려면 명시적으로 동의해야 합니다: {{consoleGoUrl}}",
|
||||||
"zen.api.error.trialEnded":
|
"zen.api.error.trialEnded":
|
||||||
"{{model}}의 무료 프로모션이 종료되었습니다. OpenCode Go를 구독하면 모델을 계속 사용할 수 있습니다 - {{link}}",
|
"{{model}}의 무료 프로모션이 종료되었습니다. OpenCode Go를 구독하면 모델을 계속 사용할 수 있습니다 - {{link}}",
|
||||||
|
|
||||||
@@ -664,14 +670,15 @@ export const dict = {
|
|||||||
'Go 모델을 사용하려면 opencode 설정에서 "OpenCode Go"를 공급자로 선택하세요.',
|
'Go 모델을 사용하려면 opencode 설정에서 "OpenCode Go"를 공급자로 선택하세요.',
|
||||||
"workspace.lite.providers.title": "공급자",
|
"workspace.lite.providers.title": "공급자",
|
||||||
"workspace.lite.providers.description": "라우팅에 사용할 공급자를 제어합니다.",
|
"workspace.lite.providers.description": "라우팅에 사용할 공급자를 제어합니다.",
|
||||||
|
"workspace.lite.providers.allowTraining": "요청 데이터를 학습에 사용하는 모델 허용",
|
||||||
"workspace.lite.providers.useChina": "중국에서 호스팅되는 모델 활성화",
|
"workspace.lite.providers.useChina": "중국에서 호스팅되는 모델 활성화",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"현재 OpenCode Black을 구독 중이거나 대기 명단에 등록되어 있습니다. Go로 전환하려면 먼저 구독을 취소해 주세요.",
|
"현재 OpenCode Black을 구독 중이거나 대기 명단에 등록되어 있습니다. Go로 전환하려면 먼저 구독을 취소해 주세요.",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"이 워크스페이스의 다른 멤버가 이미 OpenCode Go를 구독 중입니다. 워크스페이스당 한 명의 멤버만 구독할 수 있습니다.",
|
"이 워크스페이스의 다른 멤버가 이미 OpenCode Go를 구독 중입니다. 워크스페이스당 한 명의 멤버만 구독할 수 있습니다.",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go는 {{price}}부터 시작하며, 이후 $10/월로 넉넉한 사용량 한도와 함께 인기 있는 오픈 코딩 모델에 대한 안정적인 액세스를 제공합니다.",
|
"OpenCode Go는 {{price}}로 넉넉한 사용량 한도와 함께 인기 있는 오픈 코딩 모델에 대한 안정적인 액세스를 제공합니다.",
|
||||||
"workspace.lite.promo.price": "첫 달 $5",
|
"workspace.lite.promo.price": "$10/월",
|
||||||
"workspace.lite.promo.modelsTitle": "포함 내역",
|
"workspace.lite.promo.modelsTitle": "포함 내역",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"이 플랜은 주로 해외 사용자를 위해 설계되었으며, 전 세계에서 안정적으로 이용할 수 있습니다. 초기 이용 현황과 피드백을 반영하는 과정에서 가격과 사용 한도가 변경될 수 있습니다.",
|
"이 플랜은 주로 해외 사용자를 위해 설계되었으며, 전 세계에서 안정적으로 이용할 수 있습니다. 초기 이용 현황과 피드백을 반영하는 과정에서 가격과 사용 한도가 변경될 수 있습니다.",
|
||||||
|
|||||||
@@ -254,9 +254,9 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "følgende unntak",
|
"zen.privacy.exceptionsLink": "følgende unntak",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | Rimelige kodemodeller for alle",
|
"go.title": "OpenCode Go | Rimelige kodemodeller for alle",
|
||||||
"go.banner.text": "DeepSeek V4 Flash får 2x bruksgrense i en begrenset periode",
|
"go.banner.text": "Ox Alpha Free er tilgjengelig på Go i en begrenset periode",
|
||||||
"go.meta.description":
|
"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 koster $10/måned, med sjenerøse bruksgrenser og pålitelig tilgang til ledende kodemodeller.",
|
||||||
"go.hero.title": "Rimelige kodemodeller for alle",
|
"go.hero.title": "Rimelige kodemodeller for alle",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go bringer agent-koding til programmerere over hele verden. Med rause grenser og pålitelig tilgang til de mest kapable åpen kildekode-modellene, kan du bygge med kraftige agenter uten å bekymre deg for kostnader eller tilgjengelighet.",
|
"Go bringer agent-koding til programmerere over hele verden. Med rause grenser og pålitelig tilgang til de mest kapable åpen kildekode-modellene, kan du bygge med kraftige agenter uten å bekymre deg for kostnader eller tilgjengelighet.",
|
||||||
@@ -265,13 +265,13 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "Abonner på Go",
|
"go.cta.text": "Abonner på Go",
|
||||||
"go.cta.price": "$10/måned",
|
"go.cta.price": "$10/måned",
|
||||||
"go.cta.promo": "$5 første måned",
|
"go.pricing.body": "Bruk med hvilken som helst agent. $10/måned. Fyll på kreditt ved behov. Avslutt når som helst.",
|
||||||
"go.pricing.body":
|
|
||||||
"Bruk med hvilken som helst agent. $5 første måned, deretter $10/måned. Fyll på kreditt ved behov. Avslutt når som helst.",
|
|
||||||
"go.graph.free": "Gratis",
|
"go.graph.free": "Gratis",
|
||||||
"go.graph.freePill": "Big Pickle og gratis modeller",
|
"go.graph.freePill": "Big Pickle og gratis modeller",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "Forespørsler per 5 timer",
|
"go.graph.label": "Forespørsler per 5 timer",
|
||||||
|
"go.graph.limitedRegions": "begrensede regioner",
|
||||||
|
"go.graph.limitedTime": "begrenset periode",
|
||||||
"go.graph.usageLimits": "Bruksgrenser",
|
"go.graph.usageLimits": "Bruksgrenser",
|
||||||
"go.graph.aria": "Forespørsler per 5t: {{free}} vs {{go}}",
|
"go.graph.aria": "Forespørsler per 5t: {{free}} vs {{go}}",
|
||||||
|
|
||||||
@@ -298,21 +298,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "Jeg skulle ønske jeg fortsatt var hos Nvidia.",
|
"go.testimonials.frank.quote": "Jeg skulle ønske jeg fortsatt var hos Nvidia.",
|
||||||
"go.problem.title": "Hvilket problem løser Go?",
|
"go.problem.title": "Hvilket problem løser Go?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"Vi fokuserer på å bringe OpenCode-opplevelsen til så mange som mulig. OpenCode Go er et rimelig abonnement: $5 for den første måneden, deretter $10/måned. Det gir sjenerøse grenser og pålitelig tilgang til de mest kapable åpen kildekode-modellene.",
|
"Vi fokuserer på å bringe OpenCode-opplevelsen til så mange som mulig. OpenCode Go er et rimelig abonnement til $10/måned. Det gir sjenerøse grenser og pålitelig tilgang til de mest kapable åpen kildekode-modellene.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "Rimelig abonnementspris",
|
"go.problem.item1": "Rimelig abonnementspris",
|
||||||
"go.problem.item2": "Rause grenser og pålitelig tilgang",
|
"go.problem.item2": "Rause grenser og pålitelig tilgang",
|
||||||
"go.problem.item3": "Bygget for så mange programmerere som mulig",
|
"go.problem.item3": "Bygget for så mange programmerere som mulig",
|
||||||
"go.problem.item4": "Et kuratert modellutvalg testet for agent-koding",
|
"go.problem.item4": "Et kuratert modellutvalg testet for agent-koding",
|
||||||
"go.how.title": "Hvordan Go fungerer",
|
"go.how.title": "Hvordan Go fungerer",
|
||||||
"go.how.body":
|
"go.how.body": "Go koster $10/måned. Du kan bruke det med OpenCode eller hvilken som helst agent.",
|
||||||
"Go starter på $5 for den første måneden, deretter $10/måned. Du kan bruke det med OpenCode eller hvilken som helst agent.",
|
|
||||||
"go.how.step1.title": "Opprett en konto",
|
"go.how.step1.title": "Opprett en konto",
|
||||||
"go.how.step1.beforeLink": "følg",
|
"go.how.step1.beforeLink": "følg",
|
||||||
"go.how.step1.link": "oppsettsinstruksjonene",
|
"go.how.step1.link": "oppsettsinstruksjonene",
|
||||||
"go.how.step2.title": "Abonner på Go",
|
"go.how.step2.title": "Abonner på Go",
|
||||||
"go.how.step2.link": "$5 første måned",
|
"go.how.step2.link": "$10/måned",
|
||||||
"go.how.step2.afterLink": "deretter $10/måned med sjenerøse grenser",
|
"go.how.step2.afterLink": "med sjenerøse grenser",
|
||||||
"go.how.step3.title": "Begynn å kode",
|
"go.how.step3.title": "Begynn å kode",
|
||||||
"go.how.step3.body": "med pålitelig tilgang til åpen kildekode-modeller",
|
"go.how.step3.body": "med pålitelig tilgang til åpen kildekode-modeller",
|
||||||
"go.privacy.title": "Personvernet ditt er viktig for oss",
|
"go.privacy.title": "Personvernet ditt er viktig for oss",
|
||||||
@@ -329,11 +328,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go inkluderer modellene nedenfor, med høye grenser og pålitelig tilgang.",
|
"go.faq.a2": "Go inkluderer modellene nedenfor, med høye grenser og pålitelig tilgang.",
|
||||||
"go.faq.q3": "Er Go det samme som Zen?",
|
"go.faq.q3": "Er Go det samme som Zen?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"Nei. Zen er betaling etter bruk, mens Go starter på $5 for den første måneden, deretter $10/måned, med sjenerøse grenser og pålitelig tilgang til et kuratert modellutvalg.",
|
"Nei. Zen er betaling etter bruk, mens Go koster $10/måned, med sjenerøse grenser og pålitelig tilgang til et kuratert modellutvalg.",
|
||||||
"go.faq.q4": "Hva koster Go?",
|
"go.faq.q4": "Hva koster Go?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go koster",
|
"go.faq.a4.p1.beforePricing": "Go koster",
|
||||||
"go.faq.a4.p1.pricingLink": "$5 første måned",
|
"go.faq.a4.p1.pricingLink": "$10/måned",
|
||||||
"go.faq.a4.p1.afterPricing": "deretter $10/måned med sjenerøse grenser.",
|
"go.faq.a4.p1.afterPricing": "med sjenerøse grenser.",
|
||||||
"go.faq.a4.p2.beforeAccount": "Du kan administrere abonnementet ditt i din",
|
"go.faq.a4.p2.beforeAccount": "Du kan administrere abonnementet ditt i din",
|
||||||
"go.faq.a4.p2.accountLink": "konto",
|
"go.faq.a4.p2.accountLink": "konto",
|
||||||
"go.faq.a4.p3": "Avslutt når som helst.",
|
"go.faq.a4.p3": "Avslutt når som helst.",
|
||||||
@@ -346,6 +345,7 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "Brukes",
|
"go.faq.a5.used": "Brukes",
|
||||||
"go.faq.a5.notUsed": "Brukes ikke",
|
"go.faq.a5.notUsed": "Brukes ikke",
|
||||||
"go.faq.a5.noAgreement": "Ingen avtale",
|
"go.faq.a5.noAgreement": "Ingen avtale",
|
||||||
|
"go.faq.a5.notZdr": "Ikke ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"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.",
|
"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":
|
"go.faq.a5.gptRetention":
|
||||||
@@ -353,6 +353,8 @@ export const dict = {
|
|||||||
"go.faq.a5.learnMore": "Les mer",
|
"go.faq.a5.learnMore": "Les mer",
|
||||||
"go.faq.a5.deepseekRetention":
|
"go.faq.a5.deepseekRetention":
|
||||||
"ZDR-avtalen fornyes månedlig. Den gjeldende avtalen er gyldig til og med 31. august 2026.",
|
"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.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",
|
"Go-modeller hostes i USA. Leverandører følger en policy om null oppbevaring og bruker ikke dataene dine til modelltrening, med",
|
||||||
@@ -393,6 +395,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "Modellen er deaktivert",
|
"zen.api.error.modelDisabled": "Modellen er deaktivert",
|
||||||
"zen.api.error.regionNotAllowed":
|
"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}}",
|
"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":
|
"zen.api.error.trialEnded":
|
||||||
"Den gratis kampanjen for {{model}} er avsluttet. Du kan fortsette å bruke modellen ved å abonnere på OpenCode Go - {{link}}",
|
"Den gratis kampanjen for {{model}} er avsluttet. Du kan fortsette å bruke modellen ved å abonnere på OpenCode Go - {{link}}",
|
||||||
|
|
||||||
@@ -674,14 +679,15 @@ export const dict = {
|
|||||||
'Velg "OpenCode Go" som leverandør i opencode-konfigurasjonen din for å bruke Go-modeller.',
|
'Velg "OpenCode Go" som leverandør i opencode-konfigurasjonen din for å bruke Go-modeller.',
|
||||||
"workspace.lite.providers.title": "Leverandører",
|
"workspace.lite.providers.title": "Leverandører",
|
||||||
"workspace.lite.providers.description": "Kontroller hvilke leverandører som brukes til ruting.",
|
"workspace.lite.providers.description": "Kontroller hvilke leverandører som brukes til ruting.",
|
||||||
|
"workspace.lite.providers.allowTraining": "Tillat modeller som trener på forespørselsdata",
|
||||||
"workspace.lite.providers.useChina": "Aktiver modeller hostet i Kina",
|
"workspace.lite.providers.useChina": "Aktiver modeller hostet i Kina",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"Du abonnerer for øyeblikket på OpenCode Black eller står på venteliste. Vennligst avslutt abonnementet først hvis du vil bytte til Go.",
|
"Du abonnerer for øyeblikket på OpenCode Black eller står på venteliste. Vennligst avslutt abonnementet først hvis du vil bytte til Go.",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"Et annet medlem i dette arbeidsområdet abonnerer allerede på OpenCode Go. Kun ett medlem per arbeidsområde kan abonnere.",
|
"Et annet medlem i dette arbeidsområdet abonnerer allerede på OpenCode Go. Kun ett medlem per arbeidsområde kan abonnere.",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go starter på {{price}}, deretter $10/måned, og gir pålitelig tilgang til populære åpne kodingsmodeller med sjenerøse bruksgrenser.",
|
"OpenCode Go koster {{price}} og gir pålitelig tilgang til populære åpne kodingsmodeller med sjenerøse bruksgrenser.",
|
||||||
"workspace.lite.promo.price": "$5 for den første måneden",
|
"workspace.lite.promo.price": "$10/måned",
|
||||||
"workspace.lite.promo.modelsTitle": "Hva som er inkludert",
|
"workspace.lite.promo.modelsTitle": "Hva som er inkludert",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"Planen er primært utviklet for internasjonale brukere og gir stabil global tilgang. Priser og bruksgrenser kan endres etter hvert som vi lærer av tidlig bruk og tilbakemeldinger.",
|
"Planen er primært utviklet for internasjonale brukere og gir stabil global tilgang. Priser og bruksgrenser kan endres etter hvert som vi lærer av tidlig bruk og tilbakemeldinger.",
|
||||||
|
|||||||
@@ -255,9 +255,9 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "następującymi wyjątkami",
|
"zen.privacy.exceptionsLink": "następującymi wyjątkami",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | Niskokosztowe modele do kodowania dla każdego",
|
"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.banner.text": "Ox Alpha Free jest dostępny w Go przez ograniczony czas",
|
||||||
"go.meta.description":
|
"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 kosztuje $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",
|
"go.hero.title": "Niskokosztowe modele do kodowania dla każdego",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go udostępnia programowanie z agentami programistom na całym świecie. Oferuje hojne limity i niezawodny dostęp do najzdolniejszych modeli open source, dzięki czemu możesz budować za pomocą potężnych agentów, nie martwiąc się o koszty czy dostępność.",
|
"Go udostępnia programowanie z agentami programistom na całym świecie. Oferuje hojne limity i niezawodny dostęp do najzdolniejszych modeli open source, dzięki czemu możesz budować za pomocą potężnych agentów, nie martwiąc się o koszty czy dostępność.",
|
||||||
@@ -266,13 +266,14 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "Zasubskrybuj Go",
|
"go.cta.text": "Zasubskrybuj Go",
|
||||||
"go.cta.price": "$10/miesiąc",
|
"go.cta.price": "$10/miesiąc",
|
||||||
"go.cta.promo": "$5 pierwszy miesiąc",
|
|
||||||
"go.pricing.body":
|
"go.pricing.body":
|
||||||
"Używaj z dowolnym agentem. $5 za pierwszy miesiąc, potem $10/miesiąc. Doładuj konto w razie potrzeby. Anuluj w dowolnym momencie.",
|
"Używaj z dowolnym agentem. $10/miesiąc. Doładuj konto w razie potrzeby. Anuluj w dowolnym momencie.",
|
||||||
"go.graph.free": "Darmowe",
|
"go.graph.free": "Darmowe",
|
||||||
"go.graph.freePill": "Big Pickle i darmowe modele",
|
"go.graph.freePill": "Big Pickle i darmowe modele",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "Żądania na 5 godzin",
|
"go.graph.label": "Żądania na 5 godzin",
|
||||||
|
"go.graph.limitedRegions": "ograniczone regiony",
|
||||||
|
"go.graph.limitedTime": "ograniczony czas",
|
||||||
"go.graph.usageLimits": "Limity użycia",
|
"go.graph.usageLimits": "Limity użycia",
|
||||||
"go.graph.aria": "Żądania na 5h: {{free}} vs {{go}}",
|
"go.graph.aria": "Żądania na 5h: {{free}} vs {{go}}",
|
||||||
|
|
||||||
@@ -299,21 +300,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "Chciałbym wciąż być w Nvidia.",
|
"go.testimonials.frank.quote": "Chciałbym wciąż być w Nvidia.",
|
||||||
"go.problem.title": "Jaki problem rozwiązuje Go?",
|
"go.problem.title": "Jaki problem rozwiązuje Go?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"Skupiamy się na udostępnieniu doświadczenia OpenCode jak największej liczbie osób. OpenCode Go to tania subskrypcja: $5 za pierwszy miesiąc, potem $10/miesiąc. Zapewnia hojne limity i niezawodny dostęp do najbardziej wydajnych modeli open source.",
|
"Skupiamy się na udostępnieniu doświadczenia OpenCode jak największej liczbie osób. OpenCode Go to tania subskrypcja za $10/miesiąc. Zapewnia hojne limity i niezawodny dostęp do najbardziej wydajnych modeli open source.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "Niskokosztowa cena subskrypcji",
|
"go.problem.item1": "Niskokosztowa cena subskrypcji",
|
||||||
"go.problem.item2": "Hojne limity i niezawodny dostęp",
|
"go.problem.item2": "Hojne limity i niezawodny dostęp",
|
||||||
"go.problem.item3": "Stworzony dla jak największej liczby programistów",
|
"go.problem.item3": "Stworzony dla jak największej liczby programistów",
|
||||||
"go.problem.item4": "Starannie dobrany zestaw modeli przetestowanych pod kątem kodowania z agentami",
|
"go.problem.item4": "Starannie dobrany zestaw modeli przetestowanych pod kątem kodowania z agentami",
|
||||||
"go.how.title": "Jak działa Go",
|
"go.how.title": "Jak działa Go",
|
||||||
"go.how.body":
|
"go.how.body": "Go kosztuje $10/miesiąc. Możesz go używać z OpenCode lub dowolnym agentem.",
|
||||||
"Go zaczyna się od $5 za pierwszy miesiąc, potem $10/miesiąc. Możesz go używać z OpenCode lub dowolnym agentem.",
|
|
||||||
"go.how.step1.title": "Załóż konto",
|
"go.how.step1.title": "Załóż konto",
|
||||||
"go.how.step1.beforeLink": "postępuj zgodnie z",
|
"go.how.step1.beforeLink": "postępuj zgodnie z",
|
||||||
"go.how.step1.link": "instrukcją konfiguracji",
|
"go.how.step1.link": "instrukcją konfiguracji",
|
||||||
"go.how.step2.title": "Zasubskrybuj Go",
|
"go.how.step2.title": "Zasubskrybuj Go",
|
||||||
"go.how.step2.link": "$5 za pierwszy miesiąc",
|
"go.how.step2.link": "$10/miesiąc",
|
||||||
"go.how.step2.afterLink": "potem $10/miesiąc z hojnymi limitami",
|
"go.how.step2.afterLink": "z hojnymi limitami",
|
||||||
"go.how.step3.title": "Zacznij kodować",
|
"go.how.step3.title": "Zacznij kodować",
|
||||||
"go.how.step3.body": "z niezawodnym dostępem do modeli open source",
|
"go.how.step3.body": "z niezawodnym dostępem do modeli open source",
|
||||||
"go.privacy.title": "Twoja prywatność jest dla nas ważna",
|
"go.privacy.title": "Twoja prywatność jest dla nas ważna",
|
||||||
@@ -330,11 +330,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go obejmuje poniższe modele z wysokimi limitami i niezawodnym dostępem.",
|
"go.faq.a2": "Go obejmuje poniższe modele z wysokimi limitami i niezawodnym dostępem.",
|
||||||
"go.faq.q3": "Czy Go to to samo co Zen?",
|
"go.faq.q3": "Czy Go to to samo co Zen?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"Nie. Zen działa w modelu płatności za użycie, natomiast Go kosztuje $5 za pierwszy miesiąc, a następnie $10/miesiąc, oferując hojne limity i niezawodny dostęp do starannie dobranego zestawu modeli.",
|
"Nie. Zen działa w modelu płatności za użycie, natomiast Go kosztuje $10/miesiąc, oferując hojne limity i niezawodny dostęp do starannie dobranego zestawu modeli.",
|
||||||
"go.faq.q4": "Ile kosztuje Go?",
|
"go.faq.q4": "Ile kosztuje Go?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go kosztuje",
|
"go.faq.a4.p1.beforePricing": "Go kosztuje",
|
||||||
"go.faq.a4.p1.pricingLink": "$5 za pierwszy miesiąc",
|
"go.faq.a4.p1.pricingLink": "$10/miesiąc",
|
||||||
"go.faq.a4.p1.afterPricing": "potem $10/miesiąc z hojnymi limitami.",
|
"go.faq.a4.p1.afterPricing": "z hojnymi limitami.",
|
||||||
"go.faq.a4.p2.beforeAccount": "Możesz zarządzać subskrypcją na swoim",
|
"go.faq.a4.p2.beforeAccount": "Możesz zarządzać subskrypcją na swoim",
|
||||||
"go.faq.a4.p2.accountLink": "koncie",
|
"go.faq.a4.p2.accountLink": "koncie",
|
||||||
"go.faq.a4.p3": "Anuluj w dowolnym momencie.",
|
"go.faq.a4.p3": "Anuluj w dowolnym momencie.",
|
||||||
@@ -347,12 +347,15 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "Wykorzystywane",
|
"go.faq.a5.used": "Wykorzystywane",
|
||||||
"go.faq.a5.notUsed": "Niewykorzystywane",
|
"go.faq.a5.notUsed": "Niewykorzystywane",
|
||||||
"go.faq.a5.noAgreement": "Brak umowy",
|
"go.faq.a5.noAgreement": "Brak umowy",
|
||||||
|
"go.faq.a5.notZdr": "Nie ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"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.",
|
"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":
|
"go.faq.a5.gptRetention":
|
||||||
"Dzienniki monitorowania nadużyć są generowane dla każdego użycia funkcji API i przechowywane przez maksymalnie 30 dni.",
|
"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.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.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":
|
"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",
|
"Modele Go są hostowane w USA. Dostawcy stosują politykę zerowej retencji i nie używają Twoich danych do trenowania modeli, z",
|
||||||
@@ -393,6 +396,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "Model jest wyłączony",
|
"zen.api.error.modelDisabled": "Model jest wyłączony",
|
||||||
"zen.api.error.regionNotAllowed":
|
"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}}",
|
"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":
|
"zen.api.error.trialEnded":
|
||||||
"Bezpłatna promocja {{model}} dobiegła końca. Możesz dalej korzystać z modelu, subskrybując OpenCode Go - {{link}}",
|
"Bezpłatna promocja {{model}} dobiegła końca. Możesz dalej korzystać z modelu, subskrybując OpenCode Go - {{link}}",
|
||||||
|
|
||||||
@@ -674,14 +680,15 @@ export const dict = {
|
|||||||
'Wybierz "OpenCode Go" jako dostawcę w konfiguracji opencode, aby używać modeli Go.',
|
'Wybierz "OpenCode Go" jako dostawcę w konfiguracji opencode, aby używać modeli Go.',
|
||||||
"workspace.lite.providers.title": "Dostawcy",
|
"workspace.lite.providers.title": "Dostawcy",
|
||||||
"workspace.lite.providers.description": "Kontroluj, którzy dostawcy są używani do routingu.",
|
"workspace.lite.providers.description": "Kontroluj, którzy dostawcy są używani do routingu.",
|
||||||
|
"workspace.lite.providers.allowTraining": "Zezwalaj na modele wykorzystujące dane żądań do trenowania",
|
||||||
"workspace.lite.providers.useChina": "Włącz modele hostowane w Chinach",
|
"workspace.lite.providers.useChina": "Włącz modele hostowane w Chinach",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"Obecnie subskrybujesz OpenCode Black lub jesteś na liście oczekujących. Jeśli chcesz przejść na Go, najpierw anuluj subskrypcję.",
|
"Obecnie subskrybujesz OpenCode Black lub jesteś na liście oczekujących. Jeśli chcesz przejść na Go, najpierw anuluj subskrypcję.",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"Inny członek tego obszaru roboczego już subskrybuje OpenCode Go. Tylko jeden członek na obszar roboczy może subskrybować.",
|
"Inny członek tego obszaru roboczego już subskrybuje OpenCode Go. Tylko jeden członek na obszar roboczy może subskrybować.",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go zaczyna się od {{price}}, potem $10/miesiąc, i zapewnia niezawodny dostęp do popularnych otwartych modeli kodowania z hojnymi limitami użycia.",
|
"OpenCode Go kosztuje {{price}} i zapewnia niezawodny dostęp do popularnych otwartych modeli kodowania z hojnymi limitami użycia.",
|
||||||
"workspace.lite.promo.price": "$5 za pierwszy miesiąc",
|
"workspace.lite.promo.price": "$10/miesiąc",
|
||||||
"workspace.lite.promo.modelsTitle": "Co zawiera",
|
"workspace.lite.promo.modelsTitle": "Co zawiera",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"Plan został opracowany przede wszystkim z myślą o użytkownikach z całego świata i zapewnia stabilny globalny dostęp. Ceny i limity użycia mogą ulec zmianie w miarę zdobywania doświadczeń na podstawie początkowego korzystania z usługi i otrzymywanych opinii.",
|
"Plan został opracowany przede wszystkim z myślą o użytkownikach z całego świata i zapewnia stabilny globalny dostęp. Ceny i limity użycia mogą ulec zmianie w miarę zdobywania doświadczeń na podstawie początkowego korzystania z usługi i otrzymywanych opinii.",
|
||||||
|
|||||||
@@ -258,9 +258,9 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "следующими исключениями",
|
"zen.privacy.exceptionsLink": "следующими исключениями",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | Недорогие модели для кодинга для всех",
|
"go.title": "OpenCode Go | Недорогие модели для кодинга для всех",
|
||||||
"go.banner.text": "DeepSeek V4 Flash получает 2x лимиты использования на ограниченное время",
|
"go.banner.text": "Ox Alpha Free доступна в Go в течение ограниченного времени",
|
||||||
"go.meta.description":
|
"go.meta.description":
|
||||||
"Go стоит $5 за первый месяц, затем $10/месяц и предлагает щедрые лимиты использования и надежный доступ к ведущим моделям для кодинга.",
|
"Go стоит $10/месяц и предлагает щедрые лимиты использования и надежный доступ к ведущим моделям для кодинга.",
|
||||||
"go.hero.title": "Недорогие модели для кодинга для всех",
|
"go.hero.title": "Недорогие модели для кодинга для всех",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go открывает доступ к агентам-программистам разработчикам по всему миру. Предлагая щедрые лимиты и надежный доступ к наиболее способным моделям с открытым исходным кодом, вы можете создавать проекты с мощными агентами, не беспокоясь о затратах или доступности.",
|
"Go открывает доступ к агентам-программистам разработчикам по всему миру. Предлагая щедрые лимиты и надежный доступ к наиболее способным моделям с открытым исходным кодом, вы можете создавать проекты с мощными агентами, не беспокоясь о затратах или доступности.",
|
||||||
@@ -269,13 +269,14 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "Подписаться на Go",
|
"go.cta.text": "Подписаться на Go",
|
||||||
"go.cta.price": "$10/месяц",
|
"go.cta.price": "$10/месяц",
|
||||||
"go.cta.promo": "$5 первый месяц",
|
|
||||||
"go.pricing.body":
|
"go.pricing.body":
|
||||||
"Используйте с любым агентом. $5 за первый месяц, затем $10/месяц. Пополняйте баланс при необходимости. Отменить можно в любое время.",
|
"Используйте с любым агентом. $10/месяц. Пополняйте баланс при необходимости. Отменить можно в любое время.",
|
||||||
"go.graph.free": "Бесплатно",
|
"go.graph.free": "Бесплатно",
|
||||||
"go.graph.freePill": "Big Pickle и бесплатные модели",
|
"go.graph.freePill": "Big Pickle и бесплатные модели",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "Запросов за 5 часов",
|
"go.graph.label": "Запросов за 5 часов",
|
||||||
|
"go.graph.limitedRegions": "доступно в отдельных регионах",
|
||||||
|
"go.graph.limitedTime": "ограниченное время",
|
||||||
"go.graph.usageLimits": "Лимиты использования",
|
"go.graph.usageLimits": "Лимиты использования",
|
||||||
"go.graph.aria": "Запросов за 5ч: {{free}} против {{go}}",
|
"go.graph.aria": "Запросов за 5ч: {{free}} против {{go}}",
|
||||||
|
|
||||||
@@ -303,21 +304,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "Жаль, что я больше не в Nvidia.",
|
"go.testimonials.frank.quote": "Жаль, что я больше не в Nvidia.",
|
||||||
"go.problem.title": "Какую проблему решает Go?",
|
"go.problem.title": "Какую проблему решает Go?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"Мы стремимся сделать OpenCode доступным для как можно большего числа людей. OpenCode Go - это недорогая подписка: $5 за первый месяц, затем $10/месяц. Она предоставляет щедрые лимиты и надежный доступ к самым мощным моделям с открытым исходным кодом.",
|
"Мы стремимся сделать OpenCode доступным для как можно большего числа людей. OpenCode Go - это недорогая подписка за $10/месяц. Она предоставляет щедрые лимиты и надежный доступ к самым мощным моделям с открытым исходным кодом.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "Недорогая подписка",
|
"go.problem.item1": "Недорогая подписка",
|
||||||
"go.problem.item2": "Щедрые лимиты и надежный доступ",
|
"go.problem.item2": "Щедрые лимиты и надежный доступ",
|
||||||
"go.problem.item3": "Создан для максимального числа программистов",
|
"go.problem.item3": "Создан для максимального числа программистов",
|
||||||
"go.problem.item4": "Отобранные модели, протестированные для агентного программирования",
|
"go.problem.item4": "Отобранные модели, протестированные для агентного программирования",
|
||||||
"go.how.title": "Как работает Go",
|
"go.how.title": "Как работает Go",
|
||||||
"go.how.body":
|
"go.how.body": "Go стоит $10/месяц. Вы можете использовать его с OpenCode или любым агентом.",
|
||||||
"Go начинается с $5 за первый месяц, затем $10/месяц. Вы можете использовать его с OpenCode или любым агентом.",
|
|
||||||
"go.how.step1.title": "Создайте аккаунт",
|
"go.how.step1.title": "Создайте аккаунт",
|
||||||
"go.how.step1.beforeLink": "следуйте",
|
"go.how.step1.beforeLink": "следуйте",
|
||||||
"go.how.step1.link": "инструкциям по настройке",
|
"go.how.step1.link": "инструкциям по настройке",
|
||||||
"go.how.step2.title": "Подпишитесь на Go",
|
"go.how.step2.title": "Подпишитесь на Go",
|
||||||
"go.how.step2.link": "$5 за первый месяц",
|
"go.how.step2.link": "$10/месяц",
|
||||||
"go.how.step2.afterLink": "затем $10/месяц с щедрыми лимитами",
|
"go.how.step2.afterLink": "с щедрыми лимитами",
|
||||||
"go.how.step3.title": "Начните кодить",
|
"go.how.step3.title": "Начните кодить",
|
||||||
"go.how.step3.body": "с надежным доступом к open-source моделям",
|
"go.how.step3.body": "с надежным доступом к open-source моделям",
|
||||||
"go.privacy.title": "Ваша приватность важна для нас",
|
"go.privacy.title": "Ваша приватность важна для нас",
|
||||||
@@ -334,11 +334,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go включает перечисленные ниже модели с щедрыми лимитами и надежным доступом.",
|
"go.faq.a2": "Go включает перечисленные ниже модели с щедрыми лимитами и надежным доступом.",
|
||||||
"go.faq.q3": "Go — это то же самое, что и Zen?",
|
"go.faq.q3": "Go — это то же самое, что и Zen?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"Нет. Zen оплачивается по мере использования, а Go стоит $5 за первый месяц, затем $10/месяц и предлагает щедрые лимиты и надежный доступ к отобранным моделям.",
|
"Нет. Zen оплачивается по мере использования, а Go стоит $10/месяц и предлагает щедрые лимиты и надежный доступ к отобранным моделям.",
|
||||||
"go.faq.q4": "Сколько стоит Go?",
|
"go.faq.q4": "Сколько стоит Go?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go стоит",
|
"go.faq.a4.p1.beforePricing": "Go стоит",
|
||||||
"go.faq.a4.p1.pricingLink": "$5 за первый месяц",
|
"go.faq.a4.p1.pricingLink": "$10/месяц",
|
||||||
"go.faq.a4.p1.afterPricing": "затем $10/месяц с щедрыми лимитами.",
|
"go.faq.a4.p1.afterPricing": "с щедрыми лимитами.",
|
||||||
"go.faq.a4.p2.beforeAccount": "Вы можете управлять подпиской в своем",
|
"go.faq.a4.p2.beforeAccount": "Вы можете управлять подпиской в своем",
|
||||||
"go.faq.a4.p2.accountLink": "аккаунте",
|
"go.faq.a4.p2.accountLink": "аккаунте",
|
||||||
"go.faq.a4.p3": "Отмена в любое время.",
|
"go.faq.a4.p3": "Отмена в любое время.",
|
||||||
@@ -351,6 +351,7 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "Используется",
|
"go.faq.a5.used": "Используется",
|
||||||
"go.faq.a5.notUsed": "Не используется",
|
"go.faq.a5.notUsed": "Не используется",
|
||||||
"go.faq.a5.noAgreement": "Нет соглашения",
|
"go.faq.a5.noAgreement": "Нет соглашения",
|
||||||
|
"go.faq.a5.notZdr": "Не ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"go.faq.a5.grokRetention":
|
||||||
"ZDR отключает важные функции API, зависящие от сохраненных данных, включая Responses API с сохранением состояния, Files and Collections и Batch API.",
|
"ZDR отключает важные функции API, зависящие от сохраненных данных, включая Responses API с сохранением состояния, Files and Collections и Batch API.",
|
||||||
"go.faq.a5.gptRetention":
|
"go.faq.a5.gptRetention":
|
||||||
@@ -358,6 +359,8 @@ export const dict = {
|
|||||||
"go.faq.a5.learnMore": "Подробнее",
|
"go.faq.a5.learnMore": "Подробнее",
|
||||||
"go.faq.a5.deepseekRetention":
|
"go.faq.a5.deepseekRetention":
|
||||||
"Соглашение ZDR продлевается ежемесячно. Текущее соглашение действует до 31 августа 2026 года.",
|
"Соглашение ZDR продлевается ежемесячно. Текущее соглашение действует до 31 августа 2026 года.",
|
||||||
|
"go.faq.a5.museRetention":
|
||||||
|
"Значительно сниженная стоимость токенов в обмен на разрешение использовать ваши промпты и ответы для обучения будущих моделей Meta.",
|
||||||
|
|
||||||
"go.faq.a5.beforeExceptions":
|
"go.faq.a5.beforeExceptions":
|
||||||
"Модели Go размещены в США. Провайдеры следуют политике нулевого хранения и не используют ваши данные для обучения моделей, за",
|
"Модели Go размещены в США. Провайдеры следуют политике нулевого хранения и не используют ваши данные для обучения моделей, за",
|
||||||
@@ -398,6 +401,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "Модель отключена",
|
"zen.api.error.modelDisabled": "Модель отключена",
|
||||||
"zen.api.error.regionNotAllowed":
|
"zen.api.error.regionNotAllowed":
|
||||||
"Последняя версия этой модели размещена только в Китае. Чтобы использовать её, необходимо явно подтвердить согласие: {{consoleGoUrl}}",
|
"Последняя версия этой модели размещена только в Китае. Чтобы использовать её, необходимо явно подтвердить согласие: {{consoleGoUrl}}",
|
||||||
|
"zen.api.error.countryNotAllowed": "Эта модель недоступна в вашей стране.",
|
||||||
|
"zen.api.error.trainingNotAllowed":
|
||||||
|
"Эта модель собирает данные, которые используются для улучшения её качества, и требует явного согласия: {{consoleGoUrl}}",
|
||||||
"zen.api.error.trialEnded":
|
"zen.api.error.trialEnded":
|
||||||
"Бесплатная акция для {{model}} завершена. Вы можете продолжить использование модели, подписавшись на OpenCode Go - {{link}}",
|
"Бесплатная акция для {{model}} завершена. Вы можете продолжить использование модели, подписавшись на OpenCode Go - {{link}}",
|
||||||
|
|
||||||
@@ -681,14 +687,15 @@ export const dict = {
|
|||||||
'Выберите "OpenCode Go" в качестве провайдера в настройках opencode для использования моделей Go.',
|
'Выберите "OpenCode Go" в качестве провайдера в настройках opencode для использования моделей Go.',
|
||||||
"workspace.lite.providers.title": "Провайдеры",
|
"workspace.lite.providers.title": "Провайдеры",
|
||||||
"workspace.lite.providers.description": "Управляйте провайдерами, используемыми для маршрутизации.",
|
"workspace.lite.providers.description": "Управляйте провайдерами, используемыми для маршрутизации.",
|
||||||
|
"workspace.lite.providers.allowTraining": "Разрешить модели, обучающиеся на данных запросов",
|
||||||
"workspace.lite.providers.useChina": "Включить модели, размещенные в Китае",
|
"workspace.lite.providers.useChina": "Включить модели, размещенные в Китае",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"Вы подписаны на OpenCode Black или находитесь в списке ожидания. Пожалуйста, сначала отмените подписку, если хотите перейти на Go.",
|
"Вы подписаны на OpenCode Black или находитесь в списке ожидания. Пожалуйста, сначала отмените подписку, если хотите перейти на Go.",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"Другой участник в этом рабочем пространстве уже подписан на OpenCode Go. Только один участник в рабочем пространстве может оформить подписку.",
|
"Другой участник в этом рабочем пространстве уже подписан на OpenCode Go. Только один участник в рабочем пространстве может оформить подписку.",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go начинается с {{price}}, затем $10/месяц и предоставляет надежный доступ к популярным открытым моделям кодирования с щедрыми лимитами использования.",
|
"OpenCode Go стоит {{price}} и предоставляет надежный доступ к популярным открытым моделям кодирования с щедрыми лимитами использования.",
|
||||||
"workspace.lite.promo.price": "$5 за первый месяц",
|
"workspace.lite.promo.price": "$10/месяц",
|
||||||
"workspace.lite.promo.modelsTitle": "Что включено",
|
"workspace.lite.promo.modelsTitle": "Что включено",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"План предназначен в первую очередь для пользователей по всему миру и обеспечивает стабильный глобальный доступ. Цены и лимиты использования могут меняться по мере изучения первых результатов использования и отзывов.",
|
"План предназначен в первую очередь для пользователей по всему миру и обеспечивает стабильный глобальный доступ. Цены и лимиты использования могут меняться по мере изучения первых результатов использования и отзывов.",
|
||||||
|
|||||||
@@ -253,9 +253,9 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "ข้อยกเว้นดังนี้",
|
"zen.privacy.exceptionsLink": "ข้อยกเว้นดังนี้",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | โมเดลเขียนโค้ดราคาประหยัดสำหรับทุกคน",
|
"go.title": "OpenCode Go | โมเดลเขียนโค้ดราคาประหยัดสำหรับทุกคน",
|
||||||
"go.banner.text": "DeepSeek V4 Flash เพิ่มโควตาการใช้งานเป็น 2 เท่าในช่วงเวลาจำกัด",
|
"go.banner.text": "Ox Alpha Free พร้อมใช้งานบน Go ในช่วงเวลาจำกัด",
|
||||||
"go.meta.description":
|
"go.meta.description":
|
||||||
"Go เริ่มต้นที่ $5 สำหรับเดือนแรก จากนั้น $10/เดือน พร้อมขีดจำกัดการใช้งานที่เอื้อเฟื้อและการเข้าถึงโมเดลเขียนโค้ดชั้นนำอย่างเชื่อถือได้",
|
"Go มีราคา $10/เดือน พร้อมขีดจำกัดการใช้งานที่เอื้อเฟื้อและการเข้าถึงโมเดลเขียนโค้ดชั้นนำอย่างเชื่อถือได้",
|
||||||
"go.hero.title": "โมเดลเขียนโค้ดราคาประหยัดสำหรับทุกคน",
|
"go.hero.title": "โมเดลเขียนโค้ดราคาประหยัดสำหรับทุกคน",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go นำการเขียนโค้ดแบบเอเจนต์มาสู่นักเขียนโปรแกรมทั่วโลก เสนอขีดจำกัดที่กว้างขวางและการเข้าถึงโมเดลโอเพนซอร์สที่มีความสามารถสูงสุดได้อย่างน่าเชื่อถือ เพื่อให้คุณสามารถสร้างสรรค์ด้วยเอเจนต์ที่ทรงพลังโดยไม่ต้องกังวลเรื่องค่าใช้จ่ายหรือความพร้อมใช้งาน",
|
"Go นำการเขียนโค้ดแบบเอเจนต์มาสู่นักเขียนโปรแกรมทั่วโลก เสนอขีดจำกัดที่กว้างขวางและการเข้าถึงโมเดลโอเพนซอร์สที่มีความสามารถสูงสุดได้อย่างน่าเชื่อถือ เพื่อให้คุณสามารถสร้างสรรค์ด้วยเอเจนต์ที่ทรงพลังโดยไม่ต้องกังวลเรื่องค่าใช้จ่ายหรือความพร้อมใช้งาน",
|
||||||
@@ -264,12 +264,13 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "สมัครสมาชิก Go",
|
"go.cta.text": "สมัครสมาชิก Go",
|
||||||
"go.cta.price": "$10/เดือน",
|
"go.cta.price": "$10/เดือน",
|
||||||
"go.cta.promo": "$5 เดือนแรก",
|
"go.pricing.body": "ใช้กับเอเจนต์ใดก็ได้ $10/เดือน เติมเครดิตหากจำเป็น ยกเลิกได้ตลอดเวลา",
|
||||||
"go.pricing.body": "ใช้กับเอเจนต์ใดก็ได้ $5 ในเดือนแรก จากนั้น $10/เดือน เติมเครดิตหากจำเป็น ยกเลิกได้ตลอดเวลา",
|
|
||||||
"go.graph.free": "ฟรี",
|
"go.graph.free": "ฟรี",
|
||||||
"go.graph.freePill": "Big Pickle และโมเดลฟรี",
|
"go.graph.freePill": "Big Pickle และโมเดลฟรี",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "คำขอต่อ 5 ชั่วโมง",
|
"go.graph.label": "คำขอต่อ 5 ชั่วโมง",
|
||||||
|
"go.graph.limitedRegions": "เฉพาะบางภูมิภาค",
|
||||||
|
"go.graph.limitedTime": "ช่วงเวลาจำกัด",
|
||||||
"go.graph.usageLimits": "ขีดจำกัดการใช้งาน",
|
"go.graph.usageLimits": "ขีดจำกัดการใช้งาน",
|
||||||
"go.graph.aria": "คำขอต่อ 5 ชม.: {{free}} vs {{go}}",
|
"go.graph.aria": "คำขอต่อ 5 ชม.: {{free}} vs {{go}}",
|
||||||
|
|
||||||
@@ -296,20 +297,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "ผมหวังว่าผมจะยังอยู่ที่ Nvidia",
|
"go.testimonials.frank.quote": "ผมหวังว่าผมจะยังอยู่ที่ Nvidia",
|
||||||
"go.problem.title": "Go แก้ปัญหาอะไร?",
|
"go.problem.title": "Go แก้ปัญหาอะไร?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"เรามุ่งมั่นที่จะนำประสบการณ์ OpenCode ไปสู่ผู้คนให้ได้มากที่สุด OpenCode Go เป็นการสมัครสมาชิกราคาประหยัด: $5 สำหรับเดือนแรก จากนั้น $10/เดือน โดยมอบขีดจำกัดที่เอื้อเฟื้อและการเข้าถึงโมเดลโอเพนซอร์สที่มีความสามารถสูงสุดอย่างเชื่อถือได้",
|
"เรามุ่งมั่นที่จะนำประสบการณ์ OpenCode ไปสู่ผู้คนให้ได้มากที่สุด OpenCode Go เป็นการสมัครสมาชิกราคาประหยัด $10/เดือน โดยมอบขีดจำกัดที่เอื้อเฟื้อและการเข้าถึงโมเดลโอเพนซอร์สที่มีความสามารถสูงสุดอย่างเชื่อถือได้",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "ราคาการสมัครสมาชิกที่ต่ำ",
|
"go.problem.item1": "ราคาการสมัครสมาชิกที่ต่ำ",
|
||||||
"go.problem.item2": "ขีดจำกัดที่กว้างขวางและการเข้าถึงที่เชื่อถือได้",
|
"go.problem.item2": "ขีดจำกัดที่กว้างขวางและการเข้าถึงที่เชื่อถือได้",
|
||||||
"go.problem.item3": "สร้างขึ้นเพื่อโปรแกรมเมอร์จำนวนมากที่สุดเท่าที่จะเป็นไปได้",
|
"go.problem.item3": "สร้างขึ้นเพื่อโปรแกรมเมอร์จำนวนมากที่สุดเท่าที่จะเป็นไปได้",
|
||||||
"go.problem.item4": "ชุดโมเดลที่คัดสรรและผ่านการทดสอบสำหรับการเขียนโค้ดแบบเอเจนต์",
|
"go.problem.item4": "ชุดโมเดลที่คัดสรรและผ่านการทดสอบสำหรับการเขียนโค้ดแบบเอเจนต์",
|
||||||
"go.how.title": "Go ทำงานอย่างไร",
|
"go.how.title": "Go ทำงานอย่างไร",
|
||||||
"go.how.body": "Go เริ่มต้นที่ $5 สำหรับเดือนแรก จากนั้น $10/เดือน คุณสามารถใช้กับ OpenCode หรือเอเจนต์ใดก็ได้",
|
"go.how.body": "Go มีราคา $10/เดือน คุณสามารถใช้กับ OpenCode หรือเอเจนต์ใดก็ได้",
|
||||||
"go.how.step1.title": "สร้างบัญชี",
|
"go.how.step1.title": "สร้างบัญชี",
|
||||||
"go.how.step1.beforeLink": "ทำตาม",
|
"go.how.step1.beforeLink": "ทำตาม",
|
||||||
"go.how.step1.link": "คำแนะนำการตั้งค่า",
|
"go.how.step1.link": "คำแนะนำการตั้งค่า",
|
||||||
"go.how.step2.title": "สมัครสมาชิก Go",
|
"go.how.step2.title": "สมัครสมาชิก Go",
|
||||||
"go.how.step2.link": "$5 เดือนแรก",
|
"go.how.step2.link": "$10/เดือน",
|
||||||
"go.how.step2.afterLink": "จากนั้น $10/เดือน พร้อมขีดจำกัดที่เอื้อเฟื้อ",
|
"go.how.step2.afterLink": "พร้อมขีดจำกัดที่เอื้อเฟื้อ",
|
||||||
"go.how.step3.title": "เริ่มเขียนโค้ด",
|
"go.how.step3.title": "เริ่มเขียนโค้ด",
|
||||||
"go.how.step3.body": "ด้วยการเข้าถึงโมเดลโอเพนซอร์สที่เชื่อถือได้",
|
"go.how.step3.body": "ด้วยการเข้าถึงโมเดลโอเพนซอร์สที่เชื่อถือได้",
|
||||||
"go.privacy.title": "ความเป็นส่วนตัวของคุณสำคัญสำหรับเรา",
|
"go.privacy.title": "ความเป็นส่วนตัวของคุณสำคัญสำหรับเรา",
|
||||||
@@ -326,11 +327,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go รวมโมเดลด้านล่างนี้ พร้อมขีดจำกัดที่มากและการเข้าถึงที่เชื่อถือได้",
|
"go.faq.a2": "Go รวมโมเดลด้านล่างนี้ พร้อมขีดจำกัดที่มากและการเข้าถึงที่เชื่อถือได้",
|
||||||
"go.faq.q3": "Go เหมือนกับ Zen หรือไม่?",
|
"go.faq.q3": "Go เหมือนกับ Zen หรือไม่?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"ไม่ Zen เป็นแบบจ่ายตามการใช้งาน ขณะที่ Go เริ่มต้นที่ $5 สำหรับเดือนแรก จากนั้น $10/เดือน พร้อมขีดจำกัดที่เอื้อเฟื้อและการเข้าถึงชุดโมเดลที่คัดสรรอย่างเชื่อถือได้",
|
"ไม่ Zen เป็นแบบจ่ายตามการใช้งาน ขณะที่ Go มีราคา $10/เดือน พร้อมขีดจำกัดที่เอื้อเฟื้อและการเข้าถึงชุดโมเดลที่คัดสรรอย่างเชื่อถือได้",
|
||||||
"go.faq.q4": "Go ราคาเท่าไหร่?",
|
"go.faq.q4": "Go ราคาเท่าไหร่?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go ราคา",
|
"go.faq.a4.p1.beforePricing": "Go ราคา",
|
||||||
"go.faq.a4.p1.pricingLink": "$5 เดือนแรก",
|
"go.faq.a4.p1.pricingLink": "$10/เดือน",
|
||||||
"go.faq.a4.p1.afterPricing": "จากนั้น $10/เดือน พร้อมขีดจำกัดที่เอื้อเฟื้อ",
|
"go.faq.a4.p1.afterPricing": "พร้อมขีดจำกัดที่เอื้อเฟื้อ",
|
||||||
"go.faq.a4.p2.beforeAccount": "คุณสามารถจัดการการสมัครสมาชิกของคุณได้ใน",
|
"go.faq.a4.p2.beforeAccount": "คุณสามารถจัดการการสมัครสมาชิกของคุณได้ใน",
|
||||||
"go.faq.a4.p2.accountLink": "บัญชีของคุณ",
|
"go.faq.a4.p2.accountLink": "บัญชีของคุณ",
|
||||||
"go.faq.a4.p3": "ยกเลิกได้ตลอดเวลา",
|
"go.faq.a4.p3": "ยกเลิกได้ตลอดเวลา",
|
||||||
@@ -343,10 +344,13 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "นำไปใช้",
|
"go.faq.a5.used": "นำไปใช้",
|
||||||
"go.faq.a5.notUsed": "ไม่นำไปใช้",
|
"go.faq.a5.notUsed": "ไม่นำไปใช้",
|
||||||
"go.faq.a5.noAgreement": "ไม่มีข้อตกลง",
|
"go.faq.a5.noAgreement": "ไม่มีข้อตกลง",
|
||||||
|
"go.faq.a5.notZdr": "ไม่ใช่ ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"go.faq.a5.grokRetention":
|
||||||
"ZDR ปิดใช้งานฟีเจอร์ API สำคัญที่ต้องอาศัยข้อมูลที่จัดเก็บไว้ ซึ่งรวมถึง Responses API แบบมีสถานะ, Files and Collections และ Batch API",
|
"ZDR ปิดใช้งานฟีเจอร์ API สำคัญที่ต้องอาศัยข้อมูลที่จัดเก็บไว้ ซึ่งรวมถึง Responses API แบบมีสถานะ, Files and Collections และ Batch API",
|
||||||
"go.faq.a5.gptRetention":
|
"go.faq.a5.gptRetention":
|
||||||
"ระบบจะสร้างบันทึกการตรวจสอบการใช้งานในทางที่ผิดสำหรับการใช้งานฟีเจอร์ API ทั้งหมด และเก็บรักษาไว้นานสูงสุด 30 วัน",
|
"ระบบจะสร้างบันทึกการตรวจสอบการใช้งานในทางที่ผิดสำหรับการใช้งานฟีเจอร์ API ทั้งหมด และเก็บรักษาไว้นานสูงสุด 30 วัน",
|
||||||
|
"go.faq.a5.museRetention":
|
||||||
|
"ราคาของ token ลดลงอย่างมาก โดยแลกกับการอนุญาตให้นำพรอมต์และผลลัพธ์ที่สร้างขึ้นของคุณไปใช้ฝึกโมเดล Meta ในอนาคต",
|
||||||
"go.faq.a5.learnMore": "ดูข้อมูลเพิ่มเติม",
|
"go.faq.a5.learnMore": "ดูข้อมูลเพิ่มเติม",
|
||||||
"go.faq.a5.deepseekRetention": "ข้อตกลง ZDR จะต่ออายุทุกเดือน ข้อตกลงปัจจุบันมีผลใช้ถึงวันที่ 31 สิงหาคม 2026",
|
"go.faq.a5.deepseekRetention": "ข้อตกลง ZDR จะต่ออายุทุกเดือน ข้อตกลงปัจจุบันมีผลใช้ถึงวันที่ 31 สิงหาคม 2026",
|
||||||
|
|
||||||
@@ -388,6 +392,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "โมเดลถูกปิดใช้งาน",
|
"zen.api.error.modelDisabled": "โมเดลถูกปิดใช้งาน",
|
||||||
"zen.api.error.regionNotAllowed":
|
"zen.api.error.regionNotAllowed":
|
||||||
"โมเดลเวอร์ชันล่าสุดนี้ให้บริการเฉพาะผ่านระบบที่โฮสต์ในประเทศจีน และต้องให้ความยินยอมอย่างชัดแจ้งก่อนใช้งาน: {{consoleGoUrl}}",
|
"โมเดลเวอร์ชันล่าสุดนี้ให้บริการเฉพาะผ่านระบบที่โฮสต์ในประเทศจีน และต้องให้ความยินยอมอย่างชัดแจ้งก่อนใช้งาน: {{consoleGoUrl}}",
|
||||||
|
"zen.api.error.countryNotAllowed": "โมเดลนี้ไม่พร้อมให้บริการในประเทศของคุณ",
|
||||||
|
"zen.api.error.trainingNotAllowed":
|
||||||
|
"โมเดลนี้เก็บรวบรวมข้อมูลที่ใช้เพื่อปรับปรุงคุณภาพของโมเดล และต้องได้รับความยินยอมอย่างชัดแจ้งก่อนใช้งาน: {{consoleGoUrl}}",
|
||||||
"zen.api.error.trialEnded":
|
"zen.api.error.trialEnded":
|
||||||
"โปรโมชันฟรีสำหรับ {{model}} สิ้นสุดแล้ว คุณสามารถใช้โมเดลต่อได้โดยสมัครสมาชิก OpenCode Go - {{link}}",
|
"โปรโมชันฟรีสำหรับ {{model}} สิ้นสุดแล้ว คุณสามารถใช้โมเดลต่อได้โดยสมัครสมาชิก OpenCode Go - {{link}}",
|
||||||
|
|
||||||
@@ -669,14 +676,15 @@ export const dict = {
|
|||||||
'เลือก "OpenCode Go" เป็นผู้ให้บริการในการตั้งค่า opencode ของคุณเพื่อใช้โมเดล Go',
|
'เลือก "OpenCode Go" เป็นผู้ให้บริการในการตั้งค่า opencode ของคุณเพื่อใช้โมเดล Go',
|
||||||
"workspace.lite.providers.title": "ผู้ให้บริการ",
|
"workspace.lite.providers.title": "ผู้ให้บริการ",
|
||||||
"workspace.lite.providers.description": "ควบคุมผู้ให้บริการที่ใช้สำหรับการกำหนดเส้นทาง",
|
"workspace.lite.providers.description": "ควบคุมผู้ให้บริการที่ใช้สำหรับการกำหนดเส้นทาง",
|
||||||
|
"workspace.lite.providers.allowTraining": "อนุญาตโมเดลที่ฝึกด้วยข้อมูลคำขอ",
|
||||||
"workspace.lite.providers.useChina": "เปิดใช้โมเดลที่โฮสต์ในจีน",
|
"workspace.lite.providers.useChina": "เปิดใช้โมเดลที่โฮสต์ในจีน",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"ขณะนี้คุณสมัครสมาชิก OpenCode Black หรืออยู่ในรายการรอ โปรดยกเลิกการสมัครก่อนหากต้องการเปลี่ยนไปใช้ Go",
|
"ขณะนี้คุณสมัครสมาชิก OpenCode Black หรืออยู่ในรายการรอ โปรดยกเลิกการสมัครก่อนหากต้องการเปลี่ยนไปใช้ Go",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"สมาชิกคนอื่นใน Workspace นี้ได้สมัคร OpenCode Go แล้ว สามารถสมัครได้เพียงหนึ่งคนต่อหนึ่ง Workspace เท่านั้น",
|
"สมาชิกคนอื่นใน Workspace นี้ได้สมัคร OpenCode Go แล้ว สามารถสมัครได้เพียงหนึ่งคนต่อหนึ่ง Workspace เท่านั้น",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go เริ่มต้นที่ {{price}} จากนั้น $10/เดือน และมอบการเข้าถึงโมเดลการเขียนโค้ดแบบเปิดยอดนิยมอย่างเสถียรพร้อมขีดจำกัดการใช้งานที่ให้มาอย่างเหลือเฟือ",
|
"OpenCode Go ราคา {{price}} และมอบการเข้าถึงโมเดลการเขียนโค้ดแบบเปิดยอดนิยมอย่างเสถียรพร้อมขีดจำกัดการใช้งานที่ให้มาอย่างเหลือเฟือ",
|
||||||
"workspace.lite.promo.price": "$5 สำหรับเดือนแรก",
|
"workspace.lite.promo.price": "$10/เดือน",
|
||||||
"workspace.lite.promo.modelsTitle": "สิ่งที่รวมอยู่ด้วย",
|
"workspace.lite.promo.modelsTitle": "สิ่งที่รวมอยู่ด้วย",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"แผนนี้ออกแบบมาสำหรับผู้ใช้งานต่างประเทศเป็นหลักและให้การเข้าถึงที่เสถียรทั่วโลก ราคาและขีดจำกัดการใช้งานอาจเปลี่ยนแปลงได้ตามสิ่งที่เราเรียนรู้จากการใช้งานและข้อเสนอแนะในช่วงแรก",
|
"แผนนี้ออกแบบมาสำหรับผู้ใช้งานต่างประเทศเป็นหลักและให้การเข้าถึงที่เสถียรทั่วโลก ราคาและขีดจำกัดการใช้งานอาจเปลี่ยนแปลงได้ตามสิ่งที่เราเรียนรู้จากการใช้งานและข้อเสนอแนะในช่วงแรก",
|
||||||
|
|||||||
@@ -256,9 +256,9 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "aşağıdaki istisnalar",
|
"zen.privacy.exceptionsLink": "aşağıdaki istisnalar",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | Herkes için düşük maliyetli kodlama modelleri",
|
"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.banner.text": "Ox Alpha Free sınırlı bir süre için Go'da kullanılabilir",
|
||||||
"go.meta.description":
|
"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 ayda 10$'dır; 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",
|
"go.hero.title": "Herkes için düşük maliyetli kodlama modelleri",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go, dünya çapındaki programcılara ajan tabanlı kodlama getiriyor. En yetenekli açık kaynaklı modellere cömert limitler ve güvenilir erişim sunarak, maliyet veya erişilebilirlik konusunda endişelenmeden güçlü ajanlarla geliştirme yapmanızı sağlar.",
|
"Go, dünya çapındaki programcılara ajan tabanlı kodlama getiriyor. En yetenekli açık kaynaklı modellere cömert limitler ve güvenilir erişim sunarak, maliyet veya erişilebilirlik konusunda endişelenmeden güçlü ajanlarla geliştirme yapmanızı sağlar.",
|
||||||
@@ -267,13 +267,13 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "Go'ya abone ol",
|
"go.cta.text": "Go'ya abone ol",
|
||||||
"go.cta.price": "Ayda 10$",
|
"go.cta.price": "Ayda 10$",
|
||||||
"go.cta.promo": "İlk ay $5",
|
"go.pricing.body": "Herhangi bir ajanla kullanın. Ayda 10$. Gerekirse kredi yükleyin. İstediğiniz zaman iptal edin.",
|
||||||
"go.pricing.body":
|
|
||||||
"Herhangi bir ajanla kullanın. İlk ay $5, sonrasında ayda 10$. Gerekirse kredi yükleyin. İstediğiniz zaman iptal edin.",
|
|
||||||
"go.graph.free": "Ücretsiz",
|
"go.graph.free": "Ücretsiz",
|
||||||
"go.graph.freePill": "Big Pickle ve ücretsiz modeller",
|
"go.graph.freePill": "Big Pickle ve ücretsiz modeller",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "5 saat başına istekler",
|
"go.graph.label": "5 saat başına istekler",
|
||||||
|
"go.graph.limitedRegions": "sınırlı bölgeler",
|
||||||
|
"go.graph.limitedTime": "sınırlı süre",
|
||||||
"go.graph.usageLimits": "Kullanım limitleri",
|
"go.graph.usageLimits": "Kullanım limitleri",
|
||||||
"go.graph.aria": "5 saatlik istekler: {{free}} vs {{go}}",
|
"go.graph.aria": "5 saatlik istekler: {{free}} vs {{go}}",
|
||||||
|
|
||||||
@@ -301,21 +301,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "Keşke hala Nvidia'da olsaydım.",
|
"go.testimonials.frank.quote": "Keşke hala Nvidia'da olsaydım.",
|
||||||
"go.problem.title": "Go hangi sorunu çözüyor?",
|
"go.problem.title": "Go hangi sorunu çözüyor?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"OpenCode deneyimini mümkün olduğunca çok kişiye ulaştırmaya odaklandık. OpenCode Go düşük maliyetli bir aboneliktir: İlk ay $5, sonrasında ayda 10$. Cömert limitler ve en yetenekli açık kaynak modellere güvenilir erişim sağlar.",
|
"OpenCode deneyimini mümkün olduğunca çok kişiye ulaştırmaya odaklandık. OpenCode Go, ayda 10$ olan düşük maliyetli bir aboneliktir. Cömert limitler ve en yetenekli açık kaynak modellere güvenilir erişim sağlar.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "Düşük maliyetli abonelik fiyatlandırması",
|
"go.problem.item1": "Düşük maliyetli abonelik fiyatlandırması",
|
||||||
"go.problem.item2": "Cömert limitler ve güvenilir erişim",
|
"go.problem.item2": "Cömert limitler ve güvenilir erişim",
|
||||||
"go.problem.item3": "Mümkün olduğunca çok programcı için geliştirildi",
|
"go.problem.item3": "Mümkün olduğunca çok programcı için geliştirildi",
|
||||||
"go.problem.item4": "Ajan tabanlı kodlama için test edilmiş, özenle seçilmiş model seçenekleri",
|
"go.problem.item4": "Ajan tabanlı kodlama için test edilmiş, özenle seçilmiş model seçenekleri",
|
||||||
"go.how.title": "Go nasıl çalışır?",
|
"go.how.title": "Go nasıl çalışır?",
|
||||||
"go.how.body":
|
"go.how.body": "Go ayda 10$'dır. OpenCode veya herhangi bir ajanla kullanabilirsiniz.",
|
||||||
"Go ilk ay $5, sonrasında ayda 10$ fiyatıyla başlar. OpenCode veya herhangi bir ajanla kullanabilirsiniz.",
|
|
||||||
"go.how.step1.title": "Bir hesap oluşturun",
|
"go.how.step1.title": "Bir hesap oluşturun",
|
||||||
"go.how.step1.beforeLink": "takip edin",
|
"go.how.step1.beforeLink": "takip edin",
|
||||||
"go.how.step1.link": "kurulum talimatları",
|
"go.how.step1.link": "kurulum talimatları",
|
||||||
"go.how.step2.title": "Go'ya abone olun",
|
"go.how.step2.title": "Go'ya abone olun",
|
||||||
"go.how.step2.link": "İlk ay $5",
|
"go.how.step2.link": "Ayda 10$",
|
||||||
"go.how.step2.afterLink": "sonrasında cömert limitlerle ayda 10$",
|
"go.how.step2.afterLink": "cömert limitlerle",
|
||||||
"go.how.step3.title": "Kodlamaya başlayın",
|
"go.how.step3.title": "Kodlamaya başlayın",
|
||||||
"go.how.step3.body": "açık kaynaklı modellere güvenilir erişimle",
|
"go.how.step3.body": "açık kaynaklı modellere güvenilir erişimle",
|
||||||
"go.privacy.title": "Gizliliğiniz bizim için önemlidir",
|
"go.privacy.title": "Gizliliğiniz bizim için önemlidir",
|
||||||
@@ -332,11 +331,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go, aşağıda listelenen modelleri cömert limitler ve güvenilir erişimle sunar.",
|
"go.faq.a2": "Go, aşağıda listelenen modelleri cömert limitler ve güvenilir erişimle sunar.",
|
||||||
"go.faq.q3": "Go, Zen ile aynı mı?",
|
"go.faq.q3": "Go, Zen ile aynı mı?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"Hayır. Zen kullandıkça öde modelidir; Go ise ilk ay $5, sonrasında ayda 10$ fiyatıyla başlar ve özenle seçilmiş model seçeneklerine cömert limitlerle güvenilir erişim sunar.",
|
"Hayır. Zen kullandıkça öde modelidir; Go ise ayda 10$'dır ve özenle seçilmiş model seçeneklerine cömert limitlerle güvenilir erişim sunar.",
|
||||||
"go.faq.q4": "Go ne kadar?",
|
"go.faq.q4": "Go ne kadar?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go'nun maliyeti",
|
"go.faq.a4.p1.beforePricing": "Go'nun maliyeti",
|
||||||
"go.faq.a4.p1.pricingLink": "İlk ay $5",
|
"go.faq.a4.p1.pricingLink": "ayda 10$",
|
||||||
"go.faq.a4.p1.afterPricing": "sonrasında cömert limitlerle ayda 10$.",
|
"go.faq.a4.p1.afterPricing": "cömert limitlerle.",
|
||||||
"go.faq.a4.p2.beforeAccount": "Aboneliğinizi",
|
"go.faq.a4.p2.beforeAccount": "Aboneliğinizi",
|
||||||
"go.faq.a4.p2.accountLink": "hesabınızdan",
|
"go.faq.a4.p2.accountLink": "hesabınızdan",
|
||||||
"go.faq.a4.p3": "yönetebilirsiniz. İstediğiniz zaman iptal edin.",
|
"go.faq.a4.p3": "yönetebilirsiniz. İstediğiniz zaman iptal edin.",
|
||||||
@@ -349,6 +348,7 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "Kullanılır",
|
"go.faq.a5.used": "Kullanılır",
|
||||||
"go.faq.a5.notUsed": "Kullanılmaz",
|
"go.faq.a5.notUsed": "Kullanılmaz",
|
||||||
"go.faq.a5.noAgreement": "Anlaşma yok",
|
"go.faq.a5.noAgreement": "Anlaşma yok",
|
||||||
|
"go.faq.a5.notZdr": "ZDR değil",
|
||||||
"go.faq.a5.grokRetention":
|
"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.",
|
"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":
|
"go.faq.a5.gptRetention":
|
||||||
@@ -356,6 +356,8 @@ export const dict = {
|
|||||||
"go.faq.a5.learnMore": "Daha fazla bilgi",
|
"go.faq.a5.learnMore": "Daha fazla bilgi",
|
||||||
"go.faq.a5.deepseekRetention":
|
"go.faq.a5.deepseekRetention":
|
||||||
"ZDR anlaşması aylık olarak yenilenir. Mevcut anlaşma 31 Ağustos 2026 tarihine kadar geçerlidir.",
|
"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.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",
|
"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",
|
||||||
@@ -396,6 +398,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "Model devre dışı",
|
"zen.api.error.modelDisabled": "Model devre dışı",
|
||||||
"zen.api.error.regionNotAllowed":
|
"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}}",
|
"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":
|
"zen.api.error.trialEnded":
|
||||||
"{{model}} için ücretsiz promosyon sona erdi. OpenCode Go'ya abone olarak modeli kullanmaya devam edebilirsiniz - {{link}}",
|
"{{model}} için ücretsiz promosyon sona erdi. OpenCode Go'ya abone olarak modeli kullanmaya devam edebilirsiniz - {{link}}",
|
||||||
|
|
||||||
@@ -677,14 +682,15 @@ export const dict = {
|
|||||||
'Go modellerini kullanmak için opencode yapılandırmanızda "OpenCode Go"\'yu sağlayıcı olarak seçin.',
|
'Go modellerini kullanmak için opencode yapılandırmanızda "OpenCode Go"\'yu sağlayıcı olarak seçin.',
|
||||||
"workspace.lite.providers.title": "Sağlayıcılar",
|
"workspace.lite.providers.title": "Sağlayıcılar",
|
||||||
"workspace.lite.providers.description": "Yönlendirme için hangi sağlayıcıların kullanılacağını kontrol edin.",
|
"workspace.lite.providers.description": "Yönlendirme için hangi sağlayıcıların kullanılacağını kontrol edin.",
|
||||||
|
"workspace.lite.providers.allowTraining": "İstek verileriyle eğitilen modellere izin ver",
|
||||||
"workspace.lite.providers.useChina": "Çin'de barındırılan modelleri etkinleştir",
|
"workspace.lite.providers.useChina": "Çin'de barındırılan modelleri etkinleştir",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"Şu anda OpenCode Black abonesisiniz veya bekleme listesindesiniz. Go'ya geçmek istiyorsanız lütfen önce aboneliğinizi iptal edin.",
|
"Şu anda OpenCode Black abonesisiniz veya bekleme listesindesiniz. Go'ya geçmek istiyorsanız lütfen önce aboneliğinizi iptal edin.",
|
||||||
"workspace.lite.other.message":
|
"workspace.lite.other.message":
|
||||||
"Bu çalışma alanındaki başka bir üye zaten OpenCode Go abonesi. Çalışma alanı başına yalnızca bir üye abone olabilir.",
|
"Bu çalışma alanındaki başka bir üye zaten OpenCode Go abonesi. Çalışma alanı başına yalnızca bir üye abone olabilir.",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go {{price}} fiyatından başlar, sonrasında ayda 10$ olur ve cömert kullanım limitleriyle popüler açık kodlama modellerine güvenilir erişim sağlar.",
|
"OpenCode Go {{price}} fiyatıyla cömert kullanım limitleri ve popüler açık kodlama modellerine güvenilir erişim sağlar.",
|
||||||
"workspace.lite.promo.price": "İlk ay $5",
|
"workspace.lite.promo.price": "Ayda 10$",
|
||||||
"workspace.lite.promo.modelsTitle": "Neler Dahil",
|
"workspace.lite.promo.modelsTitle": "Neler Dahil",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"Plan öncelikle uluslararası kullanıcılar için tasarlanmıştır ve istikrarlı küresel erişim sağlar. Erken kullanım ve geri bildirimlerden öğrendiklerimiz doğrultusunda fiyatlandırma ve kullanım limitleri değişebilir.",
|
"Plan öncelikle uluslararası kullanıcılar için tasarlanmıştır ve istikrarlı küresel erişim sağlar. Erken kullanım ve geri bildirimlerden öğrendiklerimiz doğrultusunda fiyatlandırma ve kullanım limitleri değişebilir.",
|
||||||
|
|||||||
@@ -255,9 +255,9 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "такими винятками",
|
"zen.privacy.exceptionsLink": "такими винятками",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | Недорогі моделі кодування для всіх",
|
"go.title": "OpenCode Go | Недорогі моделі кодування для всіх",
|
||||||
"go.banner.text": "DeepSeek V4 Flash отримує 2x ліміти використання протягом обмеженого часу",
|
"go.banner.text": "Ox Alpha Free доступна в Go протягом обмеженого часу",
|
||||||
"go.meta.description":
|
"go.meta.description":
|
||||||
"Go починається від $5 за перший місяць, потім $10/місяць, зі щедрими лімітами використання та надійним доступом до провідних моделей для кодування.",
|
"Go коштує $10/місяць, зі щедрими лімітами використання та надійним доступом до провідних моделей для кодування.",
|
||||||
"go.hero.title": "Недорогі моделі кодування для всіх",
|
"go.hero.title": "Недорогі моделі кодування для всіх",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go надає агентне програмування програмістам у всьому світі, пропонуючи щедрі ліміти та надійний доступ до найкращих моделей з відкритим кодом.",
|
"Go надає агентне програмування програмістам у всьому світі, пропонуючи щедрі ліміти та надійний доступ до найкращих моделей з відкритим кодом.",
|
||||||
@@ -266,13 +266,13 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "Підписатися на Go",
|
"go.cta.text": "Підписатися на Go",
|
||||||
"go.cta.price": "$10/місяць",
|
"go.cta.price": "$10/місяць",
|
||||||
"go.cta.promo": "$5 перший місяць",
|
"go.pricing.body": "Використовуйте з будь-яким агентом. $10/місяць. Поповнюйте за потреби. Скасуйте в будь-який час.",
|
||||||
"go.pricing.body":
|
|
||||||
"Використовуйте з будь-яким агентом. $5 перший місяць, потім $10/місяць. Поповнюйте за потреби. Скасуйте в будь-який час.",
|
|
||||||
"go.graph.free": "Безкоштовно",
|
"go.graph.free": "Безкоштовно",
|
||||||
"go.graph.freePill": "Big Pickle та безкоштовні моделі",
|
"go.graph.freePill": "Big Pickle та безкоштовні моделі",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "Запитів за 5 годин",
|
"go.graph.label": "Запитів за 5 годин",
|
||||||
|
"go.graph.limitedRegions": "обмежені регіони",
|
||||||
|
"go.graph.limitedTime": "обмежений час",
|
||||||
"go.graph.usageLimits": "Ліміти використання",
|
"go.graph.usageLimits": "Ліміти використання",
|
||||||
"go.graph.aria": "Запитів за 5 год: {{free}} vs {{go}}",
|
"go.graph.aria": "Запитів за 5 год: {{free}} vs {{go}}",
|
||||||
|
|
||||||
@@ -299,21 +299,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "Хотів би я досі бути в Nvidia.",
|
"go.testimonials.frank.quote": "Хотів би я досі бути в Nvidia.",
|
||||||
"go.problem.title": "Яку проблему вирішує Go?",
|
"go.problem.title": "Яку проблему вирішує Go?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"Ми зосереджені на тому, щоб зробити досвід OpenCode доступним для якомога більшої кількості людей. OpenCode Go — це недорога підписка: $5 за перший місяць, потім $10/місяць. Вона надає щедрі ліміти та надійний доступ до найкращих моделей з відкритим кодом.",
|
"Ми зосереджені на тому, щоб зробити досвід OpenCode доступним для якомога більшої кількості людей. OpenCode Go — це недорога підписка за $10/місяць. Вона надає щедрі ліміти та надійний доступ до найкращих моделей з відкритим кодом.",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "Недорога підписка",
|
"go.problem.item1": "Недорога підписка",
|
||||||
"go.problem.item2": "Щедрі ліміти та надійний доступ",
|
"go.problem.item2": "Щедрі ліміти та надійний доступ",
|
||||||
"go.problem.item3": "Створено для якомога більшої кількості програмістів",
|
"go.problem.item3": "Створено для якомога більшої кількості програмістів",
|
||||||
"go.problem.item4": "Добірка моделей, протестованих для агентного кодування",
|
"go.problem.item4": "Добірка моделей, протестованих для агентного кодування",
|
||||||
"go.how.title": "Як працює Go",
|
"go.how.title": "Як працює Go",
|
||||||
"go.how.body":
|
"go.how.body": "Go коштує $10/місяць. Використовуйте з OpenCode або будь-яким агентом.",
|
||||||
"Go починається від $5 за перший місяць, потім $10/місяць. Використовуйте з OpenCode або будь-яким агентом.",
|
|
||||||
"go.how.step1.title": "Створіть обліковий запис",
|
"go.how.step1.title": "Створіть обліковий запис",
|
||||||
"go.how.step1.beforeLink": "дотримуйтесь",
|
"go.how.step1.beforeLink": "дотримуйтесь",
|
||||||
"go.how.step1.link": "інструкцій з налаштування",
|
"go.how.step1.link": "інструкцій з налаштування",
|
||||||
"go.how.step2.title": "Підпишіться на Go",
|
"go.how.step2.title": "Підпишіться на Go",
|
||||||
"go.how.step2.link": "$5 перший місяць",
|
"go.how.step2.link": "$10/місяць",
|
||||||
"go.how.step2.afterLink": "потім $10/місяць із щедрими лімітами",
|
"go.how.step2.afterLink": "із щедрими лімітами",
|
||||||
"go.how.step3.title": "Почніть кодувати",
|
"go.how.step3.title": "Почніть кодувати",
|
||||||
"go.how.step3.body": "з надійним доступом до моделей з відкритим кодом",
|
"go.how.step3.body": "з надійним доступом до моделей з відкритим кодом",
|
||||||
"go.privacy.title": "Ваша конфіденційність важлива для нас",
|
"go.privacy.title": "Ваша конфіденційність важлива для нас",
|
||||||
@@ -330,11 +329,11 @@ export const dict = {
|
|||||||
"go.faq.a2": "Go включає моделі, перелічені нижче, із щедрими лімітами та надійним доступом.",
|
"go.faq.a2": "Go включає моделі, перелічені нижче, із щедрими лімітами та надійним доступом.",
|
||||||
"go.faq.q3": "Чи Go те саме, що Zen?",
|
"go.faq.q3": "Чи Go те саме, що Zen?",
|
||||||
"go.faq.a3":
|
"go.faq.a3":
|
||||||
"Ні. Zen — це плата за використання, тоді як Go починається від $5 за перший місяць, потім $10/місяць, із щедрими лімітами та надійним доступом до добірки моделей.",
|
"Ні. Zen — це плата за використання, тоді як Go коштує $10/місяць, із щедрими лімітами та надійним доступом до добірки моделей.",
|
||||||
"go.faq.q4": "Скільки коштує Go?",
|
"go.faq.q4": "Скільки коштує Go?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go коштує",
|
"go.faq.a4.p1.beforePricing": "Go коштує",
|
||||||
"go.faq.a4.p1.pricingLink": "$5 за перший місяць",
|
"go.faq.a4.p1.pricingLink": "$10/місяць",
|
||||||
"go.faq.a4.p1.afterPricing": "потім $10/місяць із щедрими лімітами.",
|
"go.faq.a4.p1.afterPricing": "із щедрими лімітами.",
|
||||||
"go.faq.a4.p2.beforeAccount": "Ви можете керувати підпискою в",
|
"go.faq.a4.p2.beforeAccount": "Ви можете керувати підпискою в",
|
||||||
"go.faq.a4.p2.accountLink": "обліковому записі",
|
"go.faq.a4.p2.accountLink": "обліковому записі",
|
||||||
"go.faq.a4.p3": "Скасуйте в будь-який час.",
|
"go.faq.a4.p3": "Скасуйте в будь-який час.",
|
||||||
@@ -347,12 +346,15 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "Використовується",
|
"go.faq.a5.used": "Використовується",
|
||||||
"go.faq.a5.notUsed": "Не використовується",
|
"go.faq.a5.notUsed": "Не використовується",
|
||||||
"go.faq.a5.noAgreement": "Немає угоди",
|
"go.faq.a5.noAgreement": "Немає угоди",
|
||||||
|
"go.faq.a5.notZdr": "Не ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"go.faq.a5.grokRetention":
|
||||||
"ZDR вимикає важливі функції API, які залежать від збережених даних, зокрема Responses API зі збереженням стану, Files and Collections та Batch API.",
|
"ZDR вимикає важливі функції API, які залежать від збережених даних, зокрема Responses API зі збереженням стану, Files and Collections та Batch API.",
|
||||||
"go.faq.a5.gptRetention":
|
"go.faq.a5.gptRetention":
|
||||||
"Журнали моніторингу зловживань створюються для всіх випадків використання функцій API та зберігаються до 30 днів.",
|
"Журнали моніторингу зловживань створюються для всіх випадків використання функцій API та зберігаються до 30 днів.",
|
||||||
"go.faq.a5.learnMore": "Докладніше",
|
"go.faq.a5.learnMore": "Докладніше",
|
||||||
"go.faq.a5.deepseekRetention": "Угода ZDR поновлюється щомісяця. Поточна угода дійсна до 31 серпня 2026 року.",
|
"go.faq.a5.deepseekRetention": "Угода ZDR поновлюється щомісяця. Поточна угода дійсна до 31 серпня 2026 року.",
|
||||||
|
"go.faq.a5.museRetention":
|
||||||
|
"Значно знижені ціни на токени в обмін на дозвіл використовувати ваші промпти та відповіді для навчання майбутніх моделей Meta.",
|
||||||
|
|
||||||
"go.faq.a5.beforeExceptions":
|
"go.faq.a5.beforeExceptions":
|
||||||
"Моделі Go розміщені в США. Провайдери дотримуються політики нульового зберігання та не використовують ваші дані для навчання моделей, за",
|
"Моделі Go розміщені в США. Провайдери дотримуються політики нульового зберігання та не використовують ваші дані для навчання моделей, за",
|
||||||
@@ -392,6 +394,9 @@ export const dict = {
|
|||||||
"zen.api.error.modelDisabled": "Модель вимкнено",
|
"zen.api.error.modelDisabled": "Модель вимкнено",
|
||||||
"zen.api.error.regionNotAllowed":
|
"zen.api.error.regionNotAllowed":
|
||||||
"Остання версія цієї моделі доступна лише на серверах у Китаї, і для її використання потрібно надати явну згоду: {{consoleGoUrl}}",
|
"Остання версія цієї моделі доступна лише на серверах у Китаї, і для її використання потрібно надати явну згоду: {{consoleGoUrl}}",
|
||||||
|
"zen.api.error.countryNotAllowed": "Ця модель недоступна у вашій країні.",
|
||||||
|
"zen.api.error.trainingNotAllowed":
|
||||||
|
"Ця модель збирає дані, які використовуються для покращення її якості; для її використання потрібна ваша явна згода: {{consoleGoUrl}}",
|
||||||
"zen.api.error.trialEnded":
|
"zen.api.error.trialEnded":
|
||||||
"Безкоштовна акція для {{model}} закінчилася. Ви можете продовжити використання, підписавшись на OpenCode Go — {{link}}",
|
"Безкоштовна акція для {{model}} закінчилася. Ви можете продовжити використання, підписавшись на OpenCode Go — {{link}}",
|
||||||
|
|
||||||
@@ -672,12 +677,13 @@ export const dict = {
|
|||||||
"workspace.lite.subscription.selectProvider": 'Виберіть "OpenCode Go" як провайдера в конфігурації opencode.',
|
"workspace.lite.subscription.selectProvider": 'Виберіть "OpenCode Go" як провайдера в конфігурації opencode.',
|
||||||
"workspace.lite.providers.title": "Провайдери",
|
"workspace.lite.providers.title": "Провайдери",
|
||||||
"workspace.lite.providers.description": "Керуйте провайдерами, які використовуються для маршрутизації.",
|
"workspace.lite.providers.description": "Керуйте провайдерами, які використовуються для маршрутизації.",
|
||||||
|
"workspace.lite.providers.allowTraining": "Дозволити моделі, що навчаються на даних запитів",
|
||||||
"workspace.lite.providers.useChina": "Увімкнути моделі, розміщені в Китаї",
|
"workspace.lite.providers.useChina": "Увімкнути моделі, розміщені в Китаї",
|
||||||
"workspace.lite.black.message":
|
"workspace.lite.black.message":
|
||||||
"Ви вже підписані на OpenCode Black або в списку очікування. Спочатку скасуйте підписку, якщо хочете перейти на Go.",
|
"Ви вже підписані на OpenCode Black або в списку очікування. Спочатку скасуйте підписку, якщо хочете перейти на Go.",
|
||||||
"workspace.lite.other.message": "Інший учасник цього робочого простору вже підписаний на OpenCode Go.",
|
"workspace.lite.other.message": "Інший учасник цього робочого простору вже підписаний на OpenCode Go.",
|
||||||
"workspace.lite.promo.description": "OpenCode Go починається від {{price}}, потім $10/місяць, із щедрими лімітами.",
|
"workspace.lite.promo.description": "OpenCode Go коштує {{price}} і має щедрі ліміти.",
|
||||||
"workspace.lite.promo.price": "$5 за перший місяць",
|
"workspace.lite.promo.price": "$10/місяць",
|
||||||
"workspace.lite.promo.modelsTitle": "Що включено",
|
"workspace.lite.promo.modelsTitle": "Що включено",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"План призначений насамперед для міжнародних користувачів і забезпечує стабільний глобальний доступ. Ціни та ліміти використання можуть змінюватися з урахуванням перших даних про використання та відгуків.",
|
"План призначений насамперед для міжнародних користувачів і забезпечує стабільний глобальний доступ. Ціни та ліміти використання можуть змінюватися з урахуванням перших даних про використання та відгуків.",
|
||||||
|
|||||||
@@ -244,8 +244,8 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "以下例外情况除外",
|
"zen.privacy.exceptionsLink": "以下例外情况除外",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | 人人可用的低成本编程模型",
|
"go.title": "OpenCode Go | 人人可用的低成本编程模型",
|
||||||
"go.banner.text": "DeepSeek V4 Flash 限时享受 2 倍使用额度",
|
"go.banner.text": "Ox Alpha Free 限时加入 Go",
|
||||||
"go.meta.description": "Go 首月 $5,之后 $10/月,提供充裕的使用限额,并可可靠访问领先的编程模型。",
|
"go.meta.description": "Go 每月 $10,提供充裕的使用限额,并可可靠访问领先的编程模型。",
|
||||||
"go.hero.title": "人人可用的低成本编程模型",
|
"go.hero.title": "人人可用的低成本编程模型",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go 将代理编程带给全世界的程序员。提供充裕的限额和对最强大的开源模型的可靠访问,让您可以利用强大的代理进行构建,而无需担心成本或可用性。",
|
"Go 将代理编程带给全世界的程序员。提供充裕的限额和对最强大的开源模型的可靠访问,让您可以利用强大的代理进行构建,而无需担心成本或可用性。",
|
||||||
@@ -254,12 +254,13 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "订阅 Go",
|
"go.cta.text": "订阅 Go",
|
||||||
"go.cta.price": "$10/月",
|
"go.cta.price": "$10/月",
|
||||||
"go.cta.promo": "首月 $5",
|
"go.pricing.body": "可配合任何代理使用。每月 $10。如有需要可充值。随时取消。",
|
||||||
"go.pricing.body": "可配合任何代理使用。首月 $5,之后 $10/月。如有需要可充值。随时取消。",
|
|
||||||
"go.graph.free": "免费",
|
"go.graph.free": "免费",
|
||||||
"go.graph.freePill": "Big Pickle 和免费模型",
|
"go.graph.freePill": "Big Pickle 和免费模型",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "每 5 小时请求数",
|
"go.graph.label": "每 5 小时请求数",
|
||||||
|
"go.graph.limitedRegions": "仅限部分地区",
|
||||||
|
"go.graph.limitedTime": "限时",
|
||||||
"go.graph.usageLimits": "使用限制",
|
"go.graph.usageLimits": "使用限制",
|
||||||
"go.graph.aria": "每 5 小时请求数: {{free}} vs {{go}}",
|
"go.graph.aria": "每 5 小时请求数: {{free}} vs {{go}}",
|
||||||
|
|
||||||
@@ -286,20 +287,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "我希望我还在 Nvidia。",
|
"go.testimonials.frank.quote": "我希望我还在 Nvidia。",
|
||||||
"go.problem.title": "Go 解决了什么问题?",
|
"go.problem.title": "Go 解决了什么问题?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"我们致力于将 OpenCode 体验带给尽可能多的人。OpenCode Go 是一款低成本订阅服务:首月 $5,之后 $10/月。它提供充裕的额度,并让您能可靠地使用最强大的开源模型。",
|
"我们致力于将 OpenCode 体验带给尽可能多的人。OpenCode Go 是一款每月 $10 的低成本订阅服务。它提供充裕的额度,并让您能可靠地使用最强大的开源模型。",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "低成本订阅定价",
|
"go.problem.item1": "低成本订阅定价",
|
||||||
"go.problem.item2": "充裕的限额和可靠的访问",
|
"go.problem.item2": "充裕的限额和可靠的访问",
|
||||||
"go.problem.item3": "为尽可能多的程序员打造",
|
"go.problem.item3": "为尽可能多的程序员打造",
|
||||||
"go.problem.item4": "经过代理编程测试的精选模型阵容",
|
"go.problem.item4": "经过代理编程测试的精选模型阵容",
|
||||||
"go.how.title": "Go 如何工作",
|
"go.how.title": "Go 如何工作",
|
||||||
"go.how.body": "Go 起价为首月 $5,之后 $10/月。您可以将其与 OpenCode 或任何代理搭配使用。",
|
"go.how.body": "Go 每月 $10。您可以将其与 OpenCode 或任何代理搭配使用。",
|
||||||
"go.how.step1.title": "创建账户",
|
"go.how.step1.title": "创建账户",
|
||||||
"go.how.step1.beforeLink": "遵循",
|
"go.how.step1.beforeLink": "遵循",
|
||||||
"go.how.step1.link": "设置说明",
|
"go.how.step1.link": "设置说明",
|
||||||
"go.how.step2.title": "订阅 Go",
|
"go.how.step2.title": "订阅 Go",
|
||||||
"go.how.step2.link": "首月 $5",
|
"go.how.step2.link": "每月 $10",
|
||||||
"go.how.step2.afterLink": "之后 $10/月,额度充裕",
|
"go.how.step2.afterLink": "额度充裕",
|
||||||
"go.how.step3.title": "开始编程",
|
"go.how.step3.title": "开始编程",
|
||||||
"go.how.step3.body": "可靠访问开源模型",
|
"go.how.step3.body": "可靠访问开源模型",
|
||||||
"go.privacy.title": "您的隐私对我们很重要",
|
"go.privacy.title": "您的隐私对我们很重要",
|
||||||
@@ -312,11 +313,11 @@ export const dict = {
|
|||||||
"go.faq.q2": "Go 包含哪些模型?",
|
"go.faq.q2": "Go 包含哪些模型?",
|
||||||
"go.faq.a2": "Go 包含下方列出的模型,提供充足的限额和可靠的访问。",
|
"go.faq.a2": "Go 包含下方列出的模型,提供充足的限额和可靠的访问。",
|
||||||
"go.faq.q3": "Go 和 Zen 一样吗?",
|
"go.faq.q3": "Go 和 Zen 一样吗?",
|
||||||
"go.faq.a3": "不。Zen 是按量付费,而 Go 首月 $5,之后 $10/月,提供充裕的限额,并可可靠访问精选模型阵容。",
|
"go.faq.a3": "不。Zen 是按量付费,而 Go 每月 $10,提供充裕的限额,并可可靠访问精选模型阵容。",
|
||||||
"go.faq.q4": "Go 多少钱?",
|
"go.faq.q4": "Go 多少钱?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go 费用为",
|
"go.faq.a4.p1.beforePricing": "Go 费用为",
|
||||||
"go.faq.a4.p1.pricingLink": "首月 $5",
|
"go.faq.a4.p1.pricingLink": "每月 $10",
|
||||||
"go.faq.a4.p1.afterPricing": "之后 $10/月,额度充裕。",
|
"go.faq.a4.p1.afterPricing": "额度充裕。",
|
||||||
"go.faq.a4.p2.beforeAccount": "您可以在您的",
|
"go.faq.a4.p2.beforeAccount": "您可以在您的",
|
||||||
"go.faq.a4.p2.accountLink": "账户",
|
"go.faq.a4.p2.accountLink": "账户",
|
||||||
"go.faq.a4.p3": "中管理订阅。随时取消。",
|
"go.faq.a4.p3": "中管理订阅。随时取消。",
|
||||||
@@ -329,9 +330,11 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "使用",
|
"go.faq.a5.used": "使用",
|
||||||
"go.faq.a5.notUsed": "不使用",
|
"go.faq.a5.notUsed": "不使用",
|
||||||
"go.faq.a5.noAgreement": "无协议",
|
"go.faq.a5.noAgreement": "无协议",
|
||||||
|
"go.faq.a5.notZdr": "非 ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"go.faq.a5.grokRetention":
|
||||||
"ZDR 会禁用依赖所存储数据的重要 API 功能,包括有状态的 Responses API、Files and Collections 和 Batch API。",
|
"ZDR 会禁用依赖所存储数据的重要 API 功能,包括有状态的 Responses API、Files and Collections 和 Batch API。",
|
||||||
"go.faq.a5.gptRetention": "所有 API 功能的使用都会生成滥用监控日志,并最多保留 30 天。",
|
"go.faq.a5.gptRetention": "所有 API 功能的使用都会生成滥用监控日志,并最多保留 30 天。",
|
||||||
|
"go.faq.a5.museRetention": "以允许使用你的提示词和补全结果训练未来的 Meta 模型为交换,token 价格可获得大幅折扣。",
|
||||||
"go.faq.a5.learnMore": "了解更多",
|
"go.faq.a5.learnMore": "了解更多",
|
||||||
"go.faq.a5.deepseekRetention": "ZDR 协议每月续签。当前协议有效期至 2026 年 8 月 31 日。",
|
"go.faq.a5.deepseekRetention": "ZDR 协议每月续签。当前协议有效期至 2026 年 8 月 31 日。",
|
||||||
"go.faq.a5.beforeExceptions": "Go 模型托管在美国。提供商遵循零留存政策,不使用您的数据进行模型训练,",
|
"go.faq.a5.beforeExceptions": "Go 模型托管在美国。提供商遵循零留存政策,不使用您的数据进行模型训练,",
|
||||||
@@ -369,6 +372,8 @@ export const dict = {
|
|||||||
"zen.api.error.userMonthlyLimitReached": "您已达到每月支出限额 ${{amount}}。请在此处管理您的限额:{{membersUrl}}",
|
"zen.api.error.userMonthlyLimitReached": "您已达到每月支出限额 ${{amount}}。请在此处管理您的限额:{{membersUrl}}",
|
||||||
"zen.api.error.modelDisabled": "模型已禁用",
|
"zen.api.error.modelDisabled": "模型已禁用",
|
||||||
"zen.api.error.regionNotAllowed": "该模型的最新版本仅在中国提供托管服务,需明确选择启用:{{consoleGoUrl}}",
|
"zen.api.error.regionNotAllowed": "该模型的最新版本仅在中国提供托管服务,需明确选择启用:{{consoleGoUrl}}",
|
||||||
|
"zen.api.error.countryNotAllowed": "该模型在你所在的国家或地区不可用。",
|
||||||
|
"zen.api.error.trainingNotAllowed": "该模型会收集用于提升其质量的数据,使用前需要你明确同意:{{consoleGoUrl}}",
|
||||||
"zen.api.error.trialEnded": "{{model}} 的限免活动已结束。您可以订阅 OpenCode Go 继续使用该模型 - {{link}}",
|
"zen.api.error.trialEnded": "{{model}} 的限免活动已结束。您可以订阅 OpenCode Go 继续使用该模型 - {{link}}",
|
||||||
|
|
||||||
"black.meta.title": "OpenCode Black | 访问全球顶尖编程模型",
|
"black.meta.title": "OpenCode Black | 访问全球顶尖编程模型",
|
||||||
@@ -646,12 +651,13 @@ export const dict = {
|
|||||||
"在你的 opencode 配置中选择「OpenCode Go」作为提供商,即可使用 Go 模型。",
|
"在你的 opencode 配置中选择「OpenCode Go」作为提供商,即可使用 Go 模型。",
|
||||||
"workspace.lite.providers.title": "提供商",
|
"workspace.lite.providers.title": "提供商",
|
||||||
"workspace.lite.providers.description": "控制用于路由的提供商。",
|
"workspace.lite.providers.description": "控制用于路由的提供商。",
|
||||||
|
"workspace.lite.providers.allowTraining": "允许使用请求数据进行训练的模型",
|
||||||
"workspace.lite.providers.useChina": "启用部署在中国的模型",
|
"workspace.lite.providers.useChina": "启用部署在中国的模型",
|
||||||
"workspace.lite.black.message": "您当前已订阅 OpenCode Black 或在候补名单中。如需切换到 Go,请先取消订阅。",
|
"workspace.lite.black.message": "您当前已订阅 OpenCode Black 或在候补名单中。如需切换到 Go,请先取消订阅。",
|
||||||
"workspace.lite.other.message": "此工作区中的另一位成员已经订阅了 OpenCode Go。每个工作区只有一名成员可以订阅。",
|
"workspace.lite.other.message": "此工作区中的另一位成员已经订阅了 OpenCode Go。每个工作区只有一名成员可以订阅。",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go 起价为 {{price}},之后 $10/月,并提供对流行开放编码模型的可靠访问,同时享有充裕的使用限额。",
|
"OpenCode Go 每月 {{price}},并提供对流行开放编码模型的可靠访问,同时享有充裕的使用限额。",
|
||||||
"workspace.lite.promo.price": "首月 $5",
|
"workspace.lite.promo.price": "$10/月",
|
||||||
"workspace.lite.promo.modelsTitle": "包含模型",
|
"workspace.lite.promo.modelsTitle": "包含模型",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"该计划主要面向国际用户,提供稳定的全球访问体验。随着我们持续了解早期使用情况并收集反馈,定价和使用限额可能会有所调整。",
|
"该计划主要面向国际用户,提供稳定的全球访问体验。随着我们持续了解早期使用情况并收集反馈,定价和使用限额可能会有所调整。",
|
||||||
|
|||||||
@@ -244,8 +244,8 @@ export const dict = {
|
|||||||
"zen.privacy.exceptionsLink": "以下例外情況",
|
"zen.privacy.exceptionsLink": "以下例外情況",
|
||||||
|
|
||||||
"go.title": "OpenCode Go | 低成本全民編碼模型",
|
"go.title": "OpenCode Go | 低成本全民編碼模型",
|
||||||
"go.banner.text": "DeepSeek V4 Flash 限時享有 2 倍使用額度",
|
"go.banner.text": "Ox Alpha Free 限時加入 Go",
|
||||||
"go.meta.description": "Go 首月 $5,之後 $10/月,提供充裕的使用限額,並可穩定存取領先的編碼模型。",
|
"go.meta.description": "Go 每月 $10,提供充裕的使用限額,並可穩定存取領先的編碼模型。",
|
||||||
"go.hero.title": "低成本全民編碼模型",
|
"go.hero.title": "低成本全民編碼模型",
|
||||||
"go.hero.body":
|
"go.hero.body":
|
||||||
"Go 將代理編碼帶給全世界的程式設計師。提供寬裕的限額以及對最強大開源模型的穩定存取,讓你可以使用強大的代理進行構建,而無需擔心成本或可用性。",
|
"Go 將代理編碼帶給全世界的程式設計師。提供寬裕的限額以及對最強大開源模型的穩定存取,讓你可以使用強大的代理進行構建,而無需擔心成本或可用性。",
|
||||||
@@ -254,12 +254,13 @@ export const dict = {
|
|||||||
"go.cta.template": "{{text}} {{price}}",
|
"go.cta.template": "{{text}} {{price}}",
|
||||||
"go.cta.text": "訂閱 Go",
|
"go.cta.text": "訂閱 Go",
|
||||||
"go.cta.price": "$10/月",
|
"go.cta.price": "$10/月",
|
||||||
"go.cta.promo": "首月 $5",
|
"go.pricing.body": "可搭配任何代理使用。每月 $10。如有需要可儲值。隨時取消。",
|
||||||
"go.pricing.body": "可搭配任何代理使用。首月 $5,之後 $10/月。如有需要可儲值。隨時取消。",
|
|
||||||
"go.graph.free": "免費",
|
"go.graph.free": "免費",
|
||||||
"go.graph.freePill": "Big Pickle 與免費模型",
|
"go.graph.freePill": "Big Pickle 與免費模型",
|
||||||
"go.graph.go": "Go",
|
"go.graph.go": "Go",
|
||||||
"go.graph.label": "每 5 小時請求數",
|
"go.graph.label": "每 5 小時請求數",
|
||||||
|
"go.graph.limitedRegions": "僅限部分地區",
|
||||||
|
"go.graph.limitedTime": "限時",
|
||||||
"go.graph.usageLimits": "使用限制",
|
"go.graph.usageLimits": "使用限制",
|
||||||
"go.graph.aria": "每 5 小時請求數:{{free}} vs {{go}}",
|
"go.graph.aria": "每 5 小時請求數:{{free}} vs {{go}}",
|
||||||
|
|
||||||
@@ -286,20 +287,20 @@ export const dict = {
|
|||||||
"go.testimonials.frank.quote": "我希望我還在 Nvidia。",
|
"go.testimonials.frank.quote": "我希望我還在 Nvidia。",
|
||||||
"go.problem.title": "Go 正在解決什麼問題?",
|
"go.problem.title": "Go 正在解決什麼問題?",
|
||||||
"go.problem.body":
|
"go.problem.body":
|
||||||
"我們致力於將 OpenCode 體驗帶給盡可能多的人。OpenCode Go 是一款低成本訂閱服務:首月 $5,之後 $10/月。它提供充裕的額度,並讓您能可靠地使用最強大的開源模型。",
|
"我們致力於將 OpenCode 體驗帶給盡可能多的人。OpenCode Go 是一款每月 $10 的低成本訂閱服務。它提供充裕的額度,並讓您能可靠地使用最強大的開源模型。",
|
||||||
"go.problem.subtitle": " ",
|
"go.problem.subtitle": " ",
|
||||||
"go.problem.item1": "低成本訂閱定價",
|
"go.problem.item1": "低成本訂閱定價",
|
||||||
"go.problem.item2": "寬裕的限額與穩定存取",
|
"go.problem.item2": "寬裕的限額與穩定存取",
|
||||||
"go.problem.item3": "專為盡可能多的程式設計師打造",
|
"go.problem.item3": "專為盡可能多的程式設計師打造",
|
||||||
"go.problem.item4": "針對代理編碼測試的精選模型陣容",
|
"go.problem.item4": "針對代理編碼測試的精選模型陣容",
|
||||||
"go.how.title": "Go 如何運作",
|
"go.how.title": "Go 如何運作",
|
||||||
"go.how.body": "Go 起價為首月 $5,之後 $10/月。您可以將其與 OpenCode 或任何代理搭配使用。",
|
"go.how.body": "Go 每月 $10。您可以將其與 OpenCode 或任何代理搭配使用。",
|
||||||
"go.how.step1.title": "建立帳號",
|
"go.how.step1.title": "建立帳號",
|
||||||
"go.how.step1.beforeLink": "遵循",
|
"go.how.step1.beforeLink": "遵循",
|
||||||
"go.how.step1.link": "設定說明",
|
"go.how.step1.link": "設定說明",
|
||||||
"go.how.step2.title": "訂閱 Go",
|
"go.how.step2.title": "訂閱 Go",
|
||||||
"go.how.step2.link": "首月 $5",
|
"go.how.step2.link": "每月 $10",
|
||||||
"go.how.step2.afterLink": "之後 $10/月,額度充裕",
|
"go.how.step2.afterLink": "額度充裕",
|
||||||
"go.how.step3.title": "開始編碼",
|
"go.how.step3.title": "開始編碼",
|
||||||
"go.how.step3.body": "穩定存取開源模型",
|
"go.how.step3.body": "穩定存取開源模型",
|
||||||
"go.privacy.title": "你的隱私對我們很重要",
|
"go.privacy.title": "你的隱私對我們很重要",
|
||||||
@@ -312,11 +313,11 @@ export const dict = {
|
|||||||
"go.faq.q2": "Go 包含哪些模型?",
|
"go.faq.q2": "Go 包含哪些模型?",
|
||||||
"go.faq.a2": "Go 包含下方列出的模型,提供充足的額度與穩定的存取。",
|
"go.faq.a2": "Go 包含下方列出的模型,提供充足的額度與穩定的存取。",
|
||||||
"go.faq.q3": "Go 與 Zen 一樣嗎?",
|
"go.faq.q3": "Go 與 Zen 一樣嗎?",
|
||||||
"go.faq.a3": "不。Zen 是按量付費,而 Go 首月 $5,之後 $10/月,提供充裕的限額,並可穩定存取精選模型陣容。",
|
"go.faq.a3": "不。Zen 是按量付費,而 Go 每月 $10,提供充裕的限額,並可穩定存取精選模型陣容。",
|
||||||
"go.faq.q4": "Go 費用是多少?",
|
"go.faq.q4": "Go 費用是多少?",
|
||||||
"go.faq.a4.p1.beforePricing": "Go 費用為",
|
"go.faq.a4.p1.beforePricing": "Go 費用為",
|
||||||
"go.faq.a4.p1.pricingLink": "首月 $5",
|
"go.faq.a4.p1.pricingLink": "每月 $10",
|
||||||
"go.faq.a4.p1.afterPricing": "之後 $10/月,額度充裕。",
|
"go.faq.a4.p1.afterPricing": "額度充裕。",
|
||||||
"go.faq.a4.p2.beforeAccount": "你可以在你的",
|
"go.faq.a4.p2.beforeAccount": "你可以在你的",
|
||||||
"go.faq.a4.p2.accountLink": "帳戶",
|
"go.faq.a4.p2.accountLink": "帳戶",
|
||||||
"go.faq.a4.p3": "中管理訂閱。隨時取消。",
|
"go.faq.a4.p3": "中管理訂閱。隨時取消。",
|
||||||
@@ -329,9 +330,11 @@ export const dict = {
|
|||||||
"go.faq.a5.used": "使用",
|
"go.faq.a5.used": "使用",
|
||||||
"go.faq.a5.notUsed": "不使用",
|
"go.faq.a5.notUsed": "不使用",
|
||||||
"go.faq.a5.noAgreement": "無協議",
|
"go.faq.a5.noAgreement": "無協議",
|
||||||
|
"go.faq.a5.notZdr": "非 ZDR",
|
||||||
"go.faq.a5.grokRetention":
|
"go.faq.a5.grokRetention":
|
||||||
"ZDR 會停用依賴儲存資料的重要 API 功能,包括具狀態的 Responses API、Files and Collections 與 Batch API。",
|
"ZDR 會停用依賴儲存資料的重要 API 功能,包括具狀態的 Responses API、Files and Collections 與 Batch API。",
|
||||||
"go.faq.a5.gptRetention": "所有 API 功能的使用都會產生濫用監控日誌,並保留最多 30 天。",
|
"go.faq.a5.gptRetention": "所有 API 功能的使用都會產生濫用監控日誌,並保留最多 30 天。",
|
||||||
|
"go.faq.a5.museRetention": "以允許使用您的提示詞和生成結果來訓練未來的 Meta 模型為交換,token 價格可享大幅折扣。",
|
||||||
"go.faq.a5.learnMore": "了解更多",
|
"go.faq.a5.learnMore": "了解更多",
|
||||||
"go.faq.a5.deepseekRetention": "ZDR 協議每月續簽。目前的協議有效至 2026 年 8 月 31 日。",
|
"go.faq.a5.deepseekRetention": "ZDR 協議每月續簽。目前的協議有效至 2026 年 8 月 31 日。",
|
||||||
"go.faq.a5.beforeExceptions": "Go 模型託管在美國。供應商遵循零留存政策,不會將你的資料用於模型訓練,但有",
|
"go.faq.a5.beforeExceptions": "Go 模型託管在美國。供應商遵循零留存政策,不會將你的資料用於模型訓練,但有",
|
||||||
@@ -369,6 +372,8 @@ export const dict = {
|
|||||||
"zen.api.error.userMonthlyLimitReached": "你已達到每月支出限額 ${{amount}}。請在此處管理你的限額:{{membersUrl}}",
|
"zen.api.error.userMonthlyLimitReached": "你已達到每月支出限額 ${{amount}}。請在此處管理你的限額:{{membersUrl}}",
|
||||||
"zen.api.error.modelDisabled": "模型已停用",
|
"zen.api.error.modelDisabled": "模型已停用",
|
||||||
"zen.api.error.regionNotAllowed": "此模型的最新版本僅於中國託管,且需明確選擇啟用:{{consoleGoUrl}}",
|
"zen.api.error.regionNotAllowed": "此模型的最新版本僅於中國託管,且需明確選擇啟用:{{consoleGoUrl}}",
|
||||||
|
"zen.api.error.countryNotAllowed": "此模型無法在你所在的國家或地區使用。",
|
||||||
|
"zen.api.error.trainingNotAllowed": "此模型會收集用於提升其品質的資料,使用前須經你明確同意:{{consoleGoUrl}}",
|
||||||
"zen.api.error.trialEnded": "{{model}} 的限免活动已結束。您可以訂閱 OpenCode Go 繼續使用該模型 - {{link}}",
|
"zen.api.error.trialEnded": "{{model}} 的限免活动已結束。您可以訂閱 OpenCode Go 繼續使用該模型 - {{link}}",
|
||||||
|
|
||||||
"black.meta.title": "OpenCode Black | 存取全球最佳編碼模型",
|
"black.meta.title": "OpenCode Black | 存取全球最佳編碼模型",
|
||||||
@@ -646,12 +651,13 @@ export const dict = {
|
|||||||
"在您的 opencode 設定中選擇「OpenCode Go」作為提供商,即可使用 Go 模型。",
|
"在您的 opencode 設定中選擇「OpenCode Go」作為提供商,即可使用 Go 模型。",
|
||||||
"workspace.lite.providers.title": "提供商",
|
"workspace.lite.providers.title": "提供商",
|
||||||
"workspace.lite.providers.description": "控制用於路由的提供商。",
|
"workspace.lite.providers.description": "控制用於路由的提供商。",
|
||||||
|
"workspace.lite.providers.allowTraining": "允許使用請求資料進行訓練的模型",
|
||||||
"workspace.lite.providers.useChina": "啟用部署在中國的模型",
|
"workspace.lite.providers.useChina": "啟用部署在中國的模型",
|
||||||
"workspace.lite.black.message": "您目前已訂閱 OpenCode Black 或在候補名單中。若要切換至 Go,請先取消訂閱。",
|
"workspace.lite.black.message": "您目前已訂閱 OpenCode Black 或在候補名單中。若要切換至 Go,請先取消訂閱。",
|
||||||
"workspace.lite.other.message": "此工作區中的另一位成員已訂閱 OpenCode Go。每個工作區只能有一位成員訂閱。",
|
"workspace.lite.other.message": "此工作區中的另一位成員已訂閱 OpenCode Go。每個工作區只能有一位成員訂閱。",
|
||||||
"workspace.lite.promo.description":
|
"workspace.lite.promo.description":
|
||||||
"OpenCode Go 起價為 {{price}},之後 $10/月,並提供對熱門開放編碼模型的可靠存取,同時享有充裕的使用額度。",
|
"OpenCode Go 每月 {{price}},並提供對熱門開放編碼模型的可靠存取,同時享有充裕的使用額度。",
|
||||||
"workspace.lite.promo.price": "首月 $5",
|
"workspace.lite.promo.price": "$10/月",
|
||||||
"workspace.lite.promo.modelsTitle": "包含模型",
|
"workspace.lite.promo.modelsTitle": "包含模型",
|
||||||
"workspace.lite.promo.footer":
|
"workspace.lite.promo.footer":
|
||||||
"此方案主要為國際使用者設計,提供穩定的全球存取服務。隨著我們從初期使用情況和回饋中持續了解需求,價格和使用額度可能會有所調整。",
|
"此方案主要為國際使用者設計,提供穩定的全球存取服務。隨著我們從初期使用情況和回饋中持續了解需求,價格和使用額度可能會有所調整。",
|
||||||
|
|||||||
@@ -1,5 +1,38 @@
|
|||||||
|
const MUSE_SPARK_BLOCKED_COUNTRIES = new Set([
|
||||||
|
"AF",
|
||||||
|
"BY",
|
||||||
|
"CN",
|
||||||
|
"CU",
|
||||||
|
"EH",
|
||||||
|
"ER",
|
||||||
|
"ET",
|
||||||
|
"HK",
|
||||||
|
"HT",
|
||||||
|
"IQ",
|
||||||
|
"IR",
|
||||||
|
"KH",
|
||||||
|
"KP",
|
||||||
|
"LY",
|
||||||
|
"MM",
|
||||||
|
"MO",
|
||||||
|
"NI",
|
||||||
|
"PK",
|
||||||
|
"RU",
|
||||||
|
"SO",
|
||||||
|
"SY",
|
||||||
|
"VE",
|
||||||
|
])
|
||||||
|
|
||||||
export function countryFromRequest(request: Request | undefined) {
|
export function countryFromRequest(request: Request | undefined) {
|
||||||
if (!request) return undefined
|
if (!request) return undefined
|
||||||
const cloudflareRequest = request as Request & { cf?: { country?: string } }
|
const cloudflareRequest = request as Request & { cf?: { country?: string } }
|
||||||
return cloudflareRequest.cf?.country ?? request.headers.get("cf-ipcountry") ?? undefined
|
return cloudflareRequest.cf?.country ?? request.headers.get("cf-ipcountry") ?? undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isModelCountryRestricted(model: string, country: string | undefined) {
|
||||||
|
return (
|
||||||
|
["muse-spark-1.2-contributor", "muse-spark-1.2-contributor-free"].includes(model) &&
|
||||||
|
country !== undefined &&
|
||||||
|
MUSE_SPARK_BLOCKED_COUNTRIES.has(country.toUpperCase())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import type { APIEvent } from "@solidjs/start/server"
|
||||||
|
import { Workspace } from "@opencode-ai/console-core/workspace.js"
|
||||||
|
import { safeEqual } from "@opencode-ai/console-core/util/crypto.js"
|
||||||
|
import { Resource } from "@opencode-ai/console-resource"
|
||||||
|
import z from "zod"
|
||||||
|
|
||||||
|
const Body = z.object({ workspaceID: z.string().startsWith("wrk_") })
|
||||||
|
|
||||||
|
export async function POST(event: APIEvent) {
|
||||||
|
if (!safeEqual(event.request.headers.get("authorization") ?? "", `Bearer ${Resource.SUPPORT_API_KEY.value}`)) {
|
||||||
|
return Response.json({ error: "Unauthorized" }, { status: 401 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = Body.safeParse(await event.request.json().catch(() => undefined))
|
||||||
|
if (!body.success) {
|
||||||
|
return Response.json({ error: "Invalid request", issues: body.error.issues }, { status: 400 })
|
||||||
|
}
|
||||||
|
return Workspace.unblock(body.data)
|
||||||
|
.then(() => Response.json({ success: true, message: "Workspace unblocked" }))
|
||||||
|
.catch((error) => Response.json({ error: error instanceof Error ? error.message : String(error) }, { status: 400 }))
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { APIEvent } from "@solidjs/start"
|
import type { APIEvent } from "@solidjs/start"
|
||||||
|
import { waitUntil } from "@opencode-ai/console-resource"
|
||||||
import type { DownloadPlatform } from "../types"
|
import type { DownloadPlatform } from "../types"
|
||||||
|
|
||||||
const prodAssetNames: Record<string, string> = {
|
const prodAssetNames: Record<string, string> = {
|
||||||
@@ -30,14 +31,34 @@ export async function GET({ params: { platform, channel } }: APIEvent) {
|
|||||||
const assetName = channel === "stable" ? prodAssetNames[platform] : betaAssetNames[platform]
|
const assetName = channel === "stable" ? prodAssetNames[platform] : betaAssetNames[platform]
|
||||||
if (!assetName) return new Response(null, { status: 404 })
|
if (!assetName) return new Response(null, { status: 404 })
|
||||||
|
|
||||||
const resp = await fetch(
|
const latest = await fetch(
|
||||||
`https://github.com/anomalyco/${channel === "stable" ? "opencode" : "opencode-beta"}/releases/latest/download/${assetName}`,
|
`https://github.com/anomalyco/${channel === "stable" ? "opencode" : "opencode-beta"}/releases/latest/download/${assetName}`,
|
||||||
|
{ redirect: "manual" },
|
||||||
)
|
)
|
||||||
|
const location = latest.headers.get("location")
|
||||||
|
if (!location) return new Response(null, { status: 502 })
|
||||||
|
|
||||||
const downloadName = downloadNames[platform]
|
const key = new Request(location)
|
||||||
|
const cache = (caches as CacheStorage & { default: Cache }).default
|
||||||
|
const cached = await cache.match(key)
|
||||||
|
if (cached) return download(cached, platform, "HIT")
|
||||||
|
|
||||||
|
const resp = await fetch(location)
|
||||||
|
if (!resp.ok) return resp
|
||||||
|
|
||||||
|
const headers = new Headers(resp.headers)
|
||||||
|
headers.set("cache-control", "public, max-age=31536000, immutable")
|
||||||
|
headers.delete("set-cookie")
|
||||||
|
const result = new Response(resp.body, { status: resp.status, statusText: resp.statusText, headers })
|
||||||
|
waitUntil(cache.put(key, result.clone()))
|
||||||
|
return download(result, platform, "MISS")
|
||||||
|
}
|
||||||
|
|
||||||
|
function download(resp: Response, platform: string, cache: "HIT" | "MISS") {
|
||||||
|
const downloadName = downloadNames[platform]
|
||||||
const headers = new Headers(resp.headers)
|
const headers = new Headers(resp.headers)
|
||||||
if (downloadName) headers.set("content-disposition", `attachment; filename="${downloadName}"`)
|
if (downloadName) headers.set("content-disposition", `attachment; filename="${downloadName}"`)
|
||||||
|
headers.set("x-opencode-cache", cache)
|
||||||
|
|
||||||
return new Response(resp.body, { status: resp.status, statusText: resp.statusText, headers })
|
return new Response(resp.body, { status: resp.status, statusText: resp.statusText, headers })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -592,6 +592,16 @@ body {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:is([data-regions], [data-limited]) {
|
||||||
|
color: var(--color-text-weak);
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[data-value] {
|
[data-value] {
|
||||||
color: var(--color-text-strong);
|
color: var(--color-text-strong);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@@ -688,6 +698,11 @@ body {
|
|||||||
fill: color-mix(in srgb, var(--bar-go) 50%, transparent);
|
fill: color-mix(in srgb, var(--bar-go) 50%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-item][data-infinite] [data-value] {
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
[data-val] {
|
[data-val] {
|
||||||
fill: var(--color-text-strong);
|
fill: var(--color-text-strong);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|||||||
@@ -25,11 +25,13 @@ const checkLoggedIn = query(async () => {
|
|||||||
const models = [
|
const models = [
|
||||||
{ name: "Grok 4.5", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention30" },
|
{ 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: "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.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: "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" },
|
{ name: "Kimi K3", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
||||||
{ name: "Kimi K2.7 Code", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
{ name: "Kimi K2.7 Code", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
||||||
{ name: "Kimi K2.6", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
{ name: "Kimi K2.6", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
||||||
|
{ name: "LongCat-2.0", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
||||||
{ name: "MiMo-V2.5-Pro", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
{ name: "MiMo-V2.5-Pro", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
||||||
{ name: "MiMo-V2.5", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
{ name: "MiMo-V2.5", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
||||||
{ name: "Qwen3.8 Max", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
{ name: "Qwen3.8 Max", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
||||||
@@ -38,6 +40,7 @@ const models = [
|
|||||||
{ name: "Qwen3.6 Plus", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
{ 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 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: "MiniMax M2.7", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
||||||
|
{ name: "Muse Spark 1.2 Contributor", 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 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: "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" },
|
{ name: "Hy3", training: "go.faq.a5.notUsed", retention: "go.faq.a5.retention0" },
|
||||||
@@ -66,24 +69,19 @@ function LimitsGraph(props: { href: string }) {
|
|||||||
|
|
||||||
const baseline = 100
|
const baseline = 100
|
||||||
const graph = [
|
const graph = [
|
||||||
{ id: "grok-4.5", name: "Grok 4.5", req: 120, d: "50ms" },
|
{ id: "kimi-k3", name: "Kimi K3", req: 110, d: "50ms" },
|
||||||
{ id: "kimi-k3", name: "Kimi K3", req: 110, d: "75ms" },
|
{ id: "grok-4.5", name: "Grok 4.5", req: 120, d: "75ms" },
|
||||||
{ id: "qwen3.8-max", name: "Qwen3.8 Max", req: 160, d: "90ms" },
|
{ 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: "glm-5.2", name: "GLM-5.2", req: 880, d: "100ms" },
|
||||||
|
{ id: "gpt-5.6-luna", name: "GPT 5.6 Luna", req: 2050, d: "290ms" },
|
||||||
{ id: "minimax-m3", name: "MiniMax M3", req: 3200, d: "210ms" },
|
{ 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: "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: "longcat-2.0", name: "LongCat-2.0", req: 11400, d: "335ms" },
|
||||||
{ id: "mimo-v2.5", name: "MiMo-V2.5", req: 30100, d: "340ms" },
|
{ id: "mimo-v2.5", name: "MiMo-V2.5", req: 30100, d: "340ms" },
|
||||||
{
|
{ id: "hy3", name: "Hy3", req: 34400, baseReq: 4300, d: "320ms" },
|
||||||
id: "deepseek-v4-flash",
|
{ id: "muse-spark-1.2-contributor", name: "Muse Spark 1.2 Contributor", req: 45300, edge: true, d: "360ms" },
|
||||||
name: "DeepSeek V4 Flash",
|
{ id: "ox-alpha-free", name: "Ox Alpha Free", req: Infinity, infinite: true, edge: true, d: "400ms" },
|
||||||
req: 63300,
|
|
||||||
baseReq: 31650,
|
|
||||||
edge: true,
|
|
||||||
d: "340ms",
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
const w = 1040
|
const w = 1040
|
||||||
@@ -93,9 +91,10 @@ function LimitsGraph(props: { href: string }) {
|
|||||||
const top = 18
|
const top = 18
|
||||||
const bottom = 44
|
const bottom = 44
|
||||||
const plot = chartW - left - right
|
const plot = chartW - left - right
|
||||||
|
const infiniteX = w - 180
|
||||||
|
|
||||||
const ratio = (n: number) => n / baseline
|
const ratio = (n: number) => n / baseline
|
||||||
const rmax = Math.max(1, ...graph.map((m) => ratio(m.req)))
|
const rmax = Math.max(1, ...graph.filter((m) => !("infinite" in m)).map((m) => ratio(m.req)))
|
||||||
const log = (n: number) => Math.log10(Math.max(n, 1))
|
const log = (n: number) => Math.log10(Math.max(n, 1))
|
||||||
const base = 24
|
const base = 24
|
||||||
const p = 2.2
|
const p = 2.2
|
||||||
@@ -157,10 +156,10 @@ function LimitsGraph(props: { href: string }) {
|
|||||||
<rect
|
<rect
|
||||||
x={left}
|
x={left}
|
||||||
y={gy(i()) - bh / 2}
|
y={gy(i()) - bh / 2}
|
||||||
width={Math.max(0, x(ratio(m.baseReq ?? m.req)) - left)}
|
width={Math.max(0, ("infinite" in m ? infiniteX : x(ratio(m.baseReq ?? m.req))) - left)}
|
||||||
height={bh}
|
height={bh}
|
||||||
data-bar
|
data-bar
|
||||||
data-kind="go"
|
data-kind={"infinite" in m ? "infinite" : "go"}
|
||||||
data-model={m.id}
|
data-model={m.id}
|
||||||
/>
|
/>
|
||||||
{m.baseReq && (
|
{m.baseReq && (
|
||||||
@@ -196,7 +195,7 @@ function LimitsGraph(props: { href: string }) {
|
|||||||
</For>
|
</For>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-slot="pills" aria-hidden="true">
|
<div data-slot="pills">
|
||||||
<For each={graph}>
|
<For each={graph}>
|
||||||
{(m, i) => (
|
{(m, i) => (
|
||||||
<span
|
<span
|
||||||
@@ -204,11 +203,24 @@ function LimitsGraph(props: { href: string }) {
|
|||||||
data-kind="go"
|
data-kind="go"
|
||||||
data-model={m.id}
|
data-model={m.id}
|
||||||
data-edge={"edge" in m ? "" : undefined}
|
data-edge={"edge" in m ? "" : undefined}
|
||||||
style={{ "--x": px(x(ratio(m.req))), "--y": py(gy(i())), "--d": m.d } as any}
|
data-infinite={"infinite" in m ? "" : undefined}
|
||||||
|
style={
|
||||||
|
{ "--x": px("infinite" in m ? infiniteX : x(ratio(m.req))), "--y": py(gy(i())), "--d": m.d } as any
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<span data-value>{m.req.toLocaleString()}</span>
|
<span data-value>{"infinite" in m ? "∞" : m.req.toLocaleString()}</span>
|
||||||
<span data-name>{m.name}</span>
|
<span data-name>{m.name}</span>
|
||||||
{m.baseReq && <span data-bonus>2x usage</span>}
|
{m.id === "muse-spark-1.2-contributor" && (
|
||||||
|
<span data-regions>
|
||||||
|
(
|
||||||
|
<a href="https://ai.developer.meta.com/legal/geographic-use-policy">
|
||||||
|
{i18n.t("go.graph.limitedRegions")}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{"infinite" in m && <span data-limited>({i18n.t("go.graph.limitedTime")})</span>}
|
||||||
|
{m.baseReq && <span data-bonus>8x usage</span>}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
@@ -364,12 +376,7 @@ export default function Home() {
|
|||||||
{(part) => {
|
{(part) => {
|
||||||
if (part === "{{text}}") return <span>{i18n.t("go.cta.text")}</span>
|
if (part === "{{text}}") return <span>{i18n.t("go.cta.text")}</span>
|
||||||
if (part === "{{price}}") {
|
if (part === "{{price}}") {
|
||||||
return (
|
return <span data-slot="cta-price">{i18n.t("go.cta.price")}</span>
|
||||||
<span data-slot="cta-price">
|
|
||||||
<span data-slot="cta-price-old">{i18n.t("go.cta.price")}</span>
|
|
||||||
<span data-slot="cta-price-new">{i18n.t("go.cta.promo")}</span>
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return part
|
return part
|
||||||
}}
|
}}
|
||||||
@@ -517,6 +524,13 @@ export default function Home() {
|
|||||||
</a>
|
</a>
|
||||||
.
|
.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Muse Spark 1.2 Contributor:</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>
|
<p>
|
||||||
<strong>DeepSeek V4 Flash:</strong> {i18n.t("go.faq.a5.deepseekRetention")}
|
<strong>DeepSeek V4 Flash:</strong> {i18n.t("go.faq.a5.deepseekRetention")}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -237,9 +237,8 @@ export default function PrivacyPolicy() {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Providing, Customizing and Improving the Services</li>
|
<li>Passing through to upstream provider to provide services</li>
|
||||||
<li>Marketing the Services</li>
|
<li>Not stored</li>
|
||||||
<li>Corresponding with You</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -106,6 +106,7 @@
|
|||||||
|
|
||||||
[data-slot="setting-row"] {
|
[data-slot="setting-row"] {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
|
padding-block: var(--space-2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export const queryLiteSubscription = query(async (workspaceID: string) => {
|
|||||||
timeCreated: LiteTable.timeCreated,
|
timeCreated: LiteTable.timeCreated,
|
||||||
lite: BillingTable.lite,
|
lite: BillingTable.lite,
|
||||||
region: WorkspaceTable.region,
|
region: WorkspaceTable.region,
|
||||||
|
allowTraining: WorkspaceTable.allow_training,
|
||||||
})
|
})
|
||||||
.from(BillingTable)
|
.from(BillingTable)
|
||||||
.innerJoin(LiteTable, eq(LiteTable.workspaceID, BillingTable.workspaceID))
|
.innerJoin(LiteTable, eq(LiteTable.workspaceID, BillingTable.workspaceID))
|
||||||
@@ -54,6 +55,7 @@ export const queryLiteSubscription = query(async (workspaceID: string) => {
|
|||||||
return {
|
return {
|
||||||
mine,
|
mine,
|
||||||
useBalance: row.lite?.useBalance ?? false,
|
useBalance: row.lite?.useBalance ?? false,
|
||||||
|
allowTraining: row.allowTraining ?? false,
|
||||||
region:
|
region:
|
||||||
row.region ?? (await Workspace.setDefaultRegion({ country: countryFromRequest(getRequestEvent()?.request) })),
|
row.region ?? (await Workspace.setDefaultRegion({ country: countryFromRequest(getRequestEvent()?.request) })),
|
||||||
rollingUsage: Subscription.analyzeRollingUsage({
|
rollingUsage: Subscription.analyzeRollingUsage({
|
||||||
@@ -154,6 +156,24 @@ const setGoProviderRouting = action(async (form: FormData) => {
|
|||||||
)
|
)
|
||||||
}, "go.providerRouting.set")
|
}, "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 } }) {
|
function LiteUsageItem(props: { label: string; usage: { usagePercent: number; resetInSec: number } }) {
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
|
|
||||||
@@ -186,6 +206,7 @@ export function LiteSection(props: { lite: LiteSubscription | undefined }) {
|
|||||||
const checkoutSubmission = useSubmission(createLiteCheckoutUrl)
|
const checkoutSubmission = useSubmission(createLiteCheckoutUrl)
|
||||||
const useBalanceSubmission = useSubmission(setLiteUseBalance)
|
const useBalanceSubmission = useSubmission(setLiteUseBalance)
|
||||||
const providerRoutingSubmission = useSubmission(setGoProviderRouting)
|
const providerRoutingSubmission = useSubmission(setGoProviderRouting)
|
||||||
|
const allowTrainingSubmission = useSubmission(setGoAllowTraining)
|
||||||
const [store, setStore] = createStore({
|
const [store, setStore] = createStore({
|
||||||
loading: undefined as undefined | "session" | "checkout" | "alipay" | "upi",
|
loading: undefined as undefined | "session" | "checkout" | "alipay" | "upi",
|
||||||
showModal: false,
|
showModal: false,
|
||||||
@@ -264,6 +285,20 @@ export function LiteSection(props: { lite: LiteSubscription | undefined }) {
|
|||||||
<h3>{i18n.t("workspace.lite.providers.title")}</h3>
|
<h3>{i18n.t("workspace.lite.providers.title")}</h3>
|
||||||
<p>{i18n.t("workspace.lite.providers.description")}</p>
|
<p>{i18n.t("workspace.lite.providers.description")}</p>
|
||||||
</div>
|
</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">
|
<form action={setGoProviderRouting} method="post" data-slot="setting-row">
|
||||||
<p>{i18n.t("workspace.lite.providers.useChina")}</p>
|
<p>{i18n.t("workspace.lite.providers.useChina")}</p>
|
||||||
<input type="hidden" name="workspaceID" value={params.id} />
|
<input type="hidden" name="workspaceID" value={params.id} />
|
||||||
@@ -306,22 +341,27 @@ export function LiteSection(props: { lite: LiteSubscription | undefined }) {
|
|||||||
<ul data-slot="promo-models">
|
<ul data-slot="promo-models">
|
||||||
<li>Grok 4.5</li>
|
<li>Grok 4.5</li>
|
||||||
<li>GPT 5.6 Luna</li>
|
<li>GPT 5.6 Luna</li>
|
||||||
|
<li>GLM-5.3</li>
|
||||||
<li>GLM-5.2</li>
|
<li>GLM-5.2</li>
|
||||||
<li>GLM-5.1</li>
|
<li>GLM-5.1</li>
|
||||||
<li>Kimi K3</li>
|
<li>Kimi K3</li>
|
||||||
<li>Kimi K2.7 Code</li>
|
<li>Kimi K2.7 Code</li>
|
||||||
<li>Kimi K2.6</li>
|
<li>Kimi K2.6</li>
|
||||||
|
<li>LongCat-2.0</li>
|
||||||
<li>MiniMax M3</li>
|
<li>MiniMax M3</li>
|
||||||
<li>MiniMax M2.7</li>
|
<li>MiniMax M2.7</li>
|
||||||
|
<li>Muse Spark 1.2 Contributor</li>
|
||||||
<li>Qwen3.8 Max</li>
|
<li>Qwen3.8 Max</li>
|
||||||
<li>Qwen3.7 Max</li>
|
<li>Qwen3.7 Max</li>
|
||||||
<li>Qwen3.7 Plus</li>
|
<li>Qwen3.7 Plus</li>
|
||||||
<li>Qwen3.6 Plus</li>
|
<li>Qwen3.6 Plus</li>
|
||||||
<li>DeepSeek V4 Pro</li>
|
<li>DeepSeek V4 Pro</li>
|
||||||
<li>DeepSeek V4 Flash</li>
|
<li>DeepSeek V4 Flash</li>
|
||||||
|
<li>DeepSeek V4 Flash Vision Exp</li>
|
||||||
<li>MiMo-V2.5</li>
|
<li>MiMo-V2.5</li>
|
||||||
<li>MiMo-V2.5-Pro</li>
|
<li>MiMo-V2.5-Pro</li>
|
||||||
<li>Hy3</li>
|
<li>Hy3</li>
|
||||||
|
<li>Ox Alpha Free</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p data-slot="promo-description">{i18n.t("workspace.lite.promo.footer")}</p>
|
<p data-slot="promo-description">{i18n.t("workspace.lite.promo.footer")}</p>
|
||||||
<div data-slot="subscribe-actions">
|
<div data-slot="subscribe-actions">
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export class MonthlyLimitError extends Error {}
|
|||||||
export class UserLimitError extends Error {}
|
export class UserLimitError extends Error {}
|
||||||
export class ModelError extends Error {}
|
export class ModelError extends Error {}
|
||||||
export class RegionError extends Error {}
|
export class RegionError extends Error {}
|
||||||
|
export class DataPolicyError extends Error {}
|
||||||
|
|
||||||
class LimitError extends Error {
|
class LimitError extends Error {
|
||||||
retryAfter?: number
|
retryAfter?: number
|
||||||
|
|||||||
@@ -22,18 +22,13 @@ import {
|
|||||||
UserLimitError,
|
UserLimitError,
|
||||||
ModelError,
|
ModelError,
|
||||||
RegionError,
|
RegionError,
|
||||||
|
DataPolicyError,
|
||||||
RateLimitError,
|
RateLimitError,
|
||||||
FreeUsageLimitError,
|
FreeUsageLimitError,
|
||||||
GoUsageLimitError,
|
GoUsageLimitError,
|
||||||
BlackUsageLimitError,
|
BlackUsageLimitError,
|
||||||
} from "./error"
|
} from "./error"
|
||||||
import {
|
import { buildCostChunk, createStreamPartConverter, createResponseConverter, UsageInfo } from "./provider/provider"
|
||||||
buildCostChunk,
|
|
||||||
createBodyConverter,
|
|
||||||
createStreamPartConverter,
|
|
||||||
createResponseConverter,
|
|
||||||
UsageInfo,
|
|
||||||
} from "./provider/provider"
|
|
||||||
import { anthropicHelper } from "./provider/anthropic"
|
import { anthropicHelper } from "./provider/anthropic"
|
||||||
import { googleHelper } from "./provider/google"
|
import { googleHelper } from "./provider/google"
|
||||||
import { openaiHelper } from "./provider/openai"
|
import { openaiHelper } from "./provider/openai"
|
||||||
@@ -51,13 +46,12 @@ import { createModelTpsLimiter } from "./modelTpsLimiter"
|
|||||||
import { createProviderBudgetTracker } from "./providerBudgetTracker"
|
import { createProviderBudgetTracker } from "./providerBudgetTracker"
|
||||||
import { accumulateUsage, HOT_WORKSPACES } from "./usageBatcher"
|
import { accumulateUsage, HOT_WORKSPACES } from "./usageBatcher"
|
||||||
import { Workspace } from "@opencode-ai/console-core/workspace.js"
|
import { Workspace } from "@opencode-ai/console-core/workspace.js"
|
||||||
import { countryFromRequest } from "~/lib/request-country"
|
import { countryFromRequest, isModelCountryRestricted } from "~/lib/request-country"
|
||||||
|
import { isPeakPricing } from "./pricing"
|
||||||
|
import { prepareRequestBody } from "./requestBody"
|
||||||
|
|
||||||
type ZenData = Awaited<ReturnType<typeof ZenData.list>>
|
type ZenData = Awaited<ReturnType<typeof ZenData.list>>
|
||||||
type RetryOptions = {
|
type PreparedBody = Awaited<ReturnType<typeof prepareRequestBody>>
|
||||||
excludeProviders: string[]
|
|
||||||
retryCount: number
|
|
||||||
}
|
|
||||||
type BillingSource = "anonymous" | "free" | "byok" | "subscription" | "lite" | "balance"
|
type BillingSource = "anonymous" | "free" | "byok" | "subscription" | "lite" | "balance"
|
||||||
|
|
||||||
function resolve(text: string, params?: Record<string, string | number>) {
|
function resolve(text: string, params?: Record<string, string | number>) {
|
||||||
@@ -85,8 +79,6 @@ export async function handler(
|
|||||||
type ProviderInfo = Awaited<ReturnType<typeof selectProvider>>
|
type ProviderInfo = Awaited<ReturnType<typeof selectProvider>>
|
||||||
type CostInfo = ReturnType<typeof calculateCost>
|
type CostInfo = ReturnType<typeof calculateCost>
|
||||||
|
|
||||||
const MAX_FAILOVER_RETRIES = 3
|
|
||||||
const MAX_RETRYABLE_STATUS_RETRIES = 3
|
|
||||||
const dict = i18n(localeFromRequest(input.request))
|
const dict = i18n(localeFromRequest(input.request))
|
||||||
const t = (key: Key, params?: Record<string, string | number>) => resolve(dict[key], params)
|
const t = (key: Key, params?: Record<string, string | number>) => resolve(dict[key], params)
|
||||||
const ADMIN_WORKSPACES = [
|
const ADMIN_WORKSPACES = [
|
||||||
@@ -95,12 +87,14 @@ export async function handler(
|
|||||||
"wrk_01KKZDKDWCS1VTJF8QTX62DD50", // contributors
|
"wrk_01KKZDKDWCS1VTJF8QTX62DD50", // contributors
|
||||||
]
|
]
|
||||||
|
|
||||||
|
let requestBody: PreparedBody | undefined
|
||||||
try {
|
try {
|
||||||
const url = input.request.url
|
const url = input.request.url
|
||||||
const body = await input.request.json()
|
const body = input.request.body
|
||||||
const model = opts.parseModel(url, body)
|
if (!body) throw new Error("Missing request body")
|
||||||
const variant = opts.parseVariant(url, body)
|
requestBody = opts.format === "google" ? undefined : await prepareRequestBody(body)
|
||||||
const isStream = opts.parseIsStream(url, body)
|
const model = opts.format === "google" ? opts.parseModel(url, undefined) : (requestBody?.model ?? "")
|
||||||
|
const googleStream = opts.format === "google" ? opts.parseIsStream(url, undefined) : undefined
|
||||||
const rawIp = input.request.headers.get("x-real-ip") ?? ""
|
const rawIp = input.request.headers.get("x-real-ip") ?? ""
|
||||||
const ip = rawIp.includes(":") ? rawIp.split(":").slice(0, 4).join(":") : rawIp
|
const ip = rawIp.includes(":") ? rawIp.split(":").slice(0, 4).join(":") : rawIp
|
||||||
const rawZenApiKey = opts.parseApiKey(input.request.headers)
|
const rawZenApiKey = opts.parseApiKey(input.request.headers)
|
||||||
@@ -111,16 +105,16 @@ export async function handler(
|
|||||||
const projectId = input.request.headers.get("x-opencode-project") ?? ""
|
const projectId = input.request.headers.get("x-opencode-project") ?? ""
|
||||||
const userAgent = input.request.headers.get("user-agent") ?? ""
|
const userAgent = input.request.headers.get("user-agent") ?? ""
|
||||||
logger.metric({
|
logger.metric({
|
||||||
is_stream: isStream,
|
|
||||||
session: sessionId,
|
session: sessionId,
|
||||||
request: requestId,
|
request: requestId,
|
||||||
client: ocClient,
|
client: ocClient,
|
||||||
user_agent: userAgent,
|
user_agent: userAgent,
|
||||||
"model.variant": variant,
|
|
||||||
"model.tier": opts.modelList === "full" ? "zen" : "go",
|
"model.tier": opts.modelList === "full" ? "zen" : "go",
|
||||||
})
|
})
|
||||||
const zenData = ZenData.list(opts.modelList)
|
const zenData = ZenData.list(opts.modelList)
|
||||||
const modelInfo = validateModel(zenData, model)
|
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 trialLimiter = createTrialLimiter(modelInfo.trialProvider, ip)
|
||||||
const trialProviders = await trialLimiter?.check()
|
const trialProviders = await trialLimiter?.check()
|
||||||
const rateLimiter = modelInfo.allowAnonymous
|
const rateLimiter = modelInfo.allowAnonymous
|
||||||
@@ -128,12 +122,23 @@ export async function handler(
|
|||||||
: createKeyRateLimiter(modelInfo.id, modelInfo.rateLimit, zenApiKey, input.request)
|
: createKeyRateLimiter(modelInfo.id, modelInfo.rateLimit, zenApiKey, input.request)
|
||||||
await rateLimiter?.check()
|
await rateLimiter?.check()
|
||||||
const authInfo = await authenticate(modelInfo, zenApiKey)
|
const authInfo = await authenticate(modelInfo, zenApiKey)
|
||||||
|
if (
|
||||||
|
authInfo &&
|
||||||
|
opts.modelList === "lite" &&
|
||||||
|
modelInfo.id === "muse-spark-1.2-contributor" &&
|
||||||
|
!authInfo.allowTraining
|
||||||
|
)
|
||||||
|
throw new DataPolicyError(
|
||||||
|
t("zen.api.error.trainingNotAllowed", {
|
||||||
|
consoleGoUrl: `https://opencode.ai/workspace/${authInfo.workspaceID}/go`,
|
||||||
|
}),
|
||||||
|
)
|
||||||
const allowedRegions = authInfo?.region
|
const allowedRegions = authInfo?.region
|
||||||
? authInfo.region
|
? authInfo.region
|
||||||
: await (async () => {
|
: await (async () => {
|
||||||
if (!authInfo) return
|
if (!authInfo) return
|
||||||
return Actor.provide("system", { workspaceID: authInfo.workspaceID }, () =>
|
return Actor.provide("system", { workspaceID: authInfo.workspaceID }, () =>
|
||||||
Workspace.setDefaultRegion({ country: countryFromRequest(input.request) }),
|
Workspace.setDefaultRegion({ country }),
|
||||||
)
|
)
|
||||||
})()
|
})()
|
||||||
if (
|
if (
|
||||||
@@ -161,7 +166,7 @@ export async function handler(
|
|||||||
)
|
)
|
||||||
const providerBudget = await providerBudgetTracker?.check()
|
const providerBudget = await providerBudgetTracker?.check()
|
||||||
|
|
||||||
const retriableRequest = async (retry: RetryOptions = { excludeProviders: [], retryCount: 0 }) => {
|
const providerRequest = async () => {
|
||||||
const providerInfo = selectProvider(
|
const providerInfo = selectProvider(
|
||||||
model,
|
model,
|
||||||
zenData,
|
zenData,
|
||||||
@@ -169,7 +174,6 @@ export async function handler(
|
|||||||
modelInfo,
|
modelInfo,
|
||||||
stickyId,
|
stickyId,
|
||||||
trialProviders,
|
trialProviders,
|
||||||
retry,
|
|
||||||
stickyProvider,
|
stickyProvider,
|
||||||
modelTpmLimits,
|
modelTpmLimits,
|
||||||
modelTpsLimits,
|
modelTpsLimits,
|
||||||
@@ -185,80 +189,67 @@ export async function handler(
|
|||||||
})
|
})
|
||||||
|
|
||||||
const startTimestamp = Date.now()
|
const startTimestamp = Date.now()
|
||||||
const reqUrl = providerInfo.modifyUrl(providerInfo.api, isStream)
|
const reqUrl = providerInfo.modifyUrl(providerInfo.api, googleStream ?? false)
|
||||||
const reqBody = JSON.stringify(
|
const specialAnthropic =
|
||||||
providerInfo.modifyBody({
|
providerInfo.format === "anthropic" &&
|
||||||
...createBodyConverter(opts.format, providerInfo.format)(body),
|
(providerInfo.model.startsWith("arn:aws:bedrock:") ||
|
||||||
model: providerInfo.model,
|
providerInfo.model.startsWith("global.anthropic.") ||
|
||||||
...(() => {
|
providerInfo.model.startsWith("databricks-claude-"))
|
||||||
const replacer = (obj: Record<string, any>): Record<string, any> =>
|
if (providerInfo.format !== opts.format) throw new Error("Zen provider format must match request format")
|
||||||
Object.fromEntries(
|
if (specialAnthropic) throw new Error("Anthropic provider body modifiers are incompatible with streaming")
|
||||||
Object.entries(obj).flatMap(([k, v]) => {
|
const prepared = requestBody
|
||||||
if (Array.isArray(v)) return [[k, v]]
|
|
||||||
if (typeof v === "object") return [[k, replacer(v)]]
|
const reqBody = (() => {
|
||||||
if (typeof v === "string") {
|
if (opts.format === "google") return body
|
||||||
if (v === "$workspace") return authInfo?.workspaceID ? [[k, authInfo.workspaceID]] : []
|
if (!prepared) throw new Error("Missing prepared request body")
|
||||||
if (v === "$org")
|
return prepared.stream(providerInfo.model, providerInfo.format === "oa-compat")
|
||||||
return authInfo?.workspaceID ? [[k, authInfo.workspaceID.replace("wrk_", "org_")]] : []
|
})()
|
||||||
if (v === "$user") return stickyId ? [[k, stickyId]] : []
|
|
||||||
if (v.startsWith("$header.")) {
|
|
||||||
const headerValue = input.request.headers.get(v.slice(8))
|
|
||||||
return headerValue ? [[k, headerValue]] : []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [[k, v]]
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
return replacer(providerInfo.payloadModifier ?? {})
|
|
||||||
})(),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
logger.debug("REQUEST URL: " + reqUrl)
|
logger.debug("REQUEST URL: " + reqUrl)
|
||||||
logger.debug("REQUEST: " + reqBody.substring(0, 300) + "...")
|
logger.debug("REQUEST: " + (requestBody?.preview ?? "") + "...")
|
||||||
const isNewInference =
|
const isNewInference =
|
||||||
providerInfo.id.startsWith("console.") ||
|
providerInfo.id.startsWith("console.") ||
|
||||||
providerInfo.id.startsWith("console-go.") ||
|
providerInfo.id.startsWith("console-go.") ||
|
||||||
providerInfo.id.startsWith("inf.") ||
|
providerInfo.id.startsWith("inf.") ||
|
||||||
providerInfo.id.startsWith("inf-go.")
|
providerInfo.id.startsWith("inf-go.")
|
||||||
const res = await fetchWithRetryableStatus(
|
const res = await fetch(reqUrl, {
|
||||||
reqUrl,
|
method: "POST",
|
||||||
{
|
headers: (() => {
|
||||||
method: "POST",
|
const headers = new Headers(input.request.headers)
|
||||||
headers: (() => {
|
providerInfo.modifyHeaders(headers, providerInfo.apiKey, stickyId)
|
||||||
const headers = new Headers(input.request.headers)
|
Object.entries(providerInfo.headerModifier ?? {}).forEach(([k, v]) => {
|
||||||
providerInfo.modifyHeaders(headers, providerInfo.apiKey, stickyId)
|
if (v === "$ip") return headers.set(k, ip)
|
||||||
Object.entries(providerInfo.headerModifier ?? {}).forEach(([k, v]) => {
|
if (v === "$caller") return headers.set(k, stickyId)
|
||||||
if (v === "$ip") return headers.set(k, ip)
|
if (v === "$session") return headers.set(k, sessionId)
|
||||||
if (v === "$caller") return headers.set(k, stickyId)
|
if (v === "$model") return headers.set(k, model)
|
||||||
if (v === "$session") return headers.set(k, sessionId)
|
if (v === "$request") return headers.set(k, requestId)
|
||||||
if (v === "$model") return headers.set(k, model)
|
if (v === "$client") return headers.set(k, ocClient)
|
||||||
if (v === "$request") return headers.set(k, requestId)
|
if (v === "$project") return headers.set(k, projectId)
|
||||||
if (v === "$project") return headers.set(k, projectId)
|
if (v === "$workspace") {
|
||||||
if (v === "$workspace") {
|
if (authInfo?.workspaceID) headers.set(k, authInfo.workspaceID)
|
||||||
if (authInfo?.workspaceID) headers.set(k, authInfo.workspaceID)
|
return
|
||||||
return
|
}
|
||||||
}
|
if (v === "$org") {
|
||||||
if (v === "$org") {
|
if (authInfo?.workspaceID) headers.set(k, authInfo.workspaceID.replace("wrk_", "org_"))
|
||||||
if (authInfo?.workspaceID) headers.set(k, authInfo.workspaceID.replace("wrk_", "org_"))
|
return
|
||||||
return
|
}
|
||||||
}
|
headers.set(k, v)
|
||||||
headers.set(k, v)
|
})
|
||||||
})
|
headers.delete("host")
|
||||||
headers.delete("host")
|
headers.delete("content-length")
|
||||||
headers.delete("content-length")
|
headers.delete("x-opencode-request")
|
||||||
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-project")
|
headers.delete("x-opencode-client")
|
||||||
headers.delete("x-opencode-client")
|
return headers
|
||||||
return headers
|
})(),
|
||||||
})(),
|
body: reqBody,
|
||||||
body: reqBody,
|
duplex: "half",
|
||||||
// Propagate caller disconnects to the upstream provider request so
|
// Propagate caller disconnects to the upstream provider request so
|
||||||
// abandoned Console requests do not leave orphaned inference work open.
|
// abandoned Console requests do not leave orphaned inference work open.
|
||||||
signal: input.request.signal,
|
signal: input.request.signal,
|
||||||
},
|
} as RequestInit & { duplex: "half" })
|
||||||
{ count: isNewInference ? MAX_RETRYABLE_STATUS_RETRIES : 0 },
|
const isStream = res.headers.get("content-type")?.toLowerCase().includes("text/event-stream") ?? false
|
||||||
)
|
logger.metric({ is_stream: isStream })
|
||||||
|
|
||||||
if (isNewInference) {
|
if (isNewInference) {
|
||||||
const resEndpointId = res.headers.get("x-opencode-endpoint-id")
|
const resEndpointId = res.headers.get("x-opencode-endpoint-id")
|
||||||
@@ -277,29 +268,10 @@ export async function handler(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try another provider => stop retrying if using fallback provider
|
return { providerInfo, res, startTimestamp, isStream }
|
||||||
if (
|
|
||||||
//!isNewInference &&
|
|
||||||
res.status !== 200 &&
|
|
||||||
// ie. 400 error is usually provider error like malformed request
|
|
||||||
res.status !== 400 &&
|
|
||||||
// ie. openai 404 error: Item with id 'msg_0ead8b004a3b165d0069436a6b6834819896da85b63b196a3f' not found.
|
|
||||||
!(modelInfo.id.startsWith("gpt-") && res.status === 404) &&
|
|
||||||
// ie. cannot change codex model providers mid-session
|
|
||||||
modelInfo.stickyProvider !== "strict" &&
|
|
||||||
modelInfo.fallbackProvider &&
|
|
||||||
providerInfo.id !== modelInfo.fallbackProvider
|
|
||||||
) {
|
|
||||||
return retriableRequest({
|
|
||||||
excludeProviders: [...retry.excludeProviders, providerInfo.id],
|
|
||||||
retryCount: retry.retryCount + 1,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return { providerInfo, reqBody, res, startTimestamp }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { providerInfo, reqBody, res, startTimestamp } = await retriableRequest()
|
const { providerInfo, res, startTimestamp, isStream } = await providerRequest()
|
||||||
|
|
||||||
// Store sticky provider
|
// Store sticky provider
|
||||||
if (res.status === 200) await stickyTracker?.set(providerInfo.id)
|
if (res.status === 200) await stickyTracker?.set(providerInfo.id)
|
||||||
@@ -455,6 +427,8 @@ export async function handler(
|
|||||||
headers: resHeaders,
|
headers: resHeaders,
|
||||||
})
|
})
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
if (requestBody) void requestBody.cancel().catch(() => {})
|
||||||
|
else void input.request.body?.cancel().catch(() => {})
|
||||||
// The caller disconnected before we finished. Because the outbound provider
|
// The caller disconnected before we finished. Because the outbound provider
|
||||||
// request shares input.request.signal, an aborted caller surfaces here as an
|
// request shares input.request.signal, an aborted caller surfaces here as an
|
||||||
// AbortError. There is no client left to receive a body, so skip the error
|
// AbortError. There is no client left to receive a body, so skip the error
|
||||||
@@ -477,7 +451,7 @@ export async function handler(
|
|||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error instanceof RegionError)
|
if (error instanceof RegionError || error instanceof DataPolicyError)
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: "error",
|
type: "error",
|
||||||
@@ -579,7 +553,6 @@ export async function handler(
|
|||||||
modelInfo: ModelInfo,
|
modelInfo: ModelInfo,
|
||||||
stickyId: string,
|
stickyId: string,
|
||||||
trialProviders: string[] | undefined,
|
trialProviders: string[] | undefined,
|
||||||
retry: RetryOptions,
|
|
||||||
stickyProviderId: string | undefined,
|
stickyProviderId: string | undefined,
|
||||||
modelTpmLimits: Record<string, number> | undefined,
|
modelTpmLimits: Record<string, number> | undefined,
|
||||||
modelTpsLimits: Record<string, { qualify: number; unqualify: number }> | undefined,
|
modelTpsLimits: Record<string, { qualify: number; unqualify: number }> | undefined,
|
||||||
@@ -606,14 +579,11 @@ export async function handler(
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use fallback provider if max retries reached
|
|
||||||
const fallbackProvider = allProviders.find((provider) => provider.id === modelInfo.fallbackProvider)
|
const fallbackProvider = allProviders.find((provider) => provider.id === modelInfo.fallbackProvider)
|
||||||
if (retry.retryCount === MAX_FAILOVER_RETRIES) return fallbackProvider
|
|
||||||
|
|
||||||
let topPriority = Infinity
|
let topPriority = Infinity
|
||||||
const providers = allProviders
|
const providers = allProviders
|
||||||
.filter((provider) => provider.weight !== 0)
|
.filter((provider) => provider.weight !== 0)
|
||||||
.filter((provider) => !retry.excludeProviders.includes(provider.id))
|
|
||||||
.filter((provider) => {
|
.filter((provider) => {
|
||||||
if (provider.budgetPriority === undefined) return true
|
if (provider.budgetPriority === undefined) return true
|
||||||
if (!providerBudget) return true
|
if (!providerBudget) return true
|
||||||
@@ -708,6 +678,7 @@ export async function handler(
|
|||||||
workspace: {
|
workspace: {
|
||||||
id: WorkspaceTable.id,
|
id: WorkspaceTable.id,
|
||||||
region: WorkspaceTable.region,
|
region: WorkspaceTable.region,
|
||||||
|
allowTraining: WorkspaceTable.allow_training,
|
||||||
isBlocked: WorkspaceTable.is_blocked,
|
isBlocked: WorkspaceTable.is_blocked,
|
||||||
isFlaggedByAnthropic: WorkspaceTable.is_flagged_by_anthropic,
|
isFlaggedByAnthropic: WorkspaceTable.is_flagged_by_anthropic,
|
||||||
isFlaggedByOpenAI: WorkspaceTable.is_flagged_by_openai,
|
isFlaggedByOpenAI: WorkspaceTable.is_flagged_by_openai,
|
||||||
@@ -820,6 +791,7 @@ export async function handler(
|
|||||||
apiKeyId: data.apiKey,
|
apiKeyId: data.apiKey,
|
||||||
workspaceID: data.workspace.id,
|
workspaceID: data.workspace.id,
|
||||||
region: data.workspace.region,
|
region: data.workspace.region,
|
||||||
|
allowTraining: data.workspace.allowTraining ?? false,
|
||||||
billing: data.billing,
|
billing: data.billing,
|
||||||
user: data.user,
|
user: data.user,
|
||||||
black: data.black,
|
black: data.black,
|
||||||
@@ -894,6 +866,8 @@ export async function handler(
|
|||||||
|
|
||||||
// Validate lite subscription billing
|
// Validate lite subscription billing
|
||||||
if (opts.modelList === "lite" && authInfo.billing.lite && authInfo.lite) {
|
if (opts.modelList === "lite" && authInfo.billing.lite && authInfo.lite) {
|
||||||
|
if (Object.values(modelInfo.cost).every((price) => price === 0)) return "lite"
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const consoleGoUrl = `https://opencode.ai/workspace/${authInfo.workspaceID}/go`
|
const consoleGoUrl = `https://opencode.ai/workspace/${authInfo.workspaceID}/go`
|
||||||
const sub = authInfo.lite
|
const sub = authInfo.lite
|
||||||
@@ -1019,24 +993,17 @@ export async function handler(
|
|||||||
providerInfo.apiKey = authInfo.provider.credentials
|
providerInfo.apiKey = authInfo.provider.credentials
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchWithRetryableStatus(url: string, options: RequestInit, retry = { count: 0 }) {
|
|
||||||
const res = await fetch(url, options)
|
|
||||||
if ([429, 529].includes(res.status) && retry.count < MAX_RETRYABLE_STATUS_RETRIES) {
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, Math.pow(2, retry.count) * 500))
|
|
||||||
return fetchWithRetryableStatus(url, options, { count: retry.count + 1 })
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
function calculateCost(modelInfo: ModelInfo, usageInfo: UsageInfo) {
|
function calculateCost(modelInfo: ModelInfo, usageInfo: UsageInfo) {
|
||||||
const { inputTokens, outputTokens, reasoningTokens, cacheReadTokens, cacheWrite5mTokens, cacheWrite1hTokens } =
|
const { inputTokens, outputTokens, reasoningTokens, cacheReadTokens, cacheWrite5mTokens, cacheWrite1hTokens } =
|
||||||
usageInfo
|
usageInfo
|
||||||
|
|
||||||
const modelCost =
|
const modelCost =
|
||||||
modelInfo.cost200K &&
|
modelInfo.costPeak && isPeakPricing(new Date())
|
||||||
inputTokens + (cacheReadTokens ?? 0) + (cacheWrite5mTokens ?? 0) + (cacheWrite1hTokens ?? 0) > 200_000
|
? modelInfo.costPeak
|
||||||
? modelInfo.cost200K
|
: modelInfo.cost200K &&
|
||||||
: modelInfo.cost
|
inputTokens + (cacheReadTokens ?? 0) + (cacheWrite5mTokens ?? 0) + (cacheWrite1hTokens ?? 0) > 200_000
|
||||||
|
? modelInfo.cost200K
|
||||||
|
: modelInfo.cost
|
||||||
|
|
||||||
const inputCost = modelCost.input * inputTokens * 100
|
const inputCost = modelCost.input * inputTokens * 100
|
||||||
const outputCost = modelCost.output * outputTokens * 100
|
const outputCost = modelCost.output * outputTokens * 100
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export function isPeakPricing(date: Date) {
|
||||||
|
// DeepSeek peak pricing in China Standard Time (UTC+8):
|
||||||
|
// - Weekdays only
|
||||||
|
// - 9 AM to noon
|
||||||
|
// - 2 PM to 6 PM
|
||||||
|
const dateCN = new Date(date.getTime() + 8 * 3_600 * 1000)
|
||||||
|
const dayCN = dateCN.getUTCDay()
|
||||||
|
if (dayCN === 0 || dayCN === 6) return false
|
||||||
|
const hourCN = dateCN.getUTCHours()
|
||||||
|
return (hourCN >= 9 && hourCN < 12) || (hourCN >= 14 && hourCN < 18)
|
||||||
|
}
|
||||||
@@ -0,0 +1,237 @@
|
|||||||
|
const TAIL_LIMIT = 4 * 1024
|
||||||
|
const encoder = new TextEncoder()
|
||||||
|
|
||||||
|
export async function prepareRequestBody(body: ReadableStream<Uint8Array>) {
|
||||||
|
const reader = body.getReader()
|
||||||
|
const chunks: Uint8Array[] = []
|
||||||
|
const decoder = new TextDecoder()
|
||||||
|
let text = ""
|
||||||
|
let done = false
|
||||||
|
let bom = 0
|
||||||
|
let index = 0
|
||||||
|
let depth = 0
|
||||||
|
let stringStart = -1
|
||||||
|
let escaped = false
|
||||||
|
let phase: "key" | "colon" | "value" | "comma" = "key"
|
||||||
|
let key = ""
|
||||||
|
let found: { model: string; start: number; end: number } | undefined
|
||||||
|
|
||||||
|
const scan = () => {
|
||||||
|
while (index < text.length && !found) {
|
||||||
|
const char = text[index]
|
||||||
|
if (stringStart >= 0) {
|
||||||
|
if (escaped) escaped = false
|
||||||
|
else if (char === "\\") escaped = true
|
||||||
|
else if (char === '"') {
|
||||||
|
if (depth === 1 && phase === "key") {
|
||||||
|
key = JSON.parse(text.slice(stringStart, index + 1))
|
||||||
|
phase = "colon"
|
||||||
|
} else if (depth === 1 && phase === "value") {
|
||||||
|
if (key === "model") {
|
||||||
|
const start = bom + utf8Length(text, stringStart + 1)
|
||||||
|
found = {
|
||||||
|
model: JSON.parse(text.slice(stringStart, index + 1)),
|
||||||
|
start,
|
||||||
|
end: bom + utf8Length(text, index),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
phase = "comma"
|
||||||
|
}
|
||||||
|
stringStart = -1
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (char === '"') {
|
||||||
|
stringStart = index++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (char === "{" || char === "[") {
|
||||||
|
if (depth === 1 && phase === "value") phase = "comma"
|
||||||
|
depth++
|
||||||
|
index++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (char === "}" || char === "]") {
|
||||||
|
depth--
|
||||||
|
index++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (depth !== 1) {
|
||||||
|
index++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (char === ":" && phase === "colon") phase = "value"
|
||||||
|
else if (char === "," && phase === "comma") phase = "key"
|
||||||
|
else if (phase === "value" && !/\s/.test(char)) phase = "comma"
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!done && !found) {
|
||||||
|
const next = await reader.read()
|
||||||
|
done = next.done
|
||||||
|
if (!next.value) continue
|
||||||
|
if (!chunks.length && next.value[0] === 0xef && next.value[1] === 0xbb && next.value[2] === 0xbf) bom = 3
|
||||||
|
chunks.push(next.value)
|
||||||
|
text += decoder.decode(next.value, { stream: true })
|
||||||
|
scan()
|
||||||
|
}
|
||||||
|
if (done) {
|
||||||
|
text += decoder.decode()
|
||||||
|
scan()
|
||||||
|
}
|
||||||
|
|
||||||
|
const preview = text.substring(0, 300)
|
||||||
|
text = ""
|
||||||
|
let used = false
|
||||||
|
|
||||||
|
return {
|
||||||
|
model: found?.model ?? "",
|
||||||
|
preview,
|
||||||
|
cancel: () => reader.cancel(),
|
||||||
|
stream(providerModel: string, includeUsage: boolean) {
|
||||||
|
if (used) throw new Error("Request body stream already consumed")
|
||||||
|
if (!found) throw new Error("Missing model field")
|
||||||
|
used = true
|
||||||
|
|
||||||
|
const initial = replace(chunks, found.start, found.end, providerModel)
|
||||||
|
chunks.length = 0
|
||||||
|
const output = passthrough(initial, reader, done)
|
||||||
|
if (!includeUsage) return output
|
||||||
|
return appendUsage(output)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function utf8Length(value: string, end: number) {
|
||||||
|
let length = 0
|
||||||
|
for (let i = 0; i < end; i++) {
|
||||||
|
const code = value.charCodeAt(i)
|
||||||
|
if (code <= 0x7f) length++
|
||||||
|
else if (code <= 0x7ff) length += 2
|
||||||
|
else if (code >= 0xd800 && code <= 0xdbff && i + 1 < end && value.charCodeAt(i + 1) >= 0xdc00) {
|
||||||
|
length += 4
|
||||||
|
i++
|
||||||
|
} else length += 3
|
||||||
|
}
|
||||||
|
return length
|
||||||
|
}
|
||||||
|
|
||||||
|
function replace(chunks: Uint8Array[], start: number, end: number, value: string) {
|
||||||
|
let offset = 0
|
||||||
|
let inserted = false
|
||||||
|
return chunks.flatMap((chunk) => {
|
||||||
|
const chunkStart = offset
|
||||||
|
const chunkEnd = offset + chunk.length
|
||||||
|
offset = chunkEnd
|
||||||
|
if (chunkEnd <= start || chunkStart >= end) return [chunk]
|
||||||
|
|
||||||
|
const parts = [chunk.subarray(0, Math.max(0, start - chunkStart))]
|
||||||
|
if (!inserted) {
|
||||||
|
parts.push(encoder.encode(value))
|
||||||
|
inserted = true
|
||||||
|
}
|
||||||
|
parts.push(chunk.subarray(Math.min(chunk.length, end - chunkStart)))
|
||||||
|
return parts.filter((part) => part.length)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function passthrough(
|
||||||
|
initial: Array<Uint8Array | undefined>,
|
||||||
|
reader: ReadableStreamDefaultReader<Uint8Array>,
|
||||||
|
sourceDone: boolean,
|
||||||
|
) {
|
||||||
|
let done = sourceDone
|
||||||
|
let index = 0
|
||||||
|
return new ReadableStream<Uint8Array>({
|
||||||
|
async pull(controller) {
|
||||||
|
const chunk = initial[index]
|
||||||
|
if (chunk) {
|
||||||
|
initial[index++] = undefined
|
||||||
|
controller.enqueue(chunk)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
initial.length = 0
|
||||||
|
if (done) {
|
||||||
|
controller.close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const next = await reader.read()
|
||||||
|
done = next.done
|
||||||
|
if (next.value) controller.enqueue(next.value)
|
||||||
|
if (done) controller.close()
|
||||||
|
},
|
||||||
|
cancel(reason) {
|
||||||
|
initial.length = 0
|
||||||
|
return reader.cancel(reason)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendUsage(body: ReadableStream<Uint8Array>) {
|
||||||
|
const reader = body.getReader()
|
||||||
|
const decoder = new TextDecoder()
|
||||||
|
let tail = new Uint8Array()
|
||||||
|
let streamText = ""
|
||||||
|
let isStream = false
|
||||||
|
const inspect = (chunk?: Uint8Array) => {
|
||||||
|
streamText += chunk ? decoder.decode(chunk, { stream: true }) : decoder.decode()
|
||||||
|
for (const match of streamText.matchAll(/"stream"\s*:\s*(true|false)/g)) isStream = match[1] === "true"
|
||||||
|
streamText = streamText.slice(-64)
|
||||||
|
}
|
||||||
|
return new ReadableStream<Uint8Array>({
|
||||||
|
async pull(controller) {
|
||||||
|
while (true) {
|
||||||
|
const next = await reader.read()
|
||||||
|
if (next.done) {
|
||||||
|
inspect()
|
||||||
|
if (!isStream) {
|
||||||
|
if (tail.length) controller.enqueue(tail)
|
||||||
|
controller.close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const close = tail.lastIndexOf(125)
|
||||||
|
if (close < 0) {
|
||||||
|
controller.error(new Error("Invalid JSON request body"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (close) controller.enqueue(tail.subarray(0, close))
|
||||||
|
controller.enqueue(encoder.encode(',"stream_options":{"include_usage":true}}'))
|
||||||
|
if (close + 1 < tail.length) controller.enqueue(tail.subarray(close + 1))
|
||||||
|
controller.close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const chunk = next.value
|
||||||
|
inspect(chunk)
|
||||||
|
if (tail.length + chunk.length <= TAIL_LIMIT) {
|
||||||
|
const combined = new Uint8Array(tail.length + chunk.length)
|
||||||
|
combined.set(tail)
|
||||||
|
combined.set(chunk, tail.length)
|
||||||
|
tail = combined
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = tail.length + chunk.length - TAIL_LIMIT
|
||||||
|
if (emit <= tail.length) {
|
||||||
|
controller.enqueue(tail.subarray(0, emit))
|
||||||
|
const combined = new Uint8Array(TAIL_LIMIT)
|
||||||
|
combined.set(tail.subarray(emit))
|
||||||
|
combined.set(chunk, tail.length - emit)
|
||||||
|
tail = combined
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tail.length) controller.enqueue(tail)
|
||||||
|
controller.enqueue(chunk.subarray(0, emit - tail.length))
|
||||||
|
tail = chunk.slice(emit - tail.length)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancel(reason) {
|
||||||
|
return reader.cancel(reason)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { describe, expect, test } from "bun:test"
|
||||||
|
import { isPeakPricing } from "../src/routes/zen/util/pricing"
|
||||||
|
|
||||||
|
describe("isPeakPricing", () => {
|
||||||
|
test.each([
|
||||||
|
["weekday 09:00 CN starts peak pricing", "2026-08-27T01:00:00.000Z", true],
|
||||||
|
["weekday 12:00 CN ends peak pricing", "2026-08-27T04:00:00.000Z", false],
|
||||||
|
["weekday 14:00 CN starts peak pricing", "2026-08-27T06:00:00.000Z", true],
|
||||||
|
["weekday 18:00 CN ends peak pricing", "2026-08-27T10:00:00.000Z", false],
|
||||||
|
["Saturday in Beijing", "2026-08-29T01:00:00.000Z", false],
|
||||||
|
["Sunday in Beijing", "2026-08-30T06:00:00.000Z", false],
|
||||||
|
["Monday in Beijing", "2026-08-31T01:00:00.000Z", true],
|
||||||
|
] as const)("handles %s", (_name, timestamp, expected) => {
|
||||||
|
expect(isPeakPricing(new Date(timestamp))).toBe(expected)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
import { describe, expect, test } from "bun:test"
|
||||||
|
import { prepareRequestBody } from "../src/routes/zen/util/requestBody"
|
||||||
|
|
||||||
|
describe("Zen request body streaming", () => {
|
||||||
|
test("patches the leading model without buffering the remaining body", async () => {
|
||||||
|
let reads = 0
|
||||||
|
const body = new ReadableStream<Uint8Array>(
|
||||||
|
{
|
||||||
|
pull(controller) {
|
||||||
|
const chunks = [
|
||||||
|
'{"model":"client-model","stream":true,"messages":[',
|
||||||
|
JSON.stringify({ role: "user", content: "large payload" }),
|
||||||
|
"]}",
|
||||||
|
]
|
||||||
|
const chunk = chunks[reads++]
|
||||||
|
if (chunk) controller.enqueue(new TextEncoder().encode(chunk))
|
||||||
|
else controller.close()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ highWaterMark: 0 },
|
||||||
|
)
|
||||||
|
|
||||||
|
const request = await prepareRequestBody(body)
|
||||||
|
expect(request.model).toBe("client-model")
|
||||||
|
expect(reads).toBe(1)
|
||||||
|
|
||||||
|
const output = await new Response(request.stream("provider-model", false)).text()
|
||||||
|
expect(JSON.parse(output)).toEqual({
|
||||||
|
model: "provider-model",
|
||||||
|
stream: true,
|
||||||
|
messages: [{ role: "user", content: "large payload" }],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("ignores model fields nested before the root model", async () => {
|
||||||
|
const body = new Blob([
|
||||||
|
'{"metadata":{"model":"ox-alpha-free"},"model":"glm-5.3","messages":[],"stream":false}',
|
||||||
|
]).stream()
|
||||||
|
const request = await prepareRequestBody(body)
|
||||||
|
|
||||||
|
expect(request.model).toBe("glm-5.3")
|
||||||
|
expect(JSON.parse(await new Response(request.stream("provider-model", false)).text())).toEqual({
|
||||||
|
metadata: { model: "ox-alpha-free" },
|
||||||
|
model: "provider-model",
|
||||||
|
messages: [],
|
||||||
|
stream: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("appends stream usage options at the end of the request", async () => {
|
||||||
|
const body = new Blob(['{"model":"client-model","stream":true,"messages":[]} ']).stream()
|
||||||
|
const request = await prepareRequestBody(body)
|
||||||
|
const output = await new Response(request.stream("provider-model", true)).text()
|
||||||
|
|
||||||
|
expect(JSON.parse(output)).toEqual({
|
||||||
|
model: "provider-model",
|
||||||
|
stream: true,
|
||||||
|
messages: [],
|
||||||
|
stream_options: { include_usage: true },
|
||||||
|
})
|
||||||
|
expect(output.endsWith(" ")).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("detects streaming after a large message while forwarding", async () => {
|
||||||
|
const content = "x".repeat(128 * 1024)
|
||||||
|
let reads = 0
|
||||||
|
const chunks = [
|
||||||
|
'{"model":"client-model","messages":[',
|
||||||
|
JSON.stringify({ role: "user", content }),
|
||||||
|
'],"stream":true}',
|
||||||
|
]
|
||||||
|
const body = new ReadableStream<Uint8Array>(
|
||||||
|
{
|
||||||
|
pull(controller) {
|
||||||
|
const chunk = chunks[reads++]
|
||||||
|
if (chunk) controller.enqueue(new TextEncoder().encode(chunk))
|
||||||
|
else controller.close()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ highWaterMark: 0 },
|
||||||
|
)
|
||||||
|
const request = await prepareRequestBody(body)
|
||||||
|
expect(reads).toBe(1)
|
||||||
|
const output = await new Response(request.stream("provider-model", true)).text()
|
||||||
|
|
||||||
|
expect(JSON.parse(output)).toEqual({
|
||||||
|
model: "provider-model",
|
||||||
|
messages: [{ role: "user", content }],
|
||||||
|
stream: true,
|
||||||
|
stream_options: { include_usage: true },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("buffers through a late model field and then streams the rest", async () => {
|
||||||
|
const content = "こんにちは".repeat(32 * 1024)
|
||||||
|
let reads = 0
|
||||||
|
const chunks = [
|
||||||
|
'{"messages":[',
|
||||||
|
JSON.stringify({ role: "user", content }),
|
||||||
|
'],"model":"client-model","stream":true,"extra":"after-model"}',
|
||||||
|
]
|
||||||
|
const body = new ReadableStream<Uint8Array>(
|
||||||
|
{
|
||||||
|
pull(controller) {
|
||||||
|
const chunk = chunks[reads++]
|
||||||
|
if (chunk) controller.enqueue(new TextEncoder().encode(chunk))
|
||||||
|
else controller.close()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ highWaterMark: 0 },
|
||||||
|
)
|
||||||
|
const request = await prepareRequestBody(body)
|
||||||
|
|
||||||
|
expect(request.model).toBe("client-model")
|
||||||
|
expect(reads).toBe(3)
|
||||||
|
expect(JSON.parse(await new Response(request.stream("provider-model", true)).text())).toEqual({
|
||||||
|
messages: [{ role: "user", content }],
|
||||||
|
model: "provider-model",
|
||||||
|
stream: true,
|
||||||
|
extra: "after-model",
|
||||||
|
stream_options: { include_usage: true },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("preserves a UTF-8 BOM while patching the model", async () => {
|
||||||
|
const body = new Blob(['\uFEFF{"messages":[],"model":"client-model","stream":false}']).stream()
|
||||||
|
const request = await prepareRequestBody(body)
|
||||||
|
const output = new Uint8Array(await new Response(request.stream("provider-model", false)).arrayBuffer())
|
||||||
|
|
||||||
|
expect([...output.subarray(0, 3)]).toEqual([0xef, 0xbb, 0xbf])
|
||||||
|
expect(JSON.parse(new TextDecoder().decode(output))).toEqual({
|
||||||
|
messages: [],
|
||||||
|
model: "provider-model",
|
||||||
|
stream: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE `workspace` ADD `allow_non_zdr` boolean;
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE `workspace` RENAME COLUMN `allow_non_zdr` TO `allow_training`;
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/console-core",
|
"name": "@opencode-ai/console-core",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -328,7 +328,6 @@ export namespace Billing {
|
|||||||
return LiteData.threeMonths100Coupon
|
return LiteData.threeMonths100Coupon
|
||||||
if (coupons.some((coupon) => coupon.type === "GOFREEMONTH" && !coupon.timeRedeemed))
|
if (coupons.some((coupon) => coupon.type === "GOFREEMONTH" && !coupon.timeRedeemed))
|
||||||
return LiteData.firstMonth100Coupon
|
return LiteData.firstMonth100Coupon
|
||||||
if (!coupons.some((coupon) => coupon.type === "GO1MONTH50")) return LiteData.firstMonth50Coupon
|
|
||||||
return undefined
|
return undefined
|
||||||
})()
|
})()
|
||||||
const createSession = () =>
|
const createSession = () =>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export namespace ZenData {
|
|||||||
cost: ModelCostSchema,
|
cost: ModelCostSchema,
|
||||||
costMultiplier: z.number().default(1),
|
costMultiplier: z.number().default(1),
|
||||||
cost200K: ModelCostSchema.optional(),
|
cost200K: ModelCostSchema.optional(),
|
||||||
|
costPeak: ModelCostSchema.optional(),
|
||||||
allowAnonymous: z.boolean().optional(),
|
allowAnonymous: z.boolean().optional(),
|
||||||
byokProvider: z.enum(["openai", "anthropic", "google"]).optional(),
|
byokProvider: z.enum(["openai", "anthropic", "google"]).optional(),
|
||||||
stickyProvider: z.enum(["strict", "prefer"]).optional(),
|
stickyProvider: z.enum(["strict", "prefer"]).optional(),
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export const BillingTable = mysqlTable(
|
|||||||
...workspaceIndexes(table),
|
...workspaceIndexes(table),
|
||||||
uniqueIndex("global_customer_id").on(table.customerID),
|
uniqueIndex("global_customer_id").on(table.customerID),
|
||||||
uniqueIndex("global_subscription_id").on(table.subscriptionID),
|
uniqueIndex("global_subscription_id").on(table.subscriptionID),
|
||||||
|
uniqueIndex("global_lite_subscription_id").on(table.liteSubscriptionID),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { bigint, mysqlTable, primaryKey, uniqueIndex, varchar } from "drizzle-orm/mysql-core"
|
import { bigint, index, mysqlTable, primaryKey, uniqueIndex, varchar } from "drizzle-orm/mysql-core"
|
||||||
import { timestamps, ulid, utc, workspaceColumns } from "../drizzle/types"
|
import { timestamps, ulid, utc, workspaceColumns } from "../drizzle/types"
|
||||||
import { workspaceIndexes } from "./workspace.sql"
|
import { workspaceIndexes } from "./workspace.sql"
|
||||||
|
|
||||||
@@ -31,5 +31,8 @@ export const ReferralRewardTable = mysqlTable(
|
|||||||
amount: bigint("amount", { mode: "number" }).notNull(),
|
amount: bigint("amount", { mode: "number" }).notNull(),
|
||||||
timeApplied: utc("time_applied"),
|
timeApplied: utc("time_applied"),
|
||||||
},
|
},
|
||||||
(table) => [primaryKey({ columns: [table.workspaceID, table.referralID] })],
|
(table) => [
|
||||||
|
primaryKey({ columns: [table.workspaceID, table.referralID] }),
|
||||||
|
index("referral_id").on(table.referralID),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const WorkspaceTable = mysqlTable(
|
|||||||
slug: varchar("slug", { length: 255 }),
|
slug: varchar("slug", { length: 255 }),
|
||||||
name: varchar("name", { length: 255 }).notNull(),
|
name: varchar("name", { length: 255 }).notNull(),
|
||||||
region: json("region").$type<("us" | "eu" | "sg" | "cn")[]>(),
|
region: json("region").$type<("us" | "eu" | "sg" | "cn")[]>(),
|
||||||
|
allow_training: boolean(),
|
||||||
is_blocked: boolean(),
|
is_blocked: boolean(),
|
||||||
is_flagged_by_anthropic: boolean(),
|
is_flagged_by_anthropic: boolean(),
|
||||||
is_flagged_by_openai: boolean(),
|
is_flagged_by_openai: boolean(),
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ export namespace Workspace {
|
|||||||
z.object({
|
z.object({
|
||||||
name: z.string().min(1).max(255).optional(),
|
name: z.string().min(1).max(255).optional(),
|
||||||
region: z.array(Region).min(1).optional(),
|
region: z.array(Region).min(1).optional(),
|
||||||
|
allow_training: z.boolean().optional(),
|
||||||
}),
|
}),
|
||||||
async (input) => {
|
async (input) => {
|
||||||
Actor.assertAdmin()
|
Actor.assertAdmin()
|
||||||
@@ -72,6 +73,7 @@ export namespace Workspace {
|
|||||||
.set({
|
.set({
|
||||||
...("name" in input ? { name: input.name } : {}),
|
...("name" in input ? { name: input.name } : {}),
|
||||||
...("region" in input ? { region: input.region } : {}),
|
...("region" in input ? { region: input.region } : {}),
|
||||||
|
...("allow_training" in input ? { allow_training: input.allow_training } : {}),
|
||||||
})
|
})
|
||||||
.where(eq(WorkspaceTable.id, workspaceID)),
|
.where(eq(WorkspaceTable.id, workspaceID)),
|
||||||
)
|
)
|
||||||
@@ -95,6 +97,18 @@ export namespace Workspace {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const unblock = fn(
|
||||||
|
z.object({
|
||||||
|
workspaceID: Identifier.schema("workspace"),
|
||||||
|
}),
|
||||||
|
async (input) => {
|
||||||
|
const result = await Database.use((tx) =>
|
||||||
|
tx.update(WorkspaceTable).set({ is_blocked: false }).where(eq(WorkspaceTable.id, input.workspaceID)),
|
||||||
|
)
|
||||||
|
if (result.rowsAffected === 0) throw new Error("Workspace not found")
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
export const remove = fn(z.void(), async () => {
|
export const remove = fn(z.void(), async () => {
|
||||||
await Database.use((tx) =>
|
await Database.use((tx) =>
|
||||||
tx
|
tx
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/console-function",
|
"name": "@opencode-ai/console-function",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/console-mail",
|
"name": "@opencode-ai/console-mail",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jsx-email/all": "2.2.3",
|
"@jsx-email/all": "2.2.3",
|
||||||
"@jsx-email/cli": "1.4.3",
|
"@jsx-email/cli": "1.4.3",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/console-support",
|
"name": "@opencode-ai/console-support",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"name": "@opencode-ai/core",
|
"name": "@opencode-ai/core",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/alibaba": "1.0.17",
|
"@ai-sdk/alibaba": "1.0.17",
|
||||||
"@ai-sdk/amazon-bedrock": "4.0.112",
|
"@ai-sdk/amazon-bedrock": "4.0.158",
|
||||||
"@ai-sdk/anthropic": "3.0.82",
|
"@ai-sdk/anthropic": "3.0.82",
|
||||||
"@ai-sdk/azure": "3.0.88",
|
"@ai-sdk/azure": "3.0.88",
|
||||||
"@ai-sdk/cerebras": "2.0.41",
|
"@ai-sdk/cerebras": "2.0.41",
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
"@ai-sdk/deepinfra": "2.0.41",
|
"@ai-sdk/deepinfra": "2.0.41",
|
||||||
"@ai-sdk/gateway": "3.0.104",
|
"@ai-sdk/gateway": "3.0.104",
|
||||||
"@ai-sdk/google": "3.0.73",
|
"@ai-sdk/google": "3.0.73",
|
||||||
"@ai-sdk/google-vertex": "4.0.128",
|
"@ai-sdk/google-vertex": "4.0.181",
|
||||||
"@ai-sdk/groq": "3.0.31",
|
"@ai-sdk/groq": "3.0.31",
|
||||||
"@ai-sdk/mistral": "3.0.51",
|
"@ai-sdk/mistral": "3.0.51",
|
||||||
"@ai-sdk/openai": "3.0.84",
|
"@ai-sdk/openai": "3.0.84",
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { ConfigProviderV1 } from "../../v1/config/provider"
|
|||||||
import { ConfigProviderOptionsV1 } from "../../v1/config/provider-options"
|
import { ConfigProviderOptionsV1 } from "../../v1/config/provider-options"
|
||||||
import { ConfigV1 } from "../../v1/config/config"
|
import { ConfigV1 } from "../../v1/config/config"
|
||||||
|
|
||||||
const defaultServer = "https://console.opencode.ai"
|
const defaultServer = "https://opencode.ai/console"
|
||||||
const clientID = "opencode-cli"
|
const clientID = "opencode-cli"
|
||||||
const methodID = Integration.MethodID.make("device")
|
const methodID = Integration.MethodID.make("device")
|
||||||
const RemoteResponse = Schema.Struct({ config: ConfigV1.Info })
|
const RemoteResponse = Schema.Struct({ config: ConfigV1.Info })
|
||||||
@@ -45,9 +45,18 @@ function oauth(http: HttpClient.HttpClient) {
|
|||||||
authorize: () =>
|
authorize: () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const device = yield* post(http, `${defaultServer}/auth/device/code`, { client_id: clientID }, Device)
|
const device = yield* post(http, `${defaultServer}/auth/device/code`, { client_id: clientID }, Device)
|
||||||
|
const verification = yield* Effect.try({
|
||||||
|
try: () => {
|
||||||
|
const url = new URL(device.verification_uri_complete, `${defaultServer}/`)
|
||||||
|
if (url.protocol !== "http:" && url.protocol !== "https:") throw new Error("expected HTTP(S)")
|
||||||
|
return url
|
||||||
|
},
|
||||||
|
catch: (cause) =>
|
||||||
|
new Error(`Invalid device verification URL: ${cause instanceof Error ? cause.message : String(cause)}`),
|
||||||
|
})
|
||||||
return {
|
return {
|
||||||
mode: "auto" as const,
|
mode: "auto" as const,
|
||||||
url: `${defaultServer}${device.verification_uri_complete}`,
|
url: verification.href,
|
||||||
instructions: `Enter code: ${device.user_code}`,
|
instructions: `Enter code: ${device.user_code}`,
|
||||||
callback: poll(http, defaultServer, device.device_code, Duration.seconds(device.interval)),
|
callback: poll(http, defaultServer, device.device_code, Duration.seconds(device.interval)),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ export const make = (dependencies: Dependencies) => {
|
|||||||
.stream(
|
.stream(
|
||||||
LLM.request({
|
LLM.request({
|
||||||
model: input.model,
|
model: input.model,
|
||||||
|
http: input.request.http,
|
||||||
messages: [Message.user(summaryPrompt)],
|
messages: [Message.user(summaryPrompt)],
|
||||||
tools: [],
|
tools: [],
|
||||||
generation: { maxTokens: summaryOutput },
|
generation: { maxTokens: summaryOutput },
|
||||||
|
|||||||
@@ -204,6 +204,13 @@ const layer = Layer.effect(
|
|||||||
const promptCacheKey = /^ses_[0-9a-f]{64}$/.test(session.id) ? session.id.slice(4) : session.id
|
const promptCacheKey = /^ses_[0-9a-f]{64}$/.test(session.id) ? session.id.slice(4) : session.id
|
||||||
const request = LLM.request({
|
const request = LLM.request({
|
||||||
model,
|
model,
|
||||||
|
http: {
|
||||||
|
headers: {
|
||||||
|
"x-session-affinity": session.id,
|
||||||
|
"X-Session-Id": session.id,
|
||||||
|
...(session.parentID ? { "x-parent-session-id": session.parentID } : {}),
|
||||||
|
},
|
||||||
|
},
|
||||||
providerOptions: { openai: { promptCacheKey } },
|
providerOptions: { openai: { promptCacheKey } },
|
||||||
system: [agent.info?.system, system.baseline]
|
system: [agent.info?.system, system.baseline]
|
||||||
.filter((part): part is string => part !== undefined && part.length > 0)
|
.filter((part): part is string => part !== undefined && part.length > 0)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { describe, expect } from "bun:test"
|
import { describe, expect } from "bun:test"
|
||||||
import { Effect } from "effect"
|
import { Effect } from "effect"
|
||||||
|
import { HttpClient, HttpClientResponse } from "effect/unstable/http"
|
||||||
import { Catalog } from "@opencode-ai/core/catalog"
|
import { Catalog } from "@opencode-ai/core/catalog"
|
||||||
import { Credential } from "@opencode-ai/core/credential"
|
import { Credential } from "@opencode-ai/core/credential"
|
||||||
import { EventV2 } from "@opencode-ai/core/event"
|
import { EventV2 } from "@opencode-ai/core/event"
|
||||||
@@ -14,14 +15,16 @@ import { PluginTestLayer } from "./fixture"
|
|||||||
|
|
||||||
const it = testEffect(PluginTestLayer)
|
const it = testEffect(PluginTestLayer)
|
||||||
|
|
||||||
const addPlugin = Effect.fn(function* () {
|
const addPlugin = Effect.fn(function* (http?: HttpClient.HttpClient) {
|
||||||
const plugin = yield* PluginV2.Service
|
const plugin = yield* PluginV2.Service
|
||||||
const host = yield* PluginHost.make(plugin)
|
const host = yield* PluginHost.make(plugin)
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
const integration = yield* Integration.Service
|
const integration = yield* Integration.Service
|
||||||
|
const client = yield* HttpClient.HttpClient
|
||||||
yield* OpencodePlugin.effect(host).pipe(
|
yield* OpencodePlugin.effect(host).pipe(
|
||||||
Effect.provideService(EventV2.Service, events),
|
Effect.provideService(EventV2.Service, events),
|
||||||
Effect.provideService(Integration.Service, integration),
|
Effect.provideService(Integration.Service, integration),
|
||||||
|
Effect.provideService(HttpClient.HttpClient, http ?? client),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -82,6 +85,63 @@ describe("OpencodePlugin", () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
it.effect("resolves origin-rooted device verification URLs", () =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const http = HttpClient.make((request) =>
|
||||||
|
Effect.succeed(
|
||||||
|
HttpClientResponse.fromWeb(
|
||||||
|
request,
|
||||||
|
Response.json({
|
||||||
|
device_code: "device",
|
||||||
|
user_code: "user",
|
||||||
|
verification_uri_complete: "/console/device?user_code=user&client_id=opencode-cli",
|
||||||
|
expires_in: 60,
|
||||||
|
interval: 60,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
yield* addPlugin(http)
|
||||||
|
const integration = yield* Integration.Service
|
||||||
|
const attempt = yield* integration.connection.oauth({
|
||||||
|
integrationID: Integration.ID.make("opencode"),
|
||||||
|
methodID: Integration.MethodID.make("device"),
|
||||||
|
inputs: {},
|
||||||
|
})
|
||||||
|
expect(attempt.url).toBe("https://opencode.ai/console/device?user_code=user&client_id=opencode-cli")
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
it.effect("rejects malformed device verification URLs", () =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const http = HttpClient.make((request) =>
|
||||||
|
Effect.succeed(
|
||||||
|
HttpClientResponse.fromWeb(
|
||||||
|
request,
|
||||||
|
Response.json({
|
||||||
|
device_code: "device",
|
||||||
|
user_code: "user",
|
||||||
|
verification_uri_complete: "http://[::1",
|
||||||
|
expires_in: 60,
|
||||||
|
interval: 60,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
yield* addPlugin(http)
|
||||||
|
const integration = yield* Integration.Service
|
||||||
|
const error = yield* integration.connection
|
||||||
|
.oauth({
|
||||||
|
integrationID: Integration.ID.make("opencode"),
|
||||||
|
methodID: Integration.MethodID.make("device"),
|
||||||
|
inputs: {},
|
||||||
|
})
|
||||||
|
.pipe(Effect.flip)
|
||||||
|
expect(error).toBeInstanceOf(Integration.AuthorizationError)
|
||||||
|
expect(String(error.cause)).toContain("Invalid device verification URL")
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
it.live("loads providers and models from the connected OpenCode server", () =>
|
it.live("loads providers and models from the connected OpenCode server", () =>
|
||||||
Effect.acquireUseRelease(
|
Effect.acquireUseRelease(
|
||||||
Effect.sync(() => {
|
Effect.sync(() => {
|
||||||
|
|||||||
@@ -1101,6 +1101,16 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
expect(requests).toHaveLength(2)
|
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[0])[0]).toContain("## Objective")
|
||||||
expect(userTexts(requests[1])).toHaveLength(1)
|
expect(userTexts(requests[1])).toHaveLength(1)
|
||||||
expect(userTexts(requests[1])[0]).toContain("<summary>\n## Objective\n- Preserve the task\n</summary>")
|
expect(userTexts(requests[1])[0]).toContain("<summary>\n## Objective\n- Preserve the task\n</summary>")
|
||||||
@@ -2508,6 +2518,43 @@ 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", () =>
|
it.effect("bounds 64-character session prompt cache keys", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/desktop",
|
"name": "@opencode-ai/desktop",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "https://opencode.ai",
|
"homepage": "https://opencode.ai",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"name": "@opencode-ai/effect-drizzle-sqlite",
|
"name": "@opencode-ai/effect-drizzle-sqlite",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"name": "@opencode-ai/effect-sqlite-node",
|
"name": "@opencode-ai/effect-sqlite-node",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/enterprise",
|
"name": "@opencode-ai/enterprise",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/function",
|
"name": "@opencode-ai/function",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"test": "bun test"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cloudflare/workers-types": "catalog:",
|
"@cloudflare/workers-types": "catalog:",
|
||||||
"@tsconfig/node22": "22.0.2",
|
"@tsconfig/node22": "22.0.2",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { jwtVerify, createRemoteJWKSet } from "jose"
|
|||||||
import { createAppAuth } from "@octokit/auth-app"
|
import { createAppAuth } from "@octokit/auth-app"
|
||||||
import { Octokit } from "@octokit/rest"
|
import { Octokit } from "@octokit/rest"
|
||||||
import { Resource } from "sst"
|
import { Resource } from "sst"
|
||||||
|
import { parseRepositoryClaim } from "./github"
|
||||||
|
|
||||||
type Env = {
|
type Env = {
|
||||||
SYNC_SERVER: DurableObjectNamespace<SyncServer>
|
SYNC_SERVER: DurableObjectNamespace<SyncServer>
|
||||||
@@ -269,42 +270,41 @@ export default new Hono<{ Bindings: Env }>()
|
|||||||
|
|
||||||
// verify token
|
// verify token
|
||||||
const JWKS = createRemoteJWKSet(new URL(JWKS_URL))
|
const JWKS = createRemoteJWKSet(new URL(JWKS_URL))
|
||||||
let owner, repo
|
let repository: ReturnType<typeof parseRepositoryClaim>
|
||||||
try {
|
try {
|
||||||
const { payload } = await jwtVerify(token, JWKS, {
|
const { payload } = await jwtVerify(token, JWKS, {
|
||||||
issuer: GITHUB_ISSUER,
|
issuer: GITHUB_ISSUER,
|
||||||
audience: EXPECTED_AUDIENCE,
|
audience: EXPECTED_AUDIENCE,
|
||||||
})
|
})
|
||||||
const sub = payload.sub // e.g. 'repo:my-org/my-repo:ref:refs/heads/main'
|
repository = parseRepositoryClaim(payload)
|
||||||
const parts = sub.split(":")[1].split("/")
|
|
||||||
owner = parts[0]
|
|
||||||
repo = parts[1]
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Token verification failed:", err)
|
console.error("Token verification failed:", err)
|
||||||
return c.json({ error: "Invalid or expired token" }, { status: 403 })
|
return c.json({ error: "Invalid or expired token" }, { status: 403 })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create app JWT token
|
try {
|
||||||
const auth = createAppAuth({
|
const auth = createAppAuth({
|
||||||
appId: Resource.GITHUB_APP_ID.value,
|
appId: Resource.GITHUB_APP_ID.value,
|
||||||
privateKey: Resource.GITHUB_APP_PRIVATE_KEY.value,
|
privateKey: Resource.GITHUB_APP_PRIVATE_KEY.value,
|
||||||
})
|
})
|
||||||
const appAuth = await auth({ type: "app" })
|
const appAuth = await auth({ type: "app" })
|
||||||
|
const octokit = new Octokit({ auth: appAuth.token })
|
||||||
// Lookup installation
|
const { data: installation } = await octokit.apps.getRepoInstallation({
|
||||||
const octokit = new Octokit({ auth: appAuth.token })
|
owner: repository.owner,
|
||||||
const { data: installation } = await octokit.apps.getRepoInstallation({
|
repo: repository.repo,
|
||||||
owner,
|
})
|
||||||
repo,
|
const installationAuth = await auth({
|
||||||
})
|
type: "installation",
|
||||||
|
installationId: installation.id,
|
||||||
// Get installation token
|
})
|
||||||
const installationAuth = await auth({
|
return c.json({ token: installationAuth.token })
|
||||||
type: "installation",
|
} catch (error) {
|
||||||
installationId: installation.id,
|
console.error("GitHub App token exchange failed:", error)
|
||||||
})
|
return c.json(
|
||||||
|
{ error: `Failed to exchange GitHub App token for ${repository.owner}/${repository.repo}` },
|
||||||
return c.json({ token: installationAuth.token })
|
{ status: 502 },
|
||||||
|
)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
* Used by the GitHub action to get GitHub installation access token given user PAT token (used when testing `opencode github run` locally)
|
* Used by the GitHub action to get GitHub installation access token given user PAT token (used when testing `opencode github run` locally)
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import type { JWTPayload } from "jose"
|
||||||
|
|
||||||
|
export function parseRepositoryClaim(payload: JWTPayload) {
|
||||||
|
const claim = payload.repository
|
||||||
|
if (typeof claim !== "string") throw new Error("Repository claim is missing")
|
||||||
|
|
||||||
|
const parts = claim.split("/")
|
||||||
|
if (parts.length !== 2 || !parts[0] || !parts[1]) throw new Error("Repository claim is invalid")
|
||||||
|
|
||||||
|
return {
|
||||||
|
owner: parts[0],
|
||||||
|
repo: parts[1],
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { describe, expect, test } from "bun:test"
|
||||||
|
import { parseRepositoryClaim } from "../src/github"
|
||||||
|
|
||||||
|
describe("parseRepositoryClaim", () => {
|
||||||
|
test("reads repository identity with a legacy subject", () => {
|
||||||
|
expect(
|
||||||
|
parseRepositoryClaim({
|
||||||
|
repository: "octocat/my-repo",
|
||||||
|
sub: "repo:octocat/my-repo:ref:refs/heads/main",
|
||||||
|
}),
|
||||||
|
).toEqual({ owner: "octocat", repo: "my-repo" })
|
||||||
|
})
|
||||||
|
|
||||||
|
test("reads repository identity with an immutable subject", () => {
|
||||||
|
expect(
|
||||||
|
parseRepositoryClaim({
|
||||||
|
repository: "octocat/my-repo",
|
||||||
|
sub: "repo:octocat@123456/my-repo@456789:ref:refs/heads/main",
|
||||||
|
}),
|
||||||
|
).toEqual({ owner: "octocat", repo: "my-repo" })
|
||||||
|
})
|
||||||
|
|
||||||
|
test("does not depend on a repository path in a customized subject", () => {
|
||||||
|
expect(
|
||||||
|
parseRepositoryClaim({
|
||||||
|
repository: "octocat/my-repo",
|
||||||
|
sub: "repository_owner:octocat:repository_visibility:private",
|
||||||
|
}),
|
||||||
|
).toEqual({ owner: "octocat", repo: "my-repo" })
|
||||||
|
})
|
||||||
|
|
||||||
|
test("rejects a missing repository claim", () => {
|
||||||
|
expect(() => parseRepositoryClaim({})).toThrow("Repository claim is missing")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("rejects an invalid repository claim", () => {
|
||||||
|
expect(() => parseRepositoryClaim({ repository: "octocat" })).toThrow("Repository claim is invalid")
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"name": "@opencode-ai/http-recorder",
|
"name": "@opencode-ai/http-recorder",
|
||||||
"description": "Record and replay Effect HTTP client traffic with deterministic cassettes",
|
"description": "Record and replay Effect HTTP client traffic with deterministic cassettes",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"name": "@opencode-ai/llm",
|
"name": "@opencode-ai/llm",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"version": "1.18.18",
|
"version": "1.18.22",
|
||||||
"name": "opencode",
|
"name": "opencode",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
"@actions/github": "6.0.1",
|
"@actions/github": "6.0.1",
|
||||||
"@agentclientprotocol/sdk": "0.21.0",
|
"@agentclientprotocol/sdk": "0.21.0",
|
||||||
"@ai-sdk/alibaba": "1.0.17",
|
"@ai-sdk/alibaba": "1.0.17",
|
||||||
"@ai-sdk/amazon-bedrock": "4.0.112",
|
"@ai-sdk/amazon-bedrock": "4.0.158",
|
||||||
"@ai-sdk/anthropic": "3.0.82",
|
"@ai-sdk/anthropic": "3.0.82",
|
||||||
"@ai-sdk/azure": "3.0.88",
|
"@ai-sdk/azure": "3.0.88",
|
||||||
"@ai-sdk/cerebras": "2.0.60",
|
"@ai-sdk/cerebras": "2.0.60",
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
"@ai-sdk/deepinfra": "2.0.41",
|
"@ai-sdk/deepinfra": "2.0.41",
|
||||||
"@ai-sdk/gateway": "3.0.104",
|
"@ai-sdk/gateway": "3.0.104",
|
||||||
"@ai-sdk/google": "3.0.73",
|
"@ai-sdk/google": "3.0.73",
|
||||||
"@ai-sdk/google-vertex": "4.0.128",
|
"@ai-sdk/google-vertex": "4.0.181",
|
||||||
"@ai-sdk/groq": "3.0.31",
|
"@ai-sdk/groq": "3.0.31",
|
||||||
"@ai-sdk/mistral": "3.0.51",
|
"@ai-sdk/mistral": "3.0.51",
|
||||||
"@ai-sdk/openai": "3.0.84",
|
"@ai-sdk/openai": "3.0.84",
|
||||||
|
|||||||
@@ -396,10 +396,18 @@ const layer: Layer.Layer<Service, never, AccountRepo.Service | HttpClient.HttpCl
|
|||||||
const parsed = yield* HttpClientResponse.schemaBodyJson(DeviceAuth)(response).pipe(
|
const parsed = yield* HttpClientResponse.schemaBodyJson(DeviceAuth)(response).pipe(
|
||||||
mapAccountServiceError("Failed to decode response"),
|
mapAccountServiceError("Failed to decode response"),
|
||||||
)
|
)
|
||||||
|
const verification = yield* Effect.try({
|
||||||
|
try: () => {
|
||||||
|
const url = new URL(parsed.verification_uri_complete, `${normalizedServer}/`)
|
||||||
|
if (url.protocol !== "http:" && url.protocol !== "https:") throw new Error("expected HTTP(S)")
|
||||||
|
return url.href
|
||||||
|
},
|
||||||
|
catch: (cause) => new AccountServiceError({ message: "Invalid device verification URL", cause }),
|
||||||
|
})
|
||||||
return new Login({
|
return new Login({
|
||||||
code: parsed.device_code,
|
code: parsed.device_code,
|
||||||
user: parsed.user_code,
|
user: parsed.user_code,
|
||||||
url: `${normalizedServer}${parsed.verification_uri_complete}`,
|
url: verification,
|
||||||
server: normalizedServer,
|
server: normalizedServer,
|
||||||
expiry: parsed.expires_in,
|
expiry: parsed.expires_in,
|
||||||
interval: parsed.interval,
|
interval: parsed.interval,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const dim = (value: string) => UI.Style.TEXT_DIM + value + UI.Style.TEXT_NORMAL
|
|||||||
|
|
||||||
const activeSuffix = (isActive: boolean) => (isActive ? dim(" (active)") : "")
|
const activeSuffix = (isActive: boolean) => (isActive ? dim(" (active)") : "")
|
||||||
|
|
||||||
export const defaultConsoleUrl = "https://console.opencode.ai"
|
export const defaultConsoleUrl = "https://opencode.ai/console"
|
||||||
|
|
||||||
export const formatAccountLabel = (account: { email: string; url: string }, isActive: boolean) =>
|
export const formatAccountLabel = (account: { email: string; url: string }, isActive: boolean) =>
|
||||||
`${account.email} ${dim(account.url)}${activeSuffix(isActive)}`
|
`${account.email} ${dim(account.url)}${activeSuffix(isActive)}`
|
||||||
|
|||||||
@@ -437,6 +437,7 @@ export const githubRun = Effect.fn("Cli.github.run")(function* (args: { event?:
|
|||||||
let session: { id: SessionID; title: string; version: string }
|
let session: { id: SessionID; title: string; version: string }
|
||||||
let shareId: string | undefined
|
let shareId: string | undefined
|
||||||
let exitCode = 0
|
let exitCode = 0
|
||||||
|
let githubClientReady = false
|
||||||
type PromptFiles = Awaited<ReturnType<typeof getUserPrompt>>["promptFiles"]
|
type PromptFiles = Awaited<ReturnType<typeof getUserPrompt>>["promptFiles"]
|
||||||
const triggerCommentId = isCommentEvent
|
const triggerCommentId = isCommentEvent
|
||||||
? (payload as IssueCommentEvent | PullRequestReviewCommentEvent).comment.id
|
? (payload as IssueCommentEvent | PullRequestReviewCommentEvent).comment.id
|
||||||
@@ -485,6 +486,7 @@ export const githubRun = Effect.fn("Cli.github.run")(function* (args: { event?:
|
|||||||
octoGraph = graphql.defaults({
|
octoGraph = graphql.defaults({
|
||||||
headers: { authorization: `token ${appToken}` },
|
headers: { authorization: `token ${appToken}` },
|
||||||
})
|
})
|
||||||
|
githubClientReady = true
|
||||||
|
|
||||||
const { userPrompt, promptFiles } = await getUserPrompt()
|
const { userPrompt, promptFiles } = await getUserPrompt()
|
||||||
if (!useGithubToken) {
|
if (!useGithubToken) {
|
||||||
@@ -639,9 +641,13 @@ export const githubRun = Effect.fn("Cli.github.run")(function* (args: { event?:
|
|||||||
} else if (e instanceof Error) {
|
} else if (e instanceof Error) {
|
||||||
msg = e.message
|
msg = e.message
|
||||||
}
|
}
|
||||||
if (isUserEvent) {
|
if (isUserEvent && githubClientReady) {
|
||||||
await createComment(`${msg}${footer()}`)
|
try {
|
||||||
await removeReaction(commentType)
|
await createComment(`${msg}${footer()}`)
|
||||||
|
await removeReaction(commentType)
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to report error on GitHub:", error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
core.setFailed(msg)
|
core.setFailed(msg)
|
||||||
// Also output the clean error message for the action to capture
|
// Also output the clean error message for the action to capture
|
||||||
@@ -1004,8 +1010,9 @@ export const githubRun = Effect.fn("Cli.github.run")(function* (args: { event?:
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const responseJson = (await response.json()) as { error?: string }
|
throw new Error(
|
||||||
throw new Error(`App token exchange failed: ${response.status} ${response.statusText} - ${responseJson.error}`)
|
`App token exchange failed: ${response.status} ${response.statusText} - ${await response.text()}`,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const responseJson = (await response.json()) as { token: string }
|
const responseJson = (await response.json()) as { token: string }
|
||||||
|
|||||||
@@ -696,9 +696,14 @@ export const RunCommand = effectCmd({
|
|||||||
// created, and replies issued from inside the loop must use that client.
|
// created, and replies issued from inside the loop must use that client.
|
||||||
async function loop(client: OpencodeClient, events: Awaited<ReturnType<typeof sdk.event.subscribe>>) {
|
async function loop(client: OpencodeClient, events: Awaited<ReturnType<typeof sdk.event.subscribe>>) {
|
||||||
const toggles = new Map<string, boolean>()
|
const toggles = new Map<string, boolean>()
|
||||||
|
const sessions = new Set([sessionID])
|
||||||
let error: string | undefined
|
let error: string | undefined
|
||||||
|
|
||||||
for await (const event of events.stream) {
|
for await (const event of events.stream) {
|
||||||
|
if (event.type === "session.created" && event.properties.info.parentID) {
|
||||||
|
if (sessions.has(event.properties.info.parentID)) sessions.add(event.properties.info.id)
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
event.type === "message.updated" &&
|
event.type === "message.updated" &&
|
||||||
event.properties.sessionID === sessionID &&
|
event.properties.sessionID === sessionID &&
|
||||||
@@ -795,7 +800,7 @@ export const RunCommand = effectCmd({
|
|||||||
|
|
||||||
if (event.type === "permission.asked") {
|
if (event.type === "permission.asked") {
|
||||||
const permission = event.properties
|
const permission = event.properties
|
||||||
if (permission.sessionID !== sessionID) continue
|
if (!sessions.has(permission.sessionID)) continue
|
||||||
|
|
||||||
if (auto) {
|
if (auto) {
|
||||||
await client.permission.reply({
|
await client.permission.reply({
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import type { Hooks, PluginInput } from "@opencode-ai/plugin"
|
||||||
|
|
||||||
|
export async function CerebrasPlugin(_input: PluginInput): Promise<Hooks> {
|
||||||
|
return {
|
||||||
|
"chat.params": async (input, output) => {
|
||||||
|
if (input.model.api.npm !== "@ai-sdk/cerebras") return
|
||||||
|
if (output.options.max_completion_tokens === undefined) return
|
||||||
|
output.maxOutputTokens = undefined
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ import { CloudflareAIGatewayAuthPlugin, CloudflareWorkersAuthPlugin } from "./cl
|
|||||||
import { AzureAuthPlugin } from "./azure"
|
import { AzureAuthPlugin } from "./azure"
|
||||||
import { DigitalOceanAuthPlugin } from "./digitalocean"
|
import { DigitalOceanAuthPlugin } from "./digitalocean"
|
||||||
import { XaiAuthPlugin } from "./xai"
|
import { XaiAuthPlugin } from "./xai"
|
||||||
|
import { CerebrasPlugin } from "./cerebras"
|
||||||
import { SnowflakeCortexAuthPlugin } from "./snowflake-cortex"
|
import { SnowflakeCortexAuthPlugin } from "./snowflake-cortex"
|
||||||
import { Effect, Layer, Context } from "effect"
|
import { Effect, Layer, Context } from "effect"
|
||||||
import { EffectBridge } from "@/effect/bridge"
|
import { EffectBridge } from "@/effect/bridge"
|
||||||
@@ -80,6 +81,7 @@ function internalPlugins(flags: RuntimeFlags.Info): PluginInstance[] {
|
|||||||
DigitalOceanAuthPlugin,
|
DigitalOceanAuthPlugin,
|
||||||
SnowflakeCortexAuthPlugin,
|
SnowflakeCortexAuthPlugin,
|
||||||
XaiAuthPlugin,
|
XaiAuthPlugin,
|
||||||
|
CerebrasPlugin,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,10 +37,12 @@ function base64UrlEncode(buffer: ArrayBuffer): string {
|
|||||||
|
|
||||||
export interface IdTokenClaims {
|
export interface IdTokenClaims {
|
||||||
chatgpt_account_id?: string
|
chatgpt_account_id?: string
|
||||||
|
chatgpt_compute_residency?: string
|
||||||
organizations?: Array<{ id: string }>
|
organizations?: Array<{ id: string }>
|
||||||
email?: string
|
email?: string
|
||||||
"https://api.openai.com/auth"?: {
|
"https://api.openai.com/auth"?: {
|
||||||
chatgpt_account_id?: string
|
chatgpt_account_id?: string
|
||||||
|
chatgpt_compute_residency?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +77,14 @@ export function extractAccountId(tokens: TokenResponse): string | undefined {
|
|||||||
return 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 {
|
function buildAuthorizeUrl(redirectUri: string, pkce: PkceCodes, state: string): string {
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
response_type: "code",
|
response_type: "code",
|
||||||
@@ -299,16 +309,11 @@ export async function CodexAuthPlugin(input: PluginInput, options: CodexAuthPlug
|
|||||||
output: 0,
|
output: 0,
|
||||||
cache: { read: 0, write: 0 },
|
cache: { read: 0, write: 0 },
|
||||||
},
|
},
|
||||||
limit: model.id.includes("gpt-5.5")
|
limit:
|
||||||
? {
|
model.id.includes("gpt-5.5") || model.id.includes("gpt-5.6")
|
||||||
context: 400_000,
|
|
||||||
input: 272_000,
|
|
||||||
output: 128_000,
|
|
||||||
}
|
|
||||||
: model.id.includes("gpt-5.6")
|
|
||||||
? {
|
? {
|
||||||
context: 500_000,
|
context: 400_000,
|
||||||
input: 372_000,
|
input: 272_000,
|
||||||
output: 128_000,
|
output: 128_000,
|
||||||
}
|
}
|
||||||
: model.limit,
|
: model.limit,
|
||||||
@@ -411,10 +416,12 @@ export async function CodexAuthPlugin(input: PluginInput, options: CodexAuthPlug
|
|||||||
requestInput instanceof URL
|
requestInput instanceof URL
|
||||||
? requestInput
|
? requestInput
|
||||||
: new URL(typeof requestInput === "string" ? requestInput : requestInput.url)
|
: new URL(typeof requestInput === "string" ? requestInput : requestInput.url)
|
||||||
const url =
|
const rewrite = parsed.pathname.includes("/v1/responses") || parsed.pathname.includes("/chat/completions")
|
||||||
parsed.pathname.includes("/v1/responses") || parsed.pathname.includes("/chat/completions")
|
const url = rewrite ? new URL(codexApiEndpoint) : parsed
|
||||||
? new URL(codexApiEndpoint)
|
if (rewrite) {
|
||||||
: parsed
|
const residency = extractResidency(currentAuth.access)
|
||||||
|
if (residency) headers.set("x-openai-internal-codex-residency", residency)
|
||||||
|
}
|
||||||
|
|
||||||
const requestInit = {
|
const requestInit = {
|
||||||
...init,
|
...init,
|
||||||
|
|||||||
@@ -110,10 +110,11 @@ export function createWebSocketFetch(options?: CreateWebSocketFetchOptions) {
|
|||||||
invalidate(entry)
|
invalidate(entry)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onConnectionInvalid: (error) => {
|
onConnectionInvalid: (_error, closeCode) => {
|
||||||
entry.busy = false
|
entry.busy = false
|
||||||
entry.lastUsedAt = Date.now()
|
entry.lastUsedAt = Date.now()
|
||||||
if (!entry.fallback) recordStreamFailure(entry)
|
if (closeCode === OpenAIWebSocket.MESSAGE_TOO_BIG_CLOSE_CODE) entry.fallback = true
|
||||||
|
else if (!entry.fallback) recordStreamFailure(entry)
|
||||||
invalidate(entry)
|
invalidate(entry)
|
||||||
resolveFirstEvent(false)
|
resolveFirstEvent(false)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { ProxyEnv } from "@/util/proxy-env"
|
|||||||
import { isRecord } from "@/util/record"
|
import { isRecord } from "@/util/record"
|
||||||
|
|
||||||
export const PROTOCOL_HEADER = "responses_websockets=2026-02-06"
|
export const PROTOCOL_HEADER = "responses_websockets=2026-02-06"
|
||||||
|
export const MESSAGE_TOO_BIG_CLOSE_CODE = 1009
|
||||||
|
|
||||||
export interface ConnectResponsesWebSocketOptions {
|
export interface ConnectResponsesWebSocketOptions {
|
||||||
url: string
|
url: string
|
||||||
@@ -26,7 +27,7 @@ export interface StreamResponsesWebSocketOptions {
|
|||||||
onComplete?: (event: Record<string, unknown>) => void
|
onComplete?: (event: Record<string, unknown>) => void
|
||||||
onTerminal?: (event: Record<string, unknown>) => void
|
onTerminal?: (event: Record<string, unknown>) => void
|
||||||
onRetryableTerminal?: (event: Record<string, unknown>) => Promise<WebSocket | undefined>
|
onRetryableTerminal?: (event: Record<string, unknown>) => Promise<WebSocket | undefined>
|
||||||
onConnectionInvalid?: (error: ProviderError.ResponseStreamError) => void
|
onConnectionInvalid?: (error: ProviderError.ResponseStreamError, closeCode?: number) => void
|
||||||
onAbort?: (error: Error) => void
|
onAbort?: (error: Error) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,11 +163,11 @@ export function streamResponsesWebSocket(options: StreamResponsesWebSocketOption
|
|||||||
controller?.close()
|
controller?.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
function invalidate(error: ProviderError.ResponseStreamError) {
|
function invalidate(error: ProviderError.ResponseStreamError, closeCode?: number) {
|
||||||
if (completed) return
|
if (completed) return
|
||||||
completed = true
|
completed = true
|
||||||
cleanup()
|
cleanup()
|
||||||
options.onConnectionInvalid?.(error)
|
options.onConnectionInvalid?.(error, closeCode)
|
||||||
controller?.error(error)
|
controller?.error(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,6 +275,7 @@ export function streamResponsesWebSocket(options: StreamResponsesWebSocketOption
|
|||||||
if (completed) return
|
if (completed) return
|
||||||
invalidate(
|
invalidate(
|
||||||
new ProviderError.ResponseStreamError(closeMessage("WebSocket closed before response.completed", code, reason)),
|
new ProviderError.ResponseStreamError(closeMessage("WebSocket closed before response.completed", code, reason)),
|
||||||
|
code,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,7 +375,7 @@ function abortError(signal: AbortSignal | undefined) {
|
|||||||
|
|
||||||
function closeMessage(message: string, code: number, reason: Buffer) {
|
function closeMessage(message: string, code: number, reason: Buffer) {
|
||||||
const details = [`code ${code}`]
|
const details = [`code ${code}`]
|
||||||
if (code === 1009) details.push("message too big")
|
if (code === MESSAGE_TOO_BIG_CLOSE_CODE) details.push("message too big")
|
||||||
if (reason.length > 0) details.push(reason.toString())
|
if (reason.length > 0) details.push(reason.toString())
|
||||||
return `${message} (${details.join(": ")})`
|
return `${message} (${details.join(": ")})`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,6 +144,13 @@ export function parseStreamError(input: unknown): ParsedStreamError | undefined
|
|||||||
responseBody,
|
responseBody,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "api_error",
|
||||||
|
message: typeof body?.error?.message === "string" ? body.error.message : "Server error.",
|
||||||
|
isRetryable: true,
|
||||||
|
responseBody,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ParsedAPICallError =
|
export type ParsedAPICallError =
|
||||||
|
|||||||
@@ -98,6 +98,12 @@ function googleVertexAnthropicBaseURL(project: string | undefined, location: str
|
|||||||
return `https://aiplatform.${location}.rep.googleapis.com/v1/projects/${project}/locations/${location}/publishers/anthropic/models`
|
return `https://aiplatform.${location}.rep.googleapis.com/v1/projects/${project}/locations/${location}/publishers/anthropic/models`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function googleVertexEndpoint(location: string) {
|
||||||
|
if (location === "global") return "aiplatform.googleapis.com"
|
||||||
|
if (location === "eu" || location === "us") return `aiplatform.${location}.rep.googleapis.com`
|
||||||
|
return `${location}-aiplatform.googleapis.com`
|
||||||
|
}
|
||||||
|
|
||||||
type BundledSDK = {
|
type BundledSDK = {
|
||||||
languageModel(modelId: string): LanguageModelV3
|
languageModel(modelId: string): LanguageModelV3
|
||||||
chat?: (modelId: string) => LanguageModelV3
|
chat?: (modelId: string) => LanguageModelV3
|
||||||
@@ -519,11 +525,10 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
|
|||||||
return {
|
return {
|
||||||
autoload: true,
|
autoload: true,
|
||||||
vars(_options: Record<string, any>) {
|
vars(_options: Record<string, any>) {
|
||||||
const endpoint = location === "global" ? "aiplatform.googleapis.com" : `${location}-aiplatform.googleapis.com`
|
|
||||||
return {
|
return {
|
||||||
...(project && { GOOGLE_VERTEX_PROJECT: project }),
|
...(project && { GOOGLE_VERTEX_PROJECT: project }),
|
||||||
GOOGLE_VERTEX_LOCATION: location,
|
GOOGLE_VERTEX_LOCATION: location,
|
||||||
GOOGLE_VERTEX_ENDPOINT: endpoint,
|
GOOGLE_VERTEX_ENDPOINT: googleVertexEndpoint(location),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
@@ -804,6 +809,7 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
|
|||||||
const { createUnified } = yield* Effect.promise(() => import("ai-gateway-provider/providers/unified"))
|
const { createUnified } = yield* Effect.promise(() => import("ai-gateway-provider/providers/unified"))
|
||||||
const { createOpenAI } = yield* Effect.promise(() => import("ai-gateway-provider/providers/openai"))
|
const { createOpenAI } = yield* Effect.promise(() => import("ai-gateway-provider/providers/openai"))
|
||||||
const { createAnthropic } = yield* Effect.promise(() => import("ai-gateway-provider/providers/anthropic"))
|
const { createAnthropic } = yield* Effect.promise(() => import("ai-gateway-provider/providers/anthropic"))
|
||||||
|
const { createOpenAICompatible } = yield* Effect.promise(() => import("@ai-sdk/openai-compatible"))
|
||||||
|
|
||||||
const metadata = iife(() => {
|
const metadata = iife(() => {
|
||||||
if (input.options?.metadata) return input.options.metadata
|
if (input.options?.metadata) return input.options.metadata
|
||||||
@@ -838,18 +844,35 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
|
|||||||
// and Messages APIs; new OpenAI models reject tools+reasoning_effort on chat completions.
|
// 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
|
// 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).
|
// dispatch, so upstream billing stays on the gateway (Unified Billing / stored BYOK).
|
||||||
const route = cloudflareGatewayRoute(modelID)
|
if (modelID.startsWith("openai/")) return aigateway(createOpenAI()(modelID.slice("openai/".length)))
|
||||||
if (route.type === "openai") return aigateway(createOpenAI()(modelID.slice("openai/".length)))
|
// models.dev lists Anthropic ids with dotted versions (claude-haiku-4.5); Anthropic's
|
||||||
if (route.type === "anthropic")
|
// Messages API expects dashed native slugs (claude-haiku-4-5), so translate before passing.
|
||||||
return aigateway(createAnthropic()(modelID.slice("anthropic/".length)))
|
// No native Anthropic slug contains a dot, so the blanket replacement is lossless here -
|
||||||
|
// unlike OpenAI above, whose native ids (e.g. gpt-4.1) keep their dots and must not be touched.
|
||||||
|
if (modelID.startsWith("anthropic/"))
|
||||||
|
return aigateway(createAnthropic()(modelID.slice("anthropic/".length).replaceAll(".", "-")))
|
||||||
// Workers AI is the only first-party provider whose upstream is Cloudflare itself, so it is
|
// 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 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
|
// 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
|
// bare "@cf/..." ids. Third-party providers must not receive the token; they rely on the
|
||||||
// gateway's stored/BYOK keys instead.
|
// gateway's stored/BYOK keys instead.
|
||||||
|
// Workers AI is Cloudflare's own upstream, so it rides the unified compat route with the
|
||||||
|
// Cloudflare token as its upstream Authorization header.
|
||||||
const isWorkersAi = modelID.startsWith("workers-ai/") || modelID.startsWith("@cf/")
|
const isWorkersAi = modelID.startsWith("workers-ai/") || modelID.startsWith("@cf/")
|
||||||
const unified = createUnified(isWorkersAi ? { apiKey: apiToken } : {})
|
if (isWorkersAi) return aigateway(createUnified({ apiKey: apiToken })(modelID))
|
||||||
return aigateway(unified(modelID))
|
|
||||||
|
// Every other third-party provider (google, xai, alibaba, deepseek, moonshotai, …) is only
|
||||||
|
// served by Cloudflare's catalog-aware REST API. The universal/compat gateway route rejects
|
||||||
|
// them with "Invalid provider" (the gateway's compat endpoint doesn't front those upstreams),
|
||||||
|
// so point an OpenAI-compatible client at the REST endpoint and bind it to the gateway with
|
||||||
|
// cf-aig-gateway-id — that keeps requests gateway-routed (analytics/caching/BYOK), not a
|
||||||
|
// bypass. models.dev ids (provider/model, dotted) pass through unchanged.
|
||||||
|
return createOpenAICompatible({
|
||||||
|
name: "cloudflare-ai-gateway",
|
||||||
|
baseURL: `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/v1`,
|
||||||
|
apiKey: apiToken,
|
||||||
|
headers: { "cf-aig-gateway-id": gateway },
|
||||||
|
})(modelID)
|
||||||
},
|
},
|
||||||
options: {},
|
options: {},
|
||||||
}
|
}
|
||||||
@@ -1223,22 +1246,15 @@ function cost(c: ModelsDev.Model["cost"]): Model["cost"] {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep runtime prefix routing and transform SDK identity on one decision.
|
// Cloudflare AI Gateway routes OpenAI and Anthropic models through their native
|
||||||
function cloudflareGatewayRoute(modelID: string) {
|
// passthrough SDKs (Responses / Messages APIs). Resolving the native npm before
|
||||||
if (modelID.startsWith("openai/"))
|
// variants are computed makes reasoning variants produce payloads the native
|
||||||
return {
|
// SDKs understand (e.g. anthropic `effort` instead of compat `reasoningEffort`).
|
||||||
type: "openai" as const,
|
function cloudflareGatewayNpm(providerID: string, modelID: string) {
|
||||||
transformNpm: "@ai-sdk/openai",
|
if (providerID !== "cloudflare-ai-gateway") return undefined
|
||||||
}
|
if (modelID.startsWith("openai/")) return "@ai-sdk/openai"
|
||||||
if (modelID.startsWith("anthropic/"))
|
if (modelID.startsWith("anthropic/")) return "@ai-sdk/anthropic"
|
||||||
return {
|
return undefined
|
||||||
type: "anthropic" as const,
|
|
||||||
transformNpm: "@ai-sdk/anthropic",
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
type: "unified" as const,
|
|
||||||
transformNpm: undefined,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function fromModelsDevModel(provider: ModelsDev.Provider, model: ModelsDev.Model): Model {
|
function fromModelsDevModel(provider: ModelsDev.Provider, model: ModelsDev.Model): Model {
|
||||||
@@ -1251,7 +1267,7 @@ function fromModelsDevModel(provider: ModelsDev.Provider, model: ModelsDev.Model
|
|||||||
id: model.id,
|
id: model.id,
|
||||||
url: model.provider?.api ?? provider.api ?? "",
|
url: model.provider?.api ?? provider.api ?? "",
|
||||||
npm:
|
npm:
|
||||||
(provider.id === "cloudflare-ai-gateway" ? cloudflareGatewayRoute(model.id).transformNpm : undefined) ??
|
cloudflareGatewayNpm(provider.id, model.id) ??
|
||||||
model.provider?.npm ??
|
model.provider?.npm ??
|
||||||
provider.npm ??
|
provider.npm ??
|
||||||
"@ai-sdk/openai-compatible",
|
"@ai-sdk/openai-compatible",
|
||||||
@@ -1478,7 +1494,7 @@ const layer = Layer.effect(
|
|||||||
existingModel?.api.npm ??
|
existingModel?.api.npm ??
|
||||||
// Config-defined gateway models bypass fromModelsDevModel, so resolve the
|
// Config-defined gateway models bypass fromModelsDevModel, so resolve the
|
||||||
// native passthrough npm here before falling back to the catalog default.
|
// native passthrough npm here before falling back to the catalog default.
|
||||||
(providerID === "cloudflare-ai-gateway" ? cloudflareGatewayRoute(apiID).transformNpm : undefined) ??
|
cloudflareGatewayNpm(providerID, apiID) ??
|
||||||
modelsDev[providerID]?.npm ??
|
modelsDev[providerID]?.npm ??
|
||||||
"@ai-sdk/openai-compatible"
|
"@ai-sdk/openai-compatible"
|
||||||
const name = iife(() => {
|
const name = iife(() => {
|
||||||
|
|||||||
@@ -528,7 +528,6 @@ const GEMINI_MODELS_WITH_SAMPLING_DEFAULTS = [
|
|||||||
export function temperature(model: Provider.Model) {
|
export function temperature(model: Provider.Model) {
|
||||||
const id = model.api.id.toLowerCase()
|
const id = model.api.id.toLowerCase()
|
||||||
if (id.includes("north-mini-code")) return 1.0
|
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("claude")) return undefined
|
||||||
if (id.includes("gemini"))
|
if (id.includes("gemini"))
|
||||||
return GEMINI_MODELS_WITH_SAMPLING_DEFAULTS.some((model) => model.test(id)) ? 1.0 : undefined
|
return GEMINI_MODELS_WITH_SAMPLING_DEFAULTS.some((model) => model.test(id)) ? 1.0 : undefined
|
||||||
@@ -547,7 +546,6 @@ export function temperature(model: Provider.Model) {
|
|||||||
|
|
||||||
export function topP(model: Provider.Model) {
|
export function topP(model: Provider.Model) {
|
||||||
const id = model.api.id.toLowerCase()
|
const id = model.api.id.toLowerCase()
|
||||||
if (id.includes("qwen")) return 1
|
|
||||||
if (id.includes("gemini"))
|
if (id.includes("gemini"))
|
||||||
return GEMINI_MODELS_WITH_SAMPLING_DEFAULTS.some((model) => model.test(id)) ? 0.95 : undefined
|
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))) {
|
if (["minimax-m2", "kimi-k2.5", "kimi-k2p5", "kimi-k2-5"].some((s) => id.includes(s))) {
|
||||||
@@ -1305,13 +1303,13 @@ export function options(input: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only set textVerbosity for non-chat gpt-5.x models
|
// Generic OpenAI-compatible APIs do not necessarily support OpenAI's verbosity parameter.
|
||||||
// Chat models (e.g. gpt-5.2-chat-latest) only support "medium" verbosity
|
// Only enable the default for integrations known to implement it.
|
||||||
if (
|
if (
|
||||||
input.model.api.id.includes("gpt-5.") &&
|
input.model.api.id.includes("gpt-5.") &&
|
||||||
!input.model.api.id.includes("codex") &&
|
!input.model.api.id.includes("codex") &&
|
||||||
!input.model.api.id.includes("-chat") &&
|
!input.model.api.id.includes("-chat") &&
|
||||||
input.model.providerID !== "azure"
|
(input.model.api.npm === "@ai-sdk/openai" || input.model.api.npm === "@ai-sdk/amazon-bedrock/mantle")
|
||||||
) {
|
) {
|
||||||
result["textVerbosity"] = "low"
|
result["textVerbosity"] = "low"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import { InstanceDisposed } from "@/server/event"
|
|||||||
import "@opencode-ai/core/account"
|
import "@opencode-ai/core/account"
|
||||||
import "@/server/event"
|
import "@/server/event"
|
||||||
import { Schema } from "effect"
|
import { Schema } from "effect"
|
||||||
import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi"
|
import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
|
||||||
|
import semver from "semver"
|
||||||
import { described } from "./metadata"
|
import { described } from "./metadata"
|
||||||
|
|
||||||
const GlobalHealth = Schema.Struct({
|
const GlobalHealth = Schema.Struct({
|
||||||
@@ -48,7 +49,9 @@ const GlobalEventSchema = Schema.Struct({
|
|||||||
}).annotate({ identifier: "GlobalEvent" })
|
}).annotate({ identifier: "GlobalEvent" })
|
||||||
|
|
||||||
export const GlobalUpgradeInput = Schema.Struct({
|
export const GlobalUpgradeInput = Schema.Struct({
|
||||||
target: Schema.optional(Schema.String),
|
target: Schema.String.check(
|
||||||
|
Schema.makeFilter((value) => (semver.valid(value) === null ? "Expected a semantic version" : undefined)),
|
||||||
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
const GlobalUpgradeResult = Schema.Union([
|
const GlobalUpgradeResult = Schema.Union([
|
||||||
@@ -121,14 +124,14 @@ export const GlobalApi = HttpApi.make("global").add(
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
HttpApiEndpoint.post("upgrade", GlobalPaths.upgrade, {
|
HttpApiEndpoint.post("upgrade", GlobalPaths.upgrade, {
|
||||||
payload: [HttpApiSchema.NoContent, GlobalUpgradeInput],
|
payload: GlobalUpgradeInput,
|
||||||
success: described(GlobalUpgradeResult, "Upgrade result"),
|
success: described(GlobalUpgradeResult, "Upgrade result"),
|
||||||
error: HttpApiError.BadRequest,
|
error: HttpApiError.BadRequest,
|
||||||
}).annotateMerge(
|
}).annotateMerge(
|
||||||
OpenApi.annotations({
|
OpenApi.annotations({
|
||||||
identifier: "global.upgrade",
|
identifier: "global.upgrade",
|
||||||
summary: "Upgrade opencode",
|
summary: "Upgrade opencode",
|
||||||
description: "Upgrade opencode to the specified version or latest if not specified.",
|
description: "Upgrade opencode to the specified version.",
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import { EventV2 } from "@opencode-ai/core/event"
|
|||||||
import { Installation } from "@/installation"
|
import { Installation } from "@/installation"
|
||||||
import { disposeAllInstancesAndEmitGlobalDisposed } from "@/server/global-lifecycle"
|
import { disposeAllInstancesAndEmitGlobalDisposed } from "@/server/global-lifecycle"
|
||||||
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
||||||
import { Effect, Queue, Schema } from "effect"
|
import { Effect, Queue } from "effect"
|
||||||
import * as Stream from "effect/Stream"
|
import * as Stream from "effect/Stream"
|
||||||
import { HttpServerRequest, HttpServerResponse } from "effect/unstable/http"
|
import { HttpServerResponse } from "effect/unstable/http"
|
||||||
import { HttpApiBuilder } from "effect/unstable/httpapi"
|
import { HttpApiBuilder } from "effect/unstable/httpapi"
|
||||||
import * as Sse from "effect/unstable/encoding/Sse"
|
import * as Sse from "effect/unstable/encoding/Sse"
|
||||||
import { RootHttpApi } from "../api"
|
import { RootHttpApi } from "../api"
|
||||||
@@ -22,14 +22,6 @@ function eventData(data: unknown): Sse.Event {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseBody(body: string) {
|
|
||||||
try {
|
|
||||||
return JSON.parse(body || "{}") as unknown
|
|
||||||
} catch {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function eventResponse() {
|
function eventResponse() {
|
||||||
return Effect.gen(function* () {
|
return Effect.gen(function* () {
|
||||||
yield* Effect.logInfo("global event connected")
|
yield* Effect.logInfo("global event connected")
|
||||||
@@ -97,25 +89,22 @@ export const globalHandlers = HttpApiBuilder.group(RootHttpApi, "global", (handl
|
|||||||
const upgrade = Effect.fn("GlobalHttpApi.upgrade")(function* (ctx: { payload: typeof GlobalUpgradeInput.Type }) {
|
const upgrade = Effect.fn("GlobalHttpApi.upgrade")(function* (ctx: { payload: typeof GlobalUpgradeInput.Type }) {
|
||||||
const method = yield* installation.method()
|
const method = yield* installation.method()
|
||||||
if (method === "unknown") {
|
if (method === "unknown") {
|
||||||
return {
|
return HttpServerResponse.jsonUnsafe(
|
||||||
status: 400,
|
{ success: false as const, error: "Unknown installation method" },
|
||||||
body: { success: false as const, error: "Unknown installation method" },
|
{ status: 400 },
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
const target = ctx.payload.target || (yield* installation.latest(method))
|
const target = ctx.payload.target
|
||||||
const result = yield* installation.upgrade(method, target).pipe(
|
const result = yield* installation.upgrade(method, target).pipe(
|
||||||
Effect.as({ status: 200, body: { success: true as const, version: target } }),
|
Effect.as({ success: true as const, version: target }),
|
||||||
Effect.catch((err) =>
|
Effect.catch((err) =>
|
||||||
Effect.succeed({
|
Effect.succeed({
|
||||||
status: 500,
|
success: false as const,
|
||||||
body: {
|
error: err instanceof Error ? err.message : String(err),
|
||||||
success: false as const,
|
|
||||||
error: err instanceof Error ? err.message : String(err),
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
if (!result.body.success) return result
|
if (!result.success) return HttpServerResponse.jsonUnsafe(result, { status: 500 })
|
||||||
GlobalBus.emit("event", {
|
GlobalBus.emit("event", {
|
||||||
directory: "global",
|
directory: "global",
|
||||||
payload: {
|
payload: {
|
||||||
@@ -123,26 +112,7 @@ export const globalHandlers = HttpApiBuilder.group(RootHttpApi, "global", (handl
|
|||||||
properties: { version: target },
|
properties: { version: target },
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return result
|
return HttpServerResponse.jsonUnsafe(result)
|
||||||
})
|
|
||||||
|
|
||||||
const upgradeRaw = Effect.fn("GlobalHttpApi.upgradeRaw")(function* (ctx: {
|
|
||||||
request: HttpServerRequest.HttpServerRequest
|
|
||||||
}) {
|
|
||||||
const body = yield* Effect.orDie(ctx.request.text)
|
|
||||||
const json = parseBody(body)
|
|
||||||
if (json === undefined) {
|
|
||||||
return HttpServerResponse.jsonUnsafe({ success: false, error: "Invalid request body" }, { status: 400 })
|
|
||||||
}
|
|
||||||
const payload = yield* Schema.decodeUnknownEffect(GlobalUpgradeInput)(json).pipe(
|
|
||||||
Effect.map((payload) => ({ valid: true as const, payload })),
|
|
||||||
Effect.catch(() => Effect.succeed({ valid: false as const })),
|
|
||||||
)
|
|
||||||
if (!payload.valid) {
|
|
||||||
return HttpServerResponse.jsonUnsafe({ success: false, error: "Invalid request body" }, { status: 400 })
|
|
||||||
}
|
|
||||||
const result = yield* upgrade({ payload: payload.payload })
|
|
||||||
return HttpServerResponse.jsonUnsafe(result.body, { status: result.status })
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return handlers
|
return handlers
|
||||||
@@ -151,6 +121,6 @@ export const globalHandlers = HttpApiBuilder.group(RootHttpApi, "global", (handl
|
|||||||
.handle("configGet", configGet)
|
.handle("configGet", configGet)
|
||||||
.handle("configUpdate", configUpdate)
|
.handle("configUpdate", configUpdate)
|
||||||
.handle("dispose", dispose)
|
.handle("dispose", dispose)
|
||||||
.handleRaw("upgrade", upgradeRaw)
|
.handle("upgrade", upgrade)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { ProviderAuth } from "@/provider/auth"
|
|||||||
import { Config } from "@/config/config"
|
import { Config } from "@/config/config"
|
||||||
import { ModelsDev } from "@opencode-ai/core/models-dev"
|
import { ModelsDev } from "@opencode-ai/core/models-dev"
|
||||||
import { Provider } from "@/provider/provider"
|
import { Provider } from "@/provider/provider"
|
||||||
|
import { Auth } from "@/auth"
|
||||||
|
|
||||||
import { mapValues } from "remeda"
|
import { mapValues } from "remeda"
|
||||||
import { Effect, Schema } from "effect"
|
import { Effect, Schema } from "effect"
|
||||||
@@ -36,6 +37,7 @@ export const providerHandlers = HttpApiBuilder.group(InstanceHttpApi, "provider"
|
|||||||
const cfg = yield* Config.Service
|
const cfg = yield* Config.Service
|
||||||
const provider = yield* Provider.Service
|
const provider = yield* Provider.Service
|
||||||
const svc = yield* ProviderAuth.Service
|
const svc = yield* ProviderAuth.Service
|
||||||
|
const authStore = yield* Auth.Service
|
||||||
|
|
||||||
const list = Effect.fn("ProviderHttpApi.list")(function* () {
|
const list = Effect.fn("ProviderHttpApi.list")(function* () {
|
||||||
const config = yield* cfg.get()
|
const config = yield* cfg.get()
|
||||||
@@ -47,6 +49,7 @@ export const providerHandlers = HttpApiBuilder.group(InstanceHttpApi, "provider"
|
|||||||
if ((enabled ? enabled.has(key) : true) && !disabled.has(key)) filtered[key] = value
|
if ((enabled ? enabled.has(key) : true) && !disabled.has(key)) filtered[key] = value
|
||||||
}
|
}
|
||||||
const connected = yield* provider.list()
|
const connected = yield* provider.list()
|
||||||
|
const credentials = yield* authStore.all().pipe(Effect.orDie)
|
||||||
const providers = Object.assign(
|
const providers = Object.assign(
|
||||||
mapValues(filtered, (item) => Provider.fromModelsDevProvider(item)),
|
mapValues(filtered, (item) => Provider.fromModelsDevProvider(item)),
|
||||||
connected,
|
connected,
|
||||||
@@ -54,7 +57,7 @@ export const providerHandlers = HttpApiBuilder.group(InstanceHttpApi, "provider"
|
|||||||
return {
|
return {
|
||||||
all: Object.values(providers).map(Provider.toPublicInfo),
|
all: Object.values(providers).map(Provider.toPublicInfo),
|
||||||
default: Provider.defaultModelIDs(providers),
|
default: Provider.defaultModelIDs(providers),
|
||||||
connected: Object.keys(connected),
|
connected: Object.keys(providers).filter((id) => id in connected || credentials[id]),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { FinishReason, LLMEvent, ProviderMetadata, ToolResultValue } from "@open
|
|||||||
import { Effect, Schema } from "effect"
|
import { Effect, Schema } from "effect"
|
||||||
import { type streamText } from "ai"
|
import { type streamText } from "ai"
|
||||||
import { errorMessage } from "@/util/error"
|
import { errorMessage } from "@/util/error"
|
||||||
|
import { ProviderError } from "@/provider/error"
|
||||||
|
|
||||||
type Result = Awaited<ReturnType<typeof streamText>>
|
type Result = Awaited<ReturnType<typeof streamText>>
|
||||||
type AISDKEvent = Result["fullStream"] extends AsyncIterable<infer T> ? T : never
|
type AISDKEvent = Result["fullStream"] extends AsyncIterable<infer T> ? T : never
|
||||||
@@ -85,6 +86,8 @@ export function toLLMEvents(
|
|||||||
return Effect.succeed([LLMEvent.stepStart({ index: state.step })])
|
return Effect.succeed([LLMEvent.stepStart({ index: state.step })])
|
||||||
|
|
||||||
case "finish-step":
|
case "finish-step":
|
||||||
|
if (event.rawFinishReason === "network_error")
|
||||||
|
return Effect.fail(new ProviderError.ResponseStreamError("Provider finish_reason: network_error"))
|
||||||
return Effect.sync(() => {
|
return Effect.sync(() => {
|
||||||
const original = providerMetadata(event.providerMetadata)
|
const original = providerMetadata(event.providerMetadata)
|
||||||
const metadata =
|
const metadata =
|
||||||
|
|||||||
@@ -196,9 +196,9 @@ export const prepare = Effect.fn("LLMRequestPrep.prepare")(function* (input: Pre
|
|||||||
: {
|
: {
|
||||||
"x-session-affinity": input.sessionID,
|
"x-session-affinity": input.sessionID,
|
||||||
"X-Session-Id": input.sessionID,
|
"X-Session-Id": input.sessionID,
|
||||||
...(input.parentSessionID ? { "x-parent-session-id": input.parentSessionID } : {}),
|
|
||||||
"User-Agent": USER_AGENT,
|
"User-Agent": USER_AGENT,
|
||||||
}),
|
}),
|
||||||
|
...(input.parentSessionID ? { "x-parent-session-id": input.parentSessionID } : {}),
|
||||||
...input.model.headers,
|
...input.model.headers,
|
||||||
...headers,
|
...headers,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1110,7 +1110,7 @@ const layer = Layer.effect(
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
lastAssistant?.finish &&
|
lastAssistant?.finish &&
|
||||||
!["tool-calls"].includes(lastAssistant.finish) &&
|
!["tool-calls", "unknown"].includes(lastAssistant.finish) &&
|
||||||
!hasToolCalls &&
|
!hasToolCalls &&
|
||||||
lastAssistant.parentID === lastUser.id
|
lastAssistant.parentID === lastUser.id
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -34,9 +34,10 @@ const RETRYABLE_MESSAGE_PATTERNS = [
|
|||||||
/429|500|502|503|504|524/i,
|
/429|500|502|503|504|524/i,
|
||||||
/rate increased too quickly|rate limit|rate-limit|rate_limit|too many requests/i,
|
/rate increased too quickly|rate limit|rate-limit|rate_limit|too many requests/i,
|
||||||
/overloaded|service unavailable|service_unavailable|service-unavailable|internal error|internal_error|internal server error|server error|server_error|server-error|provider returned error|provider_returned_error|provider-returned-error/i,
|
/overloaded|service unavailable|service_unavailable|service-unavailable|internal error|internal_error|internal server error|server error|server_error|server-error|provider returned error|provider_returned_error|provider-returned-error/i,
|
||||||
/terminated|fetch failed|failed to fetch|network error|upstream connect|connection error|connection refused|connection lost|socket connection was closed|socket hang up|reset before headers|getaddrinfo|enotfound|eai_again|econnrefused|econnreset|etimedout/i,
|
/terminated|fetch failed|failed to fetch|network[-_\s]error|upstream connect|connection error|connection refused|connection lost|socket connection was closed|socket hang up|reset before headers|getaddrinfo|enotfound|eai_again|econnrefused|econnreset|etimedout/i,
|
||||||
/^timeout$|\b(?:request|response|connection|network|stream|read) (?:timeout|timed out|time out)\b/i,
|
/^timeout$|\b(?:request|response|connection|network|stream|read) (?:timeout|timed out|time out)\b/i,
|
||||||
/try your request again|retry your request|resource exhausted|resource_exhausted/i,
|
/try your request again|retry your request|resource exhausted|resource_exhausted/i,
|
||||||
|
/\btry again (?:later|in\b)|\b(?:currently|temporarily) at capacity\b/i,
|
||||||
]
|
]
|
||||||
|
|
||||||
function cap(ms: number) {
|
function cap(ms: number) {
|
||||||
@@ -102,7 +103,7 @@ export function retryable(error: Err, provider: string) {
|
|||||||
reason: "free_tier_limit",
|
reason: "free_tier_limit",
|
||||||
provider,
|
provider,
|
||||||
title: "Free limit reached",
|
title: "Free limit reached",
|
||||||
message: "Subscribe to OpenCode Go for reliable access to the best open-source models, starting at $5/month.",
|
message: "Subscribe to OpenCode Go for reliable access to the best open-source models for $10/month.",
|
||||||
label: "subscribe",
|
label: "subscribe",
|
||||||
link: GO_UPSELL_URL,
|
link: GO_UPSELL_URL,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -336,10 +336,8 @@ export function plan(input: { slug: string; time: { created: number } }, instanc
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getUsage = (input: { model: Provider.Model; usage: Usage; metadata?: ProviderMetadata }) => {
|
export const getUsage = (input: { model: Provider.Model; usage: Usage; metadata?: ProviderMetadata }) => {
|
||||||
const safe = (value: number) => {
|
const finite = (value: number) => (Number.isFinite(value) ? value : 0)
|
||||||
if (!Number.isFinite(value)) return 0
|
const safe = (value: number) => Math.max(0, finite(value))
|
||||||
return Math.max(0, value)
|
|
||||||
}
|
|
||||||
const inputTokens = safe(input.usage.inputTokens ?? 0)
|
const inputTokens = safe(input.usage.inputTokens ?? 0)
|
||||||
const outputTokens = safe(input.usage.outputTokens ?? 0)
|
const outputTokens = safe(input.usage.outputTokens ?? 0)
|
||||||
const reasoningTokens = safe(input.usage.reasoningTokens ?? 0)
|
const reasoningTokens = safe(input.usage.reasoningTokens ?? 0)
|
||||||
@@ -393,13 +391,13 @@ export const getUsage = (input: { model: Provider.Model; usage: Usage; metadata?
|
|||||||
? new Decimal(totalNanoAiu).div(100_000_000_000).toNumber()
|
? new Decimal(totalNanoAiu).div(100_000_000_000).toNumber()
|
||||||
: safe(
|
: safe(
|
||||||
new Decimal(0)
|
new Decimal(0)
|
||||||
.add(new Decimal(tokens.input).mul(costInfo?.input ?? 0).div(1_000_000))
|
.add(new Decimal(tokens.input).mul(finite(costInfo?.input ?? 0)).div(1_000_000))
|
||||||
.add(new Decimal(tokens.output).mul(costInfo?.output ?? 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(costInfo?.cache?.read ?? 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(costInfo?.cache?.write ?? 0).div(1_000_000))
|
.add(new Decimal(tokens.cache.write).mul(finite(costInfo?.cache?.write ?? 0)).div(1_000_000))
|
||||||
// TODO: update models.dev to have better pricing model, for now:
|
// TODO: update models.dev to have better pricing model, for now:
|
||||||
// charge reasoning tokens at the same rate as output tokens
|
// charge reasoning tokens at the same rate as output tokens
|
||||||
.add(new Decimal(tokens.reasoning).mul(costInfo?.output ?? 0).div(1_000_000))
|
.add(new Decimal(tokens.reasoning).mul(finite(costInfo?.output ?? 0)).div(1_000_000))
|
||||||
.toNumber(),
|
.toNumber(),
|
||||||
),
|
),
|
||||||
tokens,
|
tokens,
|
||||||
|
|||||||
@@ -56,7 +56,12 @@ import { PermissionV1 } from "@opencode-ai/core/v1/permission"
|
|||||||
import { McpCatalog } from "@/mcp/catalog"
|
import { McpCatalog } from "@/mcp/catalog"
|
||||||
|
|
||||||
export function webSearchEnabled(providerID: ProviderV2.ID, flags = { exa: false, parallel: false }) {
|
export function webSearchEnabled(providerID: ProviderV2.ID, flags = { exa: false, parallel: false }) {
|
||||||
return providerID === ProviderV2.ID.opencode || flags.exa || flags.parallel
|
return (
|
||||||
|
providerID === ProviderV2.ID.opencode ||
|
||||||
|
providerID === ProviderV2.ID.make("opencode-go") ||
|
||||||
|
flags.exa ||
|
||||||
|
flags.parallel
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
type TaskDef = Tool.InferDef<typeof TaskTool>
|
type TaskDef = Tool.InferDef<typeof TaskTool>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user