mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-23 22:23:18 -04:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 |
@@ -29,7 +29,7 @@
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@corvu/drawer": "catalog:",
|
||||
"@dnd-kit/abstract": "0.5.0",
|
||||
@@ -96,7 +96,7 @@
|
||||
},
|
||||
"packages/cli": {
|
||||
"name": "@opencode-ai/cli",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"bin": {
|
||||
"lildax": "./bin/lildax.cjs",
|
||||
},
|
||||
@@ -144,7 +144,7 @@
|
||||
},
|
||||
"packages/codemode": {
|
||||
"name": "@opencode-ai/codemode",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"acorn": "8.15.0",
|
||||
"effect": "catalog:",
|
||||
@@ -158,7 +158,7 @@
|
||||
},
|
||||
"packages/console/app": {
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@ibm/plex": "6.4.1",
|
||||
@@ -194,7 +194,7 @@
|
||||
},
|
||||
"packages/console/core": {
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sts": "3.782.0",
|
||||
"@jsx-email/render": "1.1.1",
|
||||
@@ -221,7 +221,7 @@
|
||||
},
|
||||
"packages/console/function": {
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "3.0.82",
|
||||
"@ai-sdk/openai": "3.0.48",
|
||||
@@ -243,7 +243,7 @@
|
||||
},
|
||||
"packages/console/mail": {
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
@@ -267,7 +267,7 @@
|
||||
},
|
||||
"packages/console/support": {
|
||||
"name": "@opencode-ai/console-support",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@opencode-ai/console-core": "workspace:*",
|
||||
@@ -287,13 +287,13 @@
|
||||
},
|
||||
"packages/core": {
|
||||
"name": "@opencode-ai/core",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode",
|
||||
},
|
||||
"dependencies": {
|
||||
"@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/azure": "3.0.88",
|
||||
"@ai-sdk/cerebras": "2.0.41",
|
||||
@@ -381,7 +381,7 @@
|
||||
},
|
||||
"packages/desktop": {
|
||||
"name": "@opencode-ai/desktop",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@zip.js/zip.js": "2.7.62",
|
||||
"drizzle-orm": "catalog:",
|
||||
@@ -435,7 +435,7 @@
|
||||
},
|
||||
"packages/effect-drizzle-sqlite": {
|
||||
"name": "@opencode-ai/effect-drizzle-sqlite",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"drizzle-orm": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -449,7 +449,7 @@
|
||||
},
|
||||
"packages/effect-sqlite-node": {
|
||||
"name": "@opencode-ai/effect-sqlite-node",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"effect": "catalog:",
|
||||
},
|
||||
@@ -461,7 +461,7 @@
|
||||
},
|
||||
"packages/enterprise": {
|
||||
"name": "@opencode-ai/enterprise",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@hono/standard-validator": "catalog:",
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
@@ -493,7 +493,7 @@
|
||||
},
|
||||
"packages/function": {
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@octokit/auth-app": "8.0.1",
|
||||
"@octokit/rest": "catalog:",
|
||||
@@ -509,7 +509,7 @@
|
||||
},
|
||||
"packages/http-recorder": {
|
||||
"name": "@opencode-ai/http-recorder",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@effect/platform-node": "4.0.0-beta.83",
|
||||
"@effect/platform-node-shared": "4.0.0-beta.83",
|
||||
@@ -540,7 +540,7 @@
|
||||
},
|
||||
"packages/llm": {
|
||||
"name": "@opencode-ai/llm",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@opencode-ai/schema": "workspace:*",
|
||||
"@smithy/eventstream-codec": "4.2.14",
|
||||
@@ -559,7 +559,7 @@
|
||||
},
|
||||
"packages/opencode": {
|
||||
"name": "opencode",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode",
|
||||
},
|
||||
@@ -568,7 +568,7 @@
|
||||
"@actions/github": "6.0.1",
|
||||
"@agentclientprotocol/sdk": "0.21.0",
|
||||
"@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/azure": "3.0.88",
|
||||
"@ai-sdk/cerebras": "2.0.60",
|
||||
@@ -690,7 +690,7 @@
|
||||
},
|
||||
"packages/plugin": {
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@ai-sdk/provider": "3.0.8",
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
@@ -766,7 +766,7 @@
|
||||
},
|
||||
"packages/sdk/js": {
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"cross-spawn": "catalog:",
|
||||
},
|
||||
@@ -781,7 +781,7 @@
|
||||
},
|
||||
"packages/server": {
|
||||
"name": "@opencode-ai/server",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
"@opencode-ai/protocol": "workspace:*",
|
||||
@@ -796,7 +796,7 @@
|
||||
},
|
||||
"packages/session-ui": {
|
||||
"name": "@opencode-ai/session-ui",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode-ai/client": "file:../app/vendor/opencode-ai-client-1.17.13-v2.tgz",
|
||||
@@ -836,7 +836,7 @@
|
||||
},
|
||||
"packages/slack": {
|
||||
"name": "@opencode-ai/slack",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"@slack/bolt": "^3.17.1",
|
||||
@@ -849,7 +849,7 @@
|
||||
},
|
||||
"packages/stats/app": {
|
||||
"name": "@opencode-ai/stats-app",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@ibm/plex": "6.4.1",
|
||||
"@kobalte/core": "catalog:",
|
||||
@@ -883,7 +883,7 @@
|
||||
},
|
||||
"packages/stats/core": {
|
||||
"name": "@opencode-ai/stats-core",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-athena": "3.933.0",
|
||||
"@planetscale/database": "1.19.0",
|
||||
@@ -902,7 +902,7 @@
|
||||
},
|
||||
"packages/stats/server": {
|
||||
"name": "@opencode-ai/stats-server",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-firehose": "3.933.0",
|
||||
"@effect/platform-node": "catalog:",
|
||||
@@ -944,7 +944,7 @@
|
||||
},
|
||||
"packages/tui": {
|
||||
"name": "@opencode-ai/tui",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
"@opencode-ai/plugin": "workspace:*",
|
||||
@@ -971,7 +971,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@pierre/diffs": "catalog:",
|
||||
@@ -1022,7 +1022,7 @@
|
||||
},
|
||||
"packages/web": {
|
||||
"name": "@opencode-ai/web",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@astrojs/cloudflare": "12.6.3",
|
||||
"@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/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=="],
|
||||
|
||||
@@ -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/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=="],
|
||||
|
||||
@@ -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/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/azure/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"nodeModules": {
|
||||
"x86_64-linux": "sha256-yQ8EIxxYkzlEWIMY/UiIR+7lbGBuizsoehMPZzFA65Y=",
|
||||
"aarch64-linux": "sha256-JF9VVgnl5QUZ430fqb5Qu8y0kchYJ00LO3FbYcd0lBM=",
|
||||
"aarch64-darwin": "sha256-f3Tu6eu463NWcHgr7dupfD/zUTh26bJ6N2vVXuEyi6c=",
|
||||
"x86_64-darwin": "sha256-miv9Sv4KdhD0UIi2O5LVS1wQOfq29IV+9S+BvIzAvgo="
|
||||
"x86_64-linux": "sha256-Be1I6OG6UitofhcGu2BeNzevmoQXc4Or5r/NPzwtft4=",
|
||||
"aarch64-linux": "sha256-O+d+26CQIjZ08Rn8Qm3IytdDqIMbPdhzaGOZeUKAvIU=",
|
||||
"aarch64-darwin": "sha256-ObS50y/oy6fM9wSGUL/wx6O0+fTWHC04mXJNd7w/2Z0=",
|
||||
"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)
|
||||
})
|
||||
|
||||
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 }
|
||||
|
||||
async function writeProbe(page: Page) {
|
||||
@@ -74,7 +107,10 @@ async function readProbe(page: Page) {
|
||||
.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, {
|
||||
directory,
|
||||
project: {
|
||||
@@ -119,6 +155,7 @@ async function setup(page: Page) {
|
||||
}))
|
||||
},
|
||||
fileContent: (path) => ({ type: "text", content: `contents:${path}` }),
|
||||
findFiles,
|
||||
pageMessages: () => ({ items: [] }),
|
||||
})
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ export interface MockServerConfig {
|
||||
questions?: unknown[] | (() => unknown[])
|
||||
fileList?: (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>)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -450,7 +450,7 @@ function ModelSelectorPopoverV2View(props: {
|
||||
<For each={groups()}>
|
||||
{(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>
|
||||
</MenuV2.GroupLabel>
|
||||
<MenuV2.RadioGroup value={props.current()}>
|
||||
|
||||
@@ -972,17 +972,6 @@ export default function LegacyLayout(props: ParentProps) {
|
||||
keybind: "shift+alt+arrowdown",
|
||||
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",
|
||||
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 { useLanguage } from "@/context/language"
|
||||
import { useSessionKey } from "@/pages/session/session-layout"
|
||||
import { useSessionArchive } from "@/pages/session/session-archive"
|
||||
import { useServerSDK } from "@/context/server-sdk"
|
||||
import { usePlatform } from "@/context/platform"
|
||||
import { useSettings } from "@/context/settings"
|
||||
import { useTabs } from "@/context/tabs"
|
||||
import { legacySessionHref, requireServerKey, sessionHref } from "@/utils/session-route"
|
||||
import { useSDK } from "@/context/sdk"
|
||||
import { useSync } from "@/context/sync"
|
||||
@@ -263,8 +263,8 @@ export function MessageTimeline(props: {
|
||||
const sdk = useSDK()
|
||||
const sync = useSync()
|
||||
const settings = useSettings()
|
||||
const tabs = useTabs()
|
||||
const dialog = useDialog()
|
||||
const sessionArchive = useSessionArchive()
|
||||
const language = useLanguage()
|
||||
const { params, sessionKey } = useSessionKey()
|
||||
const ownerSessionKey = sessionKey()
|
||||
@@ -790,25 +790,6 @@ export function MessageTimeline(props: {
|
||||
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) => {
|
||||
try {
|
||||
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 session = sync().session.get(sessionID)
|
||||
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(
|
||||
produce((draft) => {
|
||||
@@ -1593,7 +1544,7 @@ export function MessageTimeline(props: {
|
||||
<DropdownMenu.Item onSelect={() => exportSession(id)}>
|
||||
<DropdownMenu.ItemLabel>{language.t("common.export")}</DropdownMenu.ItemLabel>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item onSelect={() => void archiveSession(id)}>
|
||||
<DropdownMenu.Item onSelect={() => void sessionArchive.archive(id)}>
|
||||
<DropdownMenu.ItemLabel>{language.t("common.archive")}</DropdownMenu.ItemLabel>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Separator />
|
||||
@@ -1667,7 +1618,7 @@ export function MessageTimeline(props: {
|
||||
<MenuV2.Item onSelect={() => exportSession(id)}>
|
||||
{language.t("common.export")}...
|
||||
</MenuV2.Item>
|
||||
<MenuV2.Item onSelect={() => void archiveSession(id)}>
|
||||
<MenuV2.Item onSelect={() => void sessionArchive.archive(id)}>
|
||||
{language.t("common.archive")}
|
||||
</MenuV2.Item>
|
||||
<MenuV2.Separator />
|
||||
|
||||
@@ -18,6 +18,7 @@ import { createSessionTabs } from "@/pages/session/helpers"
|
||||
import { extractPromptFromParts } from "@/utils/prompt"
|
||||
import { Message, Part, UserMessage } from "@opencode-ai/sdk/v2"
|
||||
import { useSessionLayout } from "@/pages/session/session-layout"
|
||||
import { useSessionArchive } from "@/pages/session/session-archive"
|
||||
import { createSessionOwnership } from "./session-ownership"
|
||||
import { useLocal } from "@/context/local"
|
||||
|
||||
@@ -52,6 +53,7 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
||||
const navigate = useNavigate()
|
||||
const { params, sessionKey, tabs, view } = useSessionLayout()
|
||||
const sessionOwnership = createSessionOwnership(sessionKey)
|
||||
const sessionArchive = useSessionArchive()
|
||||
const openDialog = async <T,>(load: () => Promise<T>, show: (value: T) => void) => {
|
||||
const owner = sessionOwnership.capture()
|
||||
const value = await load()
|
||||
@@ -497,6 +499,16 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
||||
disabled: !params.id,
|
||||
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 = () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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 { SessionFilePanelV2, SessionFilePanelV2Empty } from "@opencode-ai/session-ui/v2/session-file-panel-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,
|
||||
enabled: value.length > 0,
|
||||
queryFn: ({ signal }) => file.searchFiles(value, { limit: 200, signal }),
|
||||
placeholderData: keepPreviousData,
|
||||
}
|
||||
})
|
||||
const files = createMemo(() => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/cli",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/codemode",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"description": "Effect-native confined code execution over schema-described tools",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -271,6 +271,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"go.graph.label": "الطلبات كل 5 ساعات",
|
||||
"go.graph.limitedRegions": "مناطق محدودة",
|
||||
"go.graph.limitedTime": "لفترة محدودة",
|
||||
"go.graph.usageLimits": "حدود الاستخدام",
|
||||
"go.graph.aria": "الطلبات كل 5 ساعات: {{free}} مقابل {{go}}",
|
||||
|
||||
|
||||
@@ -275,6 +275,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"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.aria": "Requisições por 5h: {{free}} vs {{go}}",
|
||||
|
||||
|
||||
@@ -273,6 +273,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"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.aria": "Forespørgsler pr. 5t: {{free}} vs {{go}}",
|
||||
|
||||
|
||||
@@ -275,6 +275,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"go.graph.label": "Anfragen pro 5 Stunden",
|
||||
"go.graph.limitedRegions": "begrenzte Regionen",
|
||||
"go.graph.limitedTime": "begrenzte Zeit",
|
||||
"go.graph.usageLimits": "Nutzungslimits",
|
||||
"go.graph.aria": "Anfragen pro 5h: {{free}} vs {{go}}",
|
||||
|
||||
|
||||
@@ -271,6 +271,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"go.graph.label": "Requests per 5 hour",
|
||||
"go.graph.limitedRegions": "limited regions",
|
||||
"go.graph.limitedTime": "limited time",
|
||||
"go.graph.tick": "{{n}}x",
|
||||
"go.graph.usageLimits": "Usage limits",
|
||||
"go.graph.aria": "Requests per 5h: {{free}} vs {{go}}",
|
||||
|
||||
@@ -276,6 +276,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"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.aria": "Solicitudes por 5h: {{free}} vs {{go}}",
|
||||
|
||||
|
||||
@@ -277,6 +277,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"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.aria": "Requêtes par 5h : {{free}} vs {{go}}",
|
||||
|
||||
|
||||
@@ -273,6 +273,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"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.aria": "Richieste ogni 5h: {{free}} vs {{go}}",
|
||||
|
||||
|
||||
@@ -272,6 +272,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"go.graph.label": "5時間あたりのリクエスト数",
|
||||
"go.graph.limitedRegions": "一部の地域に限定",
|
||||
"go.graph.limitedTime": "期間限定",
|
||||
"go.graph.usageLimits": "利用制限",
|
||||
"go.graph.aria": "5時間あたりのリクエスト数: {{free}} 対 {{go}}",
|
||||
|
||||
|
||||
@@ -269,6 +269,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"go.graph.label": "5시간당 요청 수",
|
||||
"go.graph.limitedRegions": "일부 지역에서만 제공",
|
||||
"go.graph.limitedTime": "한정된 기간",
|
||||
"go.graph.usageLimits": "사용 한도",
|
||||
"go.graph.aria": "5시간당 요청 수: {{free}} 대 {{go}}",
|
||||
|
||||
|
||||
@@ -273,6 +273,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"go.graph.label": "Forespørsler per 5 timer",
|
||||
"go.graph.limitedRegions": "begrensede regioner",
|
||||
"go.graph.limitedTime": "begrenset periode",
|
||||
"go.graph.usageLimits": "Bruksgrenser",
|
||||
"go.graph.aria": "Forespørsler per 5t: {{free}} vs {{go}}",
|
||||
|
||||
|
||||
@@ -274,6 +274,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"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.aria": "Żądania na 5h: {{free}} vs {{go}}",
|
||||
|
||||
|
||||
@@ -277,6 +277,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"go.graph.label": "Запросов за 5 часов",
|
||||
"go.graph.limitedRegions": "доступно в отдельных регионах",
|
||||
"go.graph.limitedTime": "ограниченное время",
|
||||
"go.graph.usageLimits": "Лимиты использования",
|
||||
"go.graph.aria": "Запросов за 5ч: {{free}} против {{go}}",
|
||||
|
||||
|
||||
@@ -271,6 +271,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"go.graph.label": "คำขอต่อ 5 ชั่วโมง",
|
||||
"go.graph.limitedRegions": "เฉพาะบางภูมิภาค",
|
||||
"go.graph.limitedTime": "ช่วงเวลาจำกัด",
|
||||
"go.graph.usageLimits": "ขีดจำกัดการใช้งาน",
|
||||
"go.graph.aria": "คำขอต่อ 5 ชม.: {{free}} vs {{go}}",
|
||||
|
||||
|
||||
@@ -275,6 +275,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"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.aria": "5 saatlik istekler: {{free}} vs {{go}}",
|
||||
|
||||
|
||||
@@ -274,6 +274,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"go.graph.label": "Запитів за 5 годин",
|
||||
"go.graph.limitedRegions": "обмежені регіони",
|
||||
"go.graph.limitedTime": "обмежений час",
|
||||
"go.graph.usageLimits": "Ліміти використання",
|
||||
"go.graph.aria": "Запитів за 5 год: {{free}} vs {{go}}",
|
||||
|
||||
|
||||
@@ -261,6 +261,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"go.graph.label": "每 5 小时请求数",
|
||||
"go.graph.limitedRegions": "仅限部分地区",
|
||||
"go.graph.limitedTime": "限时",
|
||||
"go.graph.usageLimits": "使用限制",
|
||||
"go.graph.aria": "每 5 小时请求数: {{free}} vs {{go}}",
|
||||
|
||||
|
||||
@@ -261,6 +261,7 @@ export const dict = {
|
||||
"go.graph.go": "Go",
|
||||
"go.graph.label": "每 5 小時請求數",
|
||||
"go.graph.limitedRegions": "僅限部分地區",
|
||||
"go.graph.limitedTime": "限時",
|
||||
"go.graph.usageLimits": "使用限制",
|
||||
"go.graph.aria": "每 5 小時請求數:{{free}} vs {{go}}",
|
||||
|
||||
|
||||
@@ -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 { waitUntil } from "@opencode-ai/console-resource"
|
||||
import type { DownloadPlatform } from "../types"
|
||||
|
||||
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]
|
||||
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}`,
|
||||
{ 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)
|
||||
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 })
|
||||
}
|
||||
|
||||
@@ -592,7 +592,7 @@ body {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
[data-regions] {
|
||||
:is([data-regions], [data-limited]) {
|
||||
color: var(--color-text-weak);
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -698,6 +698,11 @@ body {
|
||||
fill: color-mix(in srgb, var(--bar-go) 50%, transparent);
|
||||
}
|
||||
|
||||
[data-item][data-infinite] [data-value] {
|
||||
font-size: 18px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
[data-val] {
|
||||
fill: var(--color-text-strong);
|
||||
font-size: 13px;
|
||||
|
||||
@@ -80,6 +80,7 @@ function LimitsGraph(props: { href: string }) {
|
||||
{ id: "mimo-v2.5", name: "MiMo-V2.5", req: 30100, d: "340ms" },
|
||||
{ id: "hy3", name: "Hy3", req: 34400, baseReq: 4300, d: "320ms" },
|
||||
{ id: "muse-spark-1.2-contributor", name: "Muse Spark 1.2 Contributor", req: 45300, edge: true, d: "360ms" },
|
||||
{ id: "ox-alpha-free", name: "Ox Alpha Free", req: Infinity, infinite: true, edge: true, d: "400ms" },
|
||||
]
|
||||
|
||||
const w = 1040
|
||||
@@ -89,9 +90,10 @@ function LimitsGraph(props: { href: string }) {
|
||||
const top = 18
|
||||
const bottom = 44
|
||||
const plot = chartW - left - right
|
||||
const infiniteX = w - 180
|
||||
|
||||
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 base = 24
|
||||
const p = 2.2
|
||||
@@ -153,10 +155,10 @@ function LimitsGraph(props: { href: string }) {
|
||||
<rect
|
||||
x={left}
|
||||
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}
|
||||
data-bar
|
||||
data-kind="go"
|
||||
data-kind={"infinite" in m ? "infinite" : "go"}
|
||||
data-model={m.id}
|
||||
/>
|
||||
{m.baseReq && (
|
||||
@@ -200,9 +202,12 @@ function LimitsGraph(props: { href: string }) {
|
||||
data-kind="go"
|
||||
data-model={m.id}
|
||||
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>
|
||||
{m.id === "muse-spark-1.2-contributor" && (
|
||||
<span data-regions>
|
||||
@@ -213,6 +218,7 @@ function LimitsGraph(props: { href: string }) {
|
||||
)
|
||||
</span>
|
||||
)}
|
||||
{"infinite" in m && <span data-limited>({i18n.t("go.graph.limitedTime")})</span>}
|
||||
{m.baseReq && <span data-bonus>8x usage</span>}
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -356,9 +356,11 @@ export function LiteSection(props: { lite: LiteSubscription | undefined }) {
|
||||
<li>Qwen3.6 Plus</li>
|
||||
<li>DeepSeek V4 Pro</li>
|
||||
<li>DeepSeek V4 Flash</li>
|
||||
<li>DeepSeek V4 Flash Vision Exp</li>
|
||||
<li>MiMo-V2.5</li>
|
||||
<li>MiMo-V2.5-Pro</li>
|
||||
<li>Hy3</li>
|
||||
<li>Ox Alpha Free</li>
|
||||
</ul>
|
||||
<p data-slot="promo-description">{i18n.t("workspace.lite.promo.footer")}</p>
|
||||
<div data-slot="subscribe-actions">
|
||||
|
||||
@@ -28,13 +28,7 @@ import {
|
||||
GoUsageLimitError,
|
||||
BlackUsageLimitError,
|
||||
} from "./error"
|
||||
import {
|
||||
buildCostChunk,
|
||||
createBodyConverter,
|
||||
createStreamPartConverter,
|
||||
createResponseConverter,
|
||||
UsageInfo,
|
||||
} from "./provider/provider"
|
||||
import { buildCostChunk, createStreamPartConverter, createResponseConverter, UsageInfo } from "./provider/provider"
|
||||
import { anthropicHelper } from "./provider/anthropic"
|
||||
import { googleHelper } from "./provider/google"
|
||||
import { openaiHelper } from "./provider/openai"
|
||||
@@ -53,12 +47,10 @@ import { createProviderBudgetTracker } from "./providerBudgetTracker"
|
||||
import { accumulateUsage, HOT_WORKSPACES } from "./usageBatcher"
|
||||
import { Workspace } from "@opencode-ai/console-core/workspace.js"
|
||||
import { countryFromRequest, isModelCountryRestricted } from "~/lib/request-country"
|
||||
import { prepareRequestBody } from "./requestBody"
|
||||
|
||||
type ZenData = Awaited<ReturnType<typeof ZenData.list>>
|
||||
type RetryOptions = {
|
||||
excludeProviders: string[]
|
||||
retryCount: number
|
||||
}
|
||||
type PreparedBody = Awaited<ReturnType<typeof prepareRequestBody>>
|
||||
type BillingSource = "anonymous" | "free" | "byok" | "subscription" | "lite" | "balance"
|
||||
|
||||
function resolve(text: string, params?: Record<string, string | number>) {
|
||||
@@ -86,8 +78,6 @@ export async function handler(
|
||||
type ProviderInfo = Awaited<ReturnType<typeof selectProvider>>
|
||||
type CostInfo = ReturnType<typeof calculateCost>
|
||||
|
||||
const MAX_FAILOVER_RETRIES = 3
|
||||
const MAX_RETRYABLE_STATUS_RETRIES = 3
|
||||
const dict = i18n(localeFromRequest(input.request))
|
||||
const t = (key: Key, params?: Record<string, string | number>) => resolve(dict[key], params)
|
||||
const ADMIN_WORKSPACES = [
|
||||
@@ -96,12 +86,14 @@ export async function handler(
|
||||
"wrk_01KKZDKDWCS1VTJF8QTX62DD50", // contributors
|
||||
]
|
||||
|
||||
let requestBody: PreparedBody | undefined
|
||||
try {
|
||||
const url = input.request.url
|
||||
const body = await input.request.json()
|
||||
const model = opts.parseModel(url, body)
|
||||
const variant = opts.parseVariant(url, body)
|
||||
const isStream = opts.parseIsStream(url, body)
|
||||
const body = input.request.body
|
||||
if (!body) throw new Error("Missing request body")
|
||||
requestBody = opts.format === "google" ? undefined : await prepareRequestBody(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 ip = rawIp.includes(":") ? rawIp.split(":").slice(0, 4).join(":") : rawIp
|
||||
const rawZenApiKey = opts.parseApiKey(input.request.headers)
|
||||
@@ -112,12 +104,10 @@ export async function handler(
|
||||
const projectId = input.request.headers.get("x-opencode-project") ?? ""
|
||||
const userAgent = input.request.headers.get("user-agent") ?? ""
|
||||
logger.metric({
|
||||
is_stream: isStream,
|
||||
session: sessionId,
|
||||
request: requestId,
|
||||
client: ocClient,
|
||||
user_agent: userAgent,
|
||||
"model.variant": variant,
|
||||
"model.tier": opts.modelList === "full" ? "zen" : "go",
|
||||
})
|
||||
const zenData = ZenData.list(opts.modelList)
|
||||
@@ -175,7 +165,7 @@ export async function handler(
|
||||
)
|
||||
const providerBudget = await providerBudgetTracker?.check()
|
||||
|
||||
const retriableRequest = async (retry: RetryOptions = { excludeProviders: [], retryCount: 0 }) => {
|
||||
const providerRequest = async () => {
|
||||
const providerInfo = selectProvider(
|
||||
model,
|
||||
zenData,
|
||||
@@ -183,7 +173,6 @@ export async function handler(
|
||||
modelInfo,
|
||||
stickyId,
|
||||
trialProviders,
|
||||
retry,
|
||||
stickyProvider,
|
||||
modelTpmLimits,
|
||||
modelTpsLimits,
|
||||
@@ -199,80 +188,65 @@ export async function handler(
|
||||
})
|
||||
|
||||
const startTimestamp = Date.now()
|
||||
const reqUrl = providerInfo.modifyUrl(providerInfo.api, isStream)
|
||||
const reqBody = JSON.stringify(
|
||||
providerInfo.modifyBody({
|
||||
...createBodyConverter(opts.format, providerInfo.format)(body),
|
||||
model: providerInfo.model,
|
||||
...(() => {
|
||||
const replacer = (obj: Record<string, any>): Record<string, any> =>
|
||||
Object.fromEntries(
|
||||
Object.entries(obj).flatMap(([k, v]) => {
|
||||
if (Array.isArray(v)) return [[k, v]]
|
||||
if (typeof v === "object") return [[k, replacer(v)]]
|
||||
if (typeof v === "string") {
|
||||
if (v === "$workspace") return authInfo?.workspaceID ? [[k, authInfo.workspaceID]] : []
|
||||
if (v === "$org")
|
||||
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 ?? {})
|
||||
})(),
|
||||
}),
|
||||
)
|
||||
const reqUrl = providerInfo.modifyUrl(providerInfo.api, googleStream ?? false)
|
||||
const specialAnthropic =
|
||||
providerInfo.format === "anthropic" &&
|
||||
(providerInfo.model.startsWith("arn:aws:bedrock:") ||
|
||||
providerInfo.model.startsWith("global.anthropic.") ||
|
||||
providerInfo.model.startsWith("databricks-claude-"))
|
||||
if (providerInfo.format !== opts.format) throw new Error("Zen provider format must match request format")
|
||||
if (specialAnthropic) throw new Error("Anthropic provider body modifiers are incompatible with streaming")
|
||||
const prepared = requestBody
|
||||
|
||||
const reqBody = (() => {
|
||||
if (opts.format === "google") return body
|
||||
if (!prepared) throw new Error("Missing prepared request body")
|
||||
return prepared.stream(providerInfo.model, providerInfo.format === "oa-compat")
|
||||
})()
|
||||
logger.debug("REQUEST URL: " + reqUrl)
|
||||
logger.debug("REQUEST: " + reqBody.substring(0, 300) + "...")
|
||||
logger.debug("REQUEST: " + (requestBody?.preview ?? "") + "...")
|
||||
const isNewInference =
|
||||
providerInfo.id.startsWith("console.") ||
|
||||
providerInfo.id.startsWith("console-go.") ||
|
||||
providerInfo.id.startsWith("inf.") ||
|
||||
providerInfo.id.startsWith("inf-go.")
|
||||
const res = await fetchWithRetryableStatus(
|
||||
reqUrl,
|
||||
{
|
||||
method: "POST",
|
||||
headers: (() => {
|
||||
const headers = new Headers(input.request.headers)
|
||||
providerInfo.modifyHeaders(headers, providerInfo.apiKey, stickyId)
|
||||
Object.entries(providerInfo.headerModifier ?? {}).forEach(([k, v]) => {
|
||||
if (v === "$ip") return headers.set(k, ip)
|
||||
if (v === "$caller") return headers.set(k, stickyId)
|
||||
if (v === "$session") return headers.set(k, sessionId)
|
||||
if (v === "$model") return headers.set(k, model)
|
||||
if (v === "$request") return headers.set(k, requestId)
|
||||
if (v === "$project") return headers.set(k, projectId)
|
||||
if (v === "$workspace") {
|
||||
if (authInfo?.workspaceID) headers.set(k, authInfo.workspaceID)
|
||||
return
|
||||
}
|
||||
if (v === "$org") {
|
||||
if (authInfo?.workspaceID) headers.set(k, authInfo.workspaceID.replace("wrk_", "org_"))
|
||||
return
|
||||
}
|
||||
headers.set(k, v)
|
||||
})
|
||||
headers.delete("host")
|
||||
headers.delete("content-length")
|
||||
headers.delete("x-opencode-request")
|
||||
if (!isNewInference) headers.delete("x-opencode-session")
|
||||
headers.delete("x-opencode-project")
|
||||
headers.delete("x-opencode-client")
|
||||
return headers
|
||||
})(),
|
||||
body: reqBody,
|
||||
// Propagate caller disconnects to the upstream provider request so
|
||||
// abandoned Console requests do not leave orphaned inference work open.
|
||||
signal: input.request.signal,
|
||||
},
|
||||
{ count: isNewInference ? MAX_RETRYABLE_STATUS_RETRIES : 0 },
|
||||
)
|
||||
const res = await fetch(reqUrl, {
|
||||
method: "POST",
|
||||
headers: (() => {
|
||||
const headers = new Headers(input.request.headers)
|
||||
providerInfo.modifyHeaders(headers, providerInfo.apiKey, stickyId)
|
||||
Object.entries(providerInfo.headerModifier ?? {}).forEach(([k, v]) => {
|
||||
if (v === "$ip") return headers.set(k, ip)
|
||||
if (v === "$caller") return headers.set(k, stickyId)
|
||||
if (v === "$session") return headers.set(k, sessionId)
|
||||
if (v === "$model") return headers.set(k, model)
|
||||
if (v === "$request") return headers.set(k, requestId)
|
||||
if (v === "$project") return headers.set(k, projectId)
|
||||
if (v === "$workspace") {
|
||||
if (authInfo?.workspaceID) headers.set(k, authInfo.workspaceID)
|
||||
return
|
||||
}
|
||||
if (v === "$org") {
|
||||
if (authInfo?.workspaceID) headers.set(k, authInfo.workspaceID.replace("wrk_", "org_"))
|
||||
return
|
||||
}
|
||||
headers.set(k, v)
|
||||
})
|
||||
headers.delete("host")
|
||||
headers.delete("content-length")
|
||||
headers.delete("x-opencode-request")
|
||||
if (!isNewInference) headers.delete("x-opencode-session")
|
||||
headers.delete("x-opencode-project")
|
||||
headers.delete("x-opencode-client")
|
||||
return headers
|
||||
})(),
|
||||
body: reqBody,
|
||||
// Propagate caller disconnects to the upstream provider request so
|
||||
// abandoned Console requests do not leave orphaned inference work open.
|
||||
signal: input.request.signal,
|
||||
})
|
||||
const isStream = res.headers.get("content-type")?.toLowerCase().includes("text/event-stream") ?? false
|
||||
logger.metric({ is_stream: isStream })
|
||||
|
||||
if (isNewInference) {
|
||||
const resEndpointId = res.headers.get("x-opencode-endpoint-id")
|
||||
@@ -291,29 +265,10 @@ export async function handler(
|
||||
})
|
||||
}
|
||||
|
||||
// Try another provider => stop retrying if using fallback provider
|
||||
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 }
|
||||
return { providerInfo, res, startTimestamp, isStream }
|
||||
}
|
||||
|
||||
const { providerInfo, reqBody, res, startTimestamp } = await retriableRequest()
|
||||
const { providerInfo, res, startTimestamp, isStream } = await providerRequest()
|
||||
|
||||
// Store sticky provider
|
||||
if (res.status === 200) await stickyTracker?.set(providerInfo.id)
|
||||
@@ -469,6 +424,8 @@ export async function handler(
|
||||
headers: resHeaders,
|
||||
})
|
||||
} 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
|
||||
// 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
|
||||
@@ -593,7 +550,6 @@ export async function handler(
|
||||
modelInfo: ModelInfo,
|
||||
stickyId: string,
|
||||
trialProviders: string[] | undefined,
|
||||
retry: RetryOptions,
|
||||
stickyProviderId: string | undefined,
|
||||
modelTpmLimits: Record<string, number> | undefined,
|
||||
modelTpsLimits: Record<string, { qualify: number; unqualify: number }> | undefined,
|
||||
@@ -620,14 +576,11 @@ export async function handler(
|
||||
}))
|
||||
}
|
||||
|
||||
// Use fallback provider if max retries reached
|
||||
const fallbackProvider = allProviders.find((provider) => provider.id === modelInfo.fallbackProvider)
|
||||
if (retry.retryCount === MAX_FAILOVER_RETRIES) return fallbackProvider
|
||||
|
||||
let topPriority = Infinity
|
||||
const providers = allProviders
|
||||
.filter((provider) => provider.weight !== 0)
|
||||
.filter((provider) => !retry.excludeProviders.includes(provider.id))
|
||||
.filter((provider) => {
|
||||
if (provider.budgetPriority === undefined) return true
|
||||
if (!providerBudget) return true
|
||||
@@ -1035,15 +988,6 @@ export async function handler(
|
||||
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) {
|
||||
const { inputTokens, outputTokens, reasoningTokens, cacheReadTokens, cacheWrite5mTokens, cacheWrite1hTokens } =
|
||||
usageInfo
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
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 searchFrom = 0
|
||||
let bom = 0
|
||||
let match: RegExpExecArray | null = null
|
||||
const pattern = /("model"\s*:\s*")([^"]+)"/g
|
||||
|
||||
while (!done && !match) {
|
||||
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 })
|
||||
pattern.lastIndex = searchFrom
|
||||
match = pattern.exec(text)
|
||||
searchFrom = Math.max(0, text.length - 256)
|
||||
}
|
||||
if (done) {
|
||||
text += decoder.decode()
|
||||
if (!match) {
|
||||
pattern.lastIndex = searchFrom
|
||||
match = pattern.exec(text)
|
||||
}
|
||||
}
|
||||
|
||||
const found = (() => {
|
||||
if (!match) return
|
||||
const start = bom + utf8Length(text, match.index + match[1].length)
|
||||
return { model: match[2], start, end: start + utf8Length(match[2], match[2].length) }
|
||||
})()
|
||||
const preview = text.substring(0, 300)
|
||||
text = ""
|
||||
match = null
|
||||
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,122 @@
|
||||
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("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,
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -97,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 () => {
|
||||
await Database.use((tx) =>
|
||||
tx
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-support",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"name": "@opencode-ai/core",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
@@ -62,7 +62,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@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/azure": "3.0.88",
|
||||
"@ai-sdk/cerebras": "2.0.41",
|
||||
|
||||
@@ -45,9 +45,18 @@ function oauth(http: HttpClient.HttpClient) {
|
||||
authorize: () =>
|
||||
Effect.gen(function* () {
|
||||
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 {
|
||||
mode: "auto" as const,
|
||||
url: `${defaultServer}${device.verification_uri_complete}`,
|
||||
url: verification.href,
|
||||
instructions: `Enter code: ${device.user_code}`,
|
||||
callback: poll(http, defaultServer, device.device_code, Duration.seconds(device.interval)),
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { HttpClient, HttpClientResponse } from "effect/unstable/http"
|
||||
import { Catalog } from "@opencode-ai/core/catalog"
|
||||
import { Credential } from "@opencode-ai/core/credential"
|
||||
import { EventV2 } from "@opencode-ai/core/event"
|
||||
@@ -14,14 +15,16 @@ import { PluginTestLayer } from "./fixture"
|
||||
|
||||
const it = testEffect(PluginTestLayer)
|
||||
|
||||
const addPlugin = Effect.fn(function* () {
|
||||
const addPlugin = Effect.fn(function* (http?: HttpClient.HttpClient) {
|
||||
const plugin = yield* PluginV2.Service
|
||||
const host = yield* PluginHost.make(plugin)
|
||||
const events = yield* EventV2.Service
|
||||
const integration = yield* Integration.Service
|
||||
const client = yield* HttpClient.HttpClient
|
||||
yield* OpencodePlugin.effect(host).pipe(
|
||||
Effect.provideService(EventV2.Service, events),
|
||||
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", () =>
|
||||
Effect.acquireUseRelease(
|
||||
Effect.sync(() => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opencode-ai/desktop",
|
||||
"private": true,
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"homepage": "https://opencode.ai",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"name": "@opencode-ai/effect-drizzle-sqlite",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"name": "@opencode-ai/effect-sqlite-node",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/enterprise",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"name": "@opencode-ai/http-recorder",
|
||||
"description": "Record and replay Effect HTTP client traffic with deterministic cassettes",
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"name": "@opencode-ai/llm",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"name": "opencode",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
@@ -56,7 +56,7 @@
|
||||
"@actions/github": "6.0.1",
|
||||
"@agentclientprotocol/sdk": "0.21.0",
|
||||
"@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/azure": "3.0.88",
|
||||
"@ai-sdk/cerebras": "2.0.60",
|
||||
|
||||
@@ -396,10 +396,18 @@ const layer: Layer.Layer<Service, never, AccountRepo.Service | HttpClient.HttpCl
|
||||
const parsed = yield* HttpClientResponse.schemaBodyJson(DeviceAuth)(response).pipe(
|
||||
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({
|
||||
code: parsed.device_code,
|
||||
user: parsed.user_code,
|
||||
url: `${normalizedServer}${parsed.verification_uri_complete}`,
|
||||
url: verification,
|
||||
server: normalizedServer,
|
||||
expiry: parsed.expires_in,
|
||||
interval: parsed.interval,
|
||||
|
||||
@@ -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`
|
||||
}
|
||||
|
||||
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 = {
|
||||
languageModel(modelId: string): LanguageModelV3
|
||||
chat?: (modelId: string) => LanguageModelV3
|
||||
@@ -519,11 +525,10 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
|
||||
return {
|
||||
autoload: true,
|
||||
vars(_options: Record<string, any>) {
|
||||
const endpoint = location === "global" ? "aiplatform.googleapis.com" : `${location}-aiplatform.googleapis.com`
|
||||
return {
|
||||
...(project && { GOOGLE_VERTEX_PROJECT: project }),
|
||||
GOOGLE_VERTEX_LOCATION: location,
|
||||
GOOGLE_VERTEX_ENDPOINT: endpoint,
|
||||
GOOGLE_VERTEX_ENDPOINT: googleVertexEndpoint(location),
|
||||
}
|
||||
},
|
||||
options: {
|
||||
|
||||
@@ -1303,13 +1303,13 @@ export function options(input: {
|
||||
}
|
||||
}
|
||||
|
||||
// Only set textVerbosity for non-chat gpt-5.x models
|
||||
// Chat models (e.g. gpt-5.2-chat-latest) only support "medium" verbosity
|
||||
// Generic OpenAI-compatible APIs do not necessarily support OpenAI's verbosity parameter.
|
||||
// Only enable the default for integrations known to implement it.
|
||||
if (
|
||||
input.model.api.id.includes("gpt-5.") &&
|
||||
!input.model.api.id.includes("codex") &&
|
||||
!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"
|
||||
}
|
||||
|
||||
@@ -29,8 +29,6 @@ import * as OtelTracer from "@effect/opentelemetry/Tracer"
|
||||
import { LLMAISDK } from "./llm/ai-sdk"
|
||||
import { LLMNativeRuntime } from "./llm/native-runtime"
|
||||
import { LLMRequestPrep } from "./llm/request"
|
||||
import { ProviderError } from "@/provider/error"
|
||||
import type { LanguageModelV3StreamPart } from "@ai-sdk/provider"
|
||||
|
||||
export const OUTPUT_TOKEN_MAX = ProviderTransform.OUTPUT_TOKEN_MAX
|
||||
|
||||
@@ -340,26 +338,6 @@ const live: Layer.Layer<
|
||||
}
|
||||
return args.params
|
||||
},
|
||||
async wrapStream({ doStream }) {
|
||||
const result = await doStream()
|
||||
return {
|
||||
...result,
|
||||
stream: result.stream.pipeThrough(
|
||||
new TransformStream<LanguageModelV3StreamPart, LanguageModelV3StreamPart>({
|
||||
transform(part, controller) {
|
||||
if (part.type === "finish" && part.finishReason.raw === "network_error") {
|
||||
controller.enqueue({
|
||||
type: "error",
|
||||
error: new ProviderError.ResponseStreamError("Provider finish_reason: network_error"),
|
||||
})
|
||||
return
|
||||
}
|
||||
controller.enqueue(part)
|
||||
},
|
||||
}),
|
||||
),
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
||||
@@ -2,6 +2,7 @@ import { FinishReason, LLMEvent, ProviderMetadata, ToolResultValue } from "@open
|
||||
import { Effect, Schema } from "effect"
|
||||
import { type streamText } from "ai"
|
||||
import { errorMessage } from "@/util/error"
|
||||
import { ProviderError } from "@/provider/error"
|
||||
|
||||
type Result = Awaited<ReturnType<typeof streamText>>
|
||||
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 })])
|
||||
|
||||
case "finish-step":
|
||||
if (event.rawFinishReason === "network_error")
|
||||
return Effect.fail(new ProviderError.ResponseStreamError("Provider finish_reason: network_error"))
|
||||
return Effect.sync(() => {
|
||||
const original = providerMetadata(event.providerMetadata)
|
||||
const metadata =
|
||||
|
||||
@@ -1110,7 +1110,7 @@ const layer = Layer.effect(
|
||||
|
||||
if (
|
||||
lastAssistant?.finish &&
|
||||
!["tool-calls"].includes(lastAssistant.finish) &&
|
||||
!["tool-calls", "unknown"].includes(lastAssistant.finish) &&
|
||||
!hasToolCalls &&
|
||||
lastAssistant.parentID === lastUser.id
|
||||
) {
|
||||
|
||||
@@ -217,6 +217,10 @@ export const TaskTool = Tool.define(
|
||||
: result.info.error.name
|
||||
return yield* Effect.fail(new Error(`Subagent failed (task_id: ${nextSession.id}): ${message}`))
|
||||
}
|
||||
const failed = result.parts.findLast((item) => item.type === "tool" && item.state.status === "error")
|
||||
if (failed?.type === "tool" && failed.state.status === "error") {
|
||||
return yield* Effect.fail(new Error(`Subagent failed (task_id: ${nextSession.id}): ${failed.state.error}`))
|
||||
}
|
||||
return result.parts.findLast((item) => item.type === "text")?.text ?? ""
|
||||
})
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import { Account } from "../../src/account/account"
|
||||
import {
|
||||
AccessToken,
|
||||
AccountID,
|
||||
AccountServiceError,
|
||||
AccountTransportError,
|
||||
DeviceCode,
|
||||
Login,
|
||||
@@ -71,18 +72,18 @@ const deviceTokenClient = (body: unknown, status = 400) =>
|
||||
const poll = (body: unknown, status = 400) =>
|
||||
Account.Service.use((s) => s.poll(login())).pipe(Effect.provide(live(deviceTokenClient(body, status))))
|
||||
|
||||
it.live("login normalizes trailing slashes in the provided server URL", () =>
|
||||
it.live("login resolves origin-rooted verification URLs from servers with base paths", () =>
|
||||
Effect.gen(function* () {
|
||||
const seen: Array<string> = []
|
||||
const client = HttpClient.make((req) =>
|
||||
Effect.gen(function* () {
|
||||
seen.push(`${req.method} ${req.url}`)
|
||||
|
||||
if (req.url === "https://one.example.com/auth/device/code") {
|
||||
if (req.url === "https://one.example.com/console/auth/device/code") {
|
||||
return json(req, {
|
||||
device_code: "device-code",
|
||||
user_code: "user-code",
|
||||
verification_uri_complete: "/device?user_code=user-code",
|
||||
verification_uri_complete: "/console/device?user_code=user-code",
|
||||
expires_in: 600,
|
||||
interval: 5,
|
||||
})
|
||||
@@ -92,11 +93,31 @@ it.live("login normalizes trailing slashes in the provided server URL", () =>
|
||||
}),
|
||||
)
|
||||
|
||||
const result = yield* Account.use.login("https://one.example.com/").pipe(Effect.provide(live(client)))
|
||||
const result = yield* Account.use.login("https://one.example.com/console/").pipe(Effect.provide(live(client)))
|
||||
|
||||
expect(seen).toEqual(["POST https://one.example.com/auth/device/code"])
|
||||
expect(result.server).toBe("https://one.example.com")
|
||||
expect(result.url).toBe("https://one.example.com/device?user_code=user-code")
|
||||
expect(seen).toEqual(["POST https://one.example.com/console/auth/device/code"])
|
||||
expect(result.server).toBe("https://one.example.com/console")
|
||||
expect(result.url).toBe("https://one.example.com/console/device?user_code=user-code")
|
||||
}),
|
||||
)
|
||||
|
||||
it.live("login rejects malformed device verification URLs", () =>
|
||||
Effect.gen(function* () {
|
||||
const client = HttpClient.make((req) =>
|
||||
Effect.succeed(
|
||||
json(req, {
|
||||
device_code: "device-code",
|
||||
user_code: "user-code",
|
||||
verification_uri_complete: "http://[::1",
|
||||
expires_in: 600,
|
||||
interval: 5,
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
const error = yield* Effect.flip(Account.use.login("https://one.example.com").pipe(Effect.provide(live(client))))
|
||||
expect(error).toBeInstanceOf(AccountServiceError)
|
||||
if (error instanceof AccountServiceError) expect(error.message).toBe("Invalid device verification URL")
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
@@ -82,10 +82,10 @@ describe("opencode run (non-interactive subprocess)", () => {
|
||||
)
|
||||
|
||||
// The test provider's SSE error item is interpreted by the SDK as an unknown
|
||||
// finish, not a fatal provider/session error. Lock that distinction in so it
|
||||
// is not accidentally used as the failure compatibility oracle.
|
||||
// finish, not a fatal provider/session error. Unknown finishes should continue
|
||||
// the prompt loop so a subsequent response can complete the run.
|
||||
cliIt.concurrent(
|
||||
"unknown stream finish preserves partial output and exits 0",
|
||||
"unknown stream finish preserves partial output and continues",
|
||||
({ llm, opencode }) =>
|
||||
Effect.gen(function* () {
|
||||
yield* llm.push(
|
||||
@@ -95,9 +95,10 @@ describe("opencode run (non-interactive subprocess)", () => {
|
||||
}),
|
||||
)
|
||||
yield* llm.fail("upstream provider exploded mid-stream")
|
||||
yield* llm.text("recovered")
|
||||
const result = yield* opencode.run("trigger midstream error", { timeoutMs: 30_000 })
|
||||
expect(result.exitCode).toBe(0)
|
||||
expect(result.stdout).toBe("partial response\n")
|
||||
expect(result.stdout).toBe("partial response\nrecovered\n")
|
||||
expect(result.stderr).not.toContain("upstream provider exploded mid-stream")
|
||||
}),
|
||||
60_000,
|
||||
@@ -213,7 +214,7 @@ describe("opencode run (non-interactive subprocess)", () => {
|
||||
)
|
||||
|
||||
cliIt.concurrent(
|
||||
"--format json records partial output for an unknown stream finish",
|
||||
"--format json records an unknown stream finish and continuation",
|
||||
({ llm, opencode }) =>
|
||||
Effect.gen(function* () {
|
||||
yield* llm.push(
|
||||
@@ -223,6 +224,7 @@ describe("opencode run (non-interactive subprocess)", () => {
|
||||
}),
|
||||
)
|
||||
yield* llm.fail("provider failed")
|
||||
yield* llm.text("recovered")
|
||||
const result = yield* opencode.run("fail after output", { format: "json" })
|
||||
|
||||
const events = opencode.parseJsonEvents(result.stdout)
|
||||
@@ -234,9 +236,14 @@ describe("opencode run (non-interactive subprocess)", () => {
|
||||
"step_finish",
|
||||
"step_start",
|
||||
"step_finish",
|
||||
"step_start",
|
||||
"text",
|
||||
"step_finish",
|
||||
])
|
||||
expect(events[1]?.part).toEqual(expect.objectContaining({ type: "text", text: "partial json" }))
|
||||
expect(events.at(-1)?.part).toEqual(expect.objectContaining({ type: "step-finish", reason: "unknown" }))
|
||||
expect(events[5]?.part).toEqual(expect.objectContaining({ type: "step-finish", reason: "unknown" }))
|
||||
expect(events[7]?.part).toEqual(expect.objectContaining({ type: "text", text: "recovered" }))
|
||||
expect(events.at(-1)?.part).toEqual(expect.objectContaining({ type: "step-finish", reason: "stop" }))
|
||||
}),
|
||||
60_000,
|
||||
)
|
||||
@@ -277,50 +284,6 @@ describe("opencode run (non-interactive subprocess)", () => {
|
||||
60_000,
|
||||
)
|
||||
|
||||
cliIt.concurrent(
|
||||
"answers requested permissions from subagents",
|
||||
({ llm, opencode }) =>
|
||||
Effect.gen(function* () {
|
||||
yield* llm.tool("task", {
|
||||
description: "Run a command",
|
||||
prompt: "Run the requested command",
|
||||
subagent_type: "general",
|
||||
})
|
||||
yield* llm.tool("bash", { command: "printf child", description: "Print from the child" })
|
||||
yield* llm.text("child finished")
|
||||
yield* llm.text("parent finished")
|
||||
|
||||
const result = yield* opencode.run("delegate a command", {
|
||||
permission: { bash: "ask" },
|
||||
extraArgs: ["--dangerously-skip-permissions"],
|
||||
timeoutMs: 10_000,
|
||||
})
|
||||
|
||||
opencode.expectExit(result, 0)
|
||||
expect(result.stdout).toContain("parent finished")
|
||||
|
||||
yield* llm.reset
|
||||
yield* llm.tool("task", {
|
||||
description: "Run a command",
|
||||
prompt: "Run the requested command",
|
||||
subagent_type: "general",
|
||||
})
|
||||
yield* llm.tool("bash", { command: "printf child", description: "Print from the child" })
|
||||
yield* llm.text("child continued")
|
||||
yield* llm.text("parent continued")
|
||||
|
||||
const rejected = yield* opencode.run("delegate a rejected command", {
|
||||
permission: { bash: "ask" },
|
||||
timeoutMs: 10_000,
|
||||
})
|
||||
|
||||
opencode.expectExit(rejected, 0)
|
||||
expect(rejected.stderr).toContain("permission requested: bash")
|
||||
expect(rejected.stdout).toContain("child continued")
|
||||
}),
|
||||
30_000,
|
||||
)
|
||||
|
||||
cliIt.live(
|
||||
"attach mode sends client-local file contents without a shared path",
|
||||
({ home, llm, opencode }) =>
|
||||
|
||||
@@ -1909,6 +1909,32 @@ it.instance("Google Vertex: keeps regional Claude endpoints unchanged", () =>
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("Google Vertex: uses REP endpoint for Gemini continental multi-regions", () =>
|
||||
Effect.gen(function* () {
|
||||
yield* set("GOOGLE_CLOUD_PROJECT", "test-project")
|
||||
yield* set("VERTEX_LOCATION", "eu")
|
||||
const provider = yield* Provider.Service
|
||||
const model = yield* provider.getModel(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("gemini-3.5-flash"))
|
||||
const language = yield* provider.getLanguage(model)
|
||||
expect(languageBaseURL(language)).toBe(
|
||||
"https://aiplatform.eu.rep.googleapis.com/v1beta1/projects/test-project/locations/eu/publishers/google",
|
||||
)
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("Google Vertex: keeps regional Gemini endpoints unchanged", () =>
|
||||
Effect.gen(function* () {
|
||||
yield* set("GOOGLE_CLOUD_PROJECT", "test-project")
|
||||
yield* set("VERTEX_LOCATION", "europe-west1")
|
||||
const provider = yield* Provider.Service
|
||||
const model = yield* provider.getModel(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("gemini-3.5-flash"))
|
||||
const language = yield* provider.getLanguage(model)
|
||||
expect(languageBaseURL(language)).toBe(
|
||||
"https://europe-west1-aiplatform.googleapis.com/v1beta1/projects/test-project/locations/europe-west1/publishers/google",
|
||||
)
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("cloudflare-ai-gateway loads with env variables", () =>
|
||||
Effect.gen(function* () {
|
||||
yield* set("CLOUDFLARE_ACCOUNT_ID", "test-account")
|
||||
|
||||
@@ -523,6 +523,7 @@ describe("ProviderTransform.options - gpt-5 textVerbosity", () => {
|
||||
expect(result.reasoningEffort).toBe("medium")
|
||||
expect(result.reasoningSummary).toBeUndefined()
|
||||
expect(result.include).toBeUndefined()
|
||||
expect(result.textVerbosity).toBeUndefined()
|
||||
})
|
||||
|
||||
test("azure chat completions omit Responses-only reasoning options after variants merge", async () => {
|
||||
|
||||
@@ -651,6 +651,63 @@ it.live("session.processor effect tests retry OpenAI-compatible midstream server
|
||||
),
|
||||
)
|
||||
|
||||
it.live("session.processor effect tests retry network_error finish reasons", () =>
|
||||
provideTmpdirServer(
|
||||
({ dir, llm }) =>
|
||||
Effect.gen(function* () {
|
||||
const { processors, session, provider } = yield* boot()
|
||||
|
||||
yield* llm.push(
|
||||
raw({
|
||||
chunks: [
|
||||
{
|
||||
id: "chatcmpl-network-error",
|
||||
object: "chat.completion.chunk",
|
||||
choices: [{ index: 0, delta: { role: "assistant", content: "" }, finish_reason: "network_error" }],
|
||||
},
|
||||
],
|
||||
}),
|
||||
)
|
||||
yield* llm.text("after retry")
|
||||
|
||||
const chat = yield* session.create({})
|
||||
const parent = yield* user(chat.id, "retry network error")
|
||||
const msg = yield* assistant(chat.id, parent.id, path.resolve(dir))
|
||||
const mdl = yield* provider.getModel(ref.providerID, ref.modelID)
|
||||
const handle = yield* processors.create({
|
||||
assistantMessage: msg,
|
||||
sessionID: chat.id,
|
||||
model: mdl,
|
||||
})
|
||||
|
||||
const value = yield* handle.process({
|
||||
user: {
|
||||
id: parent.id,
|
||||
sessionID: chat.id,
|
||||
role: "user",
|
||||
time: parent.time,
|
||||
agent: parent.agent,
|
||||
model: { providerID: ref.providerID, modelID: ref.modelID },
|
||||
} satisfies SessionV1.User,
|
||||
sessionID: chat.id,
|
||||
model: mdl,
|
||||
agent: agent(),
|
||||
system: [],
|
||||
messages: [{ role: "user", content: "retry network error" }],
|
||||
tools: {},
|
||||
})
|
||||
|
||||
const parts = yield* MessageV2.parts(msg.id)
|
||||
|
||||
expect(value).toBe("continue")
|
||||
expect(yield* llm.calls).toBe(2)
|
||||
expect(parts.some((part) => part.type === "text" && part.text === "after retry")).toBe(true)
|
||||
expect(handle.message.error).toBeUndefined()
|
||||
}),
|
||||
{ config: (url) => providerCfg(url) },
|
||||
),
|
||||
)
|
||||
|
||||
it.live("session.processor effect tests publish retry status updates", () =>
|
||||
provideTmpdirServer(
|
||||
({ dir, llm }) =>
|
||||
|
||||
@@ -850,6 +850,34 @@ it.instance("loop continues when finish is tool-calls", () =>
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("loop continues when finish is unknown", () =>
|
||||
Effect.gen(function* () {
|
||||
const { llm } = yield* useServerConfig(providerCfg)
|
||||
const prompt = yield* SessionPrompt.Service
|
||||
const sessions = yield* Session.Service
|
||||
const session = yield* sessions.create({
|
||||
title: "Pinned",
|
||||
permission: [{ permission: "*", pattern: "*", action: "allow" }],
|
||||
})
|
||||
yield* prompt.prompt({
|
||||
sessionID: session.id,
|
||||
agent: "build",
|
||||
noReply: true,
|
||||
parts: [{ type: "text", text: "hello" }],
|
||||
})
|
||||
yield* llm.push(reply())
|
||||
yield* llm.text("second")
|
||||
|
||||
const result = yield* prompt.loop({ sessionID: session.id })
|
||||
expect(yield* llm.calls).toBe(2)
|
||||
expect(result.info.role).toBe("assistant")
|
||||
if (result.info.role === "assistant") {
|
||||
expect(result.parts.some((part) => part.type === "text" && part.text === "second")).toBe(true)
|
||||
expect(result.info.finish).toBe("stop")
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("glob tool keeps instance context during prompt runs", () =>
|
||||
Effect.gen(function* () {
|
||||
const { dir, llm } = yield* useServerConfig(providerCfg)
|
||||
|
||||
@@ -100,6 +100,7 @@ function stubOps(opts?: {
|
||||
onPrompt?: (input: SessionPrompt.PromptInput) => void
|
||||
text?: string
|
||||
error?: NonNullable<SessionV1.Assistant["error"]>
|
||||
toolError?: string
|
||||
}): TaskPromptOps {
|
||||
return {
|
||||
cancel: () => Effect.void,
|
||||
@@ -107,7 +108,7 @@ function stubOps(opts?: {
|
||||
prompt: (input) =>
|
||||
Effect.sync(() => {
|
||||
opts?.onPrompt?.(input)
|
||||
return reply(input, opts?.text ?? "done", opts?.error)
|
||||
return reply(input, opts?.text ?? "done", opts?.error, opts?.toolError)
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -116,6 +117,7 @@ function reply(
|
||||
input: SessionPrompt.PromptInput,
|
||||
text: string,
|
||||
error?: NonNullable<SessionV1.Assistant["error"]>,
|
||||
toolError?: string,
|
||||
): SessionV1.WithParts {
|
||||
const id = MessageID.ascending()
|
||||
return {
|
||||
@@ -143,6 +145,24 @@ function reply(
|
||||
type: "text",
|
||||
text,
|
||||
},
|
||||
...(toolError
|
||||
? [
|
||||
{
|
||||
id: PartID.ascending(),
|
||||
messageID: id,
|
||||
sessionID: input.sessionID,
|
||||
type: "tool" as const,
|
||||
tool: "read",
|
||||
callID: "call-1",
|
||||
state: {
|
||||
status: "error" as const,
|
||||
input: { filePath: "/external" },
|
||||
error: toolError,
|
||||
time: { start: Date.now(), end: Date.now() },
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
}
|
||||
}
|
||||
@@ -307,6 +327,50 @@ describe("tool.task", () => {
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("execute surfaces terminal child tool errors with a resumable task_id", () =>
|
||||
Effect.gen(function* () {
|
||||
const sessions = yield* Session.Service
|
||||
const { chat, assistant } = yield* seed()
|
||||
const tool = yield* TaskTool
|
||||
const def = yield* tool.init()
|
||||
|
||||
const exit = yield* def
|
||||
.execute(
|
||||
{
|
||||
description: "inspect external directory",
|
||||
prompt: "read the external directory",
|
||||
subagent_type: "general",
|
||||
},
|
||||
{
|
||||
sessionID: chat.id,
|
||||
messageID: assistant.id,
|
||||
agent: "build",
|
||||
abort: new AbortController().signal,
|
||||
extra: {
|
||||
promptOps: stubOps({
|
||||
text: "I will inspect the directory.",
|
||||
toolError: "The user rejected permission to use this specific tool call.",
|
||||
}),
|
||||
},
|
||||
messages: [],
|
||||
metadata: () => Effect.void,
|
||||
ask: () => Effect.void,
|
||||
},
|
||||
)
|
||||
.pipe(Effect.exit)
|
||||
|
||||
expect(Exit.isFailure(exit)).toBe(true)
|
||||
if (Exit.isSuccess(exit)) throw new Error("expected task failure")
|
||||
const child = (yield* sessions.children(chat.id))[0]
|
||||
const failure = Cause.squash(exit.cause)
|
||||
expect(failure).toBeInstanceOf(Error)
|
||||
if (!(failure instanceof Error)) throw new Error("expected Error defect")
|
||||
expect(failure.message).toBe(
|
||||
`Subagent failed (task_id: ${child?.id}): The user rejected permission to use this specific tool call.`,
|
||||
)
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("execute asks by default and skips checks when bypassed", () =>
|
||||
Effect.gen(function* () {
|
||||
const { chat, assistant } = yield* seed()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/server",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/session-ui",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/slack",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/stats-app",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -812,7 +812,8 @@ function ModelTrendSection(props: {
|
||||
<div data-slot="tooltip-divider" />
|
||||
<p>
|
||||
<span data-slot="tooltip-label">
|
||||
<i data-kind={props.lineTone === "active" ? "users" : "tokens"} /> {props.rowLabel}
|
||||
<i data-kind={props.lineTone === "active" ? "users" : "tokens"} />
|
||||
<span data-slot="tooltip-name">{props.rowLabel}</span>
|
||||
</span>
|
||||
<b>{props.formatValue(props.value(active.point))}</b>
|
||||
</p>
|
||||
|
||||
@@ -473,13 +473,15 @@ function LabUsageSection(props: { lab: ModelCatalogLab; data: StatsLabData | nul
|
||||
<div data-slot="tooltip-divider" />
|
||||
<p>
|
||||
<span data-slot="tooltip-label">
|
||||
<i data-kind="tokens" /> {i18n.t("lab.dailyTokens")}
|
||||
<i data-kind="tokens" />
|
||||
<span data-slot="tooltip-name">{i18n.t("lab.dailyTokens")}</span>
|
||||
</span>
|
||||
<b>{formatTokens(active.point.tokens)}</b>
|
||||
</p>
|
||||
<p>
|
||||
<span data-slot="tooltip-label">
|
||||
<i data-kind="users" /> {i18n.t("model.uniqueUsers")}
|
||||
<i data-kind="users" />
|
||||
<span data-slot="tooltip-name">{i18n.t("model.uniqueUsers")}</span>
|
||||
</span>
|
||||
<b>{formatUsers(active.point.users)}</b>
|
||||
</p>
|
||||
|
||||
@@ -1590,6 +1590,13 @@ body {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-component="chart-tooltip"] [data-slot="tooltip-name"] {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-component="chart-tooltip"] [data-slot="tooltip-divider"] {
|
||||
height: 1px;
|
||||
margin: 4px -16px 2px;
|
||||
@@ -1677,7 +1684,7 @@ body {
|
||||
|
||||
[data-page="stats"] :is([data-section="top-models"], [data-section="unique-users"]) [data-component="chart-tooltip"] p {
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 4px;
|
||||
gap: 1ch;
|
||||
height: 16px;
|
||||
margin: 4px 0 0;
|
||||
padding: 0 8px;
|
||||
@@ -4723,7 +4730,7 @@ body {
|
||||
|
||||
[data-page="stats"] [data-component="model-usage-chart"] [data-component="chart-tooltip"] p {
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 4px;
|
||||
gap: 1ch;
|
||||
height: 20px;
|
||||
margin: 8px 0;
|
||||
padding: 0 8px;
|
||||
|
||||
@@ -568,8 +568,8 @@ function TopModelsChart(props: {
|
||||
style={{
|
||||
background: getRankColor(item.segment.model, item.index, segmentOrder(), usageColors),
|
||||
}}
|
||||
/>{" "}
|
||||
{item.segment.model}
|
||||
/>
|
||||
<span data-slot="tooltip-name">{item.segment.model}</span>
|
||||
</span>
|
||||
<b>{formatUsageChartValue(item.segment.value, metric())}</b>
|
||||
</p>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/stats-core",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -4,6 +4,7 @@ import { modelAuthor, normalizeInferenceModel, statModel, statProvider } from ".
|
||||
|
||||
describe("inference stat normalization", () => {
|
||||
test("normalizes model suffixes used by router/provider variants", () => {
|
||||
expect(normalizeInferenceModel("GPT-5-Free")).toBe("gpt-5")
|
||||
expect(normalizeInferenceModel("deepseek-v4-flash-free")).toBe("deepseek-v4-flash")
|
||||
expect(normalizeInferenceModel("deepseek-v4-flash:global")).toBe("deepseek-v4-flash")
|
||||
expect(normalizeInferenceModel("mimo-v2.5-free")).toBe("mimo-v2.5")
|
||||
@@ -41,6 +42,17 @@ describe("inference stat normalization", () => {
|
||||
expect(statProvider("unknown", "", "custom-provider")).toBe("custom-provider")
|
||||
})
|
||||
|
||||
test("merges renamed models under their current name", () => {
|
||||
expect(statModel("x-preview-f", "")).toBe("ox-alpha")
|
||||
expect(statModel("xiaomi/mimo-v2.5", "")).toBe("mimo-v2.5")
|
||||
expect(toModelAggregate(aggregate("x-preview-f", "openai"))).toMatchObject([
|
||||
{
|
||||
provider: "openai",
|
||||
model: "ox-alpha",
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
test("model aggregates prefer provider.model and use normalized model", () => {
|
||||
expect(toModelAggregate(aggregate("alpha-gpt-next", "openai"))).toEqual([])
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
EXCLUDED_MODELS,
|
||||
FREE_MODELS,
|
||||
MODEL_AUTHOR_RULES,
|
||||
MODEL_NAME_ALIASES,
|
||||
RETIRED_STAT_PROVIDERS,
|
||||
statModel,
|
||||
statProvider,
|
||||
@@ -302,6 +303,9 @@ function statPeriods(grain: "day" | "week", periodStart: Date, periodEnd: Date)
|
||||
function statModelSql(model: string, providerModel: string) {
|
||||
return `COALESCE(NULLIF(regexp_replace(CASE
|
||||
WHEN lower(${model}) = 'big-pickle' THEN regexp_replace(NULLIF(${providerModel}, ''), '^.*/', '')
|
||||
${Object.entries(MODEL_NAME_ALIASES)
|
||||
.map(([from, to]) => ` WHEN lower(${model}) = ${sqlString(from)} THEN ${sqlString(to)}`)
|
||||
.join("\n")}
|
||||
ELSE ${model}
|
||||
END, '(-free|:free|:global)+$', ''), ''), 'unknown')`
|
||||
}
|
||||
|
||||
@@ -15,11 +15,15 @@ export const MODEL_AUTHOR_RULES = [
|
||||
] as const
|
||||
export const EXCLUDED_MODELS = new Set(["alpha-gpt-next"])
|
||||
export const FREE_MODELS = new Set(["gpt-5-nano", "grok-code", "big-pickle"])
|
||||
export const RETIRED_STAT_MODELS = ["big-pickle"]
|
||||
export const MODEL_NAME_ALIASES: Record<string, string> = {
|
||||
"x-preview-f": "ox-alpha",
|
||||
"xiaomi/mimo-v2.5": "mimo-v2.5",
|
||||
}
|
||||
export const RETIRED_STAT_MODELS = ["big-pickle", ...Object.keys(MODEL_NAME_ALIASES)]
|
||||
export const RETIRED_STAT_PROVIDERS = ["opencode"]
|
||||
|
||||
export function normalizeInferenceModel(value: string | undefined) {
|
||||
return (value || "unknown").replace(/(-free|:free|:global)+$/, "") || "unknown"
|
||||
return (value || "unknown").toLowerCase().replace(/(-free|:free|:global)+$/, "") || "unknown"
|
||||
}
|
||||
|
||||
export function modelAuthor(value: string | undefined) {
|
||||
@@ -31,6 +35,8 @@ export function modelAuthor(value: string | undefined) {
|
||||
|
||||
export function statModel(model: string | undefined, providerModel: string | undefined) {
|
||||
const normalized = normalizeInferenceModel(model)
|
||||
const alias = MODEL_NAME_ALIASES[normalized.toLowerCase()]
|
||||
if (alias) return alias
|
||||
if (RETIRED_STAT_MODELS.includes(normalized.toLowerCase()))
|
||||
return normalizeInferenceModel(providerModel?.split("/").at(-1))
|
||||
return normalized
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/stats-server",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/tui",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@opencode-ai/web",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "1.18.19",
|
||||
"version": "1.18.21",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev",
|
||||
|
||||
@@ -68,6 +68,7 @@ OpenCode Go هو اشتراك منخفض التكلفة — **$5 للشهر ال
|
||||
- **Qwen3.6 Plus**
|
||||
- **DeepSeek V4 Pro**
|
||||
- **DeepSeek V4 Flash**
|
||||
- **DeepSeek V4 Flash Vision Exp**
|
||||
- **Hy3**
|
||||
- **Ox Alpha Free** (لفترة محدودة)
|
||||
|
||||
@@ -87,29 +88,30 @@ OpenCode Go هو اشتراك منخفض التكلفة — **$5 للشهر ال
|
||||
|
||||
يوضح الجدول أدناه عددًا تقديريًا للطلبات بناءً على أنماط استخدام Go المعتادة:
|
||||
|
||||
| Model | الطلبات لكل 5 ساعات | الطلبات في الأسبوع | الطلبات في الشهر |
|
||||
| -------------------------- | ------------------- | ------------------ | ---------------- |
|
||||
| Grok 4.5 | 120 | 300 | 600 |
|
||||
| GPT 5.6 Luna | 2,050 | 5,100 | 10,250 |
|
||||
| GLM-5.3 | 220 | 540 | 1,080 |
|
||||
| GLM-5.2 | 880 | 2,150 | 4,300 |
|
||||
| GLM-5.1 | 880 | 2,150 | 4,300 |
|
||||
| Kimi K3 | 110 | 250 | 490 |
|
||||
| Kimi K2.7 Code | 1,350 | 3,380 | 6,750 |
|
||||
| Kimi K2.6 | 1,150 | 2,880 | 5,750 |
|
||||
| MiMo-V2.5 | 30,100 | 75,200 | 150,400 |
|
||||
| MiMo-V2.5-Pro | 3,250 | 8,150 | 16,300 |
|
||||
| MiniMax M3 | 3,200 | 8,000 | 16,000 |
|
||||
| MiniMax M2.7 | 3,400 | 8,500 | 17,000 |
|
||||
| Muse Spark 1.2 Contributor | 45,300 | 113,300 | 226,600 |
|
||||
| Qwen3.8 Max | 160 | 400 | 810 |
|
||||
| Qwen3.7 Max | 340 | 840 | 1,690 |
|
||||
| Qwen3.7 Plus | 4,300 | 10,800 | 21,600 |
|
||||
| Qwen3.6 Plus | 3,300 | 8,200 | 16,300 |
|
||||
| DeepSeek V4 Pro | 1,050 | 2,600 | 5,200 |
|
||||
| DeepSeek V4 Flash | 7,600 | 18,900 | 37,800 |
|
||||
| Hy3 | 4,300 | 10,750 | 21,500 |
|
||||
| Ox Alpha Free | - | - | - |
|
||||
| Model | الطلبات لكل 5 ساعات | الطلبات في الأسبوع | الطلبات في الشهر |
|
||||
| ---------------------------- | ------------------- | ------------------ | ---------------- |
|
||||
| Grok 4.5 | 120 | 300 | 600 |
|
||||
| GPT 5.6 Luna | 2,050 | 5,100 | 10,250 |
|
||||
| GLM-5.3 | 220 | 540 | 1,080 |
|
||||
| GLM-5.2 | 880 | 2,150 | 4,300 |
|
||||
| GLM-5.1 | 880 | 2,150 | 4,300 |
|
||||
| Kimi K3 | 110 | 250 | 490 |
|
||||
| Kimi K2.7 Code | 1,350 | 3,380 | 6,750 |
|
||||
| Kimi K2.6 | 1,150 | 2,880 | 5,750 |
|
||||
| MiMo-V2.5 | 30,100 | 75,200 | 150,400 |
|
||||
| MiMo-V2.5-Pro | 3,250 | 8,150 | 16,300 |
|
||||
| MiniMax M3 | 3,200 | 8,000 | 16,000 |
|
||||
| MiniMax M2.7 | 3,400 | 8,500 | 17,000 |
|
||||
| Muse Spark 1.2 Contributor | 45,300 | 113,300 | 226,600 |
|
||||
| Qwen3.8 Max | 160 | 400 | 810 |
|
||||
| Qwen3.7 Max | 340 | 840 | 1,690 |
|
||||
| Qwen3.7 Plus | 4,300 | 10,800 | 21,600 |
|
||||
| Qwen3.6 Plus | 3,300 | 8,200 | 16,300 |
|
||||
| DeepSeek V4 Pro | 1,050 | 2,600 | 5,200 |
|
||||
| DeepSeek V4 Flash | 7,600 | 18,900 | 37,800 |
|
||||
| DeepSeek V4 Flash Vision Exp | 3,800 | 9,450 | 18,900 |
|
||||
| Hy3 | 4,300 | 10,750 | 21,500 |
|
||||
| Ox Alpha Free | - | - | - |
|
||||
|
||||
تستند التقديرات إلى أنماط الطلبات المرصودة:
|
||||
|
||||
@@ -120,6 +122,7 @@ OpenCode Go هو اشتراك منخفض التكلفة — **$5 للشهر ال
|
||||
- Kimi K2.7/K2.6 — 870 input، و55,000 cached، و200 output tokens لكل طلب
|
||||
- DeepSeek V4 Pro — 750 input، و82,000 cached، و290 output tokens لكل طلب
|
||||
- DeepSeek V4 Flash — 410 input، و71,300 cached، و310 output tokens لكل طلب
|
||||
- DeepSeek V4 Flash Vision Exp — 410 input، و71,300 cached، و310 output tokens لكل طلب
|
||||
- MiniMax M3 — 510 input، و56,000 cached، و190 output tokens لكل طلب
|
||||
- MiniMax M2.7 — 300 input، و55,000 cached، و125 output tokens لكل طلب
|
||||
- Muse Spark 1.2 Contributor — 620 input، و71,400 cached، و300 output tokens لكل طلب
|
||||
@@ -133,37 +136,41 @@ OpenCode Go هو اشتراك منخفض التكلفة — **$5 للشهر ال
|
||||
|
||||
تستند التقديرات أيضًا إلى الأسعار التالية لكل 1M tokens والاستخدام الشهري المتضمن مع كل نموذج:
|
||||
|
||||
| النموذج | الإدخال | الإخراج | القراءة المخزنة | الكتابة المخزنة | الاستخدام |
|
||||
| ---------------------------- | ------- | ------- | --------------- | --------------- | --------- |
|
||||
| Grok 4.5 | $2.00 | $6.00 | $0.30 | - | $15 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 | $15 |
|
||||
| GPT 5.6 Luna (> 272K tokens) | $0.40 | $1.80 | $0.04 | $0.50 | $15 |
|
||||
| GLM-5.3 | $1.40 | $4.40 | $0.26 | - | $15 |
|
||||
| GLM-5.2 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| GLM-5.1 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| Kimi K3 | $3.00 | $15.00 | $0.30 | - | $15 |
|
||||
| Kimi K2.7 Code | $0.95 | $4.00 | $0.19 | - | $60 |
|
||||
| Kimi K2.6 | $0.95 | $4.00 | $0.16 | - | $60 |
|
||||
| MiMo V2.5 | $0.14 | $0.28 | $0.0028 | - | $60 |
|
||||
| MiMo V2.5 Pro | $0.435 | $0.87 | $0.003625 | - | $15 |
|
||||
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - | $60 |
|
||||
| MiniMax M2.7 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| Muse Spark 1.2 Contributor | $0.10 | $0.20 | $0.002 | - | $60 |
|
||||
| Qwen3.8 Max | $2.00 | $6.00 | $0.25 | $2.50 | $15 |
|
||||
| Qwen3.7 Max | $2.50 | $7.50 | $0.50 | $3.125 | $60 |
|
||||
| Qwen3.7 Plus (≤ 256K tokens) | $0.40 | $1.60 | $0.04 | $0.50 | $60 |
|
||||
| Qwen3.7 Plus (> 256K tokens) | $1.20 | $4.80 | $0.12 | $1.50 | $60 |
|
||||
| Qwen3.6 Plus (≤ 256K tokens) | $0.50 | $3.00 | $0.05 | $0.625 | $60 |
|
||||
| Qwen3.6 Plus (> 256K tokens) | $2.00 | $6.00 | $0.20 | $2.50 | $60 |
|
||||
| DeepSeek V4 Pro (Off-Peak) | $0.66 | $1.98 | $0.022 | - | $15 |
|
||||
| DeepSeek V4 Pro (Peak) | $1.32 | $3.96 | $0.044 | - | $15 |
|
||||
| DeepSeek V4 Flash (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $30 |
|
||||
| DeepSeek V4 Flash (Peak) | $0.44 | $1.32 | $0.014 | - | $30 |
|
||||
| Hy3 | $0.14 | $0.58 | $0.035 | - | $60 |
|
||||
| Ox Alpha Free | - | - | - | - | - |
|
||||
| النموذج | الإدخال | الإخراج | القراءة المخزنة | الكتابة المخزنة | الاستخدام |
|
||||
| --------------------------------------- | ------- | ------- | --------------- | --------------- | --------- |
|
||||
| Grok 4.5 | $2.00 | $6.00 | $0.30 | - | $15 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 | $15 |
|
||||
| GPT 5.6 Luna (> 272K tokens) | $0.40 | $1.80 | $0.04 | $0.50 | $15 |
|
||||
| GLM-5.3 | $1.40 | $4.40 | $0.26 | - | $15 |
|
||||
| GLM-5.2 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| GLM-5.1 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| Kimi K3 | $3.00 | $15.00 | $0.30 | - | $15 |
|
||||
| Kimi K2.7 Code | $0.95 | $4.00 | $0.19 | - | $60 |
|
||||
| Kimi K2.6 | $0.95 | $4.00 | $0.16 | - | $60 |
|
||||
| MiMo V2.5 | $0.14 | $0.28 | $0.0028 | - | $60 |
|
||||
| MiMo V2.5 Pro | $0.435 | $0.87 | $0.003625 | - | $15 |
|
||||
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - | $60 |
|
||||
| MiniMax M2.7 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| Muse Spark 1.2 Contributor | $0.10 | $0.20 | $0.002 | - | $60 |
|
||||
| Qwen3.8 Max | $2.00 | $6.00 | $0.25 | $2.50 | $15 |
|
||||
| Qwen3.7 Max | $2.50 | $7.50 | $0.50 | $3.125 | $60 |
|
||||
| Qwen3.7 Plus (≤ 256K tokens) | $0.40 | $1.60 | $0.04 | $0.50 | $60 |
|
||||
| Qwen3.7 Plus (> 256K tokens) | $1.20 | $4.80 | $0.12 | $1.50 | $60 |
|
||||
| Qwen3.6 Plus (≤ 256K tokens) | $0.50 | $3.00 | $0.05 | $0.625 | $60 |
|
||||
| Qwen3.6 Plus (> 256K tokens) | $2.00 | $6.00 | $0.20 | $2.50 | $60 |
|
||||
| DeepSeek V4 Pro (Off-Peak) | $0.66 | $1.98 | $0.022 | - | $15 |
|
||||
| DeepSeek V4 Pro (Peak) | $1.32 | $3.96 | $0.044 | - | $15 |
|
||||
| DeepSeek V4 Flash (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $30 |
|
||||
| DeepSeek V4 Flash (Peak) | $0.44 | $1.32 | $0.014 | - | $30 |
|
||||
| DeepSeek V4 Flash Vision Exp (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $15 |
|
||||
| DeepSeek V4 Flash Vision Exp (Peak) | $0.44 | $1.32 | $0.014 | - | $15 |
|
||||
| Hy3 | $0.14 | $0.58 | $0.035 | - | $60 |
|
||||
| Ox Alpha Free | - | - | - | - | - |
|
||||
|
||||
**DeepSeek V4 Flash / Pro:** ساعات Peak هي 01:00-04:00 و06:00-10:00 UTC؛ وجميع الساعات الأخرى Off-Peak. [اعرف المزيد](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
**DeepSeek V4 Flash / V4 Flash Vision Exp / V4 Pro:** ساعات Peak هي 01:00-04:00 و06:00-10:00 UTC؛ وجميع الساعات الأخرى Off-Peak. [اعرف المزيد](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
**DeepSeek V4 Flash Vision Exp:** يتم تحويل الصور إلى رموز بناءً على أبعادها، وتُحتسب كرموز إدخال إلى جانب رموز النص. [اعرف المزيد](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
**Ox Alpha Free:** مجاني لفترة محدودة.
|
||||
|
||||
@@ -199,30 +206,31 @@ OpenCode Go هو اشتراك منخفض التكلفة — **$5 للشهر ال
|
||||
|
||||
يمكنك أيضًا الوصول إلى نماذج Go عبر نقاط نهاية API التالية.
|
||||
|
||||
| Model | Model ID | Endpoint | AI SDK Package |
|
||||
| -------------------------- | -------------------------- | ------------------------------------------------ | --------------------------- |
|
||||
| Grok 4.5 | grok-4.5 | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GPT 5.6 Luna | gpt-5.6-luna | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GLM-5.3 | glm-5.3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.2 | glm-5.2 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.1 | glm-5.1 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K3 | kimi-k3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.7 Code | kimi-k2.7-code | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.6 | kimi-k2.6 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Pro | deepseek-v4-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash | deepseek-v4-flash | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5 | mimo-v2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5-Pro | mimo-v2.5-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiniMax M3 | minimax-m3 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.7 | minimax-m2.7 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Muse Spark 1.2 Contributor | muse-spark-1.2-contributor | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| Qwen3.8 Max | qwen3.8-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Max | qwen3.7-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Plus | qwen3.7-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.6 Plus | qwen3.6-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Hy3 | hy3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Ox Alpha Free | x-preview-f-free | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Model | Model ID | Endpoint | AI SDK Package |
|
||||
| ---------------------------- | ---------------------------- | ------------------------------------------------ | --------------------------- |
|
||||
| Grok 4.5 | grok-4.5 | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GPT 5.6 Luna | gpt-5.6-luna | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GLM-5.3 | glm-5.3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.2 | glm-5.2 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.1 | glm-5.1 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K3 | kimi-k3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.7 Code | kimi-k2.7-code | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.6 | kimi-k2.6 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Pro | deepseek-v4-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash | deepseek-v4-flash | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash Vision Exp | deepseek-v4-flash-vision-exp | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5 | mimo-v2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5-Pro | mimo-v2.5-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiniMax M3 | minimax-m3 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.7 | minimax-m2.7 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Muse Spark 1.2 Contributor | muse-spark-1.2-contributor | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| Qwen3.8 Max | qwen3.8-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Max | qwen3.7-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Plus | qwen3.7-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.6 Plus | qwen3.6-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Hy3 | hy3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Ox Alpha Free | ox-alpha-free | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
|
||||
يستخدم [model id](/docs/config/#models) في إعدادات OpenCode لديك التنسيق `opencode-go/<model-id>`. على سبيل المثال، بالنسبة إلى Kimi K3، ستستخدم `opencode-go/kimi-k3` في إعداداتك.
|
||||
|
||||
@@ -240,29 +248,30 @@ https://opencode.ai/zen/go/v1/models
|
||||
|
||||
## الخصوصية
|
||||
|
||||
| النموذج | تدريب النموذج | الاحتفاظ بالبيانات |
|
||||
| -------------------------- | ------------- | ------------------ |
|
||||
| Grok 4.5 | غير مستخدَمة | 30 يومًا |
|
||||
| GPT 5.6 Luna | غير مستخدَمة | 30 يومًا |
|
||||
| GLM-5.3 | غير مستخدَمة | 0 أيام |
|
||||
| GLM-5.2 | غير مستخدَمة | 0 أيام |
|
||||
| GLM-5.1 | غير مستخدَمة | 0 أيام |
|
||||
| Kimi K3 | غير مستخدَمة | 0 أيام |
|
||||
| Kimi K2.7 Code | غير مستخدَمة | 0 أيام |
|
||||
| Kimi K2.6 | غير مستخدَمة | 0 أيام |
|
||||
| MiMo-V2.5-Pro | غير مستخدَمة | 0 أيام |
|
||||
| MiMo-V2.5 | غير مستخدَمة | 0 أيام |
|
||||
| Qwen3.8 Max | غير مستخدَمة | 0 أيام |
|
||||
| Qwen3.7 Max | غير مستخدَمة | 0 أيام |
|
||||
| Qwen3.7 Plus | غير مستخدَمة | 0 أيام |
|
||||
| Qwen3.6 Plus | غير مستخدَمة | 0 أيام |
|
||||
| MiniMax M3 | غير مستخدَمة | 0 أيام |
|
||||
| MiniMax M2.7 | غير مستخدَمة | 0 أيام |
|
||||
| Muse Spark 1.2 Contributor | نعم | ليست ZDR |
|
||||
| DeepSeek V4 Pro | غير مستخدَمة | 0 أيام |
|
||||
| DeepSeek V4 Flash | غير مستخدَمة | 0 أيام |
|
||||
| Hy3 | غير مستخدَمة | 0 أيام |
|
||||
| Ox Alpha Free | غير مستخدَمة | 0 أيام |
|
||||
| النموذج | تدريب النموذج | الاحتفاظ بالبيانات |
|
||||
| ---------------------------- | ------------- | ------------------ |
|
||||
| Grok 4.5 | غير مستخدَمة | 30 يومًا |
|
||||
| GPT 5.6 Luna | غير مستخدَمة | 30 يومًا |
|
||||
| GLM-5.3 | غير مستخدَمة | 0 أيام |
|
||||
| GLM-5.2 | غير مستخدَمة | 0 أيام |
|
||||
| GLM-5.1 | غير مستخدَمة | 0 أيام |
|
||||
| Kimi K3 | غير مستخدَمة | 0 أيام |
|
||||
| Kimi K2.7 Code | غير مستخدَمة | 0 أيام |
|
||||
| Kimi K2.6 | غير مستخدَمة | 0 أيام |
|
||||
| MiMo-V2.5-Pro | غير مستخدَمة | 0 أيام |
|
||||
| MiMo-V2.5 | غير مستخدَمة | 0 أيام |
|
||||
| Qwen3.8 Max | غير مستخدَمة | 0 أيام |
|
||||
| Qwen3.7 Max | غير مستخدَمة | 0 أيام |
|
||||
| Qwen3.7 Plus | غير مستخدَمة | 0 أيام |
|
||||
| Qwen3.6 Plus | غير مستخدَمة | 0 أيام |
|
||||
| MiniMax M3 | غير مستخدَمة | 0 أيام |
|
||||
| MiniMax M2.7 | غير مستخدَمة | 0 أيام |
|
||||
| Muse Spark 1.2 Contributor | نعم | ليست ZDR |
|
||||
| DeepSeek V4 Pro | غير مستخدَمة | 0 أيام |
|
||||
| DeepSeek V4 Flash | غير مستخدَمة | 0 أيام |
|
||||
| DeepSeek V4 Flash Vision Exp | غير مستخدَمة | 0 أيام |
|
||||
| Hy3 | غير مستخدَمة | 0 أيام |
|
||||
| Ox Alpha Free | غير مستخدَمة | 0 أيام |
|
||||
|
||||
- **Grok 4.5:** تعطّل ZDR ميزات API مهمة تعتمد على البيانات المخزنة، بما في ذلك Responses API ذات الحالة، وFiles and Collections، وBatch API. [اعرف المزيد](https://docs.x.ai/developers/faq/security#what-is-zero-data-retention-zdr).
|
||||
- **GPT 5.6 Luna:** تُنشأ سجلات مراقبة إساءة الاستخدام لكل استخدام لميزات API، ويُحتفظ بها لمدة تصل إلى 30 يومًا. [اعرف المزيد](https://developers.openai.com/api/docs/guides/your-data#data-retention-controls-for-abuse-monitoring).
|
||||
|
||||
@@ -188,8 +188,8 @@ https://opencode.ai/zen/v1/models
|
||||
| Grok 4.5 (> 200K tokens) | $4.00 | $12.00 | $0.60 | - |
|
||||
| Grok Build 0.1 | $1.00 | $2.00 | $0.20 | - |
|
||||
| Muse Spark 1.2 | $1.25 | $4.25 | $0.15 | - |
|
||||
| GPT 5.6 Sol (≤ 272K tokens) | $5.00 | $30.00 | $0.50 | $6.25 |
|
||||
| GPT 5.6 Sol (> 272K tokens) | $10.00 | $45.00 | $1.00 | $12.50 |
|
||||
| GPT 5.6 Sol (≤ 272K tokens) | $2.00 | $10.00 | $0.20 | $2.50 |
|
||||
| GPT 5.6 Sol (> 272K tokens) | $4.00 | $15.00 | $0.40 | $5.00 |
|
||||
| GPT 5.6 Terra (≤ 272K tokens) | $2.00 | $12.00 | $0.20 | $2.50 |
|
||||
| GPT 5.6 Terra (> 272K tokens) | $4.00 | $18.00 | $0.40 | $5.00 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 |
|
||||
@@ -214,6 +214,8 @@ https://opencode.ai/zen/v1/models
|
||||
| GPT 5 Codex | $1.07 | $8.50 | $0.107 | - |
|
||||
| GPT 5 Nano | $0.05 | $0.40 | $0.005 | - |
|
||||
|
||||
**GPT 5.6 Sol:** تشمل الأسعار المعروضة خصمًا بنسبة 50% حتى 18 سبتمبر 2026.
|
||||
|
||||
**DeepSeek V4 Flash / Pro:** ساعات Peak هي 01:00-04:00 و06:00-10:00 UTC؛ وجميع الساعات الأخرى Off-Peak. [اعرف المزيد](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
قد تلاحظ [نماذج منخفضة التكلفة](/docs/config/#models)، مثل Haiku أو Nano أو Flash، في سجل الاستخدام. يستخدم OpenCode هذه النماذج لإنشاء عناوين الجلسات.
|
||||
|
||||
@@ -78,6 +78,7 @@ Trenutna lista modela uključuje:
|
||||
- **Qwen3.6 Plus**
|
||||
- **DeepSeek V4 Pro**
|
||||
- **DeepSeek V4 Flash**
|
||||
- **DeepSeek V4 Flash Vision Exp**
|
||||
- **Hy3**
|
||||
- **Ox Alpha Free** (ograničeno vrijeme)
|
||||
|
||||
@@ -97,29 +98,30 @@ Ograničenja su definisana u dolarskoj vrijednosti. To znači da vaš stvarni br
|
||||
|
||||
Tabela ispod pruža procijenjeni broj zahtjeva na osnovu tipičnih obrazaca korištenja Go pretplate:
|
||||
|
||||
| Model | zahtjeva na 5 sati | zahtjeva sedmično | zahtjeva mjesečno |
|
||||
| -------------------------- | ------------------ | ----------------- | ----------------- |
|
||||
| Grok 4.5 | 120 | 300 | 600 |
|
||||
| GPT 5.6 Luna | 2,050 | 5,100 | 10,250 |
|
||||
| GLM-5.3 | 220 | 540 | 1,080 |
|
||||
| GLM-5.2 | 880 | 2,150 | 4,300 |
|
||||
| GLM-5.1 | 880 | 2,150 | 4,300 |
|
||||
| Kimi K3 | 110 | 250 | 490 |
|
||||
| Kimi K2.7 Code | 1,350 | 3,380 | 6,750 |
|
||||
| Kimi K2.6 | 1,150 | 2,880 | 5,750 |
|
||||
| MiMo-V2.5 | 30,100 | 75,200 | 150,400 |
|
||||
| MiMo-V2.5-Pro | 3,250 | 8,150 | 16,300 |
|
||||
| MiniMax M3 | 3,200 | 8,000 | 16,000 |
|
||||
| MiniMax M2.7 | 3,400 | 8,500 | 17,000 |
|
||||
| Muse Spark 1.2 Contributor | 45,300 | 113,300 | 226,600 |
|
||||
| Qwen3.8 Max | 160 | 400 | 810 |
|
||||
| Qwen3.7 Max | 340 | 840 | 1,690 |
|
||||
| Qwen3.7 Plus | 4,300 | 10,800 | 21,600 |
|
||||
| Qwen3.6 Plus | 3,300 | 8,200 | 16,300 |
|
||||
| DeepSeek V4 Pro | 1,050 | 2,600 | 5,200 |
|
||||
| DeepSeek V4 Flash | 7,600 | 18,900 | 37,800 |
|
||||
| Hy3 | 4,300 | 10,750 | 21,500 |
|
||||
| Ox Alpha Free | - | - | - |
|
||||
| Model | zahtjeva na 5 sati | zahtjeva sedmično | zahtjeva mjesečno |
|
||||
| ---------------------------- | ------------------ | ----------------- | ----------------- |
|
||||
| Grok 4.5 | 120 | 300 | 600 |
|
||||
| GPT 5.6 Luna | 2,050 | 5,100 | 10,250 |
|
||||
| GLM-5.3 | 220 | 540 | 1,080 |
|
||||
| GLM-5.2 | 880 | 2,150 | 4,300 |
|
||||
| GLM-5.1 | 880 | 2,150 | 4,300 |
|
||||
| Kimi K3 | 110 | 250 | 490 |
|
||||
| Kimi K2.7 Code | 1,350 | 3,380 | 6,750 |
|
||||
| Kimi K2.6 | 1,150 | 2,880 | 5,750 |
|
||||
| MiMo-V2.5 | 30,100 | 75,200 | 150,400 |
|
||||
| MiMo-V2.5-Pro | 3,250 | 8,150 | 16,300 |
|
||||
| MiniMax M3 | 3,200 | 8,000 | 16,000 |
|
||||
| MiniMax M2.7 | 3,400 | 8,500 | 17,000 |
|
||||
| Muse Spark 1.2 Contributor | 45,300 | 113,300 | 226,600 |
|
||||
| Qwen3.8 Max | 160 | 400 | 810 |
|
||||
| Qwen3.7 Max | 340 | 840 | 1,690 |
|
||||
| Qwen3.7 Plus | 4,300 | 10,800 | 21,600 |
|
||||
| Qwen3.6 Plus | 3,300 | 8,200 | 16,300 |
|
||||
| DeepSeek V4 Pro | 1,050 | 2,600 | 5,200 |
|
||||
| DeepSeek V4 Flash | 7,600 | 18,900 | 37,800 |
|
||||
| DeepSeek V4 Flash Vision Exp | 3,800 | 9,450 | 18,900 |
|
||||
| Hy3 | 4,300 | 10,750 | 21,500 |
|
||||
| Ox Alpha Free | - | - | - |
|
||||
|
||||
Procjene se zasnivaju na zapaženim obrascima zahtjeva:
|
||||
|
||||
@@ -130,6 +132,7 @@ Procjene se zasnivaju na zapaženim obrascima zahtjeva:
|
||||
- Kimi K2.7/K2.6 — 870 ulaznih, 55,000 keširanih, 200 izlaznih tokena po zahtjevu
|
||||
- DeepSeek V4 Pro — 750 ulaznih, 82,000 keširanih, 290 izlaznih tokena po zahtjevu
|
||||
- DeepSeek V4 Flash — 410 ulaznih, 71,300 keširanih, 310 izlaznih tokena po zahtjevu
|
||||
- DeepSeek V4 Flash Vision Exp — 410 ulaznih, 71,300 keširanih, 310 izlaznih tokena po zahtjevu
|
||||
- MiniMax M3 — 510 ulaznih, 56,000 keširanih, 190 izlaznih tokena po zahtjevu
|
||||
- MiniMax M2.7 — 300 ulaznih, 55,000 keširanih, 125 izlaznih tokena po zahtjevu
|
||||
- Muse Spark 1.2 Contributor — 620 ulaznih, 71,400 keširanih, 300 izlaznih tokena po zahtjevu
|
||||
@@ -143,37 +146,41 @@ Procjene se zasnivaju na zapaženim obrascima zahtjeva:
|
||||
|
||||
Procjene se također zasnivaju na sljedećim cijenama po 1M tokena i mjesečnoj potrošnji uključenoj uz svaki model:
|
||||
|
||||
| Model | Input | Output | Cached Read | Cached Write | Potrošnja |
|
||||
| ---------------------------- | ------ | ------ | ----------- | ------------ | --------- |
|
||||
| Grok 4.5 | $2.00 | $6.00 | $0.30 | - | $15 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 | $15 |
|
||||
| GPT 5.6 Luna (> 272K tokens) | $0.40 | $1.80 | $0.04 | $0.50 | $15 |
|
||||
| GLM-5.3 | $1.40 | $4.40 | $0.26 | - | $15 |
|
||||
| GLM-5.2 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| GLM-5.1 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| Kimi K3 | $3.00 | $15.00 | $0.30 | - | $15 |
|
||||
| Kimi K2.7 Code | $0.95 | $4.00 | $0.19 | - | $60 |
|
||||
| Kimi K2.6 | $0.95 | $4.00 | $0.16 | - | $60 |
|
||||
| MiMo V2.5 | $0.14 | $0.28 | $0.0028 | - | $60 |
|
||||
| MiMo V2.5 Pro | $0.435 | $0.87 | $0.003625 | - | $15 |
|
||||
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - | $60 |
|
||||
| MiniMax M2.7 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| Muse Spark 1.2 Contributor | $0.10 | $0.20 | $0.002 | - | $60 |
|
||||
| Qwen3.8 Max | $2.00 | $6.00 | $0.25 | $2.50 | $15 |
|
||||
| Qwen3.7 Max | $2.50 | $7.50 | $0.50 | $3.125 | $60 |
|
||||
| Qwen3.7 Plus (≤ 256K tokens) | $0.40 | $1.60 | $0.04 | $0.50 | $60 |
|
||||
| Qwen3.7 Plus (> 256K tokens) | $1.20 | $4.80 | $0.12 | $1.50 | $60 |
|
||||
| Qwen3.6 Plus (≤ 256K tokens) | $0.50 | $3.00 | $0.05 | $0.625 | $60 |
|
||||
| Qwen3.6 Plus (> 256K tokens) | $2.00 | $6.00 | $0.20 | $2.50 | $60 |
|
||||
| DeepSeek V4 Pro (Off-Peak) | $0.66 | $1.98 | $0.022 | - | $15 |
|
||||
| DeepSeek V4 Pro (Peak) | $1.32 | $3.96 | $0.044 | - | $15 |
|
||||
| DeepSeek V4 Flash (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $30 |
|
||||
| DeepSeek V4 Flash (Peak) | $0.44 | $1.32 | $0.014 | - | $30 |
|
||||
| Hy3 | $0.14 | $0.58 | $0.035 | - | $60 |
|
||||
| Ox Alpha Free | - | - | - | - | - |
|
||||
| Model | Input | Output | Cached Read | Cached Write | Potrošnja |
|
||||
| --------------------------------------- | ------ | ------ | ----------- | ------------ | --------- |
|
||||
| Grok 4.5 | $2.00 | $6.00 | $0.30 | - | $15 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 | $15 |
|
||||
| GPT 5.6 Luna (> 272K tokens) | $0.40 | $1.80 | $0.04 | $0.50 | $15 |
|
||||
| GLM-5.3 | $1.40 | $4.40 | $0.26 | - | $15 |
|
||||
| GLM-5.2 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| GLM-5.1 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| Kimi K3 | $3.00 | $15.00 | $0.30 | - | $15 |
|
||||
| Kimi K2.7 Code | $0.95 | $4.00 | $0.19 | - | $60 |
|
||||
| Kimi K2.6 | $0.95 | $4.00 | $0.16 | - | $60 |
|
||||
| MiMo V2.5 | $0.14 | $0.28 | $0.0028 | - | $60 |
|
||||
| MiMo V2.5 Pro | $0.435 | $0.87 | $0.003625 | - | $15 |
|
||||
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - | $60 |
|
||||
| MiniMax M2.7 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| Muse Spark 1.2 Contributor | $0.10 | $0.20 | $0.002 | - | $60 |
|
||||
| Qwen3.8 Max | $2.00 | $6.00 | $0.25 | $2.50 | $15 |
|
||||
| Qwen3.7 Max | $2.50 | $7.50 | $0.50 | $3.125 | $60 |
|
||||
| Qwen3.7 Plus (≤ 256K tokens) | $0.40 | $1.60 | $0.04 | $0.50 | $60 |
|
||||
| Qwen3.7 Plus (> 256K tokens) | $1.20 | $4.80 | $0.12 | $1.50 | $60 |
|
||||
| Qwen3.6 Plus (≤ 256K tokens) | $0.50 | $3.00 | $0.05 | $0.625 | $60 |
|
||||
| Qwen3.6 Plus (> 256K tokens) | $2.00 | $6.00 | $0.20 | $2.50 | $60 |
|
||||
| DeepSeek V4 Pro (Off-Peak) | $0.66 | $1.98 | $0.022 | - | $15 |
|
||||
| DeepSeek V4 Pro (Peak) | $1.32 | $3.96 | $0.044 | - | $15 |
|
||||
| DeepSeek V4 Flash (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $30 |
|
||||
| DeepSeek V4 Flash (Peak) | $0.44 | $1.32 | $0.014 | - | $30 |
|
||||
| DeepSeek V4 Flash Vision Exp (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $15 |
|
||||
| DeepSeek V4 Flash Vision Exp (Peak) | $0.44 | $1.32 | $0.014 | - | $15 |
|
||||
| Hy3 | $0.14 | $0.58 | $0.035 | - | $60 |
|
||||
| Ox Alpha Free | - | - | - | - | - |
|
||||
|
||||
**DeepSeek V4 Flash / Pro:** Peak sati su 01:00-04:00 i 06:00-10:00 UTC; svi ostali sati su Off-Peak. [Saznajte više](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
**DeepSeek V4 Flash / V4 Flash Vision Exp / V4 Pro:** Peak sati su 01:00-04:00 i 06:00-10:00 UTC; svi ostali sati su Off-Peak. [Saznajte više](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
**DeepSeek V4 Flash Vision Exp:** Slike se pretvaraju u tokene na osnovu svojih dimenzija i naplaćuju kao ulazni tokeni zajedno s tekstualnim tokenima. [Saznajte više](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
**Ox Alpha Free:** Besplatan ograničeno vrijeme.
|
||||
|
||||
@@ -211,30 +218,31 @@ Za ove modele i dalje dobijate malo više nego da direktno plaćate provajderima
|
||||
|
||||
Također možete pristupiti Go modelima putem sljedećih API endpointa.
|
||||
|
||||
| Model | Model ID | Endpoint | AI SDK Paket |
|
||||
| -------------------------- | -------------------------- | ------------------------------------------------ | --------------------------- |
|
||||
| Grok 4.5 | grok-4.5 | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GPT 5.6 Luna | gpt-5.6-luna | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GLM-5.3 | glm-5.3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.2 | glm-5.2 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.1 | glm-5.1 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K3 | kimi-k3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.7 Code | kimi-k2.7-code | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.6 | kimi-k2.6 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Pro | deepseek-v4-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash | deepseek-v4-flash | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5 | mimo-v2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5-Pro | mimo-v2.5-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiniMax M3 | minimax-m3 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.7 | minimax-m2.7 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Muse Spark 1.2 Contributor | muse-spark-1.2-contributor | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| Qwen3.8 Max | qwen3.8-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Max | qwen3.7-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Plus | qwen3.7-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.6 Plus | qwen3.6-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Hy3 | hy3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Ox Alpha Free | x-preview-f-free | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Model | Model ID | Endpoint | AI SDK Paket |
|
||||
| ---------------------------- | ---------------------------- | ------------------------------------------------ | --------------------------- |
|
||||
| Grok 4.5 | grok-4.5 | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GPT 5.6 Luna | gpt-5.6-luna | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GLM-5.3 | glm-5.3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.2 | glm-5.2 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.1 | glm-5.1 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K3 | kimi-k3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.7 Code | kimi-k2.7-code | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.6 | kimi-k2.6 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Pro | deepseek-v4-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash | deepseek-v4-flash | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash Vision Exp | deepseek-v4-flash-vision-exp | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5 | mimo-v2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5-Pro | mimo-v2.5-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiniMax M3 | minimax-m3 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.7 | minimax-m2.7 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Muse Spark 1.2 Contributor | muse-spark-1.2-contributor | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| Qwen3.8 Max | qwen3.8-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Max | qwen3.7-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Plus | qwen3.7-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.6 Plus | qwen3.6-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Hy3 | hy3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Ox Alpha Free | ox-alpha-free | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
|
||||
[Model id](/docs/config/#models) u vašoj OpenCode konfiguraciji
|
||||
koristi format `opencode-go/<model-id>`. Na primjer, za Kimi K3, koristili biste
|
||||
@@ -254,29 +262,30 @@ https://opencode.ai/zen/go/v1/models
|
||||
|
||||
## Privatnost
|
||||
|
||||
| Model | Treniranje modela | Zadržavanje podataka |
|
||||
| -------------------------- | ----------------- | -------------------- |
|
||||
| Grok 4.5 | Ne koristi se | 30 dana |
|
||||
| GPT 5.6 Luna | Ne koristi se | 30 dana |
|
||||
| GLM-5.3 | Ne koristi se | 0 dana |
|
||||
| GLM-5.2 | Ne koristi se | 0 dana |
|
||||
| GLM-5.1 | Ne koristi se | 0 dana |
|
||||
| Kimi K3 | Ne koristi se | 0 dana |
|
||||
| Kimi K2.7 Code | Ne koristi se | 0 dana |
|
||||
| Kimi K2.6 | Ne koristi se | 0 dana |
|
||||
| MiMo-V2.5-Pro | Ne koristi se | 0 dana |
|
||||
| MiMo-V2.5 | Ne koristi se | 0 dana |
|
||||
| Qwen3.8 Max | Ne koristi se | 0 dana |
|
||||
| Qwen3.7 Max | Ne koristi se | 0 dana |
|
||||
| Qwen3.7 Plus | Ne koristi se | 0 dana |
|
||||
| Qwen3.6 Plus | Ne koristi se | 0 dana |
|
||||
| MiniMax M3 | Ne koristi se | 0 dana |
|
||||
| MiniMax M2.7 | Ne koristi se | 0 dana |
|
||||
| Muse Spark 1.2 Contributor | Da | Nije ZDR |
|
||||
| DeepSeek V4 Pro | Ne koristi se | 0 dana |
|
||||
| DeepSeek V4 Flash | Ne koristi se | 0 dana |
|
||||
| Hy3 | Ne koristi se | 0 dana |
|
||||
| Ox Alpha Free | Ne koristi se | 0 dana |
|
||||
| Model | Treniranje modela | Zadržavanje podataka |
|
||||
| ---------------------------- | ----------------- | -------------------- |
|
||||
| Grok 4.5 | Ne koristi se | 30 dana |
|
||||
| GPT 5.6 Luna | Ne koristi se | 30 dana |
|
||||
| GLM-5.3 | Ne koristi se | 0 dana |
|
||||
| GLM-5.2 | Ne koristi se | 0 dana |
|
||||
| GLM-5.1 | Ne koristi se | 0 dana |
|
||||
| Kimi K3 | Ne koristi se | 0 dana |
|
||||
| Kimi K2.7 Code | Ne koristi se | 0 dana |
|
||||
| Kimi K2.6 | Ne koristi se | 0 dana |
|
||||
| MiMo-V2.5-Pro | Ne koristi se | 0 dana |
|
||||
| MiMo-V2.5 | Ne koristi se | 0 dana |
|
||||
| Qwen3.8 Max | Ne koristi se | 0 dana |
|
||||
| Qwen3.7 Max | Ne koristi se | 0 dana |
|
||||
| Qwen3.7 Plus | Ne koristi se | 0 dana |
|
||||
| Qwen3.6 Plus | Ne koristi se | 0 dana |
|
||||
| MiniMax M3 | Ne koristi se | 0 dana |
|
||||
| MiniMax M2.7 | Ne koristi se | 0 dana |
|
||||
| Muse Spark 1.2 Contributor | Da | Nije ZDR |
|
||||
| DeepSeek V4 Pro | Ne koristi se | 0 dana |
|
||||
| DeepSeek V4 Flash | Ne koristi se | 0 dana |
|
||||
| DeepSeek V4 Flash Vision Exp | Ne koristi se | 0 dana |
|
||||
| Hy3 | Ne koristi se | 0 dana |
|
||||
| Ox Alpha Free | Ne koristi se | 0 dana |
|
||||
|
||||
- **Grok 4.5:** ZDR onemogućava važne API funkcije koje zavise od pohranjenih podataka, uključujući Responses API s očuvanjem stanja, Files and Collections i Batch API. [Saznajte više](https://docs.x.ai/developers/faq/security#what-is-zero-data-retention-zdr).
|
||||
- **GPT 5.6 Luna:** Zapisi o nadzoru zloupotrebe generišu se za svako korištenje API funkcija i čuvaju do 30 dana. [Saznajte više](https://developers.openai.com/api/docs/guides/your-data#data-retention-controls-for-abuse-monitoring).
|
||||
|
||||
@@ -195,8 +195,8 @@ Podržavamo pay-as-you-go model. Ispod su cijene **po 1M tokena**.
|
||||
| Grok 4.5 (> 200K tokens) | $4.00 | $12.00 | $0.60 | - |
|
||||
| Grok Build 0.1 | $1.00 | $2.00 | $0.20 | - |
|
||||
| Muse Spark 1.2 | $1.25 | $4.25 | $0.15 | - |
|
||||
| GPT 5.6 Sol (≤ 272K tokens) | $5.00 | $30.00 | $0.50 | $6.25 |
|
||||
| GPT 5.6 Sol (> 272K tokens) | $10.00 | $45.00 | $1.00 | $12.50 |
|
||||
| GPT 5.6 Sol (≤ 272K tokens) | $2.00 | $10.00 | $0.20 | $2.50 |
|
||||
| GPT 5.6 Sol (> 272K tokens) | $4.00 | $15.00 | $0.40 | $5.00 |
|
||||
| GPT 5.6 Terra (≤ 272K tokens) | $2.00 | $12.00 | $0.20 | $2.50 |
|
||||
| GPT 5.6 Terra (> 272K tokens) | $4.00 | $18.00 | $0.40 | $5.00 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 |
|
||||
@@ -221,6 +221,8 @@ Podržavamo pay-as-you-go model. Ispod su cijene **po 1M tokena**.
|
||||
| GPT 5 Codex | $1.07 | $8.50 | $0.107 | - |
|
||||
| GPT 5 Nano | $0.05 | $0.40 | $0.005 | - |
|
||||
|
||||
**GPT 5.6 Sol:** Prikazane cijene uključuju popust od 50% do 18. septembra 2026.
|
||||
|
||||
**DeepSeek V4 Flash / Pro:** Peak sati su 01:00-04:00 i 06:00-10:00 UTC; svi ostali sati su Off-Peak. [Saznajte više](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
U historiji korištenja možete primijetiti [jeftinije modele](/docs/config/#models), kao što su Haiku, Nano ili Flash. OpenCode koristi ove modele za generisanje naslova sesija.
|
||||
|
||||
@@ -78,6 +78,7 @@ Den nuværende liste over modeller inkluderer:
|
||||
- **Qwen3.6 Plus**
|
||||
- **DeepSeek V4 Pro**
|
||||
- **DeepSeek V4 Flash**
|
||||
- **DeepSeek V4 Flash Vision Exp**
|
||||
- **Hy3**
|
||||
- **Ox Alpha Free** (i en begrænset periode)
|
||||
|
||||
@@ -97,29 +98,30 @@ Grænserne er defineret i dollarværdi. Det betyder, at dit faktiske antal anmod
|
||||
|
||||
Tabellen nedenfor giver et estimeret antal anmodninger baseret på typiske Go-forbrugsmønstre:
|
||||
|
||||
| Model | anmodninger pr. 5 timer | anmodninger pr. uge | anmodninger pr. måned |
|
||||
| -------------------------- | ----------------------- | ------------------- | --------------------- |
|
||||
| Grok 4.5 | 120 | 300 | 600 |
|
||||
| GPT 5.6 Luna | 2,050 | 5,100 | 10,250 |
|
||||
| GLM-5.3 | 220 | 540 | 1,080 |
|
||||
| GLM-5.2 | 880 | 2,150 | 4,300 |
|
||||
| GLM-5.1 | 880 | 2,150 | 4,300 |
|
||||
| Kimi K3 | 110 | 250 | 490 |
|
||||
| Kimi K2.7 Code | 1,350 | 3,380 | 6,750 |
|
||||
| Kimi K2.6 | 1,150 | 2,880 | 5,750 |
|
||||
| MiMo-V2.5 | 30,100 | 75,200 | 150,400 |
|
||||
| MiMo-V2.5-Pro | 3,250 | 8,150 | 16,300 |
|
||||
| MiniMax M3 | 3,200 | 8,000 | 16,000 |
|
||||
| MiniMax M2.7 | 3,400 | 8,500 | 17,000 |
|
||||
| Muse Spark 1.2 Contributor | 45,300 | 113,300 | 226,600 |
|
||||
| Qwen3.8 Max | 160 | 400 | 810 |
|
||||
| Qwen3.7 Max | 340 | 840 | 1,690 |
|
||||
| Qwen3.7 Plus | 4,300 | 10,800 | 21,600 |
|
||||
| Qwen3.6 Plus | 3,300 | 8,200 | 16,300 |
|
||||
| DeepSeek V4 Pro | 1,050 | 2,600 | 5,200 |
|
||||
| DeepSeek V4 Flash | 7,600 | 18,900 | 37,800 |
|
||||
| Hy3 | 4,300 | 10,750 | 21,500 |
|
||||
| Ox Alpha Free | - | - | - |
|
||||
| Model | anmodninger pr. 5 timer | anmodninger pr. uge | anmodninger pr. måned |
|
||||
| ---------------------------- | ----------------------- | ------------------- | --------------------- |
|
||||
| Grok 4.5 | 120 | 300 | 600 |
|
||||
| GPT 5.6 Luna | 2,050 | 5,100 | 10,250 |
|
||||
| GLM-5.3 | 220 | 540 | 1,080 |
|
||||
| GLM-5.2 | 880 | 2,150 | 4,300 |
|
||||
| GLM-5.1 | 880 | 2,150 | 4,300 |
|
||||
| Kimi K3 | 110 | 250 | 490 |
|
||||
| Kimi K2.7 Code | 1,350 | 3,380 | 6,750 |
|
||||
| Kimi K2.6 | 1,150 | 2,880 | 5,750 |
|
||||
| MiMo-V2.5 | 30,100 | 75,200 | 150,400 |
|
||||
| MiMo-V2.5-Pro | 3,250 | 8,150 | 16,300 |
|
||||
| MiniMax M3 | 3,200 | 8,000 | 16,000 |
|
||||
| MiniMax M2.7 | 3,400 | 8,500 | 17,000 |
|
||||
| Muse Spark 1.2 Contributor | 45,300 | 113,300 | 226,600 |
|
||||
| Qwen3.8 Max | 160 | 400 | 810 |
|
||||
| Qwen3.7 Max | 340 | 840 | 1,690 |
|
||||
| Qwen3.7 Plus | 4,300 | 10,800 | 21,600 |
|
||||
| Qwen3.6 Plus | 3,300 | 8,200 | 16,300 |
|
||||
| DeepSeek V4 Pro | 1,050 | 2,600 | 5,200 |
|
||||
| DeepSeek V4 Flash | 7,600 | 18,900 | 37,800 |
|
||||
| DeepSeek V4 Flash Vision Exp | 3,800 | 9,450 | 18,900 |
|
||||
| Hy3 | 4,300 | 10,750 | 21,500 |
|
||||
| Ox Alpha Free | - | - | - |
|
||||
|
||||
Estimaterne er baseret på observerede anmodningsmønstre:
|
||||
|
||||
@@ -130,6 +132,7 @@ Estimaterne er baseret på observerede anmodningsmønstre:
|
||||
- Kimi K2.7/K2.6 — 870 input, 55.000 cachelagrede, 200 output-tokens pr. anmodning
|
||||
- DeepSeek V4 Pro — 750 input, 82.000 cachelagrede, 290 output-tokens pr. anmodning
|
||||
- DeepSeek V4 Flash — 410 input, 71.300 cachelagrede, 310 output-tokens pr. anmodning
|
||||
- DeepSeek V4 Flash Vision Exp — 410 input, 71.300 cachelagrede, 310 output-tokens pr. anmodning
|
||||
- MiniMax M3 — 510 input, 56.000 cachelagrede, 190 output-tokens pr. anmodning
|
||||
- MiniMax M2.7 — 300 input, 55.000 cachelagrede, 125 output-tokens pr. anmodning
|
||||
- Muse Spark 1.2 Contributor — 620 input, 71.400 cachelagrede, 300 output-tokens pr. anmodning
|
||||
@@ -143,37 +146,41 @@ Estimaterne er baseret på observerede anmodningsmønstre:
|
||||
|
||||
Estimaterne er også baseret på følgende priser pr. 1M tokens og det månedlige forbrug, der er inkluderet med hver model:
|
||||
|
||||
| Model | Input | Output | Cached Read | Cached Write | Forbrug |
|
||||
| ---------------------------- | ------ | ------ | ----------- | ------------ | ------- |
|
||||
| Grok 4.5 | $2.00 | $6.00 | $0.30 | - | $15 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 | $15 |
|
||||
| GPT 5.6 Luna (> 272K tokens) | $0.40 | $1.80 | $0.04 | $0.50 | $15 |
|
||||
| GLM-5.3 | $1.40 | $4.40 | $0.26 | - | $15 |
|
||||
| GLM-5.2 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| GLM-5.1 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| Kimi K3 | $3.00 | $15.00 | $0.30 | - | $15 |
|
||||
| Kimi K2.7 Code | $0.95 | $4.00 | $0.19 | - | $60 |
|
||||
| Kimi K2.6 | $0.95 | $4.00 | $0.16 | - | $60 |
|
||||
| MiMo V2.5 | $0.14 | $0.28 | $0.0028 | - | $60 |
|
||||
| MiMo V2.5 Pro | $0.435 | $0.87 | $0.003625 | - | $15 |
|
||||
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - | $60 |
|
||||
| MiniMax M2.7 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| Muse Spark 1.2 Contributor | $0.10 | $0.20 | $0.002 | - | $60 |
|
||||
| Qwen3.8 Max | $2.00 | $6.00 | $0.25 | $2.50 | $15 |
|
||||
| Qwen3.7 Max | $2.50 | $7.50 | $0.50 | $3.125 | $60 |
|
||||
| Qwen3.7 Plus (≤ 256K tokens) | $0.40 | $1.60 | $0.04 | $0.50 | $60 |
|
||||
| Qwen3.7 Plus (> 256K tokens) | $1.20 | $4.80 | $0.12 | $1.50 | $60 |
|
||||
| Qwen3.6 Plus (≤ 256K tokens) | $0.50 | $3.00 | $0.05 | $0.625 | $60 |
|
||||
| Qwen3.6 Plus (> 256K tokens) | $2.00 | $6.00 | $0.20 | $2.50 | $60 |
|
||||
| DeepSeek V4 Pro (Off-Peak) | $0.66 | $1.98 | $0.022 | - | $15 |
|
||||
| DeepSeek V4 Pro (Peak) | $1.32 | $3.96 | $0.044 | - | $15 |
|
||||
| DeepSeek V4 Flash (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $30 |
|
||||
| DeepSeek V4 Flash (Peak) | $0.44 | $1.32 | $0.014 | - | $30 |
|
||||
| Hy3 | $0.14 | $0.58 | $0.035 | - | $60 |
|
||||
| Ox Alpha Free | - | - | - | - | - |
|
||||
| Model | Input | Output | Cached Read | Cached Write | Forbrug |
|
||||
| --------------------------------------- | ------ | ------ | ----------- | ------------ | ------- |
|
||||
| Grok 4.5 | $2.00 | $6.00 | $0.30 | - | $15 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 | $15 |
|
||||
| GPT 5.6 Luna (> 272K tokens) | $0.40 | $1.80 | $0.04 | $0.50 | $15 |
|
||||
| GLM-5.3 | $1.40 | $4.40 | $0.26 | - | $15 |
|
||||
| GLM-5.2 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| GLM-5.1 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| Kimi K3 | $3.00 | $15.00 | $0.30 | - | $15 |
|
||||
| Kimi K2.7 Code | $0.95 | $4.00 | $0.19 | - | $60 |
|
||||
| Kimi K2.6 | $0.95 | $4.00 | $0.16 | - | $60 |
|
||||
| MiMo V2.5 | $0.14 | $0.28 | $0.0028 | - | $60 |
|
||||
| MiMo V2.5 Pro | $0.435 | $0.87 | $0.003625 | - | $15 |
|
||||
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - | $60 |
|
||||
| MiniMax M2.7 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| Muse Spark 1.2 Contributor | $0.10 | $0.20 | $0.002 | - | $60 |
|
||||
| Qwen3.8 Max | $2.00 | $6.00 | $0.25 | $2.50 | $15 |
|
||||
| Qwen3.7 Max | $2.50 | $7.50 | $0.50 | $3.125 | $60 |
|
||||
| Qwen3.7 Plus (≤ 256K tokens) | $0.40 | $1.60 | $0.04 | $0.50 | $60 |
|
||||
| Qwen3.7 Plus (> 256K tokens) | $1.20 | $4.80 | $0.12 | $1.50 | $60 |
|
||||
| Qwen3.6 Plus (≤ 256K tokens) | $0.50 | $3.00 | $0.05 | $0.625 | $60 |
|
||||
| Qwen3.6 Plus (> 256K tokens) | $2.00 | $6.00 | $0.20 | $2.50 | $60 |
|
||||
| DeepSeek V4 Pro (Off-Peak) | $0.66 | $1.98 | $0.022 | - | $15 |
|
||||
| DeepSeek V4 Pro (Peak) | $1.32 | $3.96 | $0.044 | - | $15 |
|
||||
| DeepSeek V4 Flash (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $30 |
|
||||
| DeepSeek V4 Flash (Peak) | $0.44 | $1.32 | $0.014 | - | $30 |
|
||||
| DeepSeek V4 Flash Vision Exp (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $15 |
|
||||
| DeepSeek V4 Flash Vision Exp (Peak) | $0.44 | $1.32 | $0.014 | - | $15 |
|
||||
| Hy3 | $0.14 | $0.58 | $0.035 | - | $60 |
|
||||
| Ox Alpha Free | - | - | - | - | - |
|
||||
|
||||
**DeepSeek V4 Flash / Pro:** Peak-tiderne er 01:00-04:00 og 06:00-10:00 UTC; alle andre tider er Off-Peak. [Læs mere](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
**DeepSeek V4 Flash / V4 Flash Vision Exp / V4 Pro:** Peak-tiderne er 01:00-04:00 og 06:00-10:00 UTC; alle andre tider er Off-Peak. [Læs mere](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
**DeepSeek V4 Flash Vision Exp:** Billeder konverteres til tokens baseret på deres dimensioner og afregnes som inputtokens sammen med teksttokens. [Læs mere](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
**Ox Alpha Free:** Gratis i en begrænset periode.
|
||||
|
||||
@@ -211,30 +218,31 @@ Med disse modeller får du stadig lidt mere, end hvis du betalte modeludbyderne
|
||||
|
||||
Du kan også få adgang til Go-modeller gennem følgende API-endpoints.
|
||||
|
||||
| Model | Model ID | Endpoint | AI SDK Package |
|
||||
| -------------------------- | -------------------------- | ------------------------------------------------ | --------------------------- |
|
||||
| Grok 4.5 | grok-4.5 | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GPT 5.6 Luna | gpt-5.6-luna | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GLM-5.3 | glm-5.3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.2 | glm-5.2 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.1 | glm-5.1 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K3 | kimi-k3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.7 Code | kimi-k2.7-code | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.6 | kimi-k2.6 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Pro | deepseek-v4-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash | deepseek-v4-flash | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5 | mimo-v2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5-Pro | mimo-v2.5-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiniMax M3 | minimax-m3 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.7 | minimax-m2.7 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Muse Spark 1.2 Contributor | muse-spark-1.2-contributor | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| Qwen3.8 Max | qwen3.8-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Max | qwen3.7-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Plus | qwen3.7-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.6 Plus | qwen3.6-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Hy3 | hy3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Ox Alpha Free | x-preview-f-free | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Model | Model ID | Endpoint | AI SDK Package |
|
||||
| ---------------------------- | ---------------------------- | ------------------------------------------------ | --------------------------- |
|
||||
| Grok 4.5 | grok-4.5 | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GPT 5.6 Luna | gpt-5.6-luna | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GLM-5.3 | glm-5.3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.2 | glm-5.2 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.1 | glm-5.1 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K3 | kimi-k3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.7 Code | kimi-k2.7-code | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.6 | kimi-k2.6 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Pro | deepseek-v4-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash | deepseek-v4-flash | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash Vision Exp | deepseek-v4-flash-vision-exp | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5 | mimo-v2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5-Pro | mimo-v2.5-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiniMax M3 | minimax-m3 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.7 | minimax-m2.7 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Muse Spark 1.2 Contributor | muse-spark-1.2-contributor | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| Qwen3.8 Max | qwen3.8-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Max | qwen3.7-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Plus | qwen3.7-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.6 Plus | qwen3.6-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Hy3 | hy3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Ox Alpha Free | ox-alpha-free | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
|
||||
Dit [model id](/docs/config/#models) i din OpenCode config
|
||||
bruger formatet `opencode-go/<model-id>`. For eksempel for Kimi K3, vil du
|
||||
@@ -254,29 +262,30 @@ https://opencode.ai/zen/go/v1/models
|
||||
|
||||
## Privatliv
|
||||
|
||||
| Model | Modeltræning | Dataopbevaring |
|
||||
| -------------------------- | ------------ | -------------- |
|
||||
| Grok 4.5 | Ikke brugt | 30 dage |
|
||||
| GPT 5.6 Luna | Ikke brugt | 30 dage |
|
||||
| GLM-5.3 | Ikke brugt | 0 dage |
|
||||
| GLM-5.2 | Ikke brugt | 0 dage |
|
||||
| GLM-5.1 | Ikke brugt | 0 dage |
|
||||
| Kimi K3 | Ikke brugt | 0 dage |
|
||||
| Kimi K2.7 Code | Ikke brugt | 0 dage |
|
||||
| Kimi K2.6 | Ikke brugt | 0 dage |
|
||||
| MiMo-V2.5-Pro | Ikke brugt | 0 dage |
|
||||
| MiMo-V2.5 | Ikke brugt | 0 dage |
|
||||
| Qwen3.8 Max | Ikke brugt | 0 dage |
|
||||
| Qwen3.7 Max | Ikke brugt | 0 dage |
|
||||
| Qwen3.7 Plus | Ikke brugt | 0 dage |
|
||||
| Qwen3.6 Plus | Ikke brugt | 0 dage |
|
||||
| MiniMax M3 | Ikke brugt | 0 dage |
|
||||
| MiniMax M2.7 | Ikke brugt | 0 dage |
|
||||
| Muse Spark 1.2 Contributor | Ja | Ikke ZDR |
|
||||
| DeepSeek V4 Pro | Ikke brugt | 0 dage |
|
||||
| DeepSeek V4 Flash | Ikke brugt | 0 dage |
|
||||
| Hy3 | Ikke brugt | 0 dage |
|
||||
| Ox Alpha Free | Ikke brugt | 0 dage |
|
||||
| Model | Modeltræning | Dataopbevaring |
|
||||
| ---------------------------- | ------------ | -------------- |
|
||||
| Grok 4.5 | Ikke brugt | 30 dage |
|
||||
| GPT 5.6 Luna | Ikke brugt | 30 dage |
|
||||
| GLM-5.3 | Ikke brugt | 0 dage |
|
||||
| GLM-5.2 | Ikke brugt | 0 dage |
|
||||
| GLM-5.1 | Ikke brugt | 0 dage |
|
||||
| Kimi K3 | Ikke brugt | 0 dage |
|
||||
| Kimi K2.7 Code | Ikke brugt | 0 dage |
|
||||
| Kimi K2.6 | Ikke brugt | 0 dage |
|
||||
| MiMo-V2.5-Pro | Ikke brugt | 0 dage |
|
||||
| MiMo-V2.5 | Ikke brugt | 0 dage |
|
||||
| Qwen3.8 Max | Ikke brugt | 0 dage |
|
||||
| Qwen3.7 Max | Ikke brugt | 0 dage |
|
||||
| Qwen3.7 Plus | Ikke brugt | 0 dage |
|
||||
| Qwen3.6 Plus | Ikke brugt | 0 dage |
|
||||
| MiniMax M3 | Ikke brugt | 0 dage |
|
||||
| MiniMax M2.7 | Ikke brugt | 0 dage |
|
||||
| Muse Spark 1.2 Contributor | Ja | Ikke ZDR |
|
||||
| DeepSeek V4 Pro | Ikke brugt | 0 dage |
|
||||
| DeepSeek V4 Flash | Ikke brugt | 0 dage |
|
||||
| DeepSeek V4 Flash Vision Exp | Ikke brugt | 0 dage |
|
||||
| Hy3 | Ikke brugt | 0 dage |
|
||||
| Ox Alpha Free | Ikke brugt | 0 dage |
|
||||
|
||||
- **Grok 4.5:** ZDR deaktiverer vigtige API-funktioner, der afhænger af lagrede data, herunder den tilstandsbevarende Responses API, Files and Collections og Batch API. [Læs mere](https://docs.x.ai/developers/faq/security#what-is-zero-data-retention-zdr).
|
||||
- **GPT 5.6 Luna:** Logfiler til overvågning af misbrug genereres ved al brug af API-funktioner og opbevares i op til 30 dage. [Læs mere](https://developers.openai.com/api/docs/guides/your-data#data-retention-controls-for-abuse-monitoring).
|
||||
|
||||
@@ -195,8 +195,8 @@ Vi understøtter en pay-as-you-go-model. Nedenfor er priserne **pr. 1M tokens**.
|
||||
| Grok 4.5 (> 200K tokens) | $4.00 | $12.00 | $0.60 | - |
|
||||
| Grok Build 0.1 | $1.00 | $2.00 | $0.20 | - |
|
||||
| Muse Spark 1.2 | $1.25 | $4.25 | $0.15 | - |
|
||||
| GPT 5.6 Sol (≤ 272K tokens) | $5.00 | $30.00 | $0.50 | $6.25 |
|
||||
| GPT 5.6 Sol (> 272K tokens) | $10.00 | $45.00 | $1.00 | $12.50 |
|
||||
| GPT 5.6 Sol (≤ 272K tokens) | $2.00 | $10.00 | $0.20 | $2.50 |
|
||||
| GPT 5.6 Sol (> 272K tokens) | $4.00 | $15.00 | $0.40 | $5.00 |
|
||||
| GPT 5.6 Terra (≤ 272K tokens) | $2.00 | $12.00 | $0.20 | $2.50 |
|
||||
| GPT 5.6 Terra (> 272K tokens) | $4.00 | $18.00 | $0.40 | $5.00 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 |
|
||||
@@ -221,6 +221,8 @@ Vi understøtter en pay-as-you-go-model. Nedenfor er priserne **pr. 1M tokens**.
|
||||
| GPT 5 Codex | $1.07 | $8.50 | $0.107 | - |
|
||||
| GPT 5 Nano | $0.05 | $0.40 | $0.005 | - |
|
||||
|
||||
**GPT 5.6 Sol:** De viste priser inkluderer 50 % rabat til og med den 18. september 2026.
|
||||
|
||||
**DeepSeek V4 Flash / Pro:** Peak-tiderne er 01:00-04:00 og 06:00-10:00 UTC; alle andre tider er Off-Peak. [Læs mere](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
Du vil måske bemærke [lavprismodeller](/docs/config/#models), såsom Haiku, Nano eller Flash, i din brugshistorik. OpenCode bruger disse modeller til at generere sessionstitler.
|
||||
|
||||
@@ -70,6 +70,7 @@ Die aktuelle Liste der Modelle umfasst:
|
||||
- **Qwen3.6 Plus**
|
||||
- **DeepSeek V4 Pro**
|
||||
- **DeepSeek V4 Flash**
|
||||
- **DeepSeek V4 Flash Vision Exp**
|
||||
- **Hy3**
|
||||
- **Ox Alpha Free** (für begrenzte Zeit)
|
||||
|
||||
@@ -89,29 +90,30 @@ Limits sind in Dollarwerten definiert. Das bedeutet, dass die tatsächliche Anza
|
||||
|
||||
Die folgende Tabelle zeigt eine geschätzte Anzahl von Anfragen basierend auf typischen Go-Nutzungsmustern:
|
||||
|
||||
| Model | Anfragen pro 5 Stunden | Anfragen pro Woche | Anfragen pro Monat |
|
||||
| -------------------------- | ---------------------- | ------------------ | ------------------ |
|
||||
| Grok 4.5 | 120 | 300 | 600 |
|
||||
| GPT 5.6 Luna | 2,050 | 5,100 | 10,250 |
|
||||
| GLM-5.3 | 220 | 540 | 1,080 |
|
||||
| GLM-5.2 | 880 | 2,150 | 4,300 |
|
||||
| GLM-5.1 | 880 | 2,150 | 4,300 |
|
||||
| Kimi K3 | 110 | 250 | 490 |
|
||||
| Kimi K2.7 Code | 1,350 | 3,380 | 6,750 |
|
||||
| Kimi K2.6 | 1,150 | 2,880 | 5,750 |
|
||||
| MiMo-V2.5 | 30,100 | 75,200 | 150,400 |
|
||||
| MiMo-V2.5-Pro | 3,250 | 8,150 | 16,300 |
|
||||
| MiniMax M3 | 3,200 | 8,000 | 16,000 |
|
||||
| MiniMax M2.7 | 3,400 | 8,500 | 17,000 |
|
||||
| Muse Spark 1.2 Contributor | 45,300 | 113,300 | 226,600 |
|
||||
| Qwen3.8 Max | 160 | 400 | 810 |
|
||||
| Qwen3.7 Max | 340 | 840 | 1,690 |
|
||||
| Qwen3.7 Plus | 4,300 | 10,800 | 21,600 |
|
||||
| Qwen3.6 Plus | 3,300 | 8,200 | 16,300 |
|
||||
| DeepSeek V4 Pro | 1,050 | 2,600 | 5,200 |
|
||||
| DeepSeek V4 Flash | 7,600 | 18,900 | 37,800 |
|
||||
| Hy3 | 4,300 | 10,750 | 21,500 |
|
||||
| Ox Alpha Free | - | - | - |
|
||||
| Model | Anfragen pro 5 Stunden | Anfragen pro Woche | Anfragen pro Monat |
|
||||
| ---------------------------- | ---------------------- | ------------------ | ------------------ |
|
||||
| Grok 4.5 | 120 | 300 | 600 |
|
||||
| GPT 5.6 Luna | 2,050 | 5,100 | 10,250 |
|
||||
| GLM-5.3 | 220 | 540 | 1,080 |
|
||||
| GLM-5.2 | 880 | 2,150 | 4,300 |
|
||||
| GLM-5.1 | 880 | 2,150 | 4,300 |
|
||||
| Kimi K3 | 110 | 250 | 490 |
|
||||
| Kimi K2.7 Code | 1,350 | 3,380 | 6,750 |
|
||||
| Kimi K2.6 | 1,150 | 2,880 | 5,750 |
|
||||
| MiMo-V2.5 | 30,100 | 75,200 | 150,400 |
|
||||
| MiMo-V2.5-Pro | 3,250 | 8,150 | 16,300 |
|
||||
| MiniMax M3 | 3,200 | 8,000 | 16,000 |
|
||||
| MiniMax M2.7 | 3,400 | 8,500 | 17,000 |
|
||||
| Muse Spark 1.2 Contributor | 45,300 | 113,300 | 226,600 |
|
||||
| Qwen3.8 Max | 160 | 400 | 810 |
|
||||
| Qwen3.7 Max | 340 | 840 | 1,690 |
|
||||
| Qwen3.7 Plus | 4,300 | 10,800 | 21,600 |
|
||||
| Qwen3.6 Plus | 3,300 | 8,200 | 16,300 |
|
||||
| DeepSeek V4 Pro | 1,050 | 2,600 | 5,200 |
|
||||
| DeepSeek V4 Flash | 7,600 | 18,900 | 37,800 |
|
||||
| DeepSeek V4 Flash Vision Exp | 3,800 | 9,450 | 18,900 |
|
||||
| Hy3 | 4,300 | 10,750 | 21,500 |
|
||||
| Ox Alpha Free | - | - | - |
|
||||
|
||||
Die Schätzungen basieren auf beobachteten Anfragemustern:
|
||||
|
||||
@@ -122,6 +124,7 @@ Die Schätzungen basieren auf beobachteten Anfragemustern:
|
||||
- Kimi K2.7/K2.6 — 870 Input-, 55.000 Cached-, 200 Output-Tokens pro Anfrage
|
||||
- DeepSeek V4 Pro — 750 Input-, 82.000 Cached-, 290 Output-Tokens pro Anfrage
|
||||
- DeepSeek V4 Flash — 410 Input-, 71.300 Cached-, 310 Output-Tokens pro Anfrage
|
||||
- DeepSeek V4 Flash Vision Exp — 410 Input-, 71.300 Cached-, 310 Output-Tokens pro Anfrage
|
||||
- MiniMax M3 — 510 Input-, 56.000 Cached-, 190 Output-Tokens pro Anfrage
|
||||
- MiniMax M2.7 — 300 Input-, 55.000 Cached-, 125 Output-Tokens pro Anfrage
|
||||
- Muse Spark 1.2 Contributor — 620 Input-, 71.400 Cached-, 300 Output-Tokens pro Anfrage
|
||||
@@ -135,37 +138,41 @@ Die Schätzungen basieren auf beobachteten Anfragemustern:
|
||||
|
||||
Die Schätzungen basieren außerdem auf den folgenden Preisen pro 1M Tokens und der monatlichen Nutzung, die bei jedem Modell enthalten ist:
|
||||
|
||||
| Model | Input | Output | Cached Read | Cached Write | Nutzung |
|
||||
| ---------------------------- | ------ | ------ | ----------- | ------------ | ------- |
|
||||
| Grok 4.5 | $2.00 | $6.00 | $0.30 | - | $15 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 | $15 |
|
||||
| GPT 5.6 Luna (> 272K tokens) | $0.40 | $1.80 | $0.04 | $0.50 | $15 |
|
||||
| GLM-5.3 | $1.40 | $4.40 | $0.26 | - | $15 |
|
||||
| GLM-5.2 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| GLM-5.1 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| Kimi K3 | $3.00 | $15.00 | $0.30 | - | $15 |
|
||||
| Kimi K2.7 Code | $0.95 | $4.00 | $0.19 | - | $60 |
|
||||
| Kimi K2.6 | $0.95 | $4.00 | $0.16 | - | $60 |
|
||||
| MiMo V2.5 | $0.14 | $0.28 | $0.0028 | - | $60 |
|
||||
| MiMo V2.5 Pro | $0.435 | $0.87 | $0.003625 | - | $15 |
|
||||
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - | $60 |
|
||||
| MiniMax M2.7 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| Muse Spark 1.2 Contributor | $0.10 | $0.20 | $0.002 | - | $60 |
|
||||
| Qwen3.8 Max | $2.00 | $6.00 | $0.25 | $2.50 | $15 |
|
||||
| Qwen3.7 Max | $2.50 | $7.50 | $0.50 | $3.125 | $60 |
|
||||
| Qwen3.7 Plus (≤ 256K tokens) | $0.40 | $1.60 | $0.04 | $0.50 | $60 |
|
||||
| Qwen3.7 Plus (> 256K tokens) | $1.20 | $4.80 | $0.12 | $1.50 | $60 |
|
||||
| Qwen3.6 Plus (≤ 256K tokens) | $0.50 | $3.00 | $0.05 | $0.625 | $60 |
|
||||
| Qwen3.6 Plus (> 256K tokens) | $2.00 | $6.00 | $0.20 | $2.50 | $60 |
|
||||
| DeepSeek V4 Pro (Off-Peak) | $0.66 | $1.98 | $0.022 | - | $15 |
|
||||
| DeepSeek V4 Pro (Peak) | $1.32 | $3.96 | $0.044 | - | $15 |
|
||||
| DeepSeek V4 Flash (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $30 |
|
||||
| DeepSeek V4 Flash (Peak) | $0.44 | $1.32 | $0.014 | - | $30 |
|
||||
| Hy3 | $0.14 | $0.58 | $0.035 | - | $60 |
|
||||
| Ox Alpha Free | - | - | - | - | - |
|
||||
| Model | Input | Output | Cached Read | Cached Write | Nutzung |
|
||||
| --------------------------------------- | ------ | ------ | ----------- | ------------ | ------- |
|
||||
| Grok 4.5 | $2.00 | $6.00 | $0.30 | - | $15 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 | $15 |
|
||||
| GPT 5.6 Luna (> 272K tokens) | $0.40 | $1.80 | $0.04 | $0.50 | $15 |
|
||||
| GLM-5.3 | $1.40 | $4.40 | $0.26 | - | $15 |
|
||||
| GLM-5.2 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| GLM-5.1 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| Kimi K3 | $3.00 | $15.00 | $0.30 | - | $15 |
|
||||
| Kimi K2.7 Code | $0.95 | $4.00 | $0.19 | - | $60 |
|
||||
| Kimi K2.6 | $0.95 | $4.00 | $0.16 | - | $60 |
|
||||
| MiMo V2.5 | $0.14 | $0.28 | $0.0028 | - | $60 |
|
||||
| MiMo V2.5 Pro | $0.435 | $0.87 | $0.003625 | - | $15 |
|
||||
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - | $60 |
|
||||
| MiniMax M2.7 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| Muse Spark 1.2 Contributor | $0.10 | $0.20 | $0.002 | - | $60 |
|
||||
| Qwen3.8 Max | $2.00 | $6.00 | $0.25 | $2.50 | $15 |
|
||||
| Qwen3.7 Max | $2.50 | $7.50 | $0.50 | $3.125 | $60 |
|
||||
| Qwen3.7 Plus (≤ 256K tokens) | $0.40 | $1.60 | $0.04 | $0.50 | $60 |
|
||||
| Qwen3.7 Plus (> 256K tokens) | $1.20 | $4.80 | $0.12 | $1.50 | $60 |
|
||||
| Qwen3.6 Plus (≤ 256K tokens) | $0.50 | $3.00 | $0.05 | $0.625 | $60 |
|
||||
| Qwen3.6 Plus (> 256K tokens) | $2.00 | $6.00 | $0.20 | $2.50 | $60 |
|
||||
| DeepSeek V4 Pro (Off-Peak) | $0.66 | $1.98 | $0.022 | - | $15 |
|
||||
| DeepSeek V4 Pro (Peak) | $1.32 | $3.96 | $0.044 | - | $15 |
|
||||
| DeepSeek V4 Flash (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $30 |
|
||||
| DeepSeek V4 Flash (Peak) | $0.44 | $1.32 | $0.014 | - | $30 |
|
||||
| DeepSeek V4 Flash Vision Exp (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $15 |
|
||||
| DeepSeek V4 Flash Vision Exp (Peak) | $0.44 | $1.32 | $0.014 | - | $15 |
|
||||
| Hy3 | $0.14 | $0.58 | $0.035 | - | $60 |
|
||||
| Ox Alpha Free | - | - | - | - | - |
|
||||
|
||||
**DeepSeek V4 Flash / Pro:** Die Peak-Zeiten sind 01:00-04:00 und 06:00-10:00 UTC; alle anderen Zeiten sind Off-Peak. [Mehr erfahren](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
**DeepSeek V4 Flash / V4 Flash Vision Exp / V4 Pro:** Die Peak-Zeiten sind 01:00-04:00 und 06:00-10:00 UTC; alle anderen Zeiten sind Off-Peak. [Mehr erfahren](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
**DeepSeek V4 Flash Vision Exp:** Bilder werden anhand ihrer Abmessungen in Tokens umgewandelt und zusammen mit Text-Tokens als Input-Tokens abgerechnet. [Mehr erfahren](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
**Ox Alpha Free:** Für begrenzte Zeit kostenlos.
|
||||
|
||||
@@ -201,30 +208,31 @@ Bei diesen Modellen erhältst du immer noch etwas mehr, als wenn du die Modellan
|
||||
|
||||
Du kannst auf die Go-Modelle auch über die folgenden API-Endpunkte zugreifen.
|
||||
|
||||
| Modell | Modell-ID | Endpunkt | AI SDK Package |
|
||||
| -------------------------- | -------------------------- | ------------------------------------------------ | --------------------------- |
|
||||
| Grok 4.5 | grok-4.5 | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GPT 5.6 Luna | gpt-5.6-luna | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GLM-5.3 | glm-5.3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.2 | glm-5.2 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.1 | glm-5.1 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K3 | kimi-k3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.7 Code | kimi-k2.7-code | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.6 | kimi-k2.6 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Pro | deepseek-v4-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash | deepseek-v4-flash | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5 | mimo-v2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5-Pro | mimo-v2.5-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiniMax M3 | minimax-m3 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.7 | minimax-m2.7 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Muse Spark 1.2 Contributor | muse-spark-1.2-contributor | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| Qwen3.8 Max | qwen3.8-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Max | qwen3.7-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Plus | qwen3.7-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.6 Plus | qwen3.6-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Hy3 | hy3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Ox Alpha Free | x-preview-f-free | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Modell | Modell-ID | Endpunkt | AI SDK Package |
|
||||
| ---------------------------- | ---------------------------- | ------------------------------------------------ | --------------------------- |
|
||||
| Grok 4.5 | grok-4.5 | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GPT 5.6 Luna | gpt-5.6-luna | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GLM-5.3 | glm-5.3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.2 | glm-5.2 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.1 | glm-5.1 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K3 | kimi-k3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.7 Code | kimi-k2.7-code | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.6 | kimi-k2.6 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Pro | deepseek-v4-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash | deepseek-v4-flash | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash Vision Exp | deepseek-v4-flash-vision-exp | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5 | mimo-v2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5-Pro | mimo-v2.5-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiniMax M3 | minimax-m3 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.7 | minimax-m2.7 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Muse Spark 1.2 Contributor | muse-spark-1.2-contributor | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| Qwen3.8 Max | qwen3.8-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Max | qwen3.7-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Plus | qwen3.7-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.6 Plus | qwen3.6-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Hy3 | hy3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Ox Alpha Free | ox-alpha-free | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
|
||||
Die [Modell-ID](/docs/config/#models) in deiner OpenCode Config verwendet das Format `opencode-go/<model-id>`. Für Kimi K3 würdest du beispielsweise `opencode-go/kimi-k3` in deiner Config verwenden.
|
||||
|
||||
@@ -242,29 +250,30 @@ https://opencode.ai/zen/go/v1/models
|
||||
|
||||
## Datenschutz
|
||||
|
||||
| Modell | Modelltraining | Datenaufbewahrung |
|
||||
| -------------------------- | --------------- | ----------------- |
|
||||
| Grok 4.5 | Nicht verwendet | 30 Tage |
|
||||
| GPT 5.6 Luna | Nicht verwendet | 30 Tage |
|
||||
| GLM-5.3 | Nicht verwendet | 0 Tage |
|
||||
| GLM-5.2 | Nicht verwendet | 0 Tage |
|
||||
| GLM-5.1 | Nicht verwendet | 0 Tage |
|
||||
| Kimi K3 | Nicht verwendet | 0 Tage |
|
||||
| Kimi K2.7 Code | Nicht verwendet | 0 Tage |
|
||||
| Kimi K2.6 | Nicht verwendet | 0 Tage |
|
||||
| MiMo-V2.5-Pro | Nicht verwendet | 0 Tage |
|
||||
| MiMo-V2.5 | Nicht verwendet | 0 Tage |
|
||||
| Qwen3.8 Max | Nicht verwendet | 0 Tage |
|
||||
| Qwen3.7 Max | Nicht verwendet | 0 Tage |
|
||||
| Qwen3.7 Plus | Nicht verwendet | 0 Tage |
|
||||
| Qwen3.6 Plus | Nicht verwendet | 0 Tage |
|
||||
| MiniMax M3 | Nicht verwendet | 0 Tage |
|
||||
| MiniMax M2.7 | Nicht verwendet | 0 Tage |
|
||||
| Muse Spark 1.2 Contributor | Ja | Kein ZDR |
|
||||
| DeepSeek V4 Pro | Nicht verwendet | 0 Tage |
|
||||
| DeepSeek V4 Flash | Nicht verwendet | 0 Tage |
|
||||
| Hy3 | Nicht verwendet | 0 Tage |
|
||||
| Ox Alpha Free | Nicht verwendet | 0 Tage |
|
||||
| Modell | Modelltraining | Datenaufbewahrung |
|
||||
| ---------------------------- | --------------- | ----------------- |
|
||||
| Grok 4.5 | Nicht verwendet | 30 Tage |
|
||||
| GPT 5.6 Luna | Nicht verwendet | 30 Tage |
|
||||
| GLM-5.3 | Nicht verwendet | 0 Tage |
|
||||
| GLM-5.2 | Nicht verwendet | 0 Tage |
|
||||
| GLM-5.1 | Nicht verwendet | 0 Tage |
|
||||
| Kimi K3 | Nicht verwendet | 0 Tage |
|
||||
| Kimi K2.7 Code | Nicht verwendet | 0 Tage |
|
||||
| Kimi K2.6 | Nicht verwendet | 0 Tage |
|
||||
| MiMo-V2.5-Pro | Nicht verwendet | 0 Tage |
|
||||
| MiMo-V2.5 | Nicht verwendet | 0 Tage |
|
||||
| Qwen3.8 Max | Nicht verwendet | 0 Tage |
|
||||
| Qwen3.7 Max | Nicht verwendet | 0 Tage |
|
||||
| Qwen3.7 Plus | Nicht verwendet | 0 Tage |
|
||||
| Qwen3.6 Plus | Nicht verwendet | 0 Tage |
|
||||
| MiniMax M3 | Nicht verwendet | 0 Tage |
|
||||
| MiniMax M2.7 | Nicht verwendet | 0 Tage |
|
||||
| Muse Spark 1.2 Contributor | Ja | Kein ZDR |
|
||||
| DeepSeek V4 Pro | Nicht verwendet | 0 Tage |
|
||||
| DeepSeek V4 Flash | Nicht verwendet | 0 Tage |
|
||||
| DeepSeek V4 Flash Vision Exp | Nicht verwendet | 0 Tage |
|
||||
| Hy3 | Nicht verwendet | 0 Tage |
|
||||
| Ox Alpha Free | Nicht verwendet | 0 Tage |
|
||||
|
||||
- **Grok 4.5:** ZDR deaktiviert wichtige API-Funktionen, die von gespeicherten Daten abhängen, einschließlich der zustandsbehafteten Responses API, Files and Collections und der Batch API. [Mehr erfahren](https://docs.x.ai/developers/faq/security#what-is-zero-data-retention-zdr).
|
||||
- **GPT 5.6 Luna:** Für die Nutzung aller API-Funktionen werden Protokolle zur Missbrauchsüberwachung erstellt und bis zu 30 Tage lang aufbewahrt. [Mehr erfahren](https://developers.openai.com/api/docs/guides/your-data#data-retention-controls-for-abuse-monitoring).
|
||||
|
||||
@@ -184,8 +184,8 @@ Wir unterstützen ein Pay-as-you-go-Modell. Unten findest du die Preise **pro 1M
|
||||
| Grok 4.5 (> 200K tokens) | $4.00 | $12.00 | $0.60 | - |
|
||||
| Grok Build 0.1 | $1.00 | $2.00 | $0.20 | - |
|
||||
| Muse Spark 1.2 | $1.25 | $4.25 | $0.15 | - |
|
||||
| GPT 5.6 Sol (≤ 272K tokens) | $5.00 | $30.00 | $0.50 | $6.25 |
|
||||
| GPT 5.6 Sol (> 272K tokens) | $10.00 | $45.00 | $1.00 | $12.50 |
|
||||
| GPT 5.6 Sol (≤ 272K tokens) | $2.00 | $10.00 | $0.20 | $2.50 |
|
||||
| GPT 5.6 Sol (> 272K tokens) | $4.00 | $15.00 | $0.40 | $5.00 |
|
||||
| GPT 5.6 Terra (≤ 272K tokens) | $2.00 | $12.00 | $0.20 | $2.50 |
|
||||
| GPT 5.6 Terra (> 272K tokens) | $4.00 | $18.00 | $0.40 | $5.00 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 |
|
||||
@@ -210,6 +210,8 @@ Wir unterstützen ein Pay-as-you-go-Modell. Unten findest du die Preise **pro 1M
|
||||
| GPT 5 Codex | $1.07 | $8.50 | $0.107 | - |
|
||||
| GPT 5 Nano | $0.05 | $0.40 | $0.005 | - |
|
||||
|
||||
**GPT 5.6 Sol:** Die angezeigten Preise enthalten bis zum 18. September 2026 einen Rabatt von 50 %.
|
||||
|
||||
**DeepSeek V4 Flash / Pro:** Die Peak-Zeiten sind 01:00-04:00 und 06:00-10:00 UTC; alle anderen Zeiten sind Off-Peak. [Mehr erfahren](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
Möglicherweise siehst du [kostengünstige Modelle](/docs/config/#models) wie Haiku, Nano oder Flash in deinem Nutzungsverlauf. OpenCode verwendet diese Modelle, um Session-Titel zu generieren.
|
||||
|
||||
@@ -78,6 +78,7 @@ La lista actual de modelos incluye:
|
||||
- **Qwen3.6 Plus**
|
||||
- **DeepSeek V4 Pro**
|
||||
- **DeepSeek V4 Flash**
|
||||
- **DeepSeek V4 Flash Vision Exp**
|
||||
- **Hy3**
|
||||
- **Ox Alpha Free** (por tiempo limitado)
|
||||
|
||||
@@ -97,29 +98,30 @@ Los límites se definen en valor en dólares. Esto significa que tu cantidad rea
|
||||
|
||||
La siguiente tabla proporciona una cantidad estimada de peticiones basada en los patrones típicos de uso de Go:
|
||||
|
||||
| Model | peticiones por 5 horas | peticiones por semana | peticiones por mes |
|
||||
| -------------------------- | ---------------------- | --------------------- | ------------------ |
|
||||
| Grok 4.5 | 120 | 300 | 600 |
|
||||
| GPT 5.6 Luna | 2,050 | 5,100 | 10,250 |
|
||||
| GLM-5.3 | 220 | 540 | 1,080 |
|
||||
| GLM-5.2 | 880 | 2,150 | 4,300 |
|
||||
| GLM-5.1 | 880 | 2,150 | 4,300 |
|
||||
| Kimi K3 | 110 | 250 | 490 |
|
||||
| Kimi K2.7 Code | 1,350 | 3,380 | 6,750 |
|
||||
| Kimi K2.6 | 1,150 | 2,880 | 5,750 |
|
||||
| MiMo-V2.5 | 30,100 | 75,200 | 150,400 |
|
||||
| MiMo-V2.5-Pro | 3,250 | 8,150 | 16,300 |
|
||||
| MiniMax M3 | 3,200 | 8,000 | 16,000 |
|
||||
| MiniMax M2.7 | 3,400 | 8,500 | 17,000 |
|
||||
| Muse Spark 1.2 Contributor | 45,300 | 113,300 | 226,600 |
|
||||
| Qwen3.8 Max | 160 | 400 | 810 |
|
||||
| Qwen3.7 Max | 340 | 840 | 1,690 |
|
||||
| Qwen3.7 Plus | 4,300 | 10,800 | 21,600 |
|
||||
| Qwen3.6 Plus | 3,300 | 8,200 | 16,300 |
|
||||
| DeepSeek V4 Pro | 1,050 | 2,600 | 5,200 |
|
||||
| DeepSeek V4 Flash | 7,600 | 18,900 | 37,800 |
|
||||
| Hy3 | 4,300 | 10,750 | 21,500 |
|
||||
| Ox Alpha Free | - | - | - |
|
||||
| Model | peticiones por 5 horas | peticiones por semana | peticiones por mes |
|
||||
| ---------------------------- | ---------------------- | --------------------- | ------------------ |
|
||||
| Grok 4.5 | 120 | 300 | 600 |
|
||||
| GPT 5.6 Luna | 2,050 | 5,100 | 10,250 |
|
||||
| GLM-5.3 | 220 | 540 | 1,080 |
|
||||
| GLM-5.2 | 880 | 2,150 | 4,300 |
|
||||
| GLM-5.1 | 880 | 2,150 | 4,300 |
|
||||
| Kimi K3 | 110 | 250 | 490 |
|
||||
| Kimi K2.7 Code | 1,350 | 3,380 | 6,750 |
|
||||
| Kimi K2.6 | 1,150 | 2,880 | 5,750 |
|
||||
| MiMo-V2.5 | 30,100 | 75,200 | 150,400 |
|
||||
| MiMo-V2.5-Pro | 3,250 | 8,150 | 16,300 |
|
||||
| MiniMax M3 | 3,200 | 8,000 | 16,000 |
|
||||
| MiniMax M2.7 | 3,400 | 8,500 | 17,000 |
|
||||
| Muse Spark 1.2 Contributor | 45,300 | 113,300 | 226,600 |
|
||||
| Qwen3.8 Max | 160 | 400 | 810 |
|
||||
| Qwen3.7 Max | 340 | 840 | 1,690 |
|
||||
| Qwen3.7 Plus | 4,300 | 10,800 | 21,600 |
|
||||
| Qwen3.6 Plus | 3,300 | 8,200 | 16,300 |
|
||||
| DeepSeek V4 Pro | 1,050 | 2,600 | 5,200 |
|
||||
| DeepSeek V4 Flash | 7,600 | 18,900 | 37,800 |
|
||||
| DeepSeek V4 Flash Vision Exp | 3,800 | 9,450 | 18,900 |
|
||||
| Hy3 | 4,300 | 10,750 | 21,500 |
|
||||
| Ox Alpha Free | - | - | - |
|
||||
|
||||
Las estimaciones se basan en los patrones de peticiones observados:
|
||||
|
||||
@@ -130,6 +132,7 @@ Las estimaciones se basan en los patrones de peticiones observados:
|
||||
- Kimi K2.7/K2.6 — 870 tokens de entrada, 55,000 en caché, 200 tokens de salida por petición
|
||||
- DeepSeek V4 Pro — 750 tokens de entrada, 82,000 en caché, 290 tokens de salida por petición
|
||||
- DeepSeek V4 Flash — 410 tokens de entrada, 71,300 en caché, 310 tokens de salida por petición
|
||||
- DeepSeek V4 Flash Vision Exp — 410 tokens de entrada, 71,300 en caché, 310 tokens de salida por petición
|
||||
- MiniMax M3 — 510 tokens de entrada, 56,000 en caché, 190 tokens de salida por petición
|
||||
- MiniMax M2.7 — 300 tokens de entrada, 55,000 en caché, 125 tokens de salida por petición
|
||||
- Muse Spark 1.2 Contributor — 620 tokens de entrada, 71,400 en caché, 300 tokens de salida por petición
|
||||
@@ -143,37 +146,41 @@ Las estimaciones se basan en los patrones de peticiones observados:
|
||||
|
||||
Las estimaciones también se basan en los siguientes precios por 1M tokens y en el uso mensual incluido con cada modelo:
|
||||
|
||||
| Modelo | Entrada | Salida | Lectura en caché | Escritura en caché | Uso |
|
||||
| ---------------------------- | ------- | ------ | ---------------- | ------------------ | --- |
|
||||
| Grok 4.5 | $2.00 | $6.00 | $0.30 | - | $15 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 | $15 |
|
||||
| GPT 5.6 Luna (> 272K tokens) | $0.40 | $1.80 | $0.04 | $0.50 | $15 |
|
||||
| GLM-5.3 | $1.40 | $4.40 | $0.26 | - | $15 |
|
||||
| GLM-5.2 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| GLM-5.1 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| Kimi K3 | $3.00 | $15.00 | $0.30 | - | $15 |
|
||||
| Kimi K2.7 Code | $0.95 | $4.00 | $0.19 | - | $60 |
|
||||
| Kimi K2.6 | $0.95 | $4.00 | $0.16 | - | $60 |
|
||||
| MiMo V2.5 | $0.14 | $0.28 | $0.0028 | - | $60 |
|
||||
| MiMo V2.5 Pro | $0.435 | $0.87 | $0.003625 | - | $15 |
|
||||
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - | $60 |
|
||||
| MiniMax M2.7 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| Muse Spark 1.2 Contributor | $0.10 | $0.20 | $0.002 | - | $60 |
|
||||
| Qwen3.8 Max | $2.00 | $6.00 | $0.25 | $2.50 | $15 |
|
||||
| Qwen3.7 Max | $2.50 | $7.50 | $0.50 | $3.125 | $60 |
|
||||
| Qwen3.7 Plus (≤ 256K tokens) | $0.40 | $1.60 | $0.04 | $0.50 | $60 |
|
||||
| Qwen3.7 Plus (> 256K tokens) | $1.20 | $4.80 | $0.12 | $1.50 | $60 |
|
||||
| Qwen3.6 Plus (≤ 256K tokens) | $0.50 | $3.00 | $0.05 | $0.625 | $60 |
|
||||
| Qwen3.6 Plus (> 256K tokens) | $2.00 | $6.00 | $0.20 | $2.50 | $60 |
|
||||
| DeepSeek V4 Pro (Off-Peak) | $0.66 | $1.98 | $0.022 | - | $15 |
|
||||
| DeepSeek V4 Pro (Peak) | $1.32 | $3.96 | $0.044 | - | $15 |
|
||||
| DeepSeek V4 Flash (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $30 |
|
||||
| DeepSeek V4 Flash (Peak) | $0.44 | $1.32 | $0.014 | - | $30 |
|
||||
| Hy3 | $0.14 | $0.58 | $0.035 | - | $60 |
|
||||
| Ox Alpha Free | - | - | - | - | - |
|
||||
| Modelo | Entrada | Salida | Lectura en caché | Escritura en caché | Uso |
|
||||
| --------------------------------------- | ------- | ------ | ---------------- | ------------------ | --- |
|
||||
| Grok 4.5 | $2.00 | $6.00 | $0.30 | - | $15 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 | $15 |
|
||||
| GPT 5.6 Luna (> 272K tokens) | $0.40 | $1.80 | $0.04 | $0.50 | $15 |
|
||||
| GLM-5.3 | $1.40 | $4.40 | $0.26 | - | $15 |
|
||||
| GLM-5.2 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| GLM-5.1 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| Kimi K3 | $3.00 | $15.00 | $0.30 | - | $15 |
|
||||
| Kimi K2.7 Code | $0.95 | $4.00 | $0.19 | - | $60 |
|
||||
| Kimi K2.6 | $0.95 | $4.00 | $0.16 | - | $60 |
|
||||
| MiMo V2.5 | $0.14 | $0.28 | $0.0028 | - | $60 |
|
||||
| MiMo V2.5 Pro | $0.435 | $0.87 | $0.003625 | - | $15 |
|
||||
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - | $60 |
|
||||
| MiniMax M2.7 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| Muse Spark 1.2 Contributor | $0.10 | $0.20 | $0.002 | - | $60 |
|
||||
| Qwen3.8 Max | $2.00 | $6.00 | $0.25 | $2.50 | $15 |
|
||||
| Qwen3.7 Max | $2.50 | $7.50 | $0.50 | $3.125 | $60 |
|
||||
| Qwen3.7 Plus (≤ 256K tokens) | $0.40 | $1.60 | $0.04 | $0.50 | $60 |
|
||||
| Qwen3.7 Plus (> 256K tokens) | $1.20 | $4.80 | $0.12 | $1.50 | $60 |
|
||||
| Qwen3.6 Plus (≤ 256K tokens) | $0.50 | $3.00 | $0.05 | $0.625 | $60 |
|
||||
| Qwen3.6 Plus (> 256K tokens) | $2.00 | $6.00 | $0.20 | $2.50 | $60 |
|
||||
| DeepSeek V4 Pro (Off-Peak) | $0.66 | $1.98 | $0.022 | - | $15 |
|
||||
| DeepSeek V4 Pro (Peak) | $1.32 | $3.96 | $0.044 | - | $15 |
|
||||
| DeepSeek V4 Flash (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $30 |
|
||||
| DeepSeek V4 Flash (Peak) | $0.44 | $1.32 | $0.014 | - | $30 |
|
||||
| DeepSeek V4 Flash Vision Exp (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $15 |
|
||||
| DeepSeek V4 Flash Vision Exp (Peak) | $0.44 | $1.32 | $0.014 | - | $15 |
|
||||
| Hy3 | $0.14 | $0.58 | $0.035 | - | $60 |
|
||||
| Ox Alpha Free | - | - | - | - | - |
|
||||
|
||||
**DeepSeek V4 Flash / Pro:** Las horas Peak son 01:00-04:00 y 06:00-10:00 UTC; todas las demás horas son Off-Peak. [Más información](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
**DeepSeek V4 Flash / V4 Flash Vision Exp / V4 Pro:** Las horas Peak son 01:00-04:00 y 06:00-10:00 UTC; todas las demás horas son Off-Peak. [Más información](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
**DeepSeek V4 Flash Vision Exp:** Las imágenes se convierten en tokens según sus dimensiones y se facturan como tokens de entrada junto con los tokens de texto. [Más información](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
**Ox Alpha Free:** Gratis por tiempo limitado.
|
||||
|
||||
@@ -211,30 +218,31 @@ Con estos modelos, aun así obtienes un poco más que si pagaras directamente a
|
||||
|
||||
También puedes acceder a los modelos de Go a través de los siguientes endpoints de la API.
|
||||
|
||||
| Modelo | ID del modelo | Endpoint | Paquete de AI SDK |
|
||||
| -------------------------- | -------------------------- | ------------------------------------------------ | --------------------------- |
|
||||
| Grok 4.5 | grok-4.5 | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GPT 5.6 Luna | gpt-5.6-luna | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GLM-5.3 | glm-5.3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.2 | glm-5.2 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.1 | glm-5.1 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K3 | kimi-k3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.7 Code | kimi-k2.7-code | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.6 | kimi-k2.6 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Pro | deepseek-v4-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash | deepseek-v4-flash | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5 | mimo-v2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5-Pro | mimo-v2.5-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiniMax M3 | minimax-m3 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.7 | minimax-m2.7 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Muse Spark 1.2 Contributor | muse-spark-1.2-contributor | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| Qwen3.8 Max | qwen3.8-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Max | qwen3.7-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Plus | qwen3.7-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.6 Plus | qwen3.6-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Hy3 | hy3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Ox Alpha Free | x-preview-f-free | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Modelo | ID del modelo | Endpoint | Paquete de AI SDK |
|
||||
| ---------------------------- | ---------------------------- | ------------------------------------------------ | --------------------------- |
|
||||
| Grok 4.5 | grok-4.5 | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GPT 5.6 Luna | gpt-5.6-luna | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GLM-5.3 | glm-5.3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.2 | glm-5.2 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.1 | glm-5.1 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K3 | kimi-k3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.7 Code | kimi-k2.7-code | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.6 | kimi-k2.6 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Pro | deepseek-v4-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash | deepseek-v4-flash | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash Vision Exp | deepseek-v4-flash-vision-exp | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5 | mimo-v2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5-Pro | mimo-v2.5-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiniMax M3 | minimax-m3 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.7 | minimax-m2.7 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Muse Spark 1.2 Contributor | muse-spark-1.2-contributor | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| Qwen3.8 Max | qwen3.8-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Max | qwen3.7-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Plus | qwen3.7-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.6 Plus | qwen3.6-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Hy3 | hy3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Ox Alpha Free | ox-alpha-free | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
|
||||
El [ID del modelo](/docs/config/#models) en tu configuración de OpenCode
|
||||
usa el formato `opencode-go/<model-id>`. Por ejemplo, para Kimi K3, usarías
|
||||
@@ -254,29 +262,30 @@ https://opencode.ai/zen/go/v1/models
|
||||
|
||||
## Privacidad
|
||||
|
||||
| Modelo | Entrenamiento del modelo | Retención de datos |
|
||||
| -------------------------- | ------------------------ | ------------------ |
|
||||
| Grok 4.5 | No utilizado | 30 días |
|
||||
| GPT 5.6 Luna | No utilizado | 30 días |
|
||||
| GLM-5.3 | No utilizado | 0 días |
|
||||
| GLM-5.2 | No utilizado | 0 días |
|
||||
| GLM-5.1 | No utilizado | 0 días |
|
||||
| Kimi K3 | No utilizado | 0 días |
|
||||
| Kimi K2.7 Code | No utilizado | 0 días |
|
||||
| Kimi K2.6 | No utilizado | 0 días |
|
||||
| MiMo-V2.5-Pro | No utilizado | 0 días |
|
||||
| MiMo-V2.5 | No utilizado | 0 días |
|
||||
| Qwen3.8 Max | No utilizado | 0 días |
|
||||
| Qwen3.7 Max | No utilizado | 0 días |
|
||||
| Qwen3.7 Plus | No utilizado | 0 días |
|
||||
| Qwen3.6 Plus | No utilizado | 0 días |
|
||||
| MiniMax M3 | No utilizado | 0 días |
|
||||
| MiniMax M2.7 | No utilizado | 0 días |
|
||||
| Muse Spark 1.2 Contributor | Sí | Sin ZDR |
|
||||
| DeepSeek V4 Pro | No utilizado | 0 días |
|
||||
| DeepSeek V4 Flash | No utilizado | 0 días |
|
||||
| Hy3 | No utilizado | 0 días |
|
||||
| Ox Alpha Free | No utilizado | 0 días |
|
||||
| Modelo | Entrenamiento del modelo | Retención de datos |
|
||||
| ---------------------------- | ------------------------ | ------------------ |
|
||||
| Grok 4.5 | No utilizado | 30 días |
|
||||
| GPT 5.6 Luna | No utilizado | 30 días |
|
||||
| GLM-5.3 | No utilizado | 0 días |
|
||||
| GLM-5.2 | No utilizado | 0 días |
|
||||
| GLM-5.1 | No utilizado | 0 días |
|
||||
| Kimi K3 | No utilizado | 0 días |
|
||||
| Kimi K2.7 Code | No utilizado | 0 días |
|
||||
| Kimi K2.6 | No utilizado | 0 días |
|
||||
| MiMo-V2.5-Pro | No utilizado | 0 días |
|
||||
| MiMo-V2.5 | No utilizado | 0 días |
|
||||
| Qwen3.8 Max | No utilizado | 0 días |
|
||||
| Qwen3.7 Max | No utilizado | 0 días |
|
||||
| Qwen3.7 Plus | No utilizado | 0 días |
|
||||
| Qwen3.6 Plus | No utilizado | 0 días |
|
||||
| MiniMax M3 | No utilizado | 0 días |
|
||||
| MiniMax M2.7 | No utilizado | 0 días |
|
||||
| Muse Spark 1.2 Contributor | Sí | Sin ZDR |
|
||||
| DeepSeek V4 Pro | No utilizado | 0 días |
|
||||
| DeepSeek V4 Flash | No utilizado | 0 días |
|
||||
| DeepSeek V4 Flash Vision Exp | No utilizado | 0 días |
|
||||
| Hy3 | No utilizado | 0 días |
|
||||
| Ox Alpha Free | No utilizado | 0 días |
|
||||
|
||||
- **Grok 4.5:** 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. [Más información](https://docs.x.ai/developers/faq/security#what-is-zero-data-retention-zdr).
|
||||
- **GPT 5.6 Luna:** 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. [Más información](https://developers.openai.com/api/docs/guides/your-data#data-retention-controls-for-abuse-monitoring).
|
||||
|
||||
@@ -195,8 +195,8 @@ Admitimos un modelo de pago por uso. A continuación se muestran los precios **p
|
||||
| Grok 4.5 (> 200K tokens) | $4.00 | $12.00 | $0.60 | - |
|
||||
| Grok Build 0.1 | $1.00 | $2.00 | $0.20 | - |
|
||||
| Muse Spark 1.2 | $1.25 | $4.25 | $0.15 | - |
|
||||
| GPT 5.6 Sol (≤ 272K tokens) | $5.00 | $30.00 | $0.50 | $6.25 |
|
||||
| GPT 5.6 Sol (> 272K tokens) | $10.00 | $45.00 | $1.00 | $12.50 |
|
||||
| GPT 5.6 Sol (≤ 272K tokens) | $2.00 | $10.00 | $0.20 | $2.50 |
|
||||
| GPT 5.6 Sol (> 272K tokens) | $4.00 | $15.00 | $0.40 | $5.00 |
|
||||
| GPT 5.6 Terra (≤ 272K tokens) | $2.00 | $12.00 | $0.20 | $2.50 |
|
||||
| GPT 5.6 Terra (> 272K tokens) | $4.00 | $18.00 | $0.40 | $5.00 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 |
|
||||
@@ -221,6 +221,8 @@ Admitimos un modelo de pago por uso. A continuación se muestran los precios **p
|
||||
| GPT 5 Codex | $1.07 | $8.50 | $0.107 | - |
|
||||
| GPT 5 Nano | $0.05 | $0.40 | $0.005 | - |
|
||||
|
||||
**GPT 5.6 Sol:** Los precios mostrados incluyen un 50 % de descuento hasta el 18 de septiembre de 2026.
|
||||
|
||||
**DeepSeek V4 Flash / Pro:** Las horas Peak son 01:00-04:00 y 06:00-10:00 UTC; todas las demás horas son Off-Peak. [Más información](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
Puede que notes [modelos de bajo costo](/docs/config/#models), como Haiku, Nano o Flash, en tu historial de uso. OpenCode usa estos modelos para generar títulos de sesiones.
|
||||
|
||||
@@ -68,6 +68,7 @@ La liste actuelle des modèles comprend :
|
||||
- **Qwen3.6 Plus**
|
||||
- **DeepSeek V4 Pro**
|
||||
- **DeepSeek V4 Flash**
|
||||
- **DeepSeek V4 Flash Vision Exp**
|
||||
- **Hy3**
|
||||
- **Ox Alpha Free** (pour une durée limitée)
|
||||
|
||||
@@ -87,29 +88,30 @@ Les limites sont définies en valeur monétaire (dollars). Cela signifie que vot
|
||||
|
||||
Le tableau ci-dessous fournit une estimation du nombre de requêtes basée sur des modèles d'utilisation typiques de Go :
|
||||
|
||||
| Model | requêtes par 5 heures | requêtes par semaine | requêtes par mois |
|
||||
| -------------------------- | --------------------- | -------------------- | ----------------- |
|
||||
| Grok 4.5 | 120 | 300 | 600 |
|
||||
| GPT 5.6 Luna | 2,050 | 5,100 | 10,250 |
|
||||
| GLM-5.3 | 220 | 540 | 1,080 |
|
||||
| GLM-5.2 | 880 | 2,150 | 4,300 |
|
||||
| GLM-5.1 | 880 | 2,150 | 4,300 |
|
||||
| Kimi K3 | 110 | 250 | 490 |
|
||||
| Kimi K2.7 Code | 1,350 | 3,380 | 6,750 |
|
||||
| Kimi K2.6 | 1,150 | 2,880 | 5,750 |
|
||||
| MiMo-V2.5 | 30,100 | 75,200 | 150,400 |
|
||||
| MiMo-V2.5-Pro | 3,250 | 8,150 | 16,300 |
|
||||
| MiniMax M3 | 3,200 | 8,000 | 16,000 |
|
||||
| MiniMax M2.7 | 3,400 | 8,500 | 17,000 |
|
||||
| Muse Spark 1.2 Contributor | 45,300 | 113,300 | 226,600 |
|
||||
| Qwen3.8 Max | 160 | 400 | 810 |
|
||||
| Qwen3.7 Max | 340 | 840 | 1,690 |
|
||||
| Qwen3.7 Plus | 4,300 | 10,800 | 21,600 |
|
||||
| Qwen3.6 Plus | 3,300 | 8,200 | 16,300 |
|
||||
| DeepSeek V4 Pro | 1,050 | 2,600 | 5,200 |
|
||||
| DeepSeek V4 Flash | 7,600 | 18,900 | 37,800 |
|
||||
| Hy3 | 4,300 | 10,750 | 21,500 |
|
||||
| Ox Alpha Free | - | - | - |
|
||||
| Model | requêtes par 5 heures | requêtes par semaine | requêtes par mois |
|
||||
| ---------------------------- | --------------------- | -------------------- | ----------------- |
|
||||
| Grok 4.5 | 120 | 300 | 600 |
|
||||
| GPT 5.6 Luna | 2,050 | 5,100 | 10,250 |
|
||||
| GLM-5.3 | 220 | 540 | 1,080 |
|
||||
| GLM-5.2 | 880 | 2,150 | 4,300 |
|
||||
| GLM-5.1 | 880 | 2,150 | 4,300 |
|
||||
| Kimi K3 | 110 | 250 | 490 |
|
||||
| Kimi K2.7 Code | 1,350 | 3,380 | 6,750 |
|
||||
| Kimi K2.6 | 1,150 | 2,880 | 5,750 |
|
||||
| MiMo-V2.5 | 30,100 | 75,200 | 150,400 |
|
||||
| MiMo-V2.5-Pro | 3,250 | 8,150 | 16,300 |
|
||||
| MiniMax M3 | 3,200 | 8,000 | 16,000 |
|
||||
| MiniMax M2.7 | 3,400 | 8,500 | 17,000 |
|
||||
| Muse Spark 1.2 Contributor | 45,300 | 113,300 | 226,600 |
|
||||
| Qwen3.8 Max | 160 | 400 | 810 |
|
||||
| Qwen3.7 Max | 340 | 840 | 1,690 |
|
||||
| Qwen3.7 Plus | 4,300 | 10,800 | 21,600 |
|
||||
| Qwen3.6 Plus | 3,300 | 8,200 | 16,300 |
|
||||
| DeepSeek V4 Pro | 1,050 | 2,600 | 5,200 |
|
||||
| DeepSeek V4 Flash | 7,600 | 18,900 | 37,800 |
|
||||
| DeepSeek V4 Flash Vision Exp | 3,800 | 9,450 | 18,900 |
|
||||
| Hy3 | 4,300 | 10,750 | 21,500 |
|
||||
| Ox Alpha Free | - | - | - |
|
||||
|
||||
Les estimations sont basées sur les schémas de requêtes observés :
|
||||
|
||||
@@ -120,6 +122,7 @@ Les estimations sont basées sur les schémas de requêtes observés :
|
||||
- Kimi K2.7/K2.6 — 870 tokens en entrée, 55,000 en cache, 200 tokens en sortie par requête
|
||||
- DeepSeek V4 Pro — 750 tokens en entrée, 82,000 en cache, 290 tokens en sortie par requête
|
||||
- DeepSeek V4 Flash — 410 tokens en entrée, 71,300 en cache, 310 tokens en sortie par requête
|
||||
- DeepSeek V4 Flash Vision Exp — 410 tokens en entrée, 71,300 en cache, 310 tokens en sortie par requête
|
||||
- MiniMax M3 — 510 tokens en entrée, 56,000 en cache, 190 tokens en sortie par requête
|
||||
- MiniMax M2.7 — 300 tokens en entrée, 55,000 en cache, 125 tokens en sortie par requête
|
||||
- Muse Spark 1.2 Contributor — 620 tokens en entrée, 71,400 en cache, 300 tokens en sortie par requête
|
||||
@@ -133,37 +136,41 @@ Les estimations sont basées sur les schémas de requêtes observés :
|
||||
|
||||
Les estimations sont également basées sur les prix suivants par 1M tokens et sur l'utilisation mensuelle incluse avec chaque modèle :
|
||||
|
||||
| Modèle | Input | Output | Cached Read | Cached Write | Utilisation |
|
||||
| ---------------------------- | ------ | ------ | ----------- | ------------ | ----------- |
|
||||
| Grok 4.5 | $2.00 | $6.00 | $0.30 | - | $15 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 | $15 |
|
||||
| GPT 5.6 Luna (> 272K tokens) | $0.40 | $1.80 | $0.04 | $0.50 | $15 |
|
||||
| GLM-5.3 | $1.40 | $4.40 | $0.26 | - | $15 |
|
||||
| GLM-5.2 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| GLM-5.1 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| Kimi K3 | $3.00 | $15.00 | $0.30 | - | $15 |
|
||||
| Kimi K2.7 Code | $0.95 | $4.00 | $0.19 | - | $60 |
|
||||
| Kimi K2.6 | $0.95 | $4.00 | $0.16 | - | $60 |
|
||||
| MiMo V2.5 | $0.14 | $0.28 | $0.0028 | - | $60 |
|
||||
| MiMo V2.5 Pro | $0.435 | $0.87 | $0.003625 | - | $15 |
|
||||
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - | $60 |
|
||||
| MiniMax M2.7 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| Muse Spark 1.2 Contributor | $0.10 | $0.20 | $0.002 | - | $60 |
|
||||
| Qwen3.8 Max | $2.00 | $6.00 | $0.25 | $2.50 | $15 |
|
||||
| Qwen3.7 Max | $2.50 | $7.50 | $0.50 | $3.125 | $60 |
|
||||
| Qwen3.7 Plus (≤ 256K tokens) | $0.40 | $1.60 | $0.04 | $0.50 | $60 |
|
||||
| Qwen3.7 Plus (> 256K tokens) | $1.20 | $4.80 | $0.12 | $1.50 | $60 |
|
||||
| Qwen3.6 Plus (≤ 256K tokens) | $0.50 | $3.00 | $0.05 | $0.625 | $60 |
|
||||
| Qwen3.6 Plus (> 256K tokens) | $2.00 | $6.00 | $0.20 | $2.50 | $60 |
|
||||
| DeepSeek V4 Pro (Off-Peak) | $0.66 | $1.98 | $0.022 | - | $15 |
|
||||
| DeepSeek V4 Pro (Peak) | $1.32 | $3.96 | $0.044 | - | $15 |
|
||||
| DeepSeek V4 Flash (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $30 |
|
||||
| DeepSeek V4 Flash (Peak) | $0.44 | $1.32 | $0.014 | - | $30 |
|
||||
| Hy3 | $0.14 | $0.58 | $0.035 | - | $60 |
|
||||
| Ox Alpha Free | - | - | - | - | - |
|
||||
| Modèle | Input | Output | Cached Read | Cached Write | Utilisation |
|
||||
| --------------------------------------- | ------ | ------ | ----------- | ------------ | ----------- |
|
||||
| Grok 4.5 | $2.00 | $6.00 | $0.30 | - | $15 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 | $15 |
|
||||
| GPT 5.6 Luna (> 272K tokens) | $0.40 | $1.80 | $0.04 | $0.50 | $15 |
|
||||
| GLM-5.3 | $1.40 | $4.40 | $0.26 | - | $15 |
|
||||
| GLM-5.2 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| GLM-5.1 | $1.40 | $4.40 | $0.26 | - | $60 |
|
||||
| Kimi K3 | $3.00 | $15.00 | $0.30 | - | $15 |
|
||||
| Kimi K2.7 Code | $0.95 | $4.00 | $0.19 | - | $60 |
|
||||
| Kimi K2.6 | $0.95 | $4.00 | $0.16 | - | $60 |
|
||||
| MiMo V2.5 | $0.14 | $0.28 | $0.0028 | - | $60 |
|
||||
| MiMo V2.5 Pro | $0.435 | $0.87 | $0.003625 | - | $15 |
|
||||
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - | $60 |
|
||||
| MiniMax M2.7 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | $0.375 | $60 |
|
||||
| Muse Spark 1.2 Contributor | $0.10 | $0.20 | $0.002 | - | $60 |
|
||||
| Qwen3.8 Max | $2.00 | $6.00 | $0.25 | $2.50 | $15 |
|
||||
| Qwen3.7 Max | $2.50 | $7.50 | $0.50 | $3.125 | $60 |
|
||||
| Qwen3.7 Plus (≤ 256K tokens) | $0.40 | $1.60 | $0.04 | $0.50 | $60 |
|
||||
| Qwen3.7 Plus (> 256K tokens) | $1.20 | $4.80 | $0.12 | $1.50 | $60 |
|
||||
| Qwen3.6 Plus (≤ 256K tokens) | $0.50 | $3.00 | $0.05 | $0.625 | $60 |
|
||||
| Qwen3.6 Plus (> 256K tokens) | $2.00 | $6.00 | $0.20 | $2.50 | $60 |
|
||||
| DeepSeek V4 Pro (Off-Peak) | $0.66 | $1.98 | $0.022 | - | $15 |
|
||||
| DeepSeek V4 Pro (Peak) | $1.32 | $3.96 | $0.044 | - | $15 |
|
||||
| DeepSeek V4 Flash (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $30 |
|
||||
| DeepSeek V4 Flash (Peak) | $0.44 | $1.32 | $0.014 | - | $30 |
|
||||
| DeepSeek V4 Flash Vision Exp (Off-Peak) | $0.22 | $0.66 | $0.007 | - | $15 |
|
||||
| DeepSeek V4 Flash Vision Exp (Peak) | $0.44 | $1.32 | $0.014 | - | $15 |
|
||||
| Hy3 | $0.14 | $0.58 | $0.035 | - | $60 |
|
||||
| Ox Alpha Free | - | - | - | - | - |
|
||||
|
||||
**DeepSeek V4 Flash / Pro:** Les heures Peak sont 01:00-04:00 et 06:00-10:00 UTC ; toutes les autres heures sont Off-Peak. [En savoir plus](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
**DeepSeek V4 Flash / V4 Flash Vision Exp / V4 Pro:** Les heures Peak sont 01:00-04:00 et 06:00-10:00 UTC ; toutes les autres heures sont Off-Peak. [En savoir plus](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
**DeepSeek V4 Flash Vision Exp:** Les images sont converties en tokens selon leurs dimensions et facturées comme tokens d’entrée avec les tokens de texte. [En savoir plus](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
**Ox Alpha Free:** Gratuit pour une durée limitée.
|
||||
|
||||
@@ -199,30 +206,31 @@ Pour ces modèles, vous obtenez tout de même un peu plus que si vous payiez dir
|
||||
|
||||
Vous pouvez également accéder aux modèles Go via les points de terminaison d'API suivants.
|
||||
|
||||
| Modèle | ID de modèle | Point de terminaison | Package AI SDK |
|
||||
| -------------------------- | -------------------------- | ------------------------------------------------ | --------------------------- |
|
||||
| Grok 4.5 | grok-4.5 | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GPT 5.6 Luna | gpt-5.6-luna | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GLM-5.3 | glm-5.3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.2 | glm-5.2 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.1 | glm-5.1 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K3 | kimi-k3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.7 Code | kimi-k2.7-code | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.6 | kimi-k2.6 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Pro | deepseek-v4-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash | deepseek-v4-flash | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5 | mimo-v2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5-Pro | mimo-v2.5-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiniMax M3 | minimax-m3 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.7 | minimax-m2.7 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Muse Spark 1.2 Contributor | muse-spark-1.2-contributor | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| Qwen3.8 Max | qwen3.8-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Max | qwen3.7-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Plus | qwen3.7-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.6 Plus | qwen3.6-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Hy3 | hy3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Ox Alpha Free | x-preview-f-free | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Modèle | ID de modèle | Point de terminaison | Package AI SDK |
|
||||
| ---------------------------- | ---------------------------- | ------------------------------------------------ | --------------------------- |
|
||||
| Grok 4.5 | grok-4.5 | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GPT 5.6 Luna | gpt-5.6-luna | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| GLM-5.3 | glm-5.3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.2 | glm-5.2 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| GLM-5.1 | glm-5.1 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K3 | kimi-k3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.7 Code | kimi-k2.7-code | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Kimi K2.6 | kimi-k2.6 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Pro | deepseek-v4-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash | deepseek-v4-flash | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| DeepSeek V4 Flash Vision Exp | deepseek-v4-flash-vision-exp | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5 | mimo-v2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiMo-V2.5-Pro | mimo-v2.5-pro | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| MiniMax M3 | minimax-m3 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.7 | minimax-m2.7 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Muse Spark 1.2 Contributor | muse-spark-1.2-contributor | `https://opencode.ai/zen/go/v1/responses` | `@ai-sdk/openai` |
|
||||
| Qwen3.8 Max | qwen3.8-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Max | qwen3.7-max | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.7 Plus | qwen3.7-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Qwen3.6 Plus | qwen3.6-plus | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` |
|
||||
| Hy3 | hy3 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
| Ox Alpha Free | ox-alpha-free | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` |
|
||||
|
||||
L'[ID de modèle](/docs/config/#models) dans votre configuration OpenCode utilise le format `opencode-go/<model-id>`. Par exemple, pour Kimi K3, vous utiliseriez `opencode-go/kimi-k3` dans votre configuration.
|
||||
|
||||
@@ -240,29 +248,30 @@ https://opencode.ai/zen/go/v1/models
|
||||
|
||||
## Confidentialité
|
||||
|
||||
| Modèle | Entraînement des modèles | Conservation des données |
|
||||
| -------------------------- | ------------------------ | ------------------------ |
|
||||
| Grok 4.5 | Non utilisé | 30 jours |
|
||||
| GPT 5.6 Luna | Non utilisé | 30 jours |
|
||||
| GLM-5.3 | Non utilisé | 0 jour |
|
||||
| GLM-5.2 | Non utilisé | 0 jour |
|
||||
| GLM-5.1 | Non utilisé | 0 jour |
|
||||
| Kimi K3 | Non utilisé | 0 jour |
|
||||
| Kimi K2.7 Code | Non utilisé | 0 jour |
|
||||
| Kimi K2.6 | Non utilisé | 0 jour |
|
||||
| MiMo-V2.5-Pro | Non utilisé | 0 jour |
|
||||
| MiMo-V2.5 | Non utilisé | 0 jour |
|
||||
| Qwen3.8 Max | Non utilisé | 0 jour |
|
||||
| Qwen3.7 Max | Non utilisé | 0 jour |
|
||||
| Qwen3.7 Plus | Non utilisé | 0 jour |
|
||||
| Qwen3.6 Plus | Non utilisé | 0 jour |
|
||||
| MiniMax M3 | Non utilisé | 0 jour |
|
||||
| MiniMax M2.7 | Non utilisé | 0 jour |
|
||||
| Muse Spark 1.2 Contributor | Oui | Pas de ZDR |
|
||||
| DeepSeek V4 Pro | Non utilisé | 0 jour |
|
||||
| DeepSeek V4 Flash | Non utilisé | 0 jour |
|
||||
| Hy3 | Non utilisé | 0 jour |
|
||||
| Ox Alpha Free | Non utilisé | 0 jour |
|
||||
| Modèle | Entraînement des modèles | Conservation des données |
|
||||
| ---------------------------- | ------------------------ | ------------------------ |
|
||||
| Grok 4.5 | Non utilisé | 30 jours |
|
||||
| GPT 5.6 Luna | Non utilisé | 30 jours |
|
||||
| GLM-5.3 | Non utilisé | 0 jour |
|
||||
| GLM-5.2 | Non utilisé | 0 jour |
|
||||
| GLM-5.1 | Non utilisé | 0 jour |
|
||||
| Kimi K3 | Non utilisé | 0 jour |
|
||||
| Kimi K2.7 Code | Non utilisé | 0 jour |
|
||||
| Kimi K2.6 | Non utilisé | 0 jour |
|
||||
| MiMo-V2.5-Pro | Non utilisé | 0 jour |
|
||||
| MiMo-V2.5 | Non utilisé | 0 jour |
|
||||
| Qwen3.8 Max | Non utilisé | 0 jour |
|
||||
| Qwen3.7 Max | Non utilisé | 0 jour |
|
||||
| Qwen3.7 Plus | Non utilisé | 0 jour |
|
||||
| Qwen3.6 Plus | Non utilisé | 0 jour |
|
||||
| MiniMax M3 | Non utilisé | 0 jour |
|
||||
| MiniMax M2.7 | Non utilisé | 0 jour |
|
||||
| Muse Spark 1.2 Contributor | Oui | Pas de ZDR |
|
||||
| DeepSeek V4 Pro | Non utilisé | 0 jour |
|
||||
| DeepSeek V4 Flash | Non utilisé | 0 jour |
|
||||
| DeepSeek V4 Flash Vision Exp | Non utilisé | 0 jour |
|
||||
| Hy3 | Non utilisé | 0 jour |
|
||||
| Ox Alpha Free | Non utilisé | 0 jour |
|
||||
|
||||
- **Grok 4.5:** 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. [En savoir plus](https://docs.x.ai/developers/faq/security#what-is-zero-data-retention-zdr).
|
||||
- **GPT 5.6 Luna:** 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. [En savoir plus](https://developers.openai.com/api/docs/guides/your-data#data-retention-controls-for-abuse-monitoring).
|
||||
|
||||
@@ -184,8 +184,8 @@ Nous prenons en charge un modèle de paiement à l'utilisation. Vous trouverez c
|
||||
| Grok 4.5 (> 200K tokens) | $4.00 | $12.00 | $0.60 | - |
|
||||
| Grok Build 0.1 | $1.00 | $2.00 | $0.20 | - |
|
||||
| Muse Spark 1.2 | $1.25 | $4.25 | $0.15 | - |
|
||||
| GPT 5.6 Sol (≤ 272K tokens) | $5.00 | $30.00 | $0.50 | $6.25 |
|
||||
| GPT 5.6 Sol (> 272K tokens) | $10.00 | $45.00 | $1.00 | $12.50 |
|
||||
| GPT 5.6 Sol (≤ 272K tokens) | $2.00 | $10.00 | $0.20 | $2.50 |
|
||||
| GPT 5.6 Sol (> 272K tokens) | $4.00 | $15.00 | $0.40 | $5.00 |
|
||||
| GPT 5.6 Terra (≤ 272K tokens) | $2.00 | $12.00 | $0.20 | $2.50 |
|
||||
| GPT 5.6 Terra (> 272K tokens) | $4.00 | $18.00 | $0.40 | $5.00 |
|
||||
| GPT 5.6 Luna (≤ 272K tokens) | $0.20 | $1.20 | $0.02 | $0.25 |
|
||||
@@ -210,6 +210,8 @@ Nous prenons en charge un modèle de paiement à l'utilisation. Vous trouverez c
|
||||
| GPT 5 Codex | $1.07 | $8.50 | $0.107 | - |
|
||||
| GPT 5 Nano | $0.05 | $0.40 | $0.005 | - |
|
||||
|
||||
**GPT 5.6 Sol:** Les prix affichés incluent une réduction de 50 % jusqu’au 18 septembre 2026.
|
||||
|
||||
**DeepSeek V4 Flash / Pro:** Les heures Peak sont 01:00-04:00 et 06:00-10:00 UTC ; toutes les autres heures sont Off-Peak. [En savoir plus](https://api-docs.deepseek.com/quick_start/pricing/).
|
||||
|
||||
Vous remarquerez peut-être des [modèles à faible coût](/docs/config/#models), tels que Haiku, Nano ou Flash, dans votre historique d'utilisation. OpenCode utilise ces modèles pour générer les titres des sessions.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user