Просмотр исходного кода

Merge branch 'dev' into anthropic-fixes

Aiden Cline 4 месяцев назад
Родитель
Сommit
3dea9e91d1
100 измененных файлов с 1013 добавлено и 344 удалено
  1. 1 0
      .github/VOUCHED.td
  2. 57 60
      bun.lock
  3. 4 4
      nix/hashes.json
  4. 2 0
      package.json
  5. 2 2
      packages/app/package.json
  6. 1 1
      packages/app/src/components/dialog-edit-project.tsx
  7. 1 1
      packages/app/src/components/dialog-fork.tsx
  8. 1 1
      packages/app/src/components/dialog-select-directory.tsx
  9. 2 2
      packages/app/src/components/dialog-select-file.tsx
  10. 1 1
      packages/app/src/components/prompt-input/build-request-parts.ts
  11. 1 1
      packages/app/src/components/prompt-input/context-items.tsx
  12. 1 1
      packages/app/src/components/prompt-input/slash-popover.tsx
  13. 1 1
      packages/app/src/components/prompt-input/submit.test.ts
  14. 15 9
      packages/app/src/components/prompt-input/submit.ts
  15. 2 2
      packages/app/src/components/session/session-context-tab.tsx
  16. 1 1
      packages/app/src/components/session/session-header.tsx
  17. 1 1
      packages/app/src/components/session/session-new-view.tsx
  18. 1 1
      packages/app/src/components/session/session-sortable-tab.tsx
  19. 1 1
      packages/app/src/context/file.tsx
  20. 1 1
      packages/app/src/context/global-sync.tsx
  21. 2 2
      packages/app/src/context/global-sync/bootstrap.ts
  22. 1 1
      packages/app/src/context/global-sync/event-reducer.ts
  23. 1 1
      packages/app/src/context/local.tsx
  24. 2 2
      packages/app/src/context/notification.tsx
  25. 1 1
      packages/app/src/context/permission-auto-respond.test.ts
  26. 1 1
      packages/app/src/context/permission-auto-respond.ts
  27. 1 1
      packages/app/src/context/prompt.tsx
  28. 2 2
      packages/app/src/context/sync.tsx
  29. 1 1
      packages/app/src/pages/directory-layout.tsx
  30. 1 1
      packages/app/src/pages/home.tsx
  31. 4 4
      packages/app/src/pages/layout.tsx
  32. 1 1
      packages/app/src/pages/layout/helpers.ts
  33. 1 1
      packages/app/src/pages/layout/sidebar-items.tsx
  34. 1 1
      packages/app/src/pages/layout/sidebar-project.tsx
  35. 2 2
      packages/app/src/pages/layout/sidebar-workspace.tsx
  36. 1 1
      packages/app/src/pages/session.tsx
  37. 1 1
      packages/app/src/pages/session/file-tabs.tsx
  38. 3 3
      packages/app/src/pages/session/message-timeline.tsx
  39. 1 1
      packages/app/src/pages/session/use-session-commands.tsx
  40. 1 1
      packages/app/src/utils/base64.ts
  41. 1 1
      packages/app/src/utils/persist.ts
  42. 1 1
      packages/console/app/package.json
  43. 6 6
      packages/console/app/src/i18n/ar.ts
  44. 6 6
      packages/console/app/src/i18n/br.ts
  45. 6 6
      packages/console/app/src/i18n/da.ts
  46. 6 6
      packages/console/app/src/i18n/de.ts
  47. 6 6
      packages/console/app/src/i18n/en.ts
  48. 6 6
      packages/console/app/src/i18n/es.ts
  49. 6 6
      packages/console/app/src/i18n/fr.ts
  50. 6 6
      packages/console/app/src/i18n/it.ts
  51. 6 6
      packages/console/app/src/i18n/ja.ts
  52. 6 6
      packages/console/app/src/i18n/ko.ts
  53. 6 6
      packages/console/app/src/i18n/no.ts
  54. 6 6
      packages/console/app/src/i18n/pl.ts
  55. 6 6
      packages/console/app/src/i18n/ru.ts
  56. 6 6
      packages/console/app/src/i18n/th.ts
  57. 6 6
      packages/console/app/src/i18n/tr.ts
  58. 6 6
      packages/console/app/src/i18n/zh.ts
  59. 6 6
      packages/console/app/src/i18n/zht.ts
  60. 1 1
      packages/console/app/src/routes/download/[channel]/[platform].ts
  61. 24 0
      packages/console/app/src/routes/go/index.css
  62. 49 10
      packages/console/app/src/routes/go/index.tsx
  63. 2 0
      packages/console/app/src/routes/workspace/[id]/go/lite-section.tsx
  64. 13 12
      packages/console/app/src/routes/zen/util/handler.ts
  65. 1 1
      packages/console/core/package.json
  66. 1 0
      packages/console/core/src/model.ts
  67. 1 1
      packages/console/function/package.json
  68. 1 1
      packages/console/mail/package.json
  69. 1 1
      packages/desktop-electron/package.json
  70. 1 1
      packages/desktop-electron/src/main/store.ts
  71. 1 1
      packages/desktop/package.json
  72. 2 2
      packages/enterprise/package.json
  73. 2 2
      packages/enterprise/src/core/share.ts
  74. 1 1
      packages/enterprise/src/core/storage.ts
  75. 3 3
      packages/enterprise/src/routes/share/[shareID].tsx
  76. 1 1
      packages/enterprise/test/core/share.test.ts
  77. 6 6
      packages/extensions/zed/extension.toml
  78. 1 1
      packages/function/package.json
  79. 6 4
      packages/opencode/package.json
  80. 310 0
      packages/opencode/specs/effect/instance-context.md
  81. 4 0
      packages/opencode/specs/effect/migration.md
  82. 1 1
      packages/opencode/src/acp/agent.ts
  83. 1 1
      packages/opencode/src/auth/index.ts
  84. 3 2
      packages/opencode/src/bus/index.ts
  85. 6 6
      packages/opencode/src/cli/cmd/tui/context/sync.tsx
  86. 1 1
      packages/opencode/src/cli/cmd/tui/context/theme.tsx
  87. 1 1
      packages/opencode/src/cli/cmd/tui/plugin/runtime.ts
  88. 1 1
      packages/opencode/src/cli/ui.ts
  89. 3 3
      packages/opencode/src/command/index.ts
  90. 5 5
      packages/opencode/src/config/config.ts
  91. 1 1
      packages/opencode/src/config/markdown.ts
  92. 1 1
      packages/opencode/src/config/paths.ts
  93. 1 1
      packages/opencode/src/config/tui.ts
  94. 4 0
      packages/opencode/src/control-plane/workspace-context.ts
  95. 238 22
      packages/opencode/src/control-plane/workspace.ts
  96. 1 1
      packages/opencode/src/effect/app-runtime.ts
  97. 49 0
      packages/opencode/src/effect/bridge.ts
  98. 14 2
      packages/opencode/src/effect/observability.ts
  99. 20 3
      packages/opencode/src/effect/run-service.ts
  100. 0 19
      packages/opencode/src/env/index.ts

+ 1 - 0
.github/VOUCHED.td

@@ -27,6 +27,7 @@ r44vc0rp
 rekram1-node
 rekram1-node
 -ricardo-m-l
 -ricardo-m-l
 -robinmordasiewicz
 -robinmordasiewicz
+shantur
 simonklee
 simonklee
 -spider-yamet clawdbot/llm psychosis, spam pinging the team
 -spider-yamet clawdbot/llm psychosis, spam pinging the team
 thdxr
 thdxr

+ 57 - 60
bun.lock

@@ -27,12 +27,12 @@
     },
     },
     "packages/app": {
     "packages/app": {
       "name": "@opencode-ai/app",
       "name": "@opencode-ai/app",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "@kobalte/core": "catalog:",
         "@kobalte/core": "catalog:",
         "@opencode-ai/sdk": "workspace:*",
         "@opencode-ai/sdk": "workspace:*",
+        "@opencode-ai/shared": "workspace:*",
         "@opencode-ai/ui": "workspace:*",
         "@opencode-ai/ui": "workspace:*",
-        "@opencode-ai/util": "workspace:*",
         "@shikijs/transformers": "3.9.2",
         "@shikijs/transformers": "3.9.2",
         "@solid-primitives/active-element": "2.1.3",
         "@solid-primitives/active-element": "2.1.3",
         "@solid-primitives/audio": "1.4.2",
         "@solid-primitives/audio": "1.4.2",
@@ -81,7 +81,7 @@
     },
     },
     "packages/console/app": {
     "packages/console/app": {
       "name": "@opencode-ai/console-app",
       "name": "@opencode-ai/console-app",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "@cloudflare/vite-plugin": "1.15.2",
         "@cloudflare/vite-plugin": "1.15.2",
         "@ibm/plex": "6.4.1",
         "@ibm/plex": "6.4.1",
@@ -115,7 +115,7 @@
     },
     },
     "packages/console/core": {
     "packages/console/core": {
       "name": "@opencode-ai/console-core",
       "name": "@opencode-ai/console-core",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "@aws-sdk/client-sts": "3.782.0",
         "@aws-sdk/client-sts": "3.782.0",
         "@jsx-email/render": "1.1.1",
         "@jsx-email/render": "1.1.1",
@@ -142,7 +142,7 @@
     },
     },
     "packages/console/function": {
     "packages/console/function": {
       "name": "@opencode-ai/console-function",
       "name": "@opencode-ai/console-function",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "@ai-sdk/anthropic": "3.0.64",
         "@ai-sdk/anthropic": "3.0.64",
         "@ai-sdk/openai": "3.0.48",
         "@ai-sdk/openai": "3.0.48",
@@ -166,7 +166,7 @@
     },
     },
     "packages/console/mail": {
     "packages/console/mail": {
       "name": "@opencode-ai/console-mail",
       "name": "@opencode-ai/console-mail",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "@jsx-email/all": "2.2.3",
         "@jsx-email/all": "2.2.3",
         "@jsx-email/cli": "1.4.3",
         "@jsx-email/cli": "1.4.3",
@@ -190,7 +190,7 @@
     },
     },
     "packages/desktop": {
     "packages/desktop": {
       "name": "@opencode-ai/desktop",
       "name": "@opencode-ai/desktop",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "@opencode-ai/app": "workspace:*",
         "@opencode-ai/app": "workspace:*",
         "@opencode-ai/ui": "workspace:*",
         "@opencode-ai/ui": "workspace:*",
@@ -223,7 +223,7 @@
     },
     },
     "packages/desktop-electron": {
     "packages/desktop-electron": {
       "name": "@opencode-ai/desktop-electron",
       "name": "@opencode-ai/desktop-electron",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "effect": "catalog:",
         "effect": "catalog:",
         "electron-context-menu": "4.1.2",
         "electron-context-menu": "4.1.2",
@@ -266,10 +266,10 @@
     },
     },
     "packages/enterprise": {
     "packages/enterprise": {
       "name": "@opencode-ai/enterprise",
       "name": "@opencode-ai/enterprise",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
+        "@opencode-ai/shared": "workspace:*",
         "@opencode-ai/ui": "workspace:*",
         "@opencode-ai/ui": "workspace:*",
-        "@opencode-ai/util": "workspace:*",
         "@pierre/diffs": "catalog:",
         "@pierre/diffs": "catalog:",
         "@solidjs/meta": "catalog:",
         "@solidjs/meta": "catalog:",
         "@solidjs/router": "catalog:",
         "@solidjs/router": "catalog:",
@@ -295,7 +295,7 @@
     },
     },
     "packages/function": {
     "packages/function": {
       "name": "@opencode-ai/function",
       "name": "@opencode-ai/function",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "@octokit/auth-app": "8.0.1",
         "@octokit/auth-app": "8.0.1",
         "@octokit/rest": "catalog:",
         "@octokit/rest": "catalog:",
@@ -311,7 +311,7 @@
     },
     },
     "packages/opencode": {
     "packages/opencode": {
       "name": "opencode",
       "name": "opencode",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "bin": {
       "bin": {
         "opencode": "./bin/opencode",
         "opencode": "./bin/opencode",
       },
       },
@@ -358,8 +358,9 @@
         "@opencode-ai/script": "workspace:*",
         "@opencode-ai/script": "workspace:*",
         "@opencode-ai/sdk": "workspace:*",
         "@opencode-ai/sdk": "workspace:*",
         "@opencode-ai/server": "workspace:*",
         "@opencode-ai/server": "workspace:*",
-        "@opencode-ai/util": "workspace:*",
         "@openrouter/ai-sdk-provider": "2.5.1",
         "@openrouter/ai-sdk-provider": "2.5.1",
+        "@opentelemetry/api": "1.9.0",
+        "@opentelemetry/context-async-hooks": "2.6.1",
         "@opentelemetry/exporter-trace-otlp-http": "0.214.0",
         "@opentelemetry/exporter-trace-otlp-http": "0.214.0",
         "@opentelemetry/sdk-trace-base": "2.6.1",
         "@opentelemetry/sdk-trace-base": "2.6.1",
         "@opentelemetry/sdk-trace-node": "2.6.1",
         "@opentelemetry/sdk-trace-node": "2.6.1",
@@ -424,6 +425,7 @@
         "@effect/language-service": "0.84.2",
         "@effect/language-service": "0.84.2",
         "@octokit/webhooks-types": "7.6.1",
         "@octokit/webhooks-types": "7.6.1",
         "@opencode-ai/script": "workspace:*",
         "@opencode-ai/script": "workspace:*",
+        "@opencode-ai/shared": "workspace:*",
         "@parcel/watcher-darwin-arm64": "2.5.1",
         "@parcel/watcher-darwin-arm64": "2.5.1",
         "@parcel/watcher-darwin-x64": "2.5.1",
         "@parcel/watcher-darwin-x64": "2.5.1",
         "@parcel/watcher-linux-arm64-glibc": "2.5.1",
         "@parcel/watcher-linux-arm64-glibc": "2.5.1",
@@ -455,7 +457,7 @@
     },
     },
     "packages/plugin": {
     "packages/plugin": {
       "name": "@opencode-ai/plugin",
       "name": "@opencode-ai/plugin",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "@opencode-ai/sdk": "workspace:*",
         "@opencode-ai/sdk": "workspace:*",
         "effect": "catalog:",
         "effect": "catalog:",
@@ -490,7 +492,7 @@
     },
     },
     "packages/sdk/js": {
     "packages/sdk/js": {
       "name": "@opencode-ai/sdk",
       "name": "@opencode-ai/sdk",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "cross-spawn": "catalog:",
         "cross-spawn": "catalog:",
       },
       },
@@ -505,17 +507,39 @@
     },
     },
     "packages/server": {
     "packages/server": {
       "name": "@opencode-ai/server",
       "name": "@opencode-ai/server",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "effect": "catalog:",
         "effect": "catalog:",
       },
       },
       "devDependencies": {
       "devDependencies": {
+        "@typescript/native-preview": "catalog:",
         "typescript": "catalog:",
         "typescript": "catalog:",
       },
       },
     },
     },
+    "packages/shared": {
+      "name": "@opencode-ai/shared",
+      "version": "1.4.6",
+      "bin": {
+        "opencode": "./bin/opencode",
+      },
+      "dependencies": {
+        "@effect/platform-node": "catalog:",
+        "@npmcli/arborist": "catalog:",
+        "effect": "catalog:",
+        "mime-types": "3.0.2",
+        "minimatch": "10.2.5",
+        "semver": "catalog:",
+        "xdg-basedir": "5.1.0",
+        "zod": "catalog:",
+      },
+      "devDependencies": {
+        "@types/bun": "catalog:",
+        "@types/semver": "catalog:",
+      },
+    },
     "packages/slack": {
     "packages/slack": {
       "name": "@opencode-ai/slack",
       "name": "@opencode-ai/slack",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "@opencode-ai/sdk": "workspace:*",
         "@opencode-ai/sdk": "workspace:*",
         "@slack/bolt": "^3.17.1",
         "@slack/bolt": "^3.17.1",
@@ -550,11 +574,11 @@
     },
     },
     "packages/ui": {
     "packages/ui": {
       "name": "@opencode-ai/ui",
       "name": "@opencode-ai/ui",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "@kobalte/core": "catalog:",
         "@kobalte/core": "catalog:",
         "@opencode-ai/sdk": "workspace:*",
         "@opencode-ai/sdk": "workspace:*",
-        "@opencode-ai/util": "workspace:*",
+        "@opencode-ai/shared": "workspace:*",
         "@pierre/diffs": "catalog:",
         "@pierre/diffs": "catalog:",
         "@shikijs/transformers": "3.9.2",
         "@shikijs/transformers": "3.9.2",
         "@solid-primitives/bounds": "0.1.3",
         "@solid-primitives/bounds": "0.1.3",
@@ -597,20 +621,9 @@
         "vite-plugin-solid": "catalog:",
         "vite-plugin-solid": "catalog:",
       },
       },
     },
     },
-    "packages/util": {
-      "name": "@opencode-ai/util",
-      "version": "1.4.4",
-      "dependencies": {
-        "zod": "catalog:",
-      },
-      "devDependencies": {
-        "@types/bun": "catalog:",
-        "typescript": "catalog:",
-      },
-    },
     "packages/web": {
     "packages/web": {
       "name": "@opencode-ai/web",
       "name": "@opencode-ai/web",
-      "version": "1.4.4",
+      "version": "1.4.6",
       "dependencies": {
       "dependencies": {
         "@astrojs/cloudflare": "12.6.3",
         "@astrojs/cloudflare": "12.6.3",
         "@astrojs/markdown-remark": "6.3.1",
         "@astrojs/markdown-remark": "6.3.1",
@@ -666,6 +679,7 @@
     "@hono/zod-validator": "0.4.2",
     "@hono/zod-validator": "0.4.2",
     "@kobalte/core": "0.13.11",
     "@kobalte/core": "0.13.11",
     "@lydell/node-pty": "1.2.0-beta.10",
     "@lydell/node-pty": "1.2.0-beta.10",
+    "@npmcli/arborist": "9.4.0",
     "@octokit/rest": "22.0.0",
     "@octokit/rest": "22.0.0",
     "@openauthjs/openauth": "0.0.0-20250322224806",
     "@openauthjs/openauth": "0.0.0-20250322224806",
     "@pierre/diffs": "1.1.0-beta.18",
     "@pierre/diffs": "1.1.0-beta.18",
@@ -698,6 +712,7 @@
     "marked-shiki": "1.2.1",
     "marked-shiki": "1.2.1",
     "remeda": "2.26.0",
     "remeda": "2.26.0",
     "remend": "1.3.0",
     "remend": "1.3.0",
+    "semver": "7.7.4",
     "shiki": "3.20.0",
     "shiki": "3.20.0",
     "solid-js": "1.9.10",
     "solid-js": "1.9.10",
     "solid-list": "0.3.0",
     "solid-list": "0.3.0",
@@ -1554,14 +1569,14 @@
 
 
     "@opencode-ai/server": ["@opencode-ai/server@workspace:packages/server"],
     "@opencode-ai/server": ["@opencode-ai/server@workspace:packages/server"],
 
 
+    "@opencode-ai/shared": ["@opencode-ai/shared@workspace:packages/shared"],
+
     "@opencode-ai/slack": ["@opencode-ai/slack@workspace:packages/slack"],
     "@opencode-ai/slack": ["@opencode-ai/slack@workspace:packages/slack"],
 
 
     "@opencode-ai/storybook": ["@opencode-ai/storybook@workspace:packages/storybook"],
     "@opencode-ai/storybook": ["@opencode-ai/storybook@workspace:packages/storybook"],
 
 
     "@opencode-ai/ui": ["@opencode-ai/ui@workspace:packages/ui"],
     "@opencode-ai/ui": ["@opencode-ai/ui@workspace:packages/ui"],
 
 
-    "@opencode-ai/util": ["@opencode-ai/util@workspace:packages/util"],
-
     "@opencode-ai/web": ["@opencode-ai/web@workspace:packages/web"],
     "@opencode-ai/web": ["@opencode-ai/web@workspace:packages/web"],
 
 
     "@openrouter/ai-sdk-provider": ["@openrouter/ai-sdk-provider@2.5.1", "", { "peerDependencies": { "ai": "^6.0.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-r1fJL1Cb3gQDa2MpWH/sfx1BsEW0uzlRriJM6eihaKqbtKDmZoBisF32VcVaQYassighX7NGCkF68EsrZA43uQ=="],
     "@openrouter/ai-sdk-provider": ["@openrouter/ai-sdk-provider@2.5.1", "", { "peerDependencies": { "ai": "^6.0.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-r1fJL1Cb3gQDa2MpWH/sfx1BsEW0uzlRriJM6eihaKqbtKDmZoBisF32VcVaQYassighX7NGCkF68EsrZA43uQ=="],
@@ -2780,7 +2795,7 @@
 
 
     "commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="],
     "commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="],
 
 
-    "common-ancestor-path": ["common-ancestor-path@1.0.1", "", {}, "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w=="],
+    "common-ancestor-path": ["common-ancestor-path@2.0.0", "", {}, "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng=="],
 
 
     "compare-version": ["compare-version@0.1.2", "", {}, "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A=="],
     "compare-version": ["compare-version@0.1.2", "", {}, "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A=="],
 
 
@@ -3880,7 +3895,7 @@
 
 
     "miniflare": ["miniflare@4.20251118.1", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "7.14.0", "workerd": "1.20251118.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-uLSAE/DvOm392fiaig4LOaatxLjM7xzIniFRG5Y3yF9IduOYLLK/pkCPQNCgKQH3ou0YJRHnTN+09LPfqYNTQQ=="],
     "miniflare": ["miniflare@4.20251118.1", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "7.14.0", "workerd": "1.20251118.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-uLSAE/DvOm392fiaig4LOaatxLjM7xzIniFRG5Y3yF9IduOYLLK/pkCPQNCgKQH3ou0YJRHnTN+09LPfqYNTQQ=="],
 
 
-    "minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="],
+    "minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
 
 
     "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
     "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
 
 
@@ -3938,7 +3953,7 @@
 
 
     "native-duplexpair": ["native-duplexpair@1.0.0", "", {}, "sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA=="],
     "native-duplexpair": ["native-duplexpair@1.0.0", "", {}, "sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA=="],
 
 
-    "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
+    "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
 
 
     "neotraverse": ["neotraverse@0.6.18", "", {}, "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA=="],
     "neotraverse": ["neotraverse@0.6.18", "", {}, "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA=="],
 
 
@@ -5440,12 +5455,6 @@
 
 
     "@modelcontextprotocol/sdk/zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="],
     "@modelcontextprotocol/sdk/zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="],
 
 
-    "@npmcli/arborist/common-ancestor-path": ["common-ancestor-path@2.0.0", "", {}, "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng=="],
-
-    "@npmcli/arborist/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
-
-    "@npmcli/map-workspaces/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
-
     "@npmcli/query/postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="],
     "@npmcli/query/postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="],
 
 
     "@octokit/auth-app/@octokit/request": ["@octokit/request@10.0.8", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-SJZNwY9pur9Agf7l87ywFi14W+Hd9Jg6Ifivsd33+/bGUQIjNujdFiXII2/qSlN2ybqUHfp5xpekMEjIBTjlSw=="],
     "@octokit/auth-app/@octokit/request": ["@octokit/request@10.0.8", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-SJZNwY9pur9Agf7l87ywFi14W+Hd9Jg6Ifivsd33+/bGUQIjNujdFiXII2/qSlN2ybqUHfp5xpekMEjIBTjlSw=="],
@@ -5614,8 +5623,6 @@
 
 
     "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="],
     "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="],
 
 
-    "@tufjs/models/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
-
     "@types/plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="],
     "@types/plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="],
 
 
     "@vitest/expect/@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="],
     "@vitest/expect/@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="],
@@ -5628,6 +5635,8 @@
 
 
     "accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
     "accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
 
 
+    "accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
+
     "ai/@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.95", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@vercel/oidc": "3.1.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZmUNNbZl3V42xwQzPaNUi+s8eqR2lnrxf0bvB6YbLXpLjHYv0k2Y78t12cNOfY0bxGeuVVTLyk856uLuQIuXEQ=="],
     "ai/@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.95", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@vercel/oidc": "3.1.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZmUNNbZl3V42xwQzPaNUi+s8eqR2lnrxf0bvB6YbLXpLjHYv0k2Y78t12cNOfY0bxGeuVVTLyk856uLuQIuXEQ=="],
 
 
     "ai-gateway-provider/@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.69", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-LshR7X3pFugY0o41G2VKTmg1XoGpSl7uoYWfzk6zjVZLhCfeFiwgpOga+eTV4XY1VVpZwKVqRnkDbIL7K2eH5g=="],
     "ai-gateway-provider/@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.69", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-LshR7X3pFugY0o41G2VKTmg1XoGpSl7uoYWfzk6zjVZLhCfeFiwgpOga+eTV4XY1VVpZwKVqRnkDbIL7K2eH5g=="],
@@ -5650,8 +5659,6 @@
 
 
     "app-builder-lib/hosted-git-info": ["hosted-git-info@4.1.0", "", { "dependencies": { "lru-cache": "^6.0.0" } }, "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA=="],
     "app-builder-lib/hosted-git-info": ["hosted-git-info@4.1.0", "", { "dependencies": { "lru-cache": "^6.0.0" } }, "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA=="],
 
 
-    "app-builder-lib/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
-
     "app-builder-lib/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="],
     "app-builder-lib/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="],
 
 
     "archiver-utils/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
     "archiver-utils/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
@@ -5660,6 +5667,8 @@
 
 
     "astro/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="],
     "astro/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="],
 
 
+    "astro/common-ancestor-path": ["common-ancestor-path@1.0.1", "", {}, "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w=="],
+
     "astro/diff": ["diff@5.2.2", "", {}, "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A=="],
     "astro/diff": ["diff@5.2.2", "", {}, "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A=="],
 
 
     "astro/unstorage": ["unstorage@1.17.5", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.10", "lru-cache": "^11.2.7", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg=="],
     "astro/unstorage": ["unstorage@1.17.5", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.10", "lru-cache": "^11.2.7", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg=="],
@@ -5784,8 +5793,6 @@
 
 
     "gitlab-ai-provider/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
     "gitlab-ai-provider/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
 
 
-    "glob/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
-
     "globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
     "globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
 
 
     "gray-matter/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="],
     "gray-matter/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="],
@@ -5802,8 +5809,6 @@
 
 
     "iconv-corefoundation/node-addon-api": ["node-addon-api@1.7.2", "", {}, "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg=="],
     "iconv-corefoundation/node-addon-api": ["node-addon-api@1.7.2", "", {}, "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg=="],
 
 
-    "ignore-walk/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
-
     "js-beautify/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
     "js-beautify/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
 
 
     "js-beautify/nopt": ["nopt@7.2.1", "", { "dependencies": { "abbrev": "^2.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w=="],
     "js-beautify/nopt": ["nopt@7.2.1", "", { "dependencies": { "abbrev": "^2.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w=="],
@@ -5818,8 +5823,6 @@
 
 
     "log-symbols/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
     "log-symbols/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
 
 
-    "make-fetch-happen/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
-
     "matcher/escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
     "matcher/escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
 
 
     "md-to-react-email/marked": ["marked@7.0.4", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ=="],
     "md-to-react-email/marked": ["marked@7.0.4", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ=="],
@@ -5858,6 +5861,8 @@
 
 
     "opencode/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="],
     "opencode/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="],
 
 
+    "opencode/minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="],
+
     "opencode-gitlab-auth/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="],
     "opencode-gitlab-auth/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="],
 
 
     "opencode-poe-auth/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="],
     "opencode-poe-auth/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="],
@@ -6668,8 +6673,6 @@
 
 
     "type-is/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
     "type-is/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
 
 
-    "vite-plugin-icons-spritesheet/glob/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
-
     "vitest/@vitest/expect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
     "vitest/@vitest/expect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
 
 
     "vitest/@vitest/expect/chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="],
     "vitest/@vitest/expect/chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="],
@@ -6806,8 +6809,6 @@
 
 
     "@electron/rebuild/node-gyp/make-fetch-happen/minipass-fetch": ["minipass-fetch@4.0.1", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^3.0.1" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ=="],
     "@electron/rebuild/node-gyp/make-fetch-happen/minipass-fetch": ["minipass-fetch@4.0.1", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^3.0.1" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ=="],
 
 
-    "@electron/rebuild/node-gyp/make-fetch-happen/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
-
     "@electron/rebuild/node-gyp/make-fetch-happen/ssri": ["ssri@12.0.0", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ=="],
     "@electron/rebuild/node-gyp/make-fetch-happen/ssri": ["ssri@12.0.0", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ=="],
 
 
     "@electron/rebuild/node-gyp/nopt/abbrev": ["abbrev@3.0.1", "", {}, "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg=="],
     "@electron/rebuild/node-gyp/nopt/abbrev": ["abbrev@3.0.1", "", {}, "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg=="],
@@ -6872,8 +6873,6 @@
 
 
     "@jsx-email/cli/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
     "@jsx-email/cli/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
 
 
-    "@modelcontextprotocol/sdk/express/accepts/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
-
     "@modelcontextprotocol/sdk/express/type-is/media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
     "@modelcontextprotocol/sdk/express/type-is/media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
 
 
     "@octokit/auth-app/@octokit/request-error/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="],
     "@octokit/auth-app/@octokit/request-error/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="],
@@ -7072,8 +7071,6 @@
 
 
     "js-beautify/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
     "js-beautify/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
 
 
-    "opencontrol/@modelcontextprotocol/sdk/express/accepts/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
-
     "opencontrol/@modelcontextprotocol/sdk/express/type-is/media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
     "opencontrol/@modelcontextprotocol/sdk/express/type-is/media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
 
 
     "pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
     "pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],

+ 4 - 4
nix/hashes.json

@@ -1,8 +1,8 @@
 {
 {
   "nodeModules": {
   "nodeModules": {
-    "x86_64-linux": "sha256-gdS7MkWGeVO0qLs0HKD156YE0uCk5vWeYjKu4JR1Apw=",
-    "aarch64-linux": "sha256-tF4pyVqzbrvdkRG23Fot37FCg8guRZkcU738fHPr/OQ=",
-    "aarch64-darwin": "sha256-FugTWzGMb2ktAbNwQvWRM3GWOb5RTR++8EocDDrQMLc=",
-    "x86_64-darwin": "sha256-jpe6EiwKr+CS00cn0eHwcDluO4LvO3t/5l/LcFBBKP0="
+    "x86_64-linux": "sha256-PvIx2g1J5QIUIzkz2ABaAM4K/k/+xlBPDUExoOJNNuo=",
+    "aarch64-linux": "sha256-YTAL+P13L5hgNJdDSiBED/UNa5zdTntnUUYDYL+Jdzo=",
+    "aarch64-darwin": "sha256-y2VCJifYAp+H0lpDcJ0QfKNMG00Q/usFElaUIpdc8Vs=",
+    "x86_64-darwin": "sha256-yz8edIlqLp06Y95ad8YjKz5azP7YATPle4TcDx6lM+U="
   }
   }
 }
 }

+ 2 - 0
package.json

@@ -28,6 +28,7 @@
     "catalog": {
     "catalog": {
       "@effect/opentelemetry": "4.0.0-beta.48",
       "@effect/opentelemetry": "4.0.0-beta.48",
       "@effect/platform-node": "4.0.0-beta.48",
       "@effect/platform-node": "4.0.0-beta.48",
+      "@npmcli/arborist": "9.4.0",
       "@types/bun": "1.3.11",
       "@types/bun": "1.3.11",
       "@types/cross-spawn": "6.0.6",
       "@types/cross-spawn": "6.0.6",
       "@octokit/rest": "22.0.0",
       "@octokit/rest": "22.0.0",
@@ -59,6 +60,7 @@
       "marked-shiki": "1.2.1",
       "marked-shiki": "1.2.1",
       "remend": "1.3.0",
       "remend": "1.3.0",
       "@playwright/test": "1.59.1",
       "@playwright/test": "1.59.1",
+      "semver": "7.7.4",
       "typescript": "5.8.2",
       "typescript": "5.8.2",
       "@typescript/native-preview": "7.0.0-dev.20251207.1",
       "@typescript/native-preview": "7.0.0-dev.20251207.1",
       "zod": "4.1.8",
       "zod": "4.1.8",

+ 2 - 2
packages/app/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@opencode-ai/app",
   "name": "@opencode-ai/app",
-  "version": "1.4.4",
+  "version": "1.4.6",
   "description": "",
   "description": "",
   "type": "module",
   "type": "module",
   "exports": {
   "exports": {
@@ -42,7 +42,7 @@
     "@kobalte/core": "catalog:",
     "@kobalte/core": "catalog:",
     "@opencode-ai/sdk": "workspace:*",
     "@opencode-ai/sdk": "workspace:*",
     "@opencode-ai/ui": "workspace:*",
     "@opencode-ai/ui": "workspace:*",
-    "@opencode-ai/util": "workspace:*",
+    "@opencode-ai/shared": "workspace:*",
     "@shikijs/transformers": "3.9.2",
     "@shikijs/transformers": "3.9.2",
     "@solid-primitives/active-element": "2.1.3",
     "@solid-primitives/active-element": "2.1.3",
     "@solid-primitives/audio": "1.4.2",
     "@solid-primitives/audio": "1.4.2",

+ 1 - 1
packages/app/src/components/dialog-edit-project.tsx

@@ -9,7 +9,7 @@ import { createStore } from "solid-js/store"
 import { useGlobalSDK } from "@/context/global-sdk"
 import { useGlobalSDK } from "@/context/global-sdk"
 import { useGlobalSync } from "@/context/global-sync"
 import { useGlobalSync } from "@/context/global-sync"
 import { type LocalProject, getAvatarColors } from "@/context/layout"
 import { type LocalProject, getAvatarColors } from "@/context/layout"
-import { getFilename } from "@opencode-ai/util/path"
+import { getFilename } from "@opencode-ai/shared/util/path"
 import { Avatar } from "@opencode-ai/ui/avatar"
 import { Avatar } from "@opencode-ai/ui/avatar"
 import { useLanguage } from "@/context/language"
 import { useLanguage } from "@/context/language"
 
 

+ 1 - 1
packages/app/src/components/dialog-fork.tsx

@@ -9,7 +9,7 @@ import { List } from "@opencode-ai/ui/list"
 import { showToast } from "@opencode-ai/ui/toast"
 import { showToast } from "@opencode-ai/ui/toast"
 import { extractPromptFromParts } from "@/utils/prompt"
 import { extractPromptFromParts } from "@/utils/prompt"
 import type { TextPart as SDKTextPart } from "@opencode-ai/sdk/v2/client"
 import type { TextPart as SDKTextPart } from "@opencode-ai/sdk/v2/client"
-import { base64Encode } from "@opencode-ai/util/encode"
+import { base64Encode } from "@opencode-ai/shared/util/encode"
 import { useLanguage } from "@/context/language"
 import { useLanguage } from "@/context/language"
 
 
 interface ForkableMessage {
 interface ForkableMessage {

+ 1 - 1
packages/app/src/components/dialog-select-directory.tsx

@@ -3,7 +3,7 @@ import { Dialog } from "@opencode-ai/ui/dialog"
 import { FileIcon } from "@opencode-ai/ui/file-icon"
 import { FileIcon } from "@opencode-ai/ui/file-icon"
 import { List } from "@opencode-ai/ui/list"
 import { List } from "@opencode-ai/ui/list"
 import type { ListRef } from "@opencode-ai/ui/list"
 import type { ListRef } from "@opencode-ai/ui/list"
-import { getDirectory, getFilename } from "@opencode-ai/util/path"
+import { getDirectory, getFilename } from "@opencode-ai/shared/util/path"
 import fuzzysort from "fuzzysort"
 import fuzzysort from "fuzzysort"
 import { createMemo, createResource, createSignal } from "solid-js"
 import { createMemo, createResource, createSignal } from "solid-js"
 import { useGlobalSDK } from "@/context/global-sdk"
 import { useGlobalSDK } from "@/context/global-sdk"

+ 2 - 2
packages/app/src/components/dialog-select-file.tsx

@@ -4,8 +4,8 @@ import { FileIcon } from "@opencode-ai/ui/file-icon"
 import { Icon } from "@opencode-ai/ui/icon"
 import { Icon } from "@opencode-ai/ui/icon"
 import { Keybind } from "@opencode-ai/ui/keybind"
 import { Keybind } from "@opencode-ai/ui/keybind"
 import { List } from "@opencode-ai/ui/list"
 import { List } from "@opencode-ai/ui/list"
-import { base64Encode } from "@opencode-ai/util/encode"
-import { getDirectory, getFilename } from "@opencode-ai/util/path"
+import { base64Encode } from "@opencode-ai/shared/util/encode"
+import { getDirectory, getFilename } from "@opencode-ai/shared/util/path"
 import { useNavigate } from "@solidjs/router"
 import { useNavigate } from "@solidjs/router"
 import { createMemo, createSignal, Match, onCleanup, Show, Switch } from "solid-js"
 import { createMemo, createSignal, Match, onCleanup, Show, Switch } from "solid-js"
 import { formatKeybind, useCommand, type CommandOption } from "@/context/command"
 import { formatKeybind, useCommand, type CommandOption } from "@/context/command"

+ 1 - 1
packages/app/src/components/prompt-input/build-request-parts.ts

@@ -1,4 +1,4 @@
-import { getFilename } from "@opencode-ai/util/path"
+import { getFilename } from "@opencode-ai/shared/util/path"
 import { type AgentPartInput, type FilePartInput, type Part, type TextPartInput } from "@opencode-ai/sdk/v2/client"
 import { type AgentPartInput, type FilePartInput, type Part, type TextPartInput } from "@opencode-ai/sdk/v2/client"
 import type { FileSelection } from "@/context/file"
 import type { FileSelection } from "@/context/file"
 import { encodeFilePath } from "@/context/file/path"
 import { encodeFilePath } from "@/context/file/path"

+ 1 - 1
packages/app/src/components/prompt-input/context-items.tsx

@@ -2,7 +2,7 @@ import { Component, For, Show } from "solid-js"
 import { FileIcon } from "@opencode-ai/ui/file-icon"
 import { FileIcon } from "@opencode-ai/ui/file-icon"
 import { IconButton } from "@opencode-ai/ui/icon-button"
 import { IconButton } from "@opencode-ai/ui/icon-button"
 import { Tooltip } from "@opencode-ai/ui/tooltip"
 import { Tooltip } from "@opencode-ai/ui/tooltip"
-import { getDirectory, getFilename, getFilenameTruncated } from "@opencode-ai/util/path"
+import { getDirectory, getFilename, getFilenameTruncated } from "@opencode-ai/shared/util/path"
 import type { ContextItem } from "@/context/prompt"
 import type { ContextItem } from "@/context/prompt"
 
 
 type PromptContextItem = ContextItem & { key: string }
 type PromptContextItem = ContextItem & { key: string }

+ 1 - 1
packages/app/src/components/prompt-input/slash-popover.tsx

@@ -1,7 +1,7 @@
 import { Component, For, Match, Show, Switch } from "solid-js"
 import { Component, For, Match, Show, Switch } from "solid-js"
 import { FileIcon } from "@opencode-ai/ui/file-icon"
 import { FileIcon } from "@opencode-ai/ui/file-icon"
 import { Icon } from "@opencode-ai/ui/icon"
 import { Icon } from "@opencode-ai/ui/icon"
-import { getDirectory, getFilename } from "@opencode-ai/util/path"
+import { getDirectory, getFilename } from "@opencode-ai/shared/util/path"
 
 
 export type AtOption =
 export type AtOption =
   | { type: "agent"; name: string; display: string }
   | { type: "agent"; name: string; display: string }

+ 1 - 1
packages/app/src/components/prompt-input/submit.test.ts

@@ -74,7 +74,7 @@ beforeAll(async () => {
     showToast: () => 0,
     showToast: () => 0,
   }))
   }))
 
 
-  mock.module("@opencode-ai/util/encode", () => ({
+  mock.module("@opencode-ai/shared/util/encode", () => ({
     base64Encode: (value: string) => value,
     base64Encode: (value: string) => value,
   }))
   }))
 
 

+ 15 - 9
packages/app/src/components/prompt-input/submit.ts

@@ -1,9 +1,9 @@
 import type { Message, Session } from "@opencode-ai/sdk/v2/client"
 import type { Message, Session } from "@opencode-ai/sdk/v2/client"
 import { showToast } from "@opencode-ai/ui/toast"
 import { showToast } from "@opencode-ai/ui/toast"
-import { base64Encode } from "@opencode-ai/util/encode"
-import { Binary } from "@opencode-ai/util/binary"
+import { base64Encode } from "@opencode-ai/shared/util/encode"
+import { Binary } from "@opencode-ai/shared/util/binary"
 import { useNavigate, useParams } from "@solidjs/router"
 import { useNavigate, useParams } from "@solidjs/router"
-import type { Accessor } from "solid-js"
+import { batch, type Accessor } from "solid-js"
 import type { FileSelection } from "@/context/file"
 import type { FileSelection } from "@/context/file"
 import { useGlobalSync } from "@/context/global-sync"
 import { useGlobalSync } from "@/context/global-sync"
 import { useLanguage } from "@/context/language"
 import { useLanguage } from "@/context/language"
@@ -138,13 +138,17 @@ export async function sendFollowupDraft(input: FollowupSendInput) {
       messageID,
       messageID,
     })
     })
 
 
-  setBusy()
-  add()
+  batch(() => {
+    setBusy()
+    add()
+  })
 
 
   try {
   try {
     if (!(await wait())) {
     if (!(await wait())) {
-      setIdle()
-      remove()
+      batch(() => {
+        setIdle()
+        remove()
+      })
       return false
       return false
     }
     }
 
 
@@ -158,8 +162,10 @@ export async function sendFollowupDraft(input: FollowupSendInput) {
     })
     })
     return true
     return true
   } catch (err) {
   } catch (err) {
-    setIdle()
-    remove()
+    batch(() => {
+      setIdle()
+      remove()
+    })
     throw err
     throw err
   }
   }
 }
 }

+ 2 - 2
packages/app/src/components/session/session-context-tab.tsx

@@ -1,8 +1,8 @@
 import { createMemo, createEffect, on, onCleanup, For, Show } from "solid-js"
 import { createMemo, createEffect, on, onCleanup, For, Show } from "solid-js"
 import type { JSX } from "solid-js"
 import type { JSX } from "solid-js"
 import { useSync } from "@/context/sync"
 import { useSync } from "@/context/sync"
-import { checksum } from "@opencode-ai/util/encode"
-import { findLast } from "@opencode-ai/util/array"
+import { checksum } from "@opencode-ai/shared/util/encode"
+import { findLast } from "@opencode-ai/shared/util/array"
 import { same } from "@/utils/same"
 import { same } from "@/utils/same"
 import { Icon } from "@opencode-ai/ui/icon"
 import { Icon } from "@opencode-ai/ui/icon"
 import { Accordion } from "@opencode-ai/ui/accordion"
 import { Accordion } from "@opencode-ai/ui/accordion"

+ 1 - 1
packages/app/src/components/session/session-header.tsx

@@ -7,7 +7,7 @@ import { Keybind } from "@opencode-ai/ui/keybind"
 import { Spinner } from "@opencode-ai/ui/spinner"
 import { Spinner } from "@opencode-ai/ui/spinner"
 import { showToast } from "@opencode-ai/ui/toast"
 import { showToast } from "@opencode-ai/ui/toast"
 import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip"
 import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip"
-import { getFilename } from "@opencode-ai/util/path"
+import { getFilename } from "@opencode-ai/shared/util/path"
 import { createEffect, createMemo, For, onCleanup, Show } from "solid-js"
 import { createEffect, createMemo, For, onCleanup, Show } from "solid-js"
 import { createStore } from "solid-js/store"
 import { createStore } from "solid-js/store"
 import { Portal } from "solid-js/web"
 import { Portal } from "solid-js/web"

+ 1 - 1
packages/app/src/components/session/session-new-view.tsx

@@ -5,7 +5,7 @@ import { useSDK } from "@/context/sdk"
 import { useLanguage } from "@/context/language"
 import { useLanguage } from "@/context/language"
 import { Icon } from "@opencode-ai/ui/icon"
 import { Icon } from "@opencode-ai/ui/icon"
 import { Mark } from "@opencode-ai/ui/logo"
 import { Mark } from "@opencode-ai/ui/logo"
-import { getDirectory, getFilename } from "@opencode-ai/util/path"
+import { getDirectory, getFilename } from "@opencode-ai/shared/util/path"
 
 
 const MAIN_WORKTREE = "main"
 const MAIN_WORKTREE = "main"
 const CREATE_WORKTREE = "create"
 const CREATE_WORKTREE = "create"

+ 1 - 1
packages/app/src/components/session/session-sortable-tab.tsx

@@ -5,7 +5,7 @@ import { FileIcon } from "@opencode-ai/ui/file-icon"
 import { IconButton } from "@opencode-ai/ui/icon-button"
 import { IconButton } from "@opencode-ai/ui/icon-button"
 import { TooltipKeybind } from "@opencode-ai/ui/tooltip"
 import { TooltipKeybind } from "@opencode-ai/ui/tooltip"
 import { Tabs } from "@opencode-ai/ui/tabs"
 import { Tabs } from "@opencode-ai/ui/tabs"
-import { getFilename } from "@opencode-ai/util/path"
+import { getFilename } from "@opencode-ai/shared/util/path"
 import { useFile } from "@/context/file"
 import { useFile } from "@/context/file"
 import { useLanguage } from "@/context/language"
 import { useLanguage } from "@/context/language"
 import { useCommand } from "@/context/command"
 import { useCommand } from "@/context/command"

+ 1 - 1
packages/app/src/context/file.tsx

@@ -3,7 +3,7 @@ import { createStore, produce, reconcile } from "solid-js/store"
 import { createSimpleContext } from "@opencode-ai/ui/context"
 import { createSimpleContext } from "@opencode-ai/ui/context"
 import { showToast } from "@opencode-ai/ui/toast"
 import { showToast } from "@opencode-ai/ui/toast"
 import { useParams } from "@solidjs/router"
 import { useParams } from "@solidjs/router"
-import { getFilename } from "@opencode-ai/util/path"
+import { getFilename } from "@opencode-ai/shared/util/path"
 import { useSDK } from "./sdk"
 import { useSDK } from "./sdk"
 import { useSync } from "./sync"
 import { useSync } from "./sync"
 import { useLanguage } from "@/context/language"
 import { useLanguage } from "@/context/language"

+ 1 - 1
packages/app/src/context/global-sync.tsx

@@ -8,7 +8,7 @@ import type {
   Todo,
   Todo,
 } from "@opencode-ai/sdk/v2/client"
 } from "@opencode-ai/sdk/v2/client"
 import { showToast } from "@opencode-ai/ui/toast"
 import { showToast } from "@opencode-ai/ui/toast"
-import { getFilename } from "@opencode-ai/util/path"
+import { getFilename } from "@opencode-ai/shared/util/path"
 import { createContext, getOwner, onCleanup, onMount, type ParentProps, untrack, useContext } from "solid-js"
 import { createContext, getOwner, onCleanup, onMount, type ParentProps, untrack, useContext } from "solid-js"
 import { createStore, produce, reconcile } from "solid-js/store"
 import { createStore, produce, reconcile } from "solid-js/store"
 import { useLanguage } from "@/context/language"
 import { useLanguage } from "@/context/language"

+ 2 - 2
packages/app/src/context/global-sync/bootstrap.ts

@@ -11,8 +11,8 @@ import type {
   Todo,
   Todo,
 } from "@opencode-ai/sdk/v2/client"
 } from "@opencode-ai/sdk/v2/client"
 import { showToast } from "@opencode-ai/ui/toast"
 import { showToast } from "@opencode-ai/ui/toast"
-import { getFilename } from "@opencode-ai/util/path"
-import { retry } from "@opencode-ai/util/retry"
+import { getFilename } from "@opencode-ai/shared/util/path"
+import { retry } from "@opencode-ai/shared/util/retry"
 import { batch } from "solid-js"
 import { batch } from "solid-js"
 import { reconcile, type SetStoreFunction, type Store } from "solid-js/store"
 import { reconcile, type SetStoreFunction, type Store } from "solid-js/store"
 import type { State, VcsCache } from "./types"
 import type { State, VcsCache } from "./types"

+ 1 - 1
packages/app/src/context/global-sync/event-reducer.ts

@@ -1,4 +1,4 @@
-import { Binary } from "@opencode-ai/util/binary"
+import { Binary } from "@opencode-ai/shared/util/binary"
 import { produce, reconcile, type SetStoreFunction, type Store } from "solid-js/store"
 import { produce, reconcile, type SetStoreFunction, type Store } from "solid-js/store"
 import type {
 import type {
   Message,
   Message,

+ 1 - 1
packages/app/src/context/local.tsx

@@ -1,5 +1,5 @@
 import { createSimpleContext } from "@opencode-ai/ui/context"
 import { createSimpleContext } from "@opencode-ai/ui/context"
-import { base64Encode } from "@opencode-ai/util/encode"
+import { base64Encode } from "@opencode-ai/shared/util/encode"
 import { useParams } from "@solidjs/router"
 import { useParams } from "@solidjs/router"
 import { batch, createEffect, createMemo } from "solid-js"
 import { batch, createEffect, createMemo } from "solid-js"
 import { createStore } from "solid-js/store"
 import { createStore } from "solid-js/store"

+ 2 - 2
packages/app/src/context/notification.tsx

@@ -7,8 +7,8 @@ import { useGlobalSync } from "./global-sync"
 import { usePlatform } from "@/context/platform"
 import { usePlatform } from "@/context/platform"
 import { useLanguage } from "@/context/language"
 import { useLanguage } from "@/context/language"
 import { useSettings } from "@/context/settings"
 import { useSettings } from "@/context/settings"
-import { Binary } from "@opencode-ai/util/binary"
-import { base64Encode } from "@opencode-ai/util/encode"
+import { Binary } from "@opencode-ai/shared/util/binary"
+import { base64Encode } from "@opencode-ai/shared/util/encode"
 import { decode64 } from "@/utils/base64"
 import { decode64 } from "@/utils/base64"
 import { EventSessionError } from "@opencode-ai/sdk/v2"
 import { EventSessionError } from "@opencode-ai/sdk/v2"
 import { Persist, persisted } from "@/utils/persist"
 import { Persist, persisted } from "@/utils/persist"

+ 1 - 1
packages/app/src/context/permission-auto-respond.test.ts

@@ -1,6 +1,6 @@
 import { describe, expect, test } from "bun:test"
 import { describe, expect, test } from "bun:test"
 import type { PermissionRequest, Session } from "@opencode-ai/sdk/v2/client"
 import type { PermissionRequest, Session } from "@opencode-ai/sdk/v2/client"
-import { base64Encode } from "@opencode-ai/util/encode"
+import { base64Encode } from "@opencode-ai/shared/util/encode"
 import { autoRespondsPermission, isDirectoryAutoAccepting } from "./permission-auto-respond"
 import { autoRespondsPermission, isDirectoryAutoAccepting } from "./permission-auto-respond"
 
 
 const session = (input: { id: string; parentID?: string }) =>
 const session = (input: { id: string; parentID?: string }) =>

+ 1 - 1
packages/app/src/context/permission-auto-respond.ts

@@ -1,4 +1,4 @@
-import { base64Encode } from "@opencode-ai/util/encode"
+import { base64Encode } from "@opencode-ai/shared/util/encode"
 
 
 export function acceptKey(sessionID: string, directory?: string) {
 export function acceptKey(sessionID: string, directory?: string) {
   if (!directory) return sessionID
   if (!directory) return sessionID

+ 1 - 1
packages/app/src/context/prompt.tsx

@@ -1,5 +1,5 @@
 import { createSimpleContext } from "@opencode-ai/ui/context"
 import { createSimpleContext } from "@opencode-ai/ui/context"
-import { checksum } from "@opencode-ai/util/encode"
+import { checksum } from "@opencode-ai/shared/util/encode"
 import { useParams } from "@solidjs/router"
 import { useParams } from "@solidjs/router"
 import { batch, createMemo, createRoot, getOwner, onCleanup } from "solid-js"
 import { batch, createMemo, createRoot, getOwner, onCleanup } from "solid-js"
 import { createStore, type SetStoreFunction } from "solid-js/store"
 import { createStore, type SetStoreFunction } from "solid-js/store"

+ 2 - 2
packages/app/src/context/sync.tsx

@@ -1,7 +1,7 @@
 import { batch, createMemo } from "solid-js"
 import { batch, createMemo } from "solid-js"
 import { createStore, produce, reconcile } from "solid-js/store"
 import { createStore, produce, reconcile } from "solid-js/store"
-import { Binary } from "@opencode-ai/util/binary"
-import { retry } from "@opencode-ai/util/retry"
+import { Binary } from "@opencode-ai/shared/util/binary"
+import { retry } from "@opencode-ai/shared/util/retry"
 import { createSimpleContext } from "@opencode-ai/ui/context"
 import { createSimpleContext } from "@opencode-ai/ui/context"
 import {
 import {
   clearSessionPrefetch,
   clearSessionPrefetch,

+ 1 - 1
packages/app/src/pages/directory-layout.tsx

@@ -1,6 +1,6 @@
 import { DataProvider } from "@opencode-ai/ui/context"
 import { DataProvider } from "@opencode-ai/ui/context"
 import { showToast } from "@opencode-ai/ui/toast"
 import { showToast } from "@opencode-ai/ui/toast"
-import { base64Encode } from "@opencode-ai/util/encode"
+import { base64Encode } from "@opencode-ai/shared/util/encode"
 import { useLocation, useNavigate, useParams } from "@solidjs/router"
 import { useLocation, useNavigate, useParams } from "@solidjs/router"
 import { createEffect, createMemo, type ParentProps, Show } from "solid-js"
 import { createEffect, createMemo, type ParentProps, Show } from "solid-js"
 import { useLanguage } from "@/context/language"
 import { useLanguage } from "@/context/language"

+ 1 - 1
packages/app/src/pages/home.tsx

@@ -3,7 +3,7 @@ import { Button } from "@opencode-ai/ui/button"
 import { Logo } from "@opencode-ai/ui/logo"
 import { Logo } from "@opencode-ai/ui/logo"
 import { useLayout } from "@/context/layout"
 import { useLayout } from "@/context/layout"
 import { useNavigate } from "@solidjs/router"
 import { useNavigate } from "@solidjs/router"
-import { base64Encode } from "@opencode-ai/util/encode"
+import { base64Encode } from "@opencode-ai/shared/util/encode"
 import { Icon } from "@opencode-ai/ui/icon"
 import { Icon } from "@opencode-ai/ui/icon"
 import { usePlatform } from "@/context/platform"
 import { usePlatform } from "@/context/platform"
 import { DateTime } from "luxon"
 import { DateTime } from "luxon"

+ 4 - 4
packages/app/src/pages/layout.tsx

@@ -17,7 +17,7 @@ import { useNavigate, useParams } from "@solidjs/router"
 import { useLayout, LocalProject } from "@/context/layout"
 import { useLayout, LocalProject } from "@/context/layout"
 import { useGlobalSync } from "@/context/global-sync"
 import { useGlobalSync } from "@/context/global-sync"
 import { Persist, persisted } from "@/utils/persist"
 import { Persist, persisted } from "@/utils/persist"
-import { base64Encode } from "@opencode-ai/util/encode"
+import { base64Encode } from "@opencode-ai/shared/util/encode"
 import { decode64 } from "@/utils/base64"
 import { decode64 } from "@/utils/base64"
 import { ResizeHandle } from "@opencode-ai/ui/resize-handle"
 import { ResizeHandle } from "@opencode-ai/ui/resize-handle"
 import { Button } from "@opencode-ai/ui/button"
 import { Button } from "@opencode-ai/ui/button"
@@ -25,7 +25,7 @@ import { IconButton } from "@opencode-ai/ui/icon-button"
 import { Tooltip } from "@opencode-ai/ui/tooltip"
 import { Tooltip } from "@opencode-ai/ui/tooltip"
 import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
 import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
 import { Dialog } from "@opencode-ai/ui/dialog"
 import { Dialog } from "@opencode-ai/ui/dialog"
-import { getFilename } from "@opencode-ai/util/path"
+import { getFilename } from "@opencode-ai/shared/util/path"
 import { Session, type Message } from "@opencode-ai/sdk/v2/client"
 import { Session, type Message } from "@opencode-ai/sdk/v2/client"
 import { usePlatform } from "@/context/platform"
 import { usePlatform } from "@/context/platform"
 import { useSettings } from "@/context/settings"
 import { useSettings } from "@/context/settings"
@@ -48,8 +48,8 @@ import {
 } from "@/context/global-sync/session-prefetch"
 } from "@/context/global-sync/session-prefetch"
 import { useNotification } from "@/context/notification"
 import { useNotification } from "@/context/notification"
 import { usePermission } from "@/context/permission"
 import { usePermission } from "@/context/permission"
-import { Binary } from "@opencode-ai/util/binary"
-import { retry } from "@opencode-ai/util/retry"
+import { Binary } from "@opencode-ai/shared/util/binary"
+import { retry } from "@opencode-ai/shared/util/retry"
 import { playSoundById } from "@/utils/sound"
 import { playSoundById } from "@/utils/sound"
 import { createAim } from "@/utils/aim"
 import { createAim } from "@/utils/aim"
 import { setNavigate } from "@/utils/notification-click"
 import { setNavigate } from "@/utils/notification-click"

+ 1 - 1
packages/app/src/pages/layout/helpers.ts

@@ -1,4 +1,4 @@
-import { getFilename } from "@opencode-ai/util/path"
+import { getFilename } from "@opencode-ai/shared/util/path"
 import { type Session } from "@opencode-ai/sdk/v2/client"
 import { type Session } from "@opencode-ai/sdk/v2/client"
 
 
 type SessionStore = {
 type SessionStore = {

+ 1 - 1
packages/app/src/pages/layout/sidebar-items.tsx

@@ -4,7 +4,7 @@ import { Icon } from "@opencode-ai/ui/icon"
 import { IconButton } from "@opencode-ai/ui/icon-button"
 import { IconButton } from "@opencode-ai/ui/icon-button"
 import { Spinner } from "@opencode-ai/ui/spinner"
 import { Spinner } from "@opencode-ai/ui/spinner"
 import { Tooltip } from "@opencode-ai/ui/tooltip"
 import { Tooltip } from "@opencode-ai/ui/tooltip"
-import { getFilename } from "@opencode-ai/util/path"
+import { getFilename } from "@opencode-ai/shared/util/path"
 import { A, useParams } from "@solidjs/router"
 import { A, useParams } from "@solidjs/router"
 import { type Accessor, createMemo, For, type JSX, Match, Show, Switch } from "solid-js"
 import { type Accessor, createMemo, For, type JSX, Match, Show, Switch } from "solid-js"
 import { useGlobalSync } from "@/context/global-sync"
 import { useGlobalSync } from "@/context/global-sync"

+ 1 - 1
packages/app/src/pages/layout/sidebar-project.tsx

@@ -1,6 +1,6 @@
 import { createMemo, For, Show, type Accessor, type JSX } from "solid-js"
 import { createMemo, For, Show, type Accessor, type JSX } from "solid-js"
 import { createStore } from "solid-js/store"
 import { createStore } from "solid-js/store"
-import { base64Encode } from "@opencode-ai/util/encode"
+import { base64Encode } from "@opencode-ai/shared/util/encode"
 import { Button } from "@opencode-ai/ui/button"
 import { Button } from "@opencode-ai/ui/button"
 import { ContextMenu } from "@opencode-ai/ui/context-menu"
 import { ContextMenu } from "@opencode-ai/ui/context-menu"
 import { HoverCard } from "@opencode-ai/ui/hover-card"
 import { HoverCard } from "@opencode-ai/ui/hover-card"

+ 2 - 2
packages/app/src/pages/layout/sidebar-workspace.tsx

@@ -3,8 +3,8 @@ import { createEffect, createMemo, For, Show, type Accessor, type JSX } from "so
 import { createStore } from "solid-js/store"
 import { createStore } from "solid-js/store"
 import { createSortable } from "@thisbeyond/solid-dnd"
 import { createSortable } from "@thisbeyond/solid-dnd"
 import { createMediaQuery } from "@solid-primitives/media"
 import { createMediaQuery } from "@solid-primitives/media"
-import { base64Encode } from "@opencode-ai/util/encode"
-import { getFilename } from "@opencode-ai/util/path"
+import { base64Encode } from "@opencode-ai/shared/util/encode"
+import { getFilename } from "@opencode-ai/shared/util/path"
 import { Button } from "@opencode-ai/ui/button"
 import { Button } from "@opencode-ai/ui/button"
 import { Collapsible } from "@opencode-ai/ui/collapsible"
 import { Collapsible } from "@opencode-ai/ui/collapsible"
 import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
 import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"

+ 1 - 1
packages/app/src/pages/session.tsx

@@ -27,7 +27,7 @@ import { createAutoScroll } from "@opencode-ai/ui/hooks"
 import { previewSelectedLines } from "@opencode-ai/ui/pierre/selection-bridge"
 import { previewSelectedLines } from "@opencode-ai/ui/pierre/selection-bridge"
 import { Button } from "@opencode-ai/ui/button"
 import { Button } from "@opencode-ai/ui/button"
 import { showToast } from "@opencode-ai/ui/toast"
 import { showToast } from "@opencode-ai/ui/toast"
-import { checksum } from "@opencode-ai/util/encode"
+import { checksum } from "@opencode-ai/shared/util/encode"
 import { useSearchParams } from "@solidjs/router"
 import { useSearchParams } from "@solidjs/router"
 import { NewSessionView, SessionHeader } from "@/components/session"
 import { NewSessionView, SessionHeader } from "@/components/session"
 import { useComments } from "@/context/comments"
 import { useComments } from "@/context/comments"

+ 1 - 1
packages/app/src/pages/session/file-tabs.tsx

@@ -6,7 +6,7 @@ import type { FileSearchHandle } from "@opencode-ai/ui/file"
 import { useFileComponent } from "@opencode-ai/ui/context/file"
 import { useFileComponent } from "@opencode-ai/ui/context/file"
 import { cloneSelectedLineRange, previewSelectedLines } from "@opencode-ai/ui/pierre/selection-bridge"
 import { cloneSelectedLineRange, previewSelectedLines } from "@opencode-ai/ui/pierre/selection-bridge"
 import { createLineCommentController } from "@opencode-ai/ui/line-comment-annotations"
 import { createLineCommentController } from "@opencode-ai/ui/line-comment-annotations"
-import { sampledChecksum } from "@opencode-ai/util/encode"
+import { sampledChecksum } from "@opencode-ai/shared/util/encode"
 import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
 import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
 import { IconButton } from "@opencode-ai/ui/icon-button"
 import { IconButton } from "@opencode-ai/ui/icon-button"
 import { Tabs } from "@opencode-ai/ui/tabs"
 import { Tabs } from "@opencode-ai/ui/tabs"

+ 3 - 3
packages/app/src/pages/session/message-timeline.tsx

@@ -15,8 +15,8 @@ import { ScrollView } from "@opencode-ai/ui/scroll-view"
 import { TextField } from "@opencode-ai/ui/text-field"
 import { TextField } from "@opencode-ai/ui/text-field"
 import type { AssistantMessage, Message as MessageType, Part, TextPart, UserMessage } from "@opencode-ai/sdk/v2"
 import type { AssistantMessage, Message as MessageType, Part, TextPart, UserMessage } from "@opencode-ai/sdk/v2"
 import { showToast } from "@opencode-ai/ui/toast"
 import { showToast } from "@opencode-ai/ui/toast"
-import { Binary } from "@opencode-ai/util/binary"
-import { getFilename } from "@opencode-ai/util/path"
+import { Binary } from "@opencode-ai/shared/util/binary"
+import { getFilename } from "@opencode-ai/shared/util/path"
 import { Popover as KobaltePopover } from "@kobalte/core/popover"
 import { Popover as KobaltePopover } from "@kobalte/core/popover"
 import { shouldMarkBoundaryGesture, normalizeWheelDelta } from "@/pages/session/message-gesture"
 import { shouldMarkBoundaryGesture, normalizeWheelDelta } from "@/pages/session/message-gesture"
 import { SessionContextUsage } from "@/components/session-context-usage"
 import { SessionContextUsage } from "@/components/session-context-usage"
@@ -791,7 +791,7 @@ export function MessageTimeline(props: {
                             data-slot="session-title-child"
                             data-slot="session-title-child"
                             value={title.draft}
                             value={title.draft}
                             disabled={titleMutation.isPending}
                             disabled={titleMutation.isPending}
-                            class="text-14-medium text-text-strong grow-1 min-w-0 rounded-[6px]"
+                            class="text-14-medium text-text-strong grow-1 min-w-0 rounded-[6px] pl-1 -ml-1"
                             style={{ "--inline-input-shadow": "var(--shadow-xs-border-select)" }}
                             style={{ "--inline-input-shadow": "var(--shadow-xs-border-select)" }}
                             onInput={(event) => setTitle("draft", event.currentTarget.value)}
                             onInput={(event) => setTitle("draft", event.currentTarget.value)}
                             onKeyDown={(event) => {
                             onKeyDown={(event) => {

+ 1 - 1
packages/app/src/pages/session/use-session-commands.tsx

@@ -12,7 +12,7 @@ import { useSDK } from "@/context/sdk"
 import { useSync } from "@/context/sync"
 import { useSync } from "@/context/sync"
 import { useTerminal } from "@/context/terminal"
 import { useTerminal } from "@/context/terminal"
 import { showToast } from "@opencode-ai/ui/toast"
 import { showToast } from "@opencode-ai/ui/toast"
-import { findLast } from "@opencode-ai/util/array"
+import { findLast } from "@opencode-ai/shared/util/array"
 import { createSessionTabs } from "@/pages/session/helpers"
 import { createSessionTabs } from "@/pages/session/helpers"
 import { extractPromptFromParts } from "@/utils/prompt"
 import { extractPromptFromParts } from "@/utils/prompt"
 import { UserMessage } from "@opencode-ai/sdk/v2"
 import { UserMessage } from "@opencode-ai/sdk/v2"

+ 1 - 1
packages/app/src/utils/base64.ts

@@ -1,4 +1,4 @@
-import { base64Decode } from "@opencode-ai/util/encode"
+import { base64Decode } from "@opencode-ai/shared/util/encode"
 
 
 export function decode64(value: string | undefined) {
 export function decode64(value: string | undefined) {
   if (value === undefined) return
   if (value === undefined) return

+ 1 - 1
packages/app/src/utils/persist.ts

@@ -1,6 +1,6 @@
 import { Platform, usePlatform } from "@/context/platform"
 import { Platform, usePlatform } from "@/context/platform"
 import { makePersisted, type AsyncStorage, type SyncStorage } from "@solid-primitives/storage"
 import { makePersisted, type AsyncStorage, type SyncStorage } from "@solid-primitives/storage"
-import { checksum } from "@opencode-ai/util/encode"
+import { checksum } from "@opencode-ai/shared/util/encode"
 import { createResource, type Accessor } from "solid-js"
 import { createResource, type Accessor } from "solid-js"
 import type { SetStoreFunction, Store } from "solid-js/store"
 import type { SetStoreFunction, Store } from "solid-js/store"
 
 

+ 1 - 1
packages/console/app/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@opencode-ai/console-app",
   "name": "@opencode-ai/console-app",
-  "version": "1.4.4",
+  "version": "1.4.6",
   "type": "module",
   "type": "module",
   "license": "MIT",
   "license": "MIT",
   "scripts": {
   "scripts": {

+ 6 - 6
packages/console/app/src/i18n/ar.ts

@@ -249,7 +249,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | نماذج برمجة منخفضة التكلفة للجميع",
   "go.title": "OpenCode Go | نماذج برمجة منخفضة التكلفة للجميع",
   "go.meta.description":
   "go.meta.description":
-    "يبدأ Go من $5 للشهر الأول، ثم $10/شهر، مع حدود طلب سخية لمدة 5 ساعات لـ GLM-5.1 وGLM-5 و Kimi K2.5 وMiMo-V2-Pro وMiMo-V2-Omni و MiniMax M2.5 وMiniMax M2.7.",
+    "يبدأ Go من $5 للشهر الأول، ثم $10/شهر، مع حدود طلب سخية لمدة 5 ساعات لـ GLM-5.1 وGLM-5 و Kimi K2.5 وMiMo-V2-Pro وMiMo-V2-Omni و Qwen3.5 Plus و Qwen3.6 Plus و MiniMax M2.5 وMiniMax M2.7.",
   "go.hero.title": "نماذج برمجة منخفضة التكلفة للجميع",
   "go.hero.title": "نماذج برمجة منخفضة التكلفة للجميع",
   "go.hero.body":
   "go.hero.body":
     "يجلب Go البرمجة الوكيلة للمبرمجين حول العالم. يوفر حدودًا سخية ووصولًا موثوقًا إلى أقوى النماذج مفتوحة المصدر، حتى تتمكن من البناء باستخدام وكلاء أقوياء دون القلق بشأن التكلفة أو التوفر.",
     "يجلب Go البرمجة الوكيلة للمبرمجين حول العالم. يوفر حدودًا سخية ووصولًا موثوقًا إلى أقوى النماذج مفتوحة المصدر، حتى تتمكن من البناء باستخدام وكلاء أقوياء دون القلق بشأن التكلفة أو التوفر.",
@@ -297,7 +297,8 @@ export const dict = {
   "go.problem.item1": "أسعار اشتراك منخفضة التكلفة",
   "go.problem.item1": "أسعار اشتراك منخفضة التكلفة",
   "go.problem.item2": "حدود سخية ووصول موثوق",
   "go.problem.item2": "حدود سخية ووصول موثوق",
   "go.problem.item3": "مصمم لأكبر عدد ممكن من المبرمجين",
   "go.problem.item3": "مصمم لأكبر عدد ممكن من المبرمجين",
-  "go.problem.item4": "يتضمن GLM-5.1 وGLM-5 وKimi K2.5 وMiMo-V2-Pro وMiMo-V2-Omni وMiniMax M2.5 وMiniMax M2.7",
+  "go.problem.item4":
+    "يتضمن GLM-5.1 وGLM-5 وKimi K2.5 وMiMo-V2-Pro وMiMo-V2-Omni وQwen3.5 Plus وQwen3.6 Plus وMiniMax M2.5 وMiniMax M2.7",
   "go.how.title": "كيف يعمل Go",
   "go.how.title": "كيف يعمل Go",
   "go.how.body": "يبدأ Go من $5 للشهر الأول، ثم $10/شهر. يمكنك استخدامه مع OpenCode أو أي وكيل.",
   "go.how.body": "يبدأ Go من $5 للشهر الأول، ثم $10/شهر. يمكنك استخدامه مع OpenCode أو أي وكيل.",
   "go.how.step1.title": "أنشئ حسابًا",
   "go.how.step1.title": "أنشئ حسابًا",
@@ -318,11 +319,10 @@ export const dict = {
   "go.faq.q1": "ما هو OpenCode Go؟",
   "go.faq.q1": "ما هو OpenCode Go؟",
   "go.faq.a1": "Go هو اشتراك منخفض التكلفة يمنحك وصولًا موثوقًا إلى نماذج مفتوحة المصدر قادرة على البرمجة الوكيلة.",
   "go.faq.a1": "Go هو اشتراك منخفض التكلفة يمنحك وصولًا موثوقًا إلى نماذج مفتوحة المصدر قادرة على البرمجة الوكيلة.",
   "go.faq.q2": "ما النماذج التي يتضمنها Go؟",
   "go.faq.q2": "ما النماذج التي يتضمنها Go؟",
-  "go.faq.a2":
-    "يتضمن Go نماذج GLM-5.1 وGLM-5 وKimi K2.5 وMiMo-V2-Pro وMiMo-V2-Omni وMiniMax M2.5 وMiniMax M2.7، مع حدود سخية ووصول موثوق.",
+  "go.faq.a2": "يتضمن Go النماذج المدرجة أدناه، مع حدود سخية وإتاحة موثوقة.",
   "go.faq.q3": "هل Go هو نفسه Zen؟",
   "go.faq.q3": "هل Go هو نفسه Zen؟",
   "go.faq.a3":
   "go.faq.a3":
-    "لا. Zen هو الدفع حسب الاستخدام، بينما يبدأ Go من $5 للشهر الأول، ثم $10/شهر، مع حدود سخية ووصول موثوق إلى نماذج المصدر المفتوح GLM-5.1 وGLM-5 و Kimi K2.5 وMiMo-V2-Pro وMiMo-V2-Omni و MiniMax M2.5 وMiniMax M2.7.",
+    "لا. Zen هو الدفع حسب الاستخدام، بينما يبدأ Go من $5 للشهر الأول، ثم $10/شهر، مع حدود سخية ووصول موثوق إلى نماذج المصدر المفتوح GLM-5.1 وGLM-5 و Kimi K2.5 وMiMo-V2-Pro وMiMo-V2-Omni و Qwen3.5 Plus و Qwen3.6 Plus و MiniMax M2.5 وMiniMax M2.7.",
   "go.faq.q4": "كم تكلفة Go؟",
   "go.faq.q4": "كم تكلفة Go؟",
   "go.faq.a4.p1.beforePricing": "تكلفة Go",
   "go.faq.a4.p1.beforePricing": "تكلفة Go",
   "go.faq.a4.p1.pricingLink": "$5 للشهر الأول",
   "go.faq.a4.p1.pricingLink": "$5 للشهر الأول",
@@ -345,7 +345,7 @@ export const dict = {
 
 
   "go.faq.q9": "ما الفرق بين النماذج المجانية وGo؟",
   "go.faq.q9": "ما الفرق بين النماذج المجانية وGo؟",
   "go.faq.a9":
   "go.faq.a9":
-    "تشمل النماذج المجانية Big Pickle بالإضافة إلى النماذج الترويجية المتاحة في ذلك الوقت، مع حصة 200 طلب/يوم. يتضمن Go نماذج GLM-5.1 وGLM-5 وKimi K2.5 وMiMo-V2-Pro وMiMo-V2-Omni وMiniMax M2.5 وMiniMax M2.7 مع حصص طلبات أعلى مطبقة عبر نوافذ متجددة (5 ساعات، أسبوعيًا، وشهريًا)، تعادل تقريبًا 12 دولارًا كل 5 ساعات، و30 دولارًا في الأسبوع، و60 دولارًا في الشهر (تختلف أعداد الطلبات الفعلية حسب النموذج والاستخدام).",
+    "تشمل النماذج المجانية Big Pickle بالإضافة إلى النماذج الترويجية المتاحة في ذلك الوقت، مع حصة 200 طلب/يوم. يتضمن Go نماذج GLM-5.1 وGLM-5 وKimi K2.5 وMiMo-V2-Pro وMiMo-V2-Omni وQwen3.5 Plus وQwen3.6 Plus وMiniMax M2.5 وMiniMax M2.7 مع حصص طلبات أعلى مطبقة عبر نوافذ متجددة (5 ساعات، أسبوعيًا، وشهريًا)، تعادل تقريبًا 12 دولارًا كل 5 ساعات، و30 دولارًا في الأسبوع، و60 دولارًا في الشهر (تختلف أعداد الطلبات الفعلية حسب النموذج والاستخدام).",
 
 
   "zen.api.error.rateLimitExceeded": "تم تجاوز حد الطلبات. يرجى المحاولة مرة أخرى لاحقًا.",
   "zen.api.error.rateLimitExceeded": "تم تجاوز حد الطلبات. يرجى المحاولة مرة أخرى لاحقًا.",
   "zen.api.error.modelNotSupported": "النموذج {{model}} غير مدعوم",
   "zen.api.error.modelNotSupported": "النموذج {{model}} غير مدعوم",

+ 6 - 6
packages/console/app/src/i18n/br.ts

@@ -253,7 +253,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | Modelos de codificação de baixo custo para todos",
   "go.title": "OpenCode Go | Modelos de codificação de baixo custo para todos",
   "go.meta.description":
   "go.meta.description":
-    "O Go começa em $5 no primeiro mês, depois $10/mês, com limites generosos de solicitação de 5 horas para GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 e MiniMax M2.7.",
+    "O Go começa em $5 no primeiro mês, depois $10/mês, com limites generosos de solicitação de 5 horas para GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 e MiniMax M2.7.",
   "go.hero.title": "Modelos de codificação de baixo custo para todos",
   "go.hero.title": "Modelos de codificação de baixo custo para todos",
   "go.hero.body":
   "go.hero.body":
     "O Go traz a codificação com agentes para programadores em todo o mundo. Oferecendo limites generosos e acesso confiável aos modelos de código aberto mais capazes, para que você possa construir com agentes poderosos sem se preocupar com custos ou disponibilidade.",
     "O Go traz a codificação com agentes para programadores em todo o mundo. Oferecendo limites generosos e acesso confiável aos modelos de código aberto mais capazes, para que você possa construir com agentes poderosos sem se preocupar com custos ou disponibilidade.",
@@ -302,7 +302,8 @@ export const dict = {
   "go.problem.item1": "Preço de assinatura de baixo custo",
   "go.problem.item1": "Preço de assinatura de baixo custo",
   "go.problem.item2": "Limites generosos e acesso confiável",
   "go.problem.item2": "Limites generosos e acesso confiável",
   "go.problem.item3": "Feito para o maior número possível de programadores",
   "go.problem.item3": "Feito para o maior número possível de programadores",
-  "go.problem.item4": "Inclui GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 e MiniMax M2.7",
+  "go.problem.item4":
+    "Inclui GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 e MiniMax M2.7",
   "go.how.title": "Como o Go funciona",
   "go.how.title": "Como o Go funciona",
   "go.how.body":
   "go.how.body":
     "O Go começa em $5 no primeiro mês, depois $10/mês. Você pode usá-lo com o OpenCode ou qualquer agente.",
     "O Go começa em $5 no primeiro mês, depois $10/mês. Você pode usá-lo com o OpenCode ou qualquer agente.",
@@ -325,11 +326,10 @@ export const dict = {
   "go.faq.a1":
   "go.faq.a1":
     "Go é uma assinatura de baixo custo que oferece acesso confiável a modelos de código aberto capazes para codificação com agentes.",
     "Go é uma assinatura de baixo custo que oferece acesso confiável a modelos de código aberto capazes para codificação com agentes.",
   "go.faq.q2": "Quais modelos o Go inclui?",
   "go.faq.q2": "Quais modelos o Go inclui?",
-  "go.faq.a2":
-    "Go inclui GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 e MiniMax M2.7, com limites generosos e acesso confiável.",
+  "go.faq.a2": "O Go inclui os modelos listados abaixo, com limites generosos e acesso confiável.",
   "go.faq.q3": "O Go é o mesmo que o Zen?",
   "go.faq.q3": "O Go é o mesmo que o Zen?",
   "go.faq.a3":
   "go.faq.a3":
-    "Não. Zen é pay-as-you-go, enquanto o Go começa em $5 no primeiro mês, depois $10/mês, com limites generosos e acesso confiável aos modelos open source GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 e MiniMax M2.7.",
+    "Não. Zen é pay-as-you-go, enquanto o Go começa em $5 no primeiro mês, depois $10/mês, com limites generosos e acesso confiável aos modelos open source GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 e MiniMax M2.7.",
   "go.faq.q4": "Quanto custa o Go?",
   "go.faq.q4": "Quanto custa o Go?",
   "go.faq.a4.p1.beforePricing": "O Go custa",
   "go.faq.a4.p1.beforePricing": "O Go custa",
   "go.faq.a4.p1.pricingLink": "$5 no primeiro mês",
   "go.faq.a4.p1.pricingLink": "$5 no primeiro mês",
@@ -353,7 +353,7 @@ export const dict = {
 
 
   "go.faq.q9": "Qual a diferença entre os modelos gratuitos e o Go?",
   "go.faq.q9": "Qual a diferença entre os modelos gratuitos e o Go?",
   "go.faq.a9":
   "go.faq.a9":
-    "Os modelos gratuitos incluem Big Pickle e modelos promocionais disponíveis no momento, com uma cota de 200 requisições/dia. O Go inclui GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 e MiniMax M2.7 com cotas de requisição mais altas aplicadas em janelas móveis (5 horas, semanal e mensal), aproximadamente equivalentes a $12 por 5 horas, $30 por semana e $60 por mês (as contagens reais de requisições variam de acordo com o modelo e o uso).",
+    "Os modelos gratuitos incluem Big Pickle e modelos promocionais disponíveis no momento, com uma cota de 200 requisições/dia. O Go inclui GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 e MiniMax M2.7 com cotas de requisição mais altas aplicadas em janelas móveis (5 horas, semanal e mensal), aproximadamente equivalentes a $12 por 5 horas, $30 por semana e $60 por mês (as contagens reais de requisições variam de acordo com o modelo e o uso).",
 
 
   "zen.api.error.rateLimitExceeded": "Limite de taxa excedido. Por favor, tente novamente mais tarde.",
   "zen.api.error.rateLimitExceeded": "Limite de taxa excedido. Por favor, tente novamente mais tarde.",
   "zen.api.error.modelNotSupported": "Modelo {{model}} não suportado",
   "zen.api.error.modelNotSupported": "Modelo {{model}} não suportado",

+ 6 - 6
packages/console/app/src/i18n/da.ts

@@ -251,7 +251,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | Kodningsmodeller til lav pris for alle",
   "go.title": "OpenCode Go | Kodningsmodeller til lav pris for alle",
   "go.meta.description":
   "go.meta.description":
-    "Go starter ved $5 for den første måned, derefter $10/måned, med generøse 5-timers anmodningsgrænser for GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 og MiniMax M2.7.",
+    "Go starter ved $5 for den første måned, derefter $10/måned, med generøse 5-timers anmodningsgrænser for GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 og MiniMax M2.7.",
   "go.hero.title": "Kodningsmodeller til lav pris for alle",
   "go.hero.title": "Kodningsmodeller til lav pris for alle",
   "go.hero.body":
   "go.hero.body":
     "Go bringer agentisk kodning til programmører over hele verden. Med generøse grænser og pålidelig adgang til de mest kapable open source-modeller, så du kan bygge med kraftfulde agenter uden at bekymre dig om omkostninger eller tilgængelighed.",
     "Go bringer agentisk kodning til programmører over hele verden. Med generøse grænser og pålidelig adgang til de mest kapable open source-modeller, så du kan bygge med kraftfulde agenter uden at bekymre dig om omkostninger eller tilgængelighed.",
@@ -299,7 +299,8 @@ export const dict = {
   "go.problem.item1": "Lavpris abonnementspriser",
   "go.problem.item1": "Lavpris abonnementspriser",
   "go.problem.item2": "Generøse grænser og pålidelig adgang",
   "go.problem.item2": "Generøse grænser og pålidelig adgang",
   "go.problem.item3": "Bygget til så mange programmører som muligt",
   "go.problem.item3": "Bygget til så mange programmører som muligt",
-  "go.problem.item4": "Inkluderer GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 og MiniMax M2.7",
+  "go.problem.item4":
+    "Inkluderer GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 og MiniMax M2.7",
   "go.how.title": "Hvordan Go virker",
   "go.how.title": "Hvordan Go virker",
   "go.how.body":
   "go.how.body":
     "Go starter ved $5 for den første måned, derefter $10/måned. Du kan bruge det med OpenCode eller enhver agent.",
     "Go starter ved $5 for den første måned, derefter $10/måned. Du kan bruge det med OpenCode eller enhver agent.",
@@ -322,11 +323,10 @@ export const dict = {
   "go.faq.a1":
   "go.faq.a1":
     "Go er et lavprisabonnement, der giver dig pålidelig adgang til kapable open source-modeller til agentisk kodning.",
     "Go er et lavprisabonnement, der giver dig pålidelig adgang til kapable open source-modeller til agentisk kodning.",
   "go.faq.q2": "Hvilke modeller inkluderer Go?",
   "go.faq.q2": "Hvilke modeller inkluderer Go?",
-  "go.faq.a2":
-    "Go inkluderer GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 og MiniMax M2.7, med generøse grænser og pålidelig adgang.",
+  "go.faq.a2": "Go inkluderer modellerne nedenfor med generøse grænser og pålidelig adgang.",
   "go.faq.q3": "Er Go det samme som Zen?",
   "go.faq.q3": "Er Go det samme som Zen?",
   "go.faq.a3":
   "go.faq.a3":
-    "Nej. Zen er pay-as-you-go, mens Go starter ved $5 for den første måned, derefter $10/måned, med generøse grænser og pålidelig adgang til open source-modellerne GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 og MiniMax M2.7.",
+    "Nej. Zen er pay-as-you-go, mens Go starter ved $5 for den første måned, derefter $10/måned, med generøse grænser og pålidelig adgang til open source-modellerne GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 og MiniMax M2.7.",
   "go.faq.q4": "Hvad koster Go?",
   "go.faq.q4": "Hvad koster Go?",
   "go.faq.a4.p1.beforePricing": "Go koster",
   "go.faq.a4.p1.beforePricing": "Go koster",
   "go.faq.a4.p1.pricingLink": "$5 første måned",
   "go.faq.a4.p1.pricingLink": "$5 første måned",
@@ -349,7 +349,7 @@ export const dict = {
 
 
   "go.faq.q9": "Hvad er forskellen på gratis modeller og Go?",
   "go.faq.q9": "Hvad er forskellen på gratis modeller og Go?",
   "go.faq.a9":
   "go.faq.a9":
-    "Gratis modeller inkluderer Big Pickle plus salgsfremmende modeller tilgængelige på det tidspunkt, med en kvote på 200 forespørgsler/dag. Go inkluderer GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 og MiniMax M2.7 med højere anmodningskvoter håndhævet over rullende vinduer (5-timers, ugentlig og månedlig), nogenlunde svarende til $12 pr. 5 timer, $30 pr. uge og $60 pr. måned (faktiske anmodningstal varierer efter model og brug).",
+    "Gratis modeller inkluderer Big Pickle plus salgsfremmende modeller tilgængelige på det tidspunkt, med en kvote på 200 forespørgsler/dag. Go inkluderer GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 og MiniMax M2.7 med højere anmodningskvoter håndhævet over rullende vinduer (5-timers, ugentlig og månedlig), nogenlunde svarende til $12 pr. 5 timer, $30 pr. uge og $60 pr. måned (faktiske anmodningstal varierer efter model og brug).",
 
 
   "zen.api.error.rateLimitExceeded": "Hastighedsgrænse overskredet. Prøv venligst igen senere.",
   "zen.api.error.rateLimitExceeded": "Hastighedsgrænse overskredet. Prøv venligst igen senere.",
   "zen.api.error.modelNotSupported": "Model {{model}} understøttes ikke",
   "zen.api.error.modelNotSupported": "Model {{model}} understøttes ikke",

+ 6 - 6
packages/console/app/src/i18n/de.ts

@@ -253,7 +253,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | Kostengünstige Coding-Modelle für alle",
   "go.title": "OpenCode Go | Kostengünstige Coding-Modelle für alle",
   "go.meta.description":
   "go.meta.description":
-    "Go beginnt bei $5 für den ersten Monat, danach $10/Monat, mit großzügigen 5-Stunden-Anfragelimits für GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 und MiniMax M2.7.",
+    "Go beginnt bei $5 für den ersten Monat, danach $10/Monat, mit großzügigen 5-Stunden-Anfragelimits für GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 und MiniMax M2.7.",
   "go.hero.title": "Kostengünstige Coding-Modelle für alle",
   "go.hero.title": "Kostengünstige Coding-Modelle für alle",
   "go.hero.body":
   "go.hero.body":
     "Go bringt Agentic Coding zu Programmierern auf der ganzen Welt. Mit großzügigen Limits und zuverlässigem Zugang zu den leistungsfähigsten Open-Source-Modellen, damit du mit leistungsstarken Agenten entwickeln kannst, ohne dir Gedanken über Kosten oder Verfügbarkeit zu machen.",
     "Go bringt Agentic Coding zu Programmierern auf der ganzen Welt. Mit großzügigen Limits und zuverlässigem Zugang zu den leistungsfähigsten Open-Source-Modellen, damit du mit leistungsstarken Agenten entwickeln kannst, ohne dir Gedanken über Kosten oder Verfügbarkeit zu machen.",
@@ -301,7 +301,8 @@ export const dict = {
   "go.problem.item1": "Kostengünstiges Abonnement",
   "go.problem.item1": "Kostengünstiges Abonnement",
   "go.problem.item2": "Großzügige Limits und zuverlässiger Zugang",
   "go.problem.item2": "Großzügige Limits und zuverlässiger Zugang",
   "go.problem.item3": "Für so viele Programmierer wie möglich gebaut",
   "go.problem.item3": "Für so viele Programmierer wie möglich gebaut",
-  "go.problem.item4": "Beinhaltet GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 und MiniMax M2.7",
+  "go.problem.item4":
+    "Beinhaltet GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 und MiniMax M2.7",
   "go.how.title": "Wie Go funktioniert",
   "go.how.title": "Wie Go funktioniert",
   "go.how.body":
   "go.how.body":
     "Go beginnt bei $5 für den ersten Monat, danach $10/Monat. Du kannst es mit OpenCode oder jedem Agenten nutzen.",
     "Go beginnt bei $5 für den ersten Monat, danach $10/Monat. Du kannst es mit OpenCode oder jedem Agenten nutzen.",
@@ -324,11 +325,10 @@ export const dict = {
   "go.faq.a1":
   "go.faq.a1":
     "Go ist ein kostengünstiges Abonnement, das dir zuverlässigen Zugang zu leistungsfähigen Open-Source-Modellen für Agentic Coding bietet.",
     "Go ist ein kostengünstiges Abonnement, das dir zuverlässigen Zugang zu leistungsfähigen Open-Source-Modellen für Agentic Coding bietet.",
   "go.faq.q2": "Welche Modelle beinhaltet Go?",
   "go.faq.q2": "Welche Modelle beinhaltet Go?",
-  "go.faq.a2":
-    "Go beinhaltet GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 und MiniMax M2.7, mit großzügigen Limits und zuverlässigem Zugang.",
+  "go.faq.a2": "Go umfasst die unten aufgeführten Modelle mit großzügigen Limits und zuverlässigem Zugriff.",
   "go.faq.q3": "Ist Go dasselbe wie Zen?",
   "go.faq.q3": "Ist Go dasselbe wie Zen?",
   "go.faq.a3":
   "go.faq.a3":
-    "Nein. Zen ist Pay-as-you-go, während Go bei $5 für den ersten Monat beginnt, danach $10/Monat, mit großzügigen Limits und zuverlässigem Zugang zu den Open-Source-Modellen GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 und MiniMax M2.7.",
+    "Nein. Zen ist Pay-as-you-go, während Go bei $5 für den ersten Monat beginnt, danach $10/Monat, mit großzügigen Limits und zuverlässigem Zugang zu den Open-Source-Modellen GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 und MiniMax M2.7.",
   "go.faq.q4": "Wie viel kostet Go?",
   "go.faq.q4": "Wie viel kostet Go?",
   "go.faq.a4.p1.beforePricing": "Go kostet",
   "go.faq.a4.p1.beforePricing": "Go kostet",
   "go.faq.a4.p1.pricingLink": "$5 im ersten Monat",
   "go.faq.a4.p1.pricingLink": "$5 im ersten Monat",
@@ -352,7 +352,7 @@ export const dict = {
 
 
   "go.faq.q9": "Was ist der Unterschied zwischen kostenlosen Modellen und Go?",
   "go.faq.q9": "Was ist der Unterschied zwischen kostenlosen Modellen und Go?",
   "go.faq.a9":
   "go.faq.a9":
-    "Kostenlose Modelle beinhalten Big Pickle sowie Werbemodelle, die zum jeweiligen Zeitpunkt verfügbar sind, mit einem Kontingent von 200 Anfragen/Tag. Go beinhaltet GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 und MiniMax M2.7 mit höheren Anfragekontingenten, die über rollierende Zeitfenster (5 Stunden, wöchentlich und monatlich) durchgesetzt werden, grob äquivalent zu $12 pro 5 Stunden, $30 pro Woche und $60 pro Monat (tatsächliche Anfragezahlen variieren je nach Modell und Nutzung).",
+    "Kostenlose Modelle beinhalten Big Pickle sowie Werbemodelle, die zum jeweiligen Zeitpunkt verfügbar sind, mit einem Kontingent von 200 Anfragen/Tag. Go beinhaltet GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 und MiniMax M2.7 mit höheren Anfragekontingenten, die über rollierende Zeitfenster (5 Stunden, wöchentlich und monatlich) durchgesetzt werden, grob äquivalent zu $12 pro 5 Stunden, $30 pro Woche und $60 pro Monat (tatsächliche Anfragezahlen variieren je nach Modell und Nutzung).",
 
 
   "zen.api.error.rateLimitExceeded": "Ratenlimit überschritten. Bitte versuche es später erneut.",
   "zen.api.error.rateLimitExceeded": "Ratenlimit überschritten. Bitte versuche es später erneut.",
   "zen.api.error.modelNotSupported": "Modell {{model}} wird nicht unterstützt",
   "zen.api.error.modelNotSupported": "Modell {{model}} wird nicht unterstützt",

+ 6 - 6
packages/console/app/src/i18n/en.ts

@@ -248,7 +248,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | Low cost coding models for everyone",
   "go.title": "OpenCode Go | Low cost coding models for everyone",
   "go.meta.description":
   "go.meta.description":
-    "Go starts at $5 for your first month, then $10/month, with generous 5-hour request limits for GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5, and MiniMax M2.7.",
+    "Go starts at $5 for your first month, then $10/month, with generous 5-hour request limits for GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5, and MiniMax M2.7.",
   "go.hero.title": "Low cost coding models for everyone",
   "go.hero.title": "Low cost coding models for everyone",
   "go.hero.body":
   "go.hero.body":
     "Go brings agentic coding to programmers around the world. Offering generous limits and reliable access to the most capable open-source models, so you can build with powerful agents without worrying about cost or availability.",
     "Go brings agentic coding to programmers around the world. Offering generous limits and reliable access to the most capable open-source models, so you can build with powerful agents without worrying about cost or availability.",
@@ -295,7 +295,8 @@ export const dict = {
   "go.problem.item1": "Low cost subscription pricing",
   "go.problem.item1": "Low cost subscription pricing",
   "go.problem.item2": "Generous limits and reliable access",
   "go.problem.item2": "Generous limits and reliable access",
   "go.problem.item3": "Built for as many programmers as possible",
   "go.problem.item3": "Built for as many programmers as possible",
-  "go.problem.item4": "Includes GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5, and MiniMax M2.7",
+  "go.problem.item4":
+    "Includes GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5, and MiniMax M2.7",
   "go.how.title": "How Go works",
   "go.how.title": "How Go works",
   "go.how.body": "Go starts at $5 for your first month, then $10/month. You can use it with OpenCode or any agent.",
   "go.how.body": "Go starts at $5 for your first month, then $10/month. You can use it with OpenCode or any agent.",
   "go.how.step1.title": "Create an account",
   "go.how.step1.title": "Create an account",
@@ -317,11 +318,10 @@ export const dict = {
   "go.faq.a1":
   "go.faq.a1":
     "Go is a low-cost subscription that gives you reliable access to capable open-source models for agentic coding.",
     "Go is a low-cost subscription that gives you reliable access to capable open-source models for agentic coding.",
   "go.faq.q2": "What models does Go include?",
   "go.faq.q2": "What models does Go include?",
-  "go.faq.a2":
-    "Go includes GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5, and MiniMax M2.7, with generous limits and reliable access.",
+  "go.faq.a2": "Go includes the models listed below, with generous limits and reliable access.",
   "go.faq.q3": "Is Go the same as Zen?",
   "go.faq.q3": "Is Go the same as Zen?",
   "go.faq.a3":
   "go.faq.a3":
-    "No. Zen is pay-as-you-go, while Go starts at $5 for your first month, then $10/month, with generous limits and reliable access to open-source models GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5, and MiniMax M2.7.",
+    "No. Zen is pay-as-you-go, while Go starts at $5 for your first month, then $10/month, with generous limits and reliable access to open-source models GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5, and MiniMax M2.7.",
   "go.faq.q4": "How much does Go cost?",
   "go.faq.q4": "How much does Go cost?",
   "go.faq.a4.p1.beforePricing": "Go costs",
   "go.faq.a4.p1.beforePricing": "Go costs",
   "go.faq.a4.p1.pricingLink": "$5 first month",
   "go.faq.a4.p1.pricingLink": "$5 first month",
@@ -345,7 +345,7 @@ export const dict = {
 
 
   "go.faq.q9": "What is the difference between free models and Go?",
   "go.faq.q9": "What is the difference between free models and Go?",
   "go.faq.a9":
   "go.faq.a9":
-    "Free models include Big Pickle plus promotional models available at the time, with a quota of 200 requests/day. Go includes GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5, and MiniMax M2.7 with higher request quotas enforced across rolling windows (5-hour, weekly, and monthly), roughly equivalent to $12 per 5 hours, $30 per week, and $60 per month (actual request counts vary by model and usage).",
+    "Free models include Big Pickle plus promotional models available at the time, with a quota of 200 requests/day. Go includes GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5, and MiniMax M2.7 with higher request quotas enforced across rolling windows (5-hour, weekly, and monthly), roughly equivalent to $12 per 5 hours, $30 per week, and $60 per month (actual request counts vary by model and usage).",
 
 
   "zen.api.error.rateLimitExceeded": "Rate limit exceeded. Please try again later.",
   "zen.api.error.rateLimitExceeded": "Rate limit exceeded. Please try again later.",
   "zen.api.error.modelNotSupported": "Model {{model}} not supported",
   "zen.api.error.modelNotSupported": "Model {{model}} not supported",

+ 6 - 6
packages/console/app/src/i18n/es.ts

@@ -254,7 +254,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | Modelos de programación de bajo coste para todos",
   "go.title": "OpenCode Go | Modelos de programación de bajo coste para todos",
   "go.meta.description":
   "go.meta.description":
-    "Go comienza en $5 el primer mes, luego 10 $/mes, con generosos límites de solicitudes de 5 horas para GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 y MiniMax M2.7.",
+    "Go comienza en $5 el primer mes, luego 10 $/mes, con generosos límites de solicitudes de 5 horas para GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 y MiniMax M2.7.",
   "go.hero.title": "Modelos de programación de bajo coste para todos",
   "go.hero.title": "Modelos de programación de bajo coste para todos",
   "go.hero.body":
   "go.hero.body":
     "Go lleva la programación agéntica a programadores de todo el mundo. Ofrece límites generosos y acceso fiable a los modelos de código abierto más capaces, para que puedas crear con agentes potentes sin preocuparte por el coste o la disponibilidad.",
     "Go lleva la programación agéntica a programadores de todo el mundo. Ofrece límites generosos y acceso fiable a los modelos de código abierto más capaces, para que puedas crear con agentes potentes sin preocuparte por el coste o la disponibilidad.",
@@ -303,7 +303,8 @@ export const dict = {
   "go.problem.item1": "Precios de suscripción de bajo coste",
   "go.problem.item1": "Precios de suscripción de bajo coste",
   "go.problem.item2": "Límites generosos y acceso fiable",
   "go.problem.item2": "Límites generosos y acceso fiable",
   "go.problem.item3": "Creado para tantos programadores como sea posible",
   "go.problem.item3": "Creado para tantos programadores como sea posible",
-  "go.problem.item4": "Incluye GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 y MiniMax M2.7",
+  "go.problem.item4":
+    "Incluye GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 y MiniMax M2.7",
   "go.how.title": "Cómo funciona Go",
   "go.how.title": "Cómo funciona Go",
   "go.how.body": "Go comienza en $5 el primer mes, luego 10 $/mes. Puedes usarlo con OpenCode o cualquier agente.",
   "go.how.body": "Go comienza en $5 el primer mes, luego 10 $/mes. Puedes usarlo con OpenCode o cualquier agente.",
   "go.how.step1.title": "Crear una cuenta",
   "go.how.step1.title": "Crear una cuenta",
@@ -325,11 +326,10 @@ export const dict = {
   "go.faq.a1":
   "go.faq.a1":
     "Go es una suscripción de bajo coste que te da acceso fiable a modelos de código abierto capaces para programación agéntica.",
     "Go es una suscripción de bajo coste que te da acceso fiable a modelos de código abierto capaces para programación agéntica.",
   "go.faq.q2": "¿Qué modelos incluye Go?",
   "go.faq.q2": "¿Qué modelos incluye Go?",
-  "go.faq.a2":
-    "Go incluye GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 y MiniMax M2.7, con límites generosos y acceso fiable.",
+  "go.faq.a2": "Go incluye los modelos que se indican abajo, con límites generosos y acceso confiable.",
   "go.faq.q3": "¿Es Go lo mismo que Zen?",
   "go.faq.q3": "¿Es Go lo mismo que Zen?",
   "go.faq.a3":
   "go.faq.a3":
-    "No. Zen es pago por uso, mientras que Go comienza en $5 el primer mes, luego 10 $/mes, con límites generosos y acceso fiable a los modelos de código abierto GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 y MiniMax M2.7.",
+    "No. Zen es pago por uso, mientras que Go comienza en $5 el primer mes, luego 10 $/mes, con límites generosos y acceso fiable a los modelos de código abierto GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 y MiniMax M2.7.",
   "go.faq.q4": "¿Cuánto cuesta Go?",
   "go.faq.q4": "¿Cuánto cuesta Go?",
   "go.faq.a4.p1.beforePricing": "Go cuesta",
   "go.faq.a4.p1.beforePricing": "Go cuesta",
   "go.faq.a4.p1.pricingLink": "$5 el primer mes",
   "go.faq.a4.p1.pricingLink": "$5 el primer mes",
@@ -353,7 +353,7 @@ export const dict = {
 
 
   "go.faq.q9": "¿Cuál es la diferencia entre los modelos gratuitos y Go?",
   "go.faq.q9": "¿Cuál es la diferencia entre los modelos gratuitos y Go?",
   "go.faq.a9":
   "go.faq.a9":
-    "Los modelos gratuitos incluyen Big Pickle más modelos promocionales disponibles en el momento, con una cuota de 200 solicitudes/día. Go incluye GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 y MiniMax M2.7 con cuotas de solicitud más altas aplicadas a través de ventanas móviles (5 horas, semanal y mensual), aproximadamente equivalente a 12 $ por 5 horas, 30 $ por semana y 60 $ por mes (los recuentos reales de solicitudes varían según el modelo y el uso).",
+    "Los modelos gratuitos incluyen Big Pickle más modelos promocionales disponibles en el momento, con una cuota de 200 solicitudes/día. Go incluye GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 y MiniMax M2.7 con cuotas de solicitud más altas aplicadas a través de ventanas móviles (5 horas, semanal y mensual), aproximadamente equivalente a 12 $ por 5 horas, 30 $ por semana y 60 $ por mes (los recuentos reales de solicitudes varían según el modelo y el uso).",
 
 
   "zen.api.error.rateLimitExceeded": "Límite de tasa excedido. Por favor, inténtalo de nuevo más tarde.",
   "zen.api.error.rateLimitExceeded": "Límite de tasa excedido. Por favor, inténtalo de nuevo más tarde.",
   "zen.api.error.modelNotSupported": "Modelo {{model}} no soportado",
   "zen.api.error.modelNotSupported": "Modelo {{model}} no soportado",

+ 6 - 6
packages/console/app/src/i18n/fr.ts

@@ -255,7 +255,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | Modèles de code à faible coût pour tous",
   "go.title": "OpenCode Go | Modèles de code à faible coût pour tous",
   "go.meta.description":
   "go.meta.description":
-    "Go commence à $5 pour le premier mois, puis 10 $/mois, avec des limites de requêtes généreuses sur 5 heures pour GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 et MiniMax M2.7.",
+    "Go commence à $5 pour le premier mois, puis 10 $/mois, avec des limites de requêtes généreuses sur 5 heures pour GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 et MiniMax M2.7.",
   "go.hero.title": "Modèles de code à faible coût pour tous",
   "go.hero.title": "Modèles de code à faible coût pour tous",
   "go.hero.body":
   "go.hero.body":
     "Go apporte le codage agentique aux programmeurs du monde entier. Offrant des limites généreuses et un accès fiable aux modèles open source les plus capables, pour que vous puissiez construire avec des agents puissants sans vous soucier du coût ou de la disponibilité.",
     "Go apporte le codage agentique aux programmeurs du monde entier. Offrant des limites généreuses et un accès fiable aux modèles open source les plus capables, pour que vous puissiez construire avec des agents puissants sans vous soucier du coût ou de la disponibilité.",
@@ -303,7 +303,8 @@ export const dict = {
   "go.problem.item1": "Prix d'abonnement bas",
   "go.problem.item1": "Prix d'abonnement bas",
   "go.problem.item2": "Limites généreuses et accès fiable",
   "go.problem.item2": "Limites généreuses et accès fiable",
   "go.problem.item3": "Conçu pour autant de programmeurs que possible",
   "go.problem.item3": "Conçu pour autant de programmeurs que possible",
-  "go.problem.item4": "Inclut GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 et MiniMax M2.7",
+  "go.problem.item4":
+    "Inclut GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 et MiniMax M2.7",
   "go.how.title": "Comment fonctionne Go",
   "go.how.title": "Comment fonctionne Go",
   "go.how.body":
   "go.how.body":
     "Go commence à $5 pour le premier mois, puis 10 $/mois. Vous pouvez l'utiliser avec OpenCode ou n'importe quel agent.",
     "Go commence à $5 pour le premier mois, puis 10 $/mois. Vous pouvez l'utiliser avec OpenCode ou n'importe quel agent.",
@@ -326,11 +327,10 @@ export const dict = {
   "go.faq.a1":
   "go.faq.a1":
     "Go est un abonnement à faible coût qui vous donne un accès fiable à des modèles open source performants pour le codage agentique.",
     "Go est un abonnement à faible coût qui vous donne un accès fiable à des modèles open source performants pour le codage agentique.",
   "go.faq.q2": "Quels modèles Go inclut-il ?",
   "go.faq.q2": "Quels modèles Go inclut-il ?",
-  "go.faq.a2":
-    "Go inclut GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 et MiniMax M2.7, avec des limites généreuses et un accès fiable.",
+  "go.faq.a2": "Go inclut les modèles ci-dessous, avec des limites généreuses et un accès fiable.",
   "go.faq.q3": "Est-ce que Go est la même chose que Zen ?",
   "go.faq.q3": "Est-ce que Go est la même chose que Zen ?",
   "go.faq.a3":
   "go.faq.a3":
-    "Non. Zen est un paiement à l'utilisation, tandis que Go commence à $5 pour le premier mois, puis 10 $/mois, avec des limites généreuses et un accès fiable aux modèles open source GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 et MiniMax M2.7.",
+    "Non. Zen est un paiement à l'utilisation, tandis que Go commence à $5 pour le premier mois, puis 10 $/mois, avec des limites généreuses et un accès fiable aux modèles open source GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 et MiniMax M2.7.",
   "go.faq.q4": "Combien coûte Go ?",
   "go.faq.q4": "Combien coûte Go ?",
   "go.faq.a4.p1.beforePricing": "Go coûte",
   "go.faq.a4.p1.beforePricing": "Go coûte",
   "go.faq.a4.p1.pricingLink": "$5 le premier mois",
   "go.faq.a4.p1.pricingLink": "$5 le premier mois",
@@ -353,7 +353,7 @@ export const dict = {
     "Oui, vous pouvez utiliser Go avec n'importe quel agent. Suivez les instructions de configuration dans votre agent de code préféré.",
     "Oui, vous pouvez utiliser Go avec n'importe quel agent. Suivez les instructions de configuration dans votre agent de code préféré.",
   "go.faq.q9": "Quelle est la différence entre les modèles gratuits et Go ?",
   "go.faq.q9": "Quelle est la différence entre les modèles gratuits et Go ?",
   "go.faq.a9":
   "go.faq.a9":
-    "Les modèles gratuits incluent Big Pickle ainsi que des modèles promotionnels disponibles à ce moment-là, avec un quota de 200 requêtes/jour. Go inclut GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 et MiniMax M2.7 avec des quotas de requêtes plus élevés appliqués sur des fenêtres glissantes (5 heures, hebdomadaire et mensuelle), à peu près équivalent à 12 $ par 5 heures, 30 $ par semaine et 60 $ par mois (le nombre réel de requêtes varie selon le modèle et l'utilisation).",
+    "Les modèles gratuits incluent Big Pickle ainsi que des modèles promotionnels disponibles à ce moment-là, avec un quota de 200 requêtes/jour. Go inclut GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 et MiniMax M2.7 avec des quotas de requêtes plus élevés appliqués sur des fenêtres glissantes (5 heures, hebdomadaire et mensuelle), à peu près équivalent à 12 $ par 5 heures, 30 $ par semaine et 60 $ par mois (le nombre réel de requêtes varie selon le modèle et l'utilisation).",
 
 
   "zen.api.error.rateLimitExceeded": "Limite de débit dépassée. Veuillez réessayer plus tard.",
   "zen.api.error.rateLimitExceeded": "Limite de débit dépassée. Veuillez réessayer plus tard.",
   "zen.api.error.modelNotSupported": "Modèle {{model}} non pris en charge",
   "zen.api.error.modelNotSupported": "Modèle {{model}} non pris en charge",

+ 6 - 6
packages/console/app/src/i18n/it.ts

@@ -251,7 +251,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | Modelli di coding a basso costo per tutti",
   "go.title": "OpenCode Go | Modelli di coding a basso costo per tutti",
   "go.meta.description":
   "go.meta.description":
-    "Go inizia a $5 per il primo mese, poi $10/mese, con generosi limiti di richiesta di 5 ore per GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 e MiniMax M2.7.",
+    "Go inizia a $5 per il primo mese, poi $10/mese, con generosi limiti di richiesta di 5 ore per GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 e MiniMax M2.7.",
   "go.hero.title": "Modelli di coding a basso costo per tutti",
   "go.hero.title": "Modelli di coding a basso costo per tutti",
   "go.hero.body":
   "go.hero.body":
     "Go porta il coding agentico ai programmatori di tutto il mondo. Offrendo limiti generosi e un accesso affidabile ai modelli open source più capaci, in modo da poter costruire con agenti potenti senza preoccuparsi dei costi o della disponibilità.",
     "Go porta il coding agentico ai programmatori di tutto il mondo. Offrendo limiti generosi e un accesso affidabile ai modelli open source più capaci, in modo da poter costruire con agenti potenti senza preoccuparsi dei costi o della disponibilità.",
@@ -299,7 +299,8 @@ export const dict = {
   "go.problem.item1": "Prezzo di abbonamento a basso costo",
   "go.problem.item1": "Prezzo di abbonamento a basso costo",
   "go.problem.item2": "Limiti generosi e accesso affidabile",
   "go.problem.item2": "Limiti generosi e accesso affidabile",
   "go.problem.item3": "Costruito per il maggior numero possibile di programmatori",
   "go.problem.item3": "Costruito per il maggior numero possibile di programmatori",
-  "go.problem.item4": "Include GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 e MiniMax M2.7",
+  "go.problem.item4":
+    "Include GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 e MiniMax M2.7",
   "go.how.title": "Come funziona Go",
   "go.how.title": "Come funziona Go",
   "go.how.body": "Go inizia a $5 per il primo mese, poi $10/mese. Puoi usarlo con OpenCode o qualsiasi agente.",
   "go.how.body": "Go inizia a $5 per il primo mese, poi $10/mese. Puoi usarlo con OpenCode o qualsiasi agente.",
   "go.how.step1.title": "Crea un account",
   "go.how.step1.title": "Crea un account",
@@ -321,11 +322,10 @@ export const dict = {
   "go.faq.a1":
   "go.faq.a1":
     "Go è un abbonamento a basso costo che ti dà un accesso affidabile a modelli open source capaci per il coding agentico.",
     "Go è un abbonamento a basso costo che ti dà un accesso affidabile a modelli open source capaci per il coding agentico.",
   "go.faq.q2": "Quali modelli include Go?",
   "go.faq.q2": "Quali modelli include Go?",
-  "go.faq.a2":
-    "Go include GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 e MiniMax M2.7, con limiti generosi e accesso affidabile.",
+  "go.faq.a2": "Go include i modelli elencati di seguito, con limiti generosi e accesso affidabile.",
   "go.faq.q3": "Go è lo stesso di Zen?",
   "go.faq.q3": "Go è lo stesso di Zen?",
   "go.faq.a3":
   "go.faq.a3":
-    "No. Zen è a consumo, mentre Go inizia a $5 per il primo mese, poi $10/mese, con limiti generosi e accesso affidabile ai modelli open source GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 e MiniMax M2.7.",
+    "No. Zen è a consumo, mentre Go inizia a $5 per il primo mese, poi $10/mese, con limiti generosi e accesso affidabile ai modelli open source GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 e MiniMax M2.7.",
   "go.faq.q4": "Quanto costa Go?",
   "go.faq.q4": "Quanto costa Go?",
   "go.faq.a4.p1.beforePricing": "Go costa",
   "go.faq.a4.p1.beforePricing": "Go costa",
   "go.faq.a4.p1.pricingLink": "$5 il primo mese",
   "go.faq.a4.p1.pricingLink": "$5 il primo mese",
@@ -349,7 +349,7 @@ export const dict = {
 
 
   "go.faq.q9": "Qual è la differenza tra i modelli gratuiti e Go?",
   "go.faq.q9": "Qual è la differenza tra i modelli gratuiti e Go?",
   "go.faq.a9":
   "go.faq.a9":
-    "I modelli gratuiti includono Big Pickle più modelli promozionali disponibili al momento, con una quota di 200 richieste/giorno. Go include GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 e MiniMax M2.7 con quote di richiesta più elevate applicate su finestre mobili (5 ore, settimanale e mensile), approssimativamente equivalenti a $12 ogni 5 ore, $30 a settimana e $60 al mese (il conteggio effettivo delle richieste varia in base al modello e all'utilizzo).",
+    "I modelli gratuiti includono Big Pickle più modelli promozionali disponibili al momento, con una quota di 200 richieste/giorno. Go include GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 e MiniMax M2.7 con quote di richiesta più elevate applicate su finestre mobili (5 ore, settimanale e mensile), approssimativamente equivalenti a $12 ogni 5 ore, $30 a settimana e $60 al mese (il conteggio effettivo delle richieste varia in base al modello e all'utilizzo).",
 
 
   "zen.api.error.rateLimitExceeded": "Limite di richieste superato. Riprova più tardi.",
   "zen.api.error.rateLimitExceeded": "Limite di richieste superato. Riprova più tardi.",
   "zen.api.error.modelNotSupported": "Modello {{model}} non supportato",
   "zen.api.error.modelNotSupported": "Modello {{model}} non supportato",

+ 6 - 6
packages/console/app/src/i18n/ja.ts

@@ -250,7 +250,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | すべての人のための低価格なコーディングモデル",
   "go.title": "OpenCode Go | すべての人のための低価格なコーディングモデル",
   "go.meta.description":
   "go.meta.description":
-    "Goは最初の月$5、その後$10/月で、GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、MiniMax M2.5、MiniMax M2.7に対して5時間のゆとりあるリクエスト上限があります。",
+    "Goは最初の月$5、その後$10/月で、GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、Qwen3.5 Plus、Qwen3.6 Plus、MiniMax M2.5、MiniMax M2.7に対して5時間のゆとりあるリクエスト上限があります。",
   "go.hero.title": "すべての人のための低価格なコーディングモデル",
   "go.hero.title": "すべての人のための低価格なコーディングモデル",
   "go.hero.body":
   "go.hero.body":
     "Goは、世界中のプログラマーにエージェント型コーディングをもたらします。最も高性能なオープンソースモデルへの十分な制限と安定したアクセスを提供し、コストや可用性を気にすることなく強力なエージェントで構築できます。",
     "Goは、世界中のプログラマーにエージェント型コーディングをもたらします。最も高性能なオープンソースモデルへの十分な制限と安定したアクセスを提供し、コストや可用性を気にすることなく強力なエージェントで構築できます。",
@@ -299,7 +299,8 @@ export const dict = {
   "go.problem.item1": "低価格なサブスクリプション料金",
   "go.problem.item1": "低価格なサブスクリプション料金",
   "go.problem.item2": "十分な制限と安定したアクセス",
   "go.problem.item2": "十分な制限と安定したアクセス",
   "go.problem.item3": "できるだけ多くのプログラマーのために構築",
   "go.problem.item3": "できるだけ多くのプログラマーのために構築",
-  "go.problem.item4": "GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、MiniMax M2.5、MiniMax M2.7を含む",
+  "go.problem.item4":
+    "GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、Qwen3.5 Plus、Qwen3.6 Plus、MiniMax M2.5、MiniMax M2.7を含む",
   "go.how.title": "Goの仕組み",
   "go.how.title": "Goの仕組み",
   "go.how.body": "Goは最初の月$5、その後$10/月で始まります。OpenCodeまたは任意のエージェントで使えます。",
   "go.how.body": "Goは最初の月$5、その後$10/月で始まります。OpenCodeまたは任意のエージェントで使えます。",
   "go.how.step1.title": "アカウントを作成",
   "go.how.step1.title": "アカウントを作成",
@@ -321,11 +322,10 @@ export const dict = {
   "go.faq.a1":
   "go.faq.a1":
     "Goは、エージェント型コーディングのための有能なオープンソースモデルへの安定したアクセスを提供する低価格なサブスクリプションです。",
     "Goは、エージェント型コーディングのための有能なオープンソースモデルへの安定したアクセスを提供する低価格なサブスクリプションです。",
   "go.faq.q2": "Goにはどのモデルが含まれますか?",
   "go.faq.q2": "Goにはどのモデルが含まれますか?",
-  "go.faq.a2":
-    "Goには、GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、MiniMax M2.5、MiniMax M2.7が含まれており、十分な制限と安定したアクセスが提供されます。",
+  "go.faq.a2": "Go には、十分な利用上限と安定したアクセスを備えた、以下のモデルが含まれます。",
   "go.faq.q3": "GoはZenと同じですか?",
   "go.faq.q3": "GoはZenと同じですか?",
   "go.faq.a3":
   "go.faq.a3":
-    "いいえ。Zenは従量課金制ですが、Goは最初の月$5、その後$10/月で始まり、GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、MiniMax M2.5、MiniMax M2.7のオープンソースモデルに対して、ゆとりある上限と信頼できるアクセスを提供します。",
+    "いいえ。Zenは従量課金制ですが、Goは最初の月$5、その後$10/月で始まり、GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、Qwen3.5 Plus、Qwen3.6 Plus、MiniMax M2.5、MiniMax M2.7のオープンソースモデルに対して、ゆとりある上限と信頼できるアクセスを提供します。",
   "go.faq.q4": "Goの料金は?",
   "go.faq.q4": "Goの料金は?",
   "go.faq.a4.p1.beforePricing": "Goは",
   "go.faq.a4.p1.beforePricing": "Goは",
   "go.faq.a4.p1.pricingLink": "最初の月$5",
   "go.faq.a4.p1.pricingLink": "最初の月$5",
@@ -349,7 +349,7 @@ export const dict = {
 
 
   "go.faq.q9": "無料モデルとGoの違いは何ですか?",
   "go.faq.q9": "無料モデルとGoの違いは何ですか?",
   "go.faq.a9":
   "go.faq.a9":
-    "無料モデルにはBig Pickleと、その時点で利用可能なプロモーションモデルが含まれ、1日200リクエストの制限があります。GoにはGLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、MiniMax M2.5、MiniMax M2.7が含まれ、ローリングウィンドウ(5時間、週間、月間)全体でより高いリクエスト制限が適用されます。これは概算で5時間あたり$12、週間$30、月間$60相当です(実際のリクエスト数はモデルと使用状況により異なります)。",
+    "無料モデルにはBig Pickleと、その時点で利用可能なプロモーションモデルが含まれ、1日200リクエストの制限があります。GoにはGLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、Qwen3.5 Plus、Qwen3.6 Plus、MiniMax M2.5、MiniMax M2.7が含まれ、ローリングウィンドウ(5時間、週間、月間)全体でより高いリクエスト制限が適用されます。これは概算で5時間あたり$12、週間$30、月間$60相当です(実際のリクエスト数はモデルと使用状況により異なります)。",
 
 
   "zen.api.error.rateLimitExceeded": "レート制限を超えました。後でもう一度お試しください。",
   "zen.api.error.rateLimitExceeded": "レート制限を超えました。後でもう一度お試しください。",
   "zen.api.error.modelNotSupported": "モデル {{model}} はサポートされていません",
   "zen.api.error.modelNotSupported": "モデル {{model}} はサポートされていません",

+ 6 - 6
packages/console/app/src/i18n/ko.ts

@@ -247,7 +247,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | 모두를 위한 저비용 코딩 모델",
   "go.title": "OpenCode Go | 모두를 위한 저비용 코딩 모델",
   "go.meta.description":
   "go.meta.description":
-    "Go는 첫 달 $5, 이후 $10/월로 시작하며, GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5, MiniMax M2.7에 대해 넉넉한 5시간 요청 한도를 제공합니다.",
+    "Go는 첫 달 $5, 이후 $10/월로 시작하며, GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5, MiniMax M2.7에 대해 넉넉한 5시간 요청 한도를 제공합니다.",
   "go.hero.title": "모두를 위한 저비용 코딩 모델",
   "go.hero.title": "모두를 위한 저비용 코딩 모델",
   "go.hero.body":
   "go.hero.body":
     "Go는 전 세계 프로그래머들에게 에이전트 코딩을 제공합니다. 가장 유능한 오픈 소스 모델에 대한 넉넉한 한도와 안정적인 액세스를 제공하므로, 비용이나 가용성 걱정 없이 강력한 에이전트로 빌드할 수 있습니다.",
     "Go는 전 세계 프로그래머들에게 에이전트 코딩을 제공합니다. 가장 유능한 오픈 소스 모델에 대한 넉넉한 한도와 안정적인 액세스를 제공하므로, 비용이나 가용성 걱정 없이 강력한 에이전트로 빌드할 수 있습니다.",
@@ -296,7 +296,8 @@ export const dict = {
   "go.problem.item1": "저렴한 구독 가격",
   "go.problem.item1": "저렴한 구독 가격",
   "go.problem.item2": "넉넉한 한도와 안정적인 액세스",
   "go.problem.item2": "넉넉한 한도와 안정적인 액세스",
   "go.problem.item3": "가능한 한 많은 프로그래머를 위해 제작됨",
   "go.problem.item3": "가능한 한 많은 프로그래머를 위해 제작됨",
-  "go.problem.item4": "GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5, MiniMax M2.7 포함",
+  "go.problem.item4":
+    "GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5, MiniMax M2.7 포함",
   "go.how.title": "Go 작동 방식",
   "go.how.title": "Go 작동 방식",
   "go.how.body": "Go는 첫 달 $5, 이후 $10/월로 시작합니다. OpenCode 또는 어떤 에이전트와도 함께 사용할 수 있습니다.",
   "go.how.body": "Go는 첫 달 $5, 이후 $10/월로 시작합니다. OpenCode 또는 어떤 에이전트와도 함께 사용할 수 있습니다.",
   "go.how.step1.title": "계정 생성",
   "go.how.step1.title": "계정 생성",
@@ -317,11 +318,10 @@ export const dict = {
   "go.faq.q1": "OpenCode Go란 무엇인가요?",
   "go.faq.q1": "OpenCode Go란 무엇인가요?",
   "go.faq.a1": "Go는 에이전트 코딩을 위한 유능한 오픈 소스 모델에 대해 안정적인 액세스를 제공하는 저비용 구독입니다.",
   "go.faq.a1": "Go는 에이전트 코딩을 위한 유능한 오픈 소스 모델에 대해 안정적인 액세스를 제공하는 저비용 구독입니다.",
   "go.faq.q2": "Go에는 어떤 모델이 포함되나요?",
   "go.faq.q2": "Go에는 어떤 모델이 포함되나요?",
-  "go.faq.a2":
-    "Go에는 넉넉한 한도와 안정적인 액세스를 제공하는 GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5, MiniMax M2.7가 포함됩니다.",
+  "go.faq.a2": "Go에는 넉넉한 한도와 안정적인 액세스를 제공하는 아래 모델이 포함됩니다.",
   "go.faq.q3": "Go는 Zen과 같은가요?",
   "go.faq.q3": "Go는 Zen과 같은가요?",
   "go.faq.a3":
   "go.faq.a3":
-    "아니요. Zen은 종량제인 반면, Go는 첫 달 $5, 이후 $10/월로 시작하며, GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5, MiniMax M2.7 오픈 소스 모델에 대한 넉넉한 한도와 안정적인 액세스를 제공합니다.",
+    "아니요. Zen은 종량제인 반면, Go는 첫 달 $5, 이후 $10/월로 시작하며, GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5, MiniMax M2.7 오픈 소스 모델에 대한 넉넉한 한도와 안정적인 액세스를 제공합니다.",
   "go.faq.q4": "Go 비용은 얼마인가요?",
   "go.faq.q4": "Go 비용은 얼마인가요?",
   "go.faq.a4.p1.beforePricing": "Go 비용은",
   "go.faq.a4.p1.beforePricing": "Go 비용은",
   "go.faq.a4.p1.pricingLink": "첫 달 $5",
   "go.faq.a4.p1.pricingLink": "첫 달 $5",
@@ -344,7 +344,7 @@ export const dict = {
 
 
   "go.faq.q9": "무료 모델과 Go의 차이점은 무엇인가요?",
   "go.faq.q9": "무료 모델과 Go의 차이점은 무엇인가요?",
   "go.faq.a9":
   "go.faq.a9":
-    "무료 모델에는 Big Pickle과 당시 사용 가능한 프로모션 모델이 포함되며, 하루 200회 요청 할당량이 적용됩니다. Go는 GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5, MiniMax M2.7를 포함하며, 롤링 윈도우(5시간, 주간, 월간)에 걸쳐 더 높은 요청 할당량을 적용합니다. 이는 대략 5시간당 $12, 주당 $30, 월 $60에 해당합니다(실제 요청 수는 모델 및 사용량에 따라 다름).",
+    "무료 모델에는 Big Pickle과 당시 사용 가능한 프로모션 모델이 포함되며, 하루 200회 요청 할당량이 적용됩니다. Go는 GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5, MiniMax M2.7를 포함하며, 롤링 윈도우(5시간, 주간, 월간)에 걸쳐 더 높은 요청 할당량을 적용합니다. 이는 대략 5시간당 $12, 주당 $30, 월 $60에 해당합니다(실제 요청 수는 모델 및 사용량에 따라 다름).",
 
 
   "zen.api.error.rateLimitExceeded": "속도 제한을 초과했습니다. 나중에 다시 시도해 주세요.",
   "zen.api.error.rateLimitExceeded": "속도 제한을 초과했습니다. 나중에 다시 시도해 주세요.",
   "zen.api.error.modelNotSupported": "{{model}} 모델은 지원되지 않습니다",
   "zen.api.error.modelNotSupported": "{{model}} 모델은 지원되지 않습니다",

+ 6 - 6
packages/console/app/src/i18n/no.ts

@@ -251,7 +251,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | Rimelige kodemodeller for alle",
   "go.title": "OpenCode Go | Rimelige kodemodeller for alle",
   "go.meta.description":
   "go.meta.description":
-    "Go starter på $5 for den første måneden, deretter $10/måned, med sjenerøse 5-timers forespørselsgrenser for GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 og MiniMax M2.7.",
+    "Go starter på $5 for den første måneden, deretter $10/måned, med sjenerøse 5-timers forespørselsgrenser for GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 og MiniMax M2.7.",
   "go.hero.title": "Rimelige kodemodeller for alle",
   "go.hero.title": "Rimelige kodemodeller for alle",
   "go.hero.body":
   "go.hero.body":
     "Go bringer agent-koding til programmerere over hele verden. Med rause grenser og pålitelig tilgang til de mest kapable åpen kildekode-modellene, kan du bygge med kraftige agenter uten å bekymre deg for kostnader eller tilgjengelighet.",
     "Go bringer agent-koding til programmerere over hele verden. Med rause grenser og pålitelig tilgang til de mest kapable åpen kildekode-modellene, kan du bygge med kraftige agenter uten å bekymre deg for kostnader eller tilgjengelighet.",
@@ -299,7 +299,8 @@ export const dict = {
   "go.problem.item1": "Rimelig abonnementspris",
   "go.problem.item1": "Rimelig abonnementspris",
   "go.problem.item2": "Rause grenser og pålitelig tilgang",
   "go.problem.item2": "Rause grenser og pålitelig tilgang",
   "go.problem.item3": "Bygget for så mange programmerere som mulig",
   "go.problem.item3": "Bygget for så mange programmerere som mulig",
-  "go.problem.item4": "Inkluderer GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 og MiniMax M2.7",
+  "go.problem.item4":
+    "Inkluderer GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 og MiniMax M2.7",
   "go.how.title": "Hvordan Go fungerer",
   "go.how.title": "Hvordan Go fungerer",
   "go.how.body":
   "go.how.body":
     "Go starter på $5 for den første måneden, deretter $10/måned. Du kan bruke det med OpenCode eller hvilken som helst agent.",
     "Go starter på $5 for den første måneden, deretter $10/måned. Du kan bruke det med OpenCode eller hvilken som helst agent.",
@@ -322,11 +323,10 @@ export const dict = {
   "go.faq.a1":
   "go.faq.a1":
     "Go er et rimelig abonnement som gir deg pålitelig tilgang til kapable åpen kildekode-modeller for agent-koding.",
     "Go er et rimelig abonnement som gir deg pålitelig tilgang til kapable åpen kildekode-modeller for agent-koding.",
   "go.faq.q2": "Hvilke modeller inkluderer Go?",
   "go.faq.q2": "Hvilke modeller inkluderer Go?",
-  "go.faq.a2":
-    "Go inkluderer GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 og MiniMax M2.7, med rause grenser og pålitelig tilgang.",
+  "go.faq.a2": "Go inkluderer modellene nedenfor, med høye grenser og pålitelig tilgang.",
   "go.faq.q3": "Er Go det samme som Zen?",
   "go.faq.q3": "Er Go det samme som Zen?",
   "go.faq.a3":
   "go.faq.a3":
-    "Nei. Zen er betaling etter bruk, mens Go starter på $5 for den første måneden, deretter $10/måned, med sjenerøse grenser og pålitelig tilgang til åpen kildekode-modellene GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 og MiniMax M2.7.",
+    "Nei. Zen er betaling etter bruk, mens Go starter på $5 for den første måneden, deretter $10/måned, med sjenerøse grenser og pålitelig tilgang til åpen kildekode-modellene GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 og MiniMax M2.7.",
   "go.faq.q4": "Hva koster Go?",
   "go.faq.q4": "Hva koster Go?",
   "go.faq.a4.p1.beforePricing": "Go koster",
   "go.faq.a4.p1.beforePricing": "Go koster",
   "go.faq.a4.p1.pricingLink": "$5 første måned",
   "go.faq.a4.p1.pricingLink": "$5 første måned",
@@ -350,7 +350,7 @@ export const dict = {
 
 
   "go.faq.q9": "Hva er forskjellen mellom gratis modeller og Go?",
   "go.faq.q9": "Hva er forskjellen mellom gratis modeller og Go?",
   "go.faq.a9":
   "go.faq.a9":
-    "Gratis modeller inkluderer Big Pickle pluss kampanjemodeller tilgjengelig på det tidspunktet, med en kvote på 200 forespørsler/dag. Go inkluderer GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 og MiniMax M2.7 med høyere kvoter håndhevet over rullerende vinduer (5 timer, ukentlig og månedlig), omtrent tilsvarende $12 per 5 timer, $30 per uke og $60 per måned (faktiske forespørselsantall varierer etter modell og bruk).",
+    "Gratis modeller inkluderer Big Pickle pluss kampanjemodeller tilgjengelig på det tidspunktet, med en kvote på 200 forespørsler/dag. Go inkluderer GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 og MiniMax M2.7 med høyere kvoter håndhevet over rullerende vinduer (5 timer, ukentlig og månedlig), omtrent tilsvarende $12 per 5 timer, $30 per uke og $60 per måned (faktiske forespørselsantall varierer etter modell og bruk).",
 
 
   "zen.api.error.rateLimitExceeded": "Rate limit overskredet. Vennligst prøv igjen senere.",
   "zen.api.error.rateLimitExceeded": "Rate limit overskredet. Vennligst prøv igjen senere.",
   "zen.api.error.modelNotSupported": "Modell {{model}} støttes ikke",
   "zen.api.error.modelNotSupported": "Modell {{model}} støttes ikke",

+ 6 - 6
packages/console/app/src/i18n/pl.ts

@@ -252,7 +252,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | Niskokosztowe modele do kodowania dla każdego",
   "go.title": "OpenCode Go | Niskokosztowe modele do kodowania dla każdego",
   "go.meta.description":
   "go.meta.description":
-    "Go zaczyna się od $5 za pierwszy miesiąc, potem $10/miesiąc, z hojnymi 5-godzinnymi limitami zapytań dla GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 i MiniMax M2.7.",
+    "Go zaczyna się od $5 za pierwszy miesiąc, potem $10/miesiąc, z hojnymi 5-godzinnymi limitami zapytań dla GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 i MiniMax M2.7.",
   "go.hero.title": "Niskokosztowe modele do kodowania dla każdego",
   "go.hero.title": "Niskokosztowe modele do kodowania dla każdego",
   "go.hero.body":
   "go.hero.body":
     "Go udostępnia programowanie z agentami programistom na całym świecie. Oferuje hojne limity i niezawodny dostęp do najzdolniejszych modeli open source, dzięki czemu możesz budować za pomocą potężnych agentów, nie martwiąc się o koszty czy dostępność.",
     "Go udostępnia programowanie z agentami programistom na całym świecie. Oferuje hojne limity i niezawodny dostęp do najzdolniejszych modeli open source, dzięki czemu możesz budować za pomocą potężnych agentów, nie martwiąc się o koszty czy dostępność.",
@@ -300,7 +300,8 @@ export const dict = {
   "go.problem.item1": "Niskokosztowa cena subskrypcji",
   "go.problem.item1": "Niskokosztowa cena subskrypcji",
   "go.problem.item2": "Hojne limity i niezawodny dostęp",
   "go.problem.item2": "Hojne limity i niezawodny dostęp",
   "go.problem.item3": "Stworzony dla jak największej liczby programistów",
   "go.problem.item3": "Stworzony dla jak największej liczby programistów",
-  "go.problem.item4": "Zawiera GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 i MiniMax M2.7",
+  "go.problem.item4":
+    "Zawiera GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 i MiniMax M2.7",
   "go.how.title": "Jak działa Go",
   "go.how.title": "Jak działa Go",
   "go.how.body":
   "go.how.body":
     "Go zaczyna się od $5 za pierwszy miesiąc, potem $10/miesiąc. Możesz go używać z OpenCode lub dowolnym agentem.",
     "Go zaczyna się od $5 za pierwszy miesiąc, potem $10/miesiąc. Możesz go używać z OpenCode lub dowolnym agentem.",
@@ -323,11 +324,10 @@ export const dict = {
   "go.faq.a1":
   "go.faq.a1":
     "Go to niskokosztowa subskrypcja, która daje niezawodny dostęp do zdolnych modeli open source dla agentów kodujących.",
     "Go to niskokosztowa subskrypcja, która daje niezawodny dostęp do zdolnych modeli open source dla agentów kodujących.",
   "go.faq.q2": "Jakie modele zawiera Go?",
   "go.faq.q2": "Jakie modele zawiera Go?",
-  "go.faq.a2":
-    "Go zawiera GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 i MiniMax M2.7, z hojnymi limitami i niezawodnym dostępem.",
+  "go.faq.a2": "Go obejmuje poniższe modele z wysokimi limitami i niezawodnym dostępem.",
   "go.faq.q3": "Czy Go to to samo co Zen?",
   "go.faq.q3": "Czy Go to to samo co Zen?",
   "go.faq.a3":
   "go.faq.a3":
-    "Nie. Zen to model płatności za użycie, podczas gdy Go zaczyna się od $5 za pierwszy miesiąc, potem $10/miesiąc, z hojnymi limitami i niezawodnym dostępem do modeli open source GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 i MiniMax M2.7.",
+    "Nie. Zen to model płatności za użycie, podczas gdy Go zaczyna się od $5 za pierwszy miesiąc, potem $10/miesiąc, z hojnymi limitami i niezawodnym dostępem do modeli open source GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 i MiniMax M2.7.",
   "go.faq.q4": "Ile kosztuje Go?",
   "go.faq.q4": "Ile kosztuje Go?",
   "go.faq.a4.p1.beforePricing": "Go kosztuje",
   "go.faq.a4.p1.beforePricing": "Go kosztuje",
   "go.faq.a4.p1.pricingLink": "$5 za pierwszy miesiąc",
   "go.faq.a4.p1.pricingLink": "$5 za pierwszy miesiąc",
@@ -351,7 +351,7 @@ export const dict = {
 
 
   "go.faq.q9": "Jaka jest różnica między darmowymi modelami a Go?",
   "go.faq.q9": "Jaka jest różnica między darmowymi modelami a Go?",
   "go.faq.a9":
   "go.faq.a9":
-    "Darmowe modele obejmują Big Pickle oraz modele promocyjne dostępne w danym momencie, z limitem 200 zapytań/dzień. Go zawiera GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 i MiniMax M2.7 z wyższymi limitami zapytań egzekwowanymi w oknach kroczących (5-godzinnych, tygodniowych i miesięcznych), w przybliżeniu równoważnymi $12 na 5 godzin, $30 tygodniowo i $60 miesięcznie (rzeczywista liczba zapytań zależy od modelu i użycia).",
+    "Darmowe modele obejmują Big Pickle oraz modele promocyjne dostępne w danym momencie, z limitem 200 zapytań/dzień. Go zawiera GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 i MiniMax M2.7 z wyższymi limitami zapytań egzekwowanymi w oknach kroczących (5-godzinnych, tygodniowych i miesięcznych), w przybliżeniu równoważnymi $12 na 5 godzin, $30 tygodniowo i $60 miesięcznie (rzeczywista liczba zapytań zależy od modelu i użycia).",
 
 
   "zen.api.error.rateLimitExceeded": "Przekroczono limit zapytań. Spróbuj ponownie później.",
   "zen.api.error.rateLimitExceeded": "Przekroczono limit zapytań. Spróbuj ponownie później.",
   "zen.api.error.modelNotSupported": "Model {{model}} nie jest obsługiwany",
   "zen.api.error.modelNotSupported": "Model {{model}} nie jest obsługiwany",

+ 6 - 6
packages/console/app/src/i18n/ru.ts

@@ -255,7 +255,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | Недорогие модели для кодинга для всех",
   "go.title": "OpenCode Go | Недорогие модели для кодинга для всех",
   "go.meta.description":
   "go.meta.description":
-    "Go начинается с $5 за первый месяц, затем $10/месяц, с щедрыми лимитами запросов за 5 часов для GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 и MiniMax M2.7.",
+    "Go начинается с $5 за первый месяц, затем $10/месяц, с щедрыми лимитами запросов за 5 часов для GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 и MiniMax M2.7.",
   "go.hero.title": "Недорогие модели для кодинга для всех",
   "go.hero.title": "Недорогие модели для кодинга для всех",
   "go.hero.body":
   "go.hero.body":
     "Go открывает доступ к агентам-программистам разработчикам по всему миру. Предлагая щедрые лимиты и надежный доступ к наиболее способным моделям с открытым исходным кодом, вы можете создавать проекты с мощными агентами, не беспокоясь о затратах или доступности.",
     "Go открывает доступ к агентам-программистам разработчикам по всему миру. Предлагая щедрые лимиты и надежный доступ к наиболее способным моделям с открытым исходным кодом, вы можете создавать проекты с мощными агентами, не беспокоясь о затратах или доступности.",
@@ -304,7 +304,8 @@ export const dict = {
   "go.problem.item1": "Недорогая подписка",
   "go.problem.item1": "Недорогая подписка",
   "go.problem.item2": "Щедрые лимиты и надежный доступ",
   "go.problem.item2": "Щедрые лимиты и надежный доступ",
   "go.problem.item3": "Создан для максимального числа программистов",
   "go.problem.item3": "Создан для максимального числа программистов",
-  "go.problem.item4": "Включает GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 и MiniMax M2.7",
+  "go.problem.item4":
+    "Включает GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 и MiniMax M2.7",
   "go.how.title": "Как работает Go",
   "go.how.title": "Как работает Go",
   "go.how.body":
   "go.how.body":
     "Go начинается с $5 за первый месяц, затем $10/месяц. Вы можете использовать его с OpenCode или любым агентом.",
     "Go начинается с $5 за первый месяц, затем $10/месяц. Вы можете использовать его с OpenCode или любым агентом.",
@@ -327,11 +328,10 @@ export const dict = {
   "go.faq.a1":
   "go.faq.a1":
     "Go — это недорогая подписка, дающая надежный доступ к мощным моделям с открытым исходным кодом для агентов-программистов.",
     "Go — это недорогая подписка, дающая надежный доступ к мощным моделям с открытым исходным кодом для агентов-программистов.",
   "go.faq.q2": "Какие модели включает Go?",
   "go.faq.q2": "Какие модели включает Go?",
-  "go.faq.a2":
-    "Go включает GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 и MiniMax M2.7, с щедрыми лимитами и надежным доступом.",
+  "go.faq.a2": "Go включает перечисленные ниже модели с щедрыми лимитами и надежным доступом.",
   "go.faq.q3": "Go — это то же самое, что и Zen?",
   "go.faq.q3": "Go — это то же самое, что и Zen?",
   "go.faq.a3":
   "go.faq.a3":
-    "Нет. Zen - это оплата по мере использования, в то время как Go начинается с $5 за первый месяц, затем $10/месяц, с щедрыми лимитами и надежным доступом к моделям с открытым исходным кодом GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 и MiniMax M2.7.",
+    "Нет. Zen - это оплата по мере использования, в то время как Go начинается с $5 за первый месяц, затем $10/месяц, с щедрыми лимитами и надежным доступом к моделям с открытым исходным кодом GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 и MiniMax M2.7.",
   "go.faq.q4": "Сколько стоит Go?",
   "go.faq.q4": "Сколько стоит Go?",
   "go.faq.a4.p1.beforePricing": "Go стоит",
   "go.faq.a4.p1.beforePricing": "Go стоит",
   "go.faq.a4.p1.pricingLink": "$5 за первый месяц",
   "go.faq.a4.p1.pricingLink": "$5 за первый месяц",
@@ -355,7 +355,7 @@ export const dict = {
 
 
   "go.faq.q9": "В чем разница между бесплатными моделями и Go?",
   "go.faq.q9": "В чем разница между бесплатными моделями и Go?",
   "go.faq.a9":
   "go.faq.a9":
-    "Бесплатные модели включают Big Pickle плюс промо-модели, доступные на данный момент, с квотой 200 запросов/день. Go включает GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 и MiniMax M2.7 с более высокими квотами запросов, применяемыми в скользящих окнах (5 часов, неделя и месяц), что примерно эквивалентно $12 за 5 часов, $30 в неделю и $60 в месяц (фактическое количество запросов зависит от модели и использования).",
+    "Бесплатные модели включают Big Pickle плюс промо-модели, доступные на данный момент, с квотой 200 запросов/день. Go включает GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 и MiniMax M2.7 с более высокими квотами запросов, применяемыми в скользящих окнах (5 часов, неделя и месяц), что примерно эквивалентно $12 за 5 часов, $30 в неделю и $60 в месяц (фактическое количество запросов зависит от модели и использования).",
 
 
   "zen.api.error.rateLimitExceeded": "Превышен лимит запросов. Пожалуйста, попробуйте позже.",
   "zen.api.error.rateLimitExceeded": "Превышен лимит запросов. Пожалуйста, попробуйте позже.",
   "zen.api.error.modelNotSupported": "Модель {{model}} не поддерживается",
   "zen.api.error.modelNotSupported": "Модель {{model}} не поддерживается",

+ 6 - 6
packages/console/app/src/i18n/th.ts

@@ -250,7 +250,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | โมเดลเขียนโค้ดราคาประหยัดสำหรับทุกคน",
   "go.title": "OpenCode Go | โมเดลเขียนโค้ดราคาประหยัดสำหรับทุกคน",
   "go.meta.description":
   "go.meta.description":
-    "Go เริ่มต้นที่ $5 สำหรับเดือนแรก จากนั้น $10/เดือน พร้อมขีดจำกัดคำขอ 5 ชั่วโมงที่เอื้อเฟื้อสำหรับ GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 และ MiniMax M2.7",
+    "Go เริ่มต้นที่ $5 สำหรับเดือนแรก จากนั้น $10/เดือน พร้อมขีดจำกัดคำขอ 5 ชั่วโมงที่เอื้อเฟื้อสำหรับ GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 และ MiniMax M2.7",
   "go.hero.title": "โมเดลเขียนโค้ดราคาประหยัดสำหรับทุกคน",
   "go.hero.title": "โมเดลเขียนโค้ดราคาประหยัดสำหรับทุกคน",
   "go.hero.body":
   "go.hero.body":
     "Go นำการเขียนโค้ดแบบเอเจนต์มาสู่นักเขียนโปรแกรมทั่วโลก เสนอขีดจำกัดที่กว้างขวางและการเข้าถึงโมเดลโอเพนซอร์สที่มีความสามารถสูงสุดได้อย่างน่าเชื่อถือ เพื่อให้คุณสามารถสร้างสรรค์ด้วยเอเจนต์ที่ทรงพลังโดยไม่ต้องกังวลเรื่องค่าใช้จ่ายหรือความพร้อมใช้งาน",
     "Go นำการเขียนโค้ดแบบเอเจนต์มาสู่นักเขียนโปรแกรมทั่วโลก เสนอขีดจำกัดที่กว้างขวางและการเข้าถึงโมเดลโอเพนซอร์สที่มีความสามารถสูงสุดได้อย่างน่าเชื่อถือ เพื่อให้คุณสามารถสร้างสรรค์ด้วยเอเจนต์ที่ทรงพลังโดยไม่ต้องกังวลเรื่องค่าใช้จ่ายหรือความพร้อมใช้งาน",
@@ -297,7 +297,8 @@ export const dict = {
   "go.problem.item1": "ราคาการสมัครสมาชิกที่ต่ำ",
   "go.problem.item1": "ราคาการสมัครสมาชิกที่ต่ำ",
   "go.problem.item2": "ขีดจำกัดที่กว้างขวางและการเข้าถึงที่เชื่อถือได้",
   "go.problem.item2": "ขีดจำกัดที่กว้างขวางและการเข้าถึงที่เชื่อถือได้",
   "go.problem.item3": "สร้างขึ้นเพื่อโปรแกรมเมอร์จำนวนมากที่สุดเท่าที่จะเป็นไปได้",
   "go.problem.item3": "สร้างขึ้นเพื่อโปรแกรมเมอร์จำนวนมากที่สุดเท่าที่จะเป็นไปได้",
-  "go.problem.item4": "รวมถึง GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 และ MiniMax M2.7",
+  "go.problem.item4":
+    "รวมถึง GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 และ MiniMax M2.7",
   "go.how.title": "Go ทำงานอย่างไร",
   "go.how.title": "Go ทำงานอย่างไร",
   "go.how.body": "Go เริ่มต้นที่ $5 สำหรับเดือนแรก จากนั้น $10/เดือน คุณสามารถใช้กับ OpenCode หรือเอเจนต์ใดก็ได้",
   "go.how.body": "Go เริ่มต้นที่ $5 สำหรับเดือนแรก จากนั้น $10/เดือน คุณสามารถใช้กับ OpenCode หรือเอเจนต์ใดก็ได้",
   "go.how.step1.title": "สร้างบัญชี",
   "go.how.step1.title": "สร้างบัญชี",
@@ -319,11 +320,10 @@ export const dict = {
   "go.faq.a1":
   "go.faq.a1":
     "Go คือการสมัครสมาชิกราคาประหยัดที่ให้คุณเข้าถึงโมเดลโอเพนซอร์สที่มีความสามารถสำหรับการเขียนโค้ดแบบเอเจนต์ได้อย่างน่าเชื่อถือ",
     "Go คือการสมัครสมาชิกราคาประหยัดที่ให้คุณเข้าถึงโมเดลโอเพนซอร์สที่มีความสามารถสำหรับการเขียนโค้ดแบบเอเจนต์ได้อย่างน่าเชื่อถือ",
   "go.faq.q2": "Go รวมโมเดลอะไรบ้าง?",
   "go.faq.q2": "Go รวมโมเดลอะไรบ้าง?",
-  "go.faq.a2":
-    "Go รวมถึง GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 และ MiniMax M2.7 พร้อมขีดจำกัดที่กว้างขวางและการเข้าถึงที่เชื่อถือได้",
+  "go.faq.a2": "Go รวมโมเดลด้านล่างนี้ พร้อมขีดจำกัดที่มากและการเข้าถึงที่เชื่อถือได้",
   "go.faq.q3": "Go เหมือนกับ Zen หรือไม่?",
   "go.faq.q3": "Go เหมือนกับ Zen หรือไม่?",
   "go.faq.a3":
   "go.faq.a3":
-    "ไม่ Zen เป็นแบบจ่ายตามการใช้งาน ในขณะที่ Go เริ่มต้นที่ $5 สำหรับเดือนแรก จากนั้น $10/เดือน พร้อมขีดจำกัดที่เอื้อเฟื้อและการเข้าถึงโมเดลโอเพนซอร์ส GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 และ MiniMax M2.7 อย่างเชื่อถือได้",
+    "ไม่ Zen เป็นแบบจ่ายตามการใช้งาน ในขณะที่ Go เริ่มต้นที่ $5 สำหรับเดือนแรก จากนั้น $10/เดือน พร้อมขีดจำกัดที่เอื้อเฟื้อและการเข้าถึงโมเดลโอเพนซอร์ส GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 และ MiniMax M2.7 อย่างเชื่อถือได้",
   "go.faq.q4": "Go ราคาเท่าไหร่?",
   "go.faq.q4": "Go ราคาเท่าไหร่?",
   "go.faq.a4.p1.beforePricing": "Go ราคา",
   "go.faq.a4.p1.beforePricing": "Go ราคา",
   "go.faq.a4.p1.pricingLink": "$5 เดือนแรก",
   "go.faq.a4.p1.pricingLink": "$5 เดือนแรก",
@@ -346,7 +346,7 @@ export const dict = {
 
 
   "go.faq.q9": "ความแตกต่างระหว่างโมเดลฟรีและ Go คืออะไร?",
   "go.faq.q9": "ความแตกต่างระหว่างโมเดลฟรีและ Go คืออะไร?",
   "go.faq.a9":
   "go.faq.a9":
-    "โมเดลฟรีรวมถึง Big Pickle บวกกับโมเดลโปรโมชั่นที่มีให้ในขณะนั้น ด้วยโควต้า 200 คำขอ/วัน Go รวมถึง GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 และ MiniMax M2.7 ที่มีโควต้าคำขอสูงกว่า ซึ่งบังคับใช้ผ่านช่วงเวลาหมุนเวียน (5 ชั่วโมง, รายสัปดาห์ และรายเดือน) เทียบเท่าประมาณ $12 ต่อ 5 ชั่วโมง, $30 ต่อสัปดาห์ และ $60 ต่อเดือน (จำนวนคำขอจริงจะแตกต่างกันไปตามโมเดลและการใช้งาน)",
+    "โมเดลฟรีรวมถึง Big Pickle บวกกับโมเดลโปรโมชั่นที่มีให้ในขณะนั้น ด้วยโควต้า 200 คำขอ/วัน Go รวมถึง GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 และ MiniMax M2.7 ที่มีโควต้าคำขอสูงกว่า ซึ่งบังคับใช้ผ่านช่วงเวลาหมุนเวียน (5 ชั่วโมง, รายสัปดาห์ และรายเดือน) เทียบเท่าประมาณ $12 ต่อ 5 ชั่วโมง, $30 ต่อสัปดาห์ และ $60 ต่อเดือน (จำนวนคำขอจริงจะแตกต่างกันไปตามโมเดลและการใช้งาน)",
 
 
   "zen.api.error.rateLimitExceeded": "เกินขีดจำกัดอัตราการใช้งาน กรุณาลองใหม่ในภายหลัง",
   "zen.api.error.rateLimitExceeded": "เกินขีดจำกัดอัตราการใช้งาน กรุณาลองใหม่ในภายหลัง",
   "zen.api.error.modelNotSupported": "ไม่รองรับโมเดล {{model}}",
   "zen.api.error.modelNotSupported": "ไม่รองรับโมเดล {{model}}",

+ 6 - 6
packages/console/app/src/i18n/tr.ts

@@ -253,7 +253,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | Herkes için düşük maliyetli kodlama modelleri",
   "go.title": "OpenCode Go | Herkes için düşük maliyetli kodlama modelleri",
   "go.meta.description":
   "go.meta.description":
-    "Go ilk ay $5, sonrasında ayda 10$ fiyatıyla başlar; GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 ve MiniMax M2.7 için cömert 5 saatlik istek limitleri sunar.",
+    "Go ilk ay $5, sonrasında ayda 10$ fiyatıyla başlar; GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 ve MiniMax M2.7 için cömert 5 saatlik istek limitleri sunar.",
   "go.hero.title": "Herkes için düşük maliyetli kodlama modelleri",
   "go.hero.title": "Herkes için düşük maliyetli kodlama modelleri",
   "go.hero.body":
   "go.hero.body":
     "Go, dünya çapındaki programcılara ajan tabanlı kodlama getiriyor. En yetenekli açık kaynaklı modellere cömert limitler ve güvenilir erişim sunarak, maliyet veya erişilebilirlik konusunda endişelenmeden güçlü ajanlarla geliştirme yapmanızı sağlar.",
     "Go, dünya çapındaki programcılara ajan tabanlı kodlama getiriyor. En yetenekli açık kaynaklı modellere cömert limitler ve güvenilir erişim sunarak, maliyet veya erişilebilirlik konusunda endişelenmeden güçlü ajanlarla geliştirme yapmanızı sağlar.",
@@ -302,7 +302,8 @@ export const dict = {
   "go.problem.item1": "Düşük maliyetli abonelik fiyatlandırması",
   "go.problem.item1": "Düşük maliyetli abonelik fiyatlandırması",
   "go.problem.item2": "Cömert limitler ve güvenilir erişim",
   "go.problem.item2": "Cömert limitler ve güvenilir erişim",
   "go.problem.item3": "Mümkün olduğunca çok programcı için geliştirildi",
   "go.problem.item3": "Mümkün olduğunca çok programcı için geliştirildi",
-  "go.problem.item4": "GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 ve MiniMax M2.7 içerir",
+  "go.problem.item4":
+    "GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 ve MiniMax M2.7 içerir",
   "go.how.title": "Go nasıl çalışır?",
   "go.how.title": "Go nasıl çalışır?",
   "go.how.body":
   "go.how.body":
     "Go ilk ay $5, sonrasında ayda 10$ fiyatıyla başlar. OpenCode veya herhangi bir ajanla kullanabilirsiniz.",
     "Go ilk ay $5, sonrasında ayda 10$ fiyatıyla başlar. OpenCode veya herhangi bir ajanla kullanabilirsiniz.",
@@ -325,11 +326,10 @@ export const dict = {
   "go.faq.a1":
   "go.faq.a1":
     "Go, ajan tabanlı kodlama için yetenekli açık kaynaklı modellere güvenilir erişim sağlayan düşük maliyetli bir aboneliktir.",
     "Go, ajan tabanlı kodlama için yetenekli açık kaynaklı modellere güvenilir erişim sağlayan düşük maliyetli bir aboneliktir.",
   "go.faq.q2": "Go hangi modelleri içerir?",
   "go.faq.q2": "Go hangi modelleri içerir?",
-  "go.faq.a2":
-    "Go, cömert limitler ve güvenilir erişim ile GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 ve MiniMax M2.7 modellerini içerir.",
+  "go.faq.a2": "Go, aşağıda listelenen modelleri cömert limitler ve güvenilir erişimle sunar.",
   "go.faq.q3": "Go, Zen ile aynı mı?",
   "go.faq.q3": "Go, Zen ile aynı mı?",
   "go.faq.a3":
   "go.faq.a3":
-    "Hayır. Zen kullandıkça öde modelidir, Go ise ilk ay $5, sonrasında ayda 10$ fiyatıyla başlar; GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 ve MiniMax M2.7 açık kaynak modellerine cömert limitler ve güvenilir erişim sunar.",
+    "Hayır. Zen kullandıkça öde modelidir, Go ise ilk ay $5, sonrasında ayda 10$ fiyatıyla başlar; GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 ve MiniMax M2.7 açık kaynak modellerine cömert limitler ve güvenilir erişim sunar.",
   "go.faq.q4": "Go ne kadar?",
   "go.faq.q4": "Go ne kadar?",
   "go.faq.a4.p1.beforePricing": "Go'nun maliyeti",
   "go.faq.a4.p1.beforePricing": "Go'nun maliyeti",
   "go.faq.a4.p1.pricingLink": "İlk ay $5",
   "go.faq.a4.p1.pricingLink": "İlk ay $5",
@@ -353,7 +353,7 @@ export const dict = {
 
 
   "go.faq.q9": "Ücretsiz modeller ve Go arasındaki fark nedir?",
   "go.faq.q9": "Ücretsiz modeller ve Go arasındaki fark nedir?",
   "go.faq.a9":
   "go.faq.a9":
-    "Ücretsiz modeller, günlük 200 istek kotası ile Big Pickle ve o sırada mevcut olan promosyonel modelleri içerir. Go ise GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 ve MiniMax M2.7 modellerini; yuvarlanan pencereler (5 saatlik, haftalık ve aylık) üzerinden uygulanan daha yüksek istek kotalarıyla içerir. Bu kotalar kabaca her 5 saatte 12$, haftada 30$ ve ayda 60$ değerine eşdeğerdir (gerçek istek sayıları modele ve kullanıma göre değişir).",
+    "Ücretsiz modeller, günlük 200 istek kotası ile Big Pickle ve o sırada mevcut olan promosyonel modelleri içerir. Go ise GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 ve MiniMax M2.7 modellerini; yuvarlanan pencereler (5 saatlik, haftalık ve aylık) üzerinden uygulanan daha yüksek istek kotalarıyla içerir. Bu kotalar kabaca her 5 saatte 12$, haftada 30$ ve ayda 60$ değerine eşdeğerdir (gerçek istek sayıları modele ve kullanıma göre değişir).",
 
 
   "zen.api.error.rateLimitExceeded": "İstek limiti aşıldı. Lütfen daha sonra tekrar deneyin.",
   "zen.api.error.rateLimitExceeded": "İstek limiti aşıldı. Lütfen daha sonra tekrar deneyin.",
   "zen.api.error.modelNotSupported": "{{model}} modeli desteklenmiyor",
   "zen.api.error.modelNotSupported": "{{model}} modeli desteklenmiyor",

+ 6 - 6
packages/console/app/src/i18n/zh.ts

@@ -241,7 +241,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | 人人可用的低成本编程模型",
   "go.title": "OpenCode Go | 人人可用的低成本编程模型",
   "go.meta.description":
   "go.meta.description":
-    "Go 首月 $5,之后 $10/月,提供对 GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、MiniMax M2.5 和 MiniMax M2.7 的 5 小时充裕请求额度。",
+    "Go 首月 $5,之后 $10/月,提供对 GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、Qwen3.5 Plus、Qwen3.6 Plus、MiniMax M2.5 和 MiniMax M2.7 的 5 小时充裕请求额度。",
   "go.hero.title": "人人可用的低成本编程模型",
   "go.hero.title": "人人可用的低成本编程模型",
   "go.hero.body":
   "go.hero.body":
     "Go 将代理编程带给全世界的程序员。提供充裕的限额和对最强大的开源模型的可靠访问,让您可以利用强大的代理进行构建,而无需担心成本或可用性。",
     "Go 将代理编程带给全世界的程序员。提供充裕的限额和对最强大的开源模型的可靠访问,让您可以利用强大的代理进行构建,而无需担心成本或可用性。",
@@ -288,7 +288,8 @@ export const dict = {
   "go.problem.item1": "低成本订阅定价",
   "go.problem.item1": "低成本订阅定价",
   "go.problem.item2": "充裕的限额和可靠的访问",
   "go.problem.item2": "充裕的限额和可靠的访问",
   "go.problem.item3": "为尽可能多的程序员打造",
   "go.problem.item3": "为尽可能多的程序员打造",
-  "go.problem.item4": "包含 GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 和 MiniMax M2.7",
+  "go.problem.item4":
+    "包含 GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 和 MiniMax M2.7",
   "go.how.title": "Go 如何工作",
   "go.how.title": "Go 如何工作",
   "go.how.body": "Go 起价为首月 $5,之后 $10/月。您可以将其与 OpenCode 或任何代理搭配使用。",
   "go.how.body": "Go 起价为首月 $5,之后 $10/月。您可以将其与 OpenCode 或任何代理搭配使用。",
   "go.how.step1.title": "创建账户",
   "go.how.step1.title": "创建账户",
@@ -307,11 +308,10 @@ export const dict = {
   "go.faq.q1": "什么是 OpenCode Go?",
   "go.faq.q1": "什么是 OpenCode Go?",
   "go.faq.a1": "Go 是一项低成本订阅服务,为您提供对强大的开源模型的可靠访问,用于代理编程。",
   "go.faq.a1": "Go 是一项低成本订阅服务,为您提供对强大的开源模型的可靠访问,用于代理编程。",
   "go.faq.q2": "Go 包含哪些模型?",
   "go.faq.q2": "Go 包含哪些模型?",
-  "go.faq.a2":
-    "Go 包含 GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 和 MiniMax M2.7,并提供充裕的限额和可靠的访问。",
+  "go.faq.a2": "Go 包含下方列出的模型,提供充足的限额和可靠的访问。",
   "go.faq.q3": "Go 和 Zen 一样吗?",
   "go.faq.q3": "Go 和 Zen 一样吗?",
   "go.faq.a3":
   "go.faq.a3":
-    "不。Zen 是按量付费,而 Go 首月 $5,之后 $10/月,提供充裕的额度,并可可靠地访问 GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、MiniMax M2.5 和 MiniMax M2.7 等开源模型。",
+    "不。Zen 是按量付费,而 Go 首月 $5,之后 $10/月,提供充裕的额度,并可可靠地访问 GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、Qwen3.5 Plus、Qwen3.6 Plus、MiniMax M2.5 和 MiniMax M2.7 等开源模型。",
   "go.faq.q4": "Go 多少钱?",
   "go.faq.q4": "Go 多少钱?",
   "go.faq.a4.p1.beforePricing": "Go 费用为",
   "go.faq.a4.p1.beforePricing": "Go 费用为",
   "go.faq.a4.p1.pricingLink": "首月 $5",
   "go.faq.a4.p1.pricingLink": "首月 $5",
@@ -333,7 +333,7 @@ export const dict = {
 
 
   "go.faq.q9": "免费模型和 Go 之间的区别是什么?",
   "go.faq.q9": "免费模型和 Go 之间的区别是什么?",
   "go.faq.a9":
   "go.faq.a9":
-    "免费模型包含 Big Pickle 加上当时可用的促销模型,每天有 200 次请求的配额。Go 包含 GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, MiniMax M2.5 和 MiniMax M2.7,并在滚动窗口(5 小时、每周和每月)内执行更高的请求配额,大致相当于每 5 小时 $12、每周 $30 和每月 $60(实际请求计数因模型和使用情况而异)。",
+    "免费模型包含 Big Pickle 加上当时可用的促销模型,每天有 200 次请求的配额。Go 包含 GLM-5.1, GLM-5, Kimi K2.5, MiMo-V2-Pro, MiMo-V2-Omni, Qwen3.5 Plus, Qwen3.6 Plus, MiniMax M2.5 和 MiniMax M2.7,并在滚动窗口(5 小时、每周和每月)内执行更高的请求配额,大致相当于每 5 小时 $12、每周 $30 和每月 $60(实际请求计数因模型和使用情况而异)。",
 
 
   "zen.api.error.rateLimitExceeded": "超出速率限制。请稍后重试。",
   "zen.api.error.rateLimitExceeded": "超出速率限制。请稍后重试。",
   "zen.api.error.modelNotSupported": "不支持模型 {{model}}",
   "zen.api.error.modelNotSupported": "不支持模型 {{model}}",

+ 6 - 6
packages/console/app/src/i18n/zht.ts

@@ -241,7 +241,7 @@ export const dict = {
 
 
   "go.title": "OpenCode Go | 低成本全民編碼模型",
   "go.title": "OpenCode Go | 低成本全民編碼模型",
   "go.meta.description":
   "go.meta.description":
-    "Go 首月 $5,之後 $10/月,提供對 GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、MiniMax M2.5 和 MiniMax M2.7 的 5 小時充裕請求額度。",
+    "Go 首月 $5,之後 $10/月,提供對 GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、Qwen3.5 Plus、Qwen3.6 Plus、MiniMax M2.5 和 MiniMax M2.7 的 5 小時充裕請求額度。",
   "go.hero.title": "低成本全民編碼模型",
   "go.hero.title": "低成本全民編碼模型",
   "go.hero.body":
   "go.hero.body":
     "Go 將代理編碼帶給全世界的程式設計師。提供寬裕的限額以及對最強大開源模型的穩定存取,讓你可以使用強大的代理進行構建,而無需擔心成本或可用性。",
     "Go 將代理編碼帶給全世界的程式設計師。提供寬裕的限額以及對最強大開源模型的穩定存取,讓你可以使用強大的代理進行構建,而無需擔心成本或可用性。",
@@ -288,7 +288,8 @@ export const dict = {
   "go.problem.item1": "低成本訂閱定價",
   "go.problem.item1": "低成本訂閱定價",
   "go.problem.item2": "寬裕的限額與穩定存取",
   "go.problem.item2": "寬裕的限額與穩定存取",
   "go.problem.item3": "專為盡可能多的程式設計師打造",
   "go.problem.item3": "專為盡可能多的程式設計師打造",
-  "go.problem.item4": "包含 GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、MiniMax M2.5 與 MiniMax M2.7",
+  "go.problem.item4":
+    "包含 GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、Qwen3.5 Plus、Qwen3.6 Plus、MiniMax M2.5 與 MiniMax M2.7",
   "go.how.title": "Go 如何運作",
   "go.how.title": "Go 如何運作",
   "go.how.body": "Go 起價為首月 $5,之後 $10/月。您可以將其與 OpenCode 或任何代理搭配使用。",
   "go.how.body": "Go 起價為首月 $5,之後 $10/月。您可以將其與 OpenCode 或任何代理搭配使用。",
   "go.how.step1.title": "建立帳號",
   "go.how.step1.title": "建立帳號",
@@ -307,11 +308,10 @@ export const dict = {
   "go.faq.q1": "什麼是 OpenCode Go?",
   "go.faq.q1": "什麼是 OpenCode Go?",
   "go.faq.a1": "Go 是一個低成本訂閱方案,讓你穩定存取強大的開源模型以進行代理編碼。",
   "go.faq.a1": "Go 是一個低成本訂閱方案,讓你穩定存取強大的開源模型以進行代理編碼。",
   "go.faq.q2": "Go 包含哪些模型?",
   "go.faq.q2": "Go 包含哪些模型?",
-  "go.faq.a2":
-    "Go 包含 GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、MiniMax M2.5 與 MiniMax M2.7,並提供寬裕的限額與穩定存取。",
+  "go.faq.a2": "Go 包含下方列出的模型,提供充足的額度與穩定的存取。",
   "go.faq.q3": "Go 與 Zen 一樣嗎?",
   "go.faq.q3": "Go 與 Zen 一樣嗎?",
   "go.faq.a3":
   "go.faq.a3":
-    "不。Zen 是按量付費,而 Go 首月 $5,之後 $10/月,提供充裕的額度,並可可靠地存取 GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、MiniMax M2.5 和 MiniMax M2.7 等開源模型。",
+    "不。Zen 是按量付費,而 Go 首月 $5,之後 $10/月,提供充裕的額度,並可可靠地存取 GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、Qwen3.5 Plus、Qwen3.6 Plus、MiniMax M2.5 和 MiniMax M2.7 等開源模型。",
   "go.faq.q4": "Go 費用是多少?",
   "go.faq.q4": "Go 費用是多少?",
   "go.faq.a4.p1.beforePricing": "Go 費用為",
   "go.faq.a4.p1.beforePricing": "Go 費用為",
   "go.faq.a4.p1.pricingLink": "首月 $5",
   "go.faq.a4.p1.pricingLink": "首月 $5",
@@ -333,7 +333,7 @@ export const dict = {
 
 
   "go.faq.q9": "免費模型與 Go 有什麼區別?",
   "go.faq.q9": "免費模型與 Go 有什麼區別?",
   "go.faq.a9":
   "go.faq.a9":
-    "免費模型包括 Big Pickle 以及當時可用的促銷模型,配額為 200 次請求/天。Go 包括 GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、MiniMax M2.5 與 MiniMax M2.7,並在滾動視窗(5 小時、每週和每月)內執行更高的請求配額,大約相當於每 5 小時 $12、每週 $30 和每月 $60(實際請求數因模型和使用情況而異)。",
+    "免費模型包括 Big Pickle 以及當時可用的促銷模型,配額為 200 次請求/天。Go 包括 GLM-5.1、GLM-5、Kimi K2.5、MiMo-V2-Pro、MiMo-V2-Omni、Qwen3.5 Plus、Qwen3.6 Plus、MiniMax M2.5 與 MiniMax M2.7,並在滾動視窗(5 小時、每週和每月)內執行更高的請求配額,大約相當於每 5 小時 $12、每週 $30 和每月 $60(實際請求數因模型和使用情況而異)。",
 
 
   "zen.api.error.rateLimitExceeded": "超出頻率限制。請稍後再試。",
   "zen.api.error.rateLimitExceeded": "超出頻率限制。請稍後再試。",
   "zen.api.error.modelNotSupported": "不支援模型 {{model}}",
   "zen.api.error.modelNotSupported": "不支援模型 {{model}}",

+ 1 - 1
packages/console/app/src/routes/download/[channel]/[platform].ts

@@ -22,7 +22,7 @@ export async function GET({ params: { platform, channel } }: APIEvent) {
   if (!assetName) return new Response(null, { status: 404 })
   if (!assetName) return new Response(null, { status: 404 })
 
 
   const resp = await fetch(
   const resp = await fetch(
-    `https://github.com/anomalyco/${channel === "stable" ? "opencode" : "opencode-beta"}/releases/download/v1.4.3/${assetName}`,
+    `https://github.com/anomalyco/${channel === "stable" ? "opencode" : "opencode-beta"}/releases/latest/download/${assetName}`,
     {
     {
       cf: {
       cf: {
         // in case gh releases has rate limits
         // in case gh releases has rate limits

+ 24 - 0
packages/console/app/src/routes/go/index.css

@@ -1017,6 +1017,30 @@ body {
     [data-slot="faq-answer"] {
     [data-slot="faq-answer"] {
       margin-left: 40px;
       margin-left: 40px;
       margin-bottom: 32px;
       margin-bottom: 32px;
+
+      [data-slot="faq-models"] {
+        margin-top: 16px;
+        overflow-x: auto;
+
+        table {
+          width: 100%;
+          min-width: 28rem;
+          border-collapse: collapse;
+        }
+
+        th,
+        td {
+          padding: 12px 16px;
+          text-align: left;
+          white-space: nowrap;
+        }
+
+        th {
+          background: var(--color-background-weak);
+          color: var(--color-text-strong);
+          font-weight: 500;
+        }
+      }
     }
     }
   }
   }
 
 

+ 49 - 10
packages/console/app/src/routes/go/index.tsx

@@ -12,7 +12,7 @@ import { Footer } from "~/component/footer"
 import { Header } from "~/component/header"
 import { Header } from "~/component/header"
 import { config } from "~/config"
 import { config } from "~/config"
 import { getLastSeenWorkspaceID } from "../workspace/common"
 import { getLastSeenWorkspaceID } from "../workspace/common"
-import { IconMiniMax, IconMiMo, IconZai } from "~/component/icon"
+import { IconMiniMax, IconMiMo, IconZai, IconAlibaba } from "~/component/icon"
 import { useI18n } from "~/context/i18n"
 import { useI18n } from "~/context/i18n"
 import { useLanguage } from "~/context/language"
 import { useLanguage } from "~/context/language"
 import { LocaleLinks } from "~/component/locale-links"
 import { LocaleLinks } from "~/component/locale-links"
@@ -22,6 +22,18 @@ const checkLoggedIn = query(async () => {
   return await getLastSeenWorkspaceID().catch(() => undefined)
   return await getLastSeenWorkspaceID().catch(() => undefined)
 }, "checkLoggedIn.get")
 }, "checkLoggedIn.get")
 
 
+const models = [
+  { name: "GLM-5.1", provider: "DeepInfra, Z.ai" },
+  { name: "GLM-5", provider: "DeepInfra, Z.ai" },
+  { name: "Kimi K2.5", provider: "Moonshot AI" },
+  { name: "MiMo-V2-Pro", provider: "Xiaomi MiMo" },
+  { name: "MiMo-V2-Omni", provider: "Xiaomi MiMo" },
+  { name: "Qwen3.5 Plus", provider: "Alibaba Cloud Model Studio" },
+  { name: "Qwen3.6 Plus", provider: "Alibaba Cloud Model Studio" },
+  { name: "MiniMax M2.7", provider: "MiniMax" },
+  { name: "MiniMax M2.5", provider: "MiniMax" },
+]
+
 function LimitsGraph(props: { href: string }) {
 function LimitsGraph(props: { href: string }) {
   let root!: HTMLElement
   let root!: HTMLElement
   const [visible, setVisible] = createSignal(false)
   const [visible, setVisible] = createSignal(false)
@@ -44,13 +56,13 @@ function LimitsGraph(props: { href: string }) {
   })
   })
 
 
   const free = 200
   const free = 200
-  const models = [
+  const graph = [
     { id: "glm-5.1", name: "GLM-5.1", req: 880, d: "100ms" },
     { id: "glm-5.1", name: "GLM-5.1", req: 880, d: "100ms" },
-    { id: "glm-5", name: "GLM-5", req: 1150, d: "120ms" },
     { id: "mimo-v2-pro", name: "MiMo-V2-Pro", req: 1290, d: "150ms" },
     { id: "mimo-v2-pro", name: "MiMo-V2-Pro", req: 1290, d: "150ms" },
     { id: "kimi", name: "Kimi K2.5", req: 1850, d: "240ms" },
     { id: "kimi", name: "Kimi K2.5", req: 1850, d: "240ms" },
-    { id: "minimax-m2.7", name: "MiniMax M2.7", req: 14000, d: "330ms" },
-    { id: "minimax-m2.5", name: "MiniMax M2.5", req: 20000, d: "360ms" },
+    { id: "qwen3.6-plus", name: "Qwen3.6 Plus", req: 3300, d: "280ms" },
+    { id: "minimax-m2.7", name: "MiniMax M2.7", req: 3400, d: "300ms" },
+    { id: "qwen3.5-plus", name: "Qwen3.5 Plus", req: 10200, d: "360ms" },
   ]
   ]
 
 
   const w = 720
   const w = 720
@@ -62,7 +74,7 @@ function LimitsGraph(props: { href: string }) {
   const plot = w - left - right
   const plot = w - left - right
 
 
   const ratio = (n: number) => n / free
   const ratio = (n: number) => n / free
-  const rmax = Math.max(1, ...models.map((m) => ratio(m.req)))
+  const rmax = Math.max(1, ...graph.map((m) => ratio(m.req)))
   const log = (n: number) => Math.log10(Math.max(n, 1))
   const log = (n: number) => Math.log10(Math.max(n, 1))
   const base = 24
   const base = 24
   const p = 1.8
   const p = 1.8
@@ -93,7 +105,7 @@ function LimitsGraph(props: { href: string }) {
   const sep = bh + 40
   const sep = bh + 40
   const fy = top + 22
   const fy = top + 22
   const gy = (i: number) => fy + sep + step * i
   const gy = (i: number) => fy + sep + step * i
-  const my = models.length < 2 ? gy(0) : (gy(0) + gy(models.length - 1)) / 2
+  const my = graph.length < 2 ? gy(0) : (gy(0) + gy(graph.length - 1)) / 2
   const px = (n: number) => `${(n / w) * 100}%`
   const px = (n: number) => `${(n / w) * 100}%`
   const py = (n: number) => `${(n / h) * 100}%`
   const py = (n: number) => `${(n / h) * 100}%`
   const lx = px(left - 16)
   const lx = px(left - 16)
@@ -132,7 +144,7 @@ function LimitsGraph(props: { href: string }) {
               <rect x={left} y={fy - bh / 2} width={Math.max(0, x(1) - left)} height={bh} data-bar data-kind="free" />
               <rect x={left} y={fy - bh / 2} width={Math.max(0, x(1) - left)} height={bh} data-bar data-kind="free" />
             </g>
             </g>
 
 
-            <For each={models}>
+            <For each={graph}>
               {(m, i) => (
               {(m, i) => (
                 <g style={{ "--d": m.d } as any}>
                 <g style={{ "--d": m.d } as any}>
                   <rect
                   <rect
@@ -174,7 +186,7 @@ function LimitsGraph(props: { href: string }) {
             <span data-value>{free.toLocaleString()}</span>
             <span data-value>{free.toLocaleString()}</span>
             <span data-name>{i18n.t("go.graph.freePill")}</span>
             <span data-name>{i18n.t("go.graph.freePill")}</span>
           </span>
           </span>
-          <For each={models}>
+          <For each={graph}>
             {(m, i) => (
             {(m, i) => (
               <span
               <span
                 data-item
                 data-item
@@ -300,6 +312,9 @@ export default function Home() {
                 <div>
                 <div>
                   <IconZai width="24" height="24" />
                   <IconZai width="24" height="24" />
                 </div>
                 </div>
+                <div>
+                  <IconAlibaba width="24" height="24" />
+                </div>
                 <div>
                 <div>
                   <IconMiMo width="24" height="24" />
                   <IconMiMo width="24" height="24" />
                 </div>
                 </div>
@@ -420,7 +435,31 @@ export default function Home() {
                 <Faq question={i18n.t("go.faq.q1")}>{i18n.t("go.faq.a1")}</Faq>
                 <Faq question={i18n.t("go.faq.q1")}>{i18n.t("go.faq.a1")}</Faq>
               </li>
               </li>
               <li>
               <li>
-                <Faq question={i18n.t("go.faq.q2")}>{i18n.t("go.faq.a2")}</Faq>
+                <Faq question={i18n.t("go.faq.q2")}>
+                  {i18n.t("go.faq.a2")}
+                  {language.locale() === "en" && (
+                    <div data-slot="faq-models">
+                      <table>
+                        <thead>
+                          <tr>
+                            <th>{i18n.t("workspace.models.table.model")}</th>
+                            <th>{i18n.t("workspace.providers.table.provider")}</th>
+                          </tr>
+                        </thead>
+                        <tbody>
+                          <For each={models}>
+                            {(m) => (
+                              <tr>
+                                <td>{m.name}</td>
+                                <td>{m.provider}</td>
+                              </tr>
+                            )}
+                          </For>
+                        </tbody>
+                      </table>
+                    </div>
+                  )}
+                </Faq>
               </li>
               </li>
               <li>
               <li>
                 <Faq question={i18n.t("go.faq.q9")}>{i18n.t("go.faq.a9")}</Faq>
                 <Faq question={i18n.t("go.faq.q9")}>{i18n.t("go.faq.a9")}</Faq>

+ 2 - 0
packages/console/app/src/routes/workspace/[id]/go/lite-section.tsx

@@ -292,6 +292,8 @@ export function LiteSection() {
             <li>Mimo-V2-Omni</li>
             <li>Mimo-V2-Omni</li>
             <li>MiniMax M2.5</li>
             <li>MiniMax M2.5</li>
             <li>MiniMax M2.7</li>
             <li>MiniMax M2.7</li>
+            <li>Qwen3.5 Plus</li>
+            <li>Qwen3.6 Plus</li>
           </ul>
           </ul>
           <p data-slot="promo-description">{i18n.t("workspace.lite.promo.footer")}</p>
           <p data-slot="promo-description">{i18n.t("workspace.lite.promo.footer")}</p>
           <div data-slot="subscribe-actions">
           <div data-slot="subscribe-actions">

+ 13 - 12
packages/console/app/src/routes/zen/util/handler.ts

@@ -222,22 +222,23 @@ export async function handler(
     logger.debug("STATUS: " + res.status + " " + res.statusText)
     logger.debug("STATUS: " + res.status + " " + res.statusText)
 
 
     // Handle non-streaming response
     // Handle non-streaming response
-    if (!isStream) {
+    if (!isStream || res.status === 429) {
       const json = await res.json()
       const json = await res.json()
-      const usageInfo = providerInfo.normalizeUsage(json.usage)
-      const costInfo = calculateCost(modelInfo, usageInfo)
-      await trialLimiter?.track(usageInfo)
       await rateLimiter?.track()
       await rateLimiter?.track()
-      await trackUsage(sessionId, billingSource, authInfo, modelInfo, providerInfo, usageInfo, costInfo)
-      await reload(billingSource, authInfo, costInfo)
+      if (json.usage) {
+        const usageInfo = providerInfo.normalizeUsage(json.usage)
+        const costInfo = calculateCost(modelInfo, usageInfo)
+        await trialLimiter?.track(usageInfo)
+        await trackUsage(sessionId, billingSource, authInfo, modelInfo, providerInfo, usageInfo, costInfo)
+        await reload(billingSource, authInfo, costInfo)
+        json.cost = calculateOccurredCost(billingSource, costInfo)
+      }
+      if (json.error?.message) {
+        json.error.message = `Error from provider${providerInfo.displayName ? ` (${providerInfo.displayName})` : ""}: ${json.error.message}`
+      }
 
 
       const responseConverter = createResponseConverter(providerInfo.format, opts.format)
       const responseConverter = createResponseConverter(providerInfo.format, opts.format)
-      const body = JSON.stringify(
-        responseConverter({
-          ...json,
-          cost: calculateOccurredCost(billingSource, costInfo),
-        }),
-      )
+      const body = JSON.stringify(responseConverter(json))
       logger.metric({ response_length: body.length })
       logger.metric({ response_length: body.length })
       logger.debug("RESPONSE: " + body)
       logger.debug("RESPONSE: " + body)
       dataDumper?.provideResponse(body)
       dataDumper?.provideResponse(body)

+ 1 - 1
packages/console/core/package.json

@@ -1,7 +1,7 @@
 {
 {
   "$schema": "https://json.schemastore.org/package.json",
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@opencode-ai/console-core",
   "name": "@opencode-ai/console-core",
-  "version": "1.4.4",
+  "version": "1.4.6",
   "private": true,
   "private": true,
   "type": "module",
   "type": "module",
   "license": "MIT",
   "license": "MIT",

+ 1 - 0
packages/console/core/src/model.ts

@@ -44,6 +44,7 @@ export namespace ZenData {
   })
   })
 
 
   const ProviderSchema = z.object({
   const ProviderSchema = z.object({
+    displayName: z.string().optional(),
     api: z.string(),
     api: z.string(),
     apiKey: z.union([z.string(), z.record(z.string(), z.string())]),
     apiKey: z.union([z.string(), z.record(z.string(), z.string())]),
     format: FormatSchema.optional(),
     format: FormatSchema.optional(),

+ 1 - 1
packages/console/function/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@opencode-ai/console-function",
   "name": "@opencode-ai/console-function",
-  "version": "1.4.4",
+  "version": "1.4.6",
   "$schema": "https://json.schemastore.org/package.json",
   "$schema": "https://json.schemastore.org/package.json",
   "private": true,
   "private": true,
   "type": "module",
   "type": "module",

+ 1 - 1
packages/console/mail/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@opencode-ai/console-mail",
   "name": "@opencode-ai/console-mail",
-  "version": "1.4.4",
+  "version": "1.4.6",
   "dependencies": {
   "dependencies": {
     "@jsx-email/all": "2.2.3",
     "@jsx-email/all": "2.2.3",
     "@jsx-email/cli": "1.4.3",
     "@jsx-email/cli": "1.4.3",

+ 1 - 1
packages/desktop-electron/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@opencode-ai/desktop-electron",
   "name": "@opencode-ai/desktop-electron",
   "private": true,
   "private": true,
-  "version": "1.4.4",
+  "version": "1.4.6",
   "type": "module",
   "type": "module",
   "license": "MIT",
   "license": "MIT",
   "homepage": "https://opencode.ai",
   "homepage": "https://opencode.ai",

+ 1 - 1
packages/desktop-electron/src/main/store.ts

@@ -7,7 +7,7 @@ const cache = new Map<string, Store>()
 export function getStore(name = SETTINGS_STORE) {
 export function getStore(name = SETTINGS_STORE) {
   const cached = cache.get(name)
   const cached = cache.get(name)
   if (cached) return cached
   if (cached) return cached
-  const next = new Store({ name, fileExtension: "" })
+  const next = new Store({ name, fileExtension: "", accessPropertiesByDotNotation: false })
   cache.set(name, next)
   cache.set(name, next)
   return next
   return next
 }
 }

+ 1 - 1
packages/desktop/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@opencode-ai/desktop",
   "name": "@opencode-ai/desktop",
   "private": true,
   "private": true,
-  "version": "1.4.4",
+  "version": "1.4.6",
   "type": "module",
   "type": "module",
   "license": "MIT",
   "license": "MIT",
   "scripts": {
   "scripts": {

+ 2 - 2
packages/enterprise/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@opencode-ai/enterprise",
   "name": "@opencode-ai/enterprise",
-  "version": "1.4.4",
+  "version": "1.4.6",
   "private": true,
   "private": true,
   "type": "module",
   "type": "module",
   "license": "MIT",
   "license": "MIT",
@@ -13,7 +13,7 @@
     "shell-prod": "sst shell --target Teams --stage production"
     "shell-prod": "sst shell --target Teams --stage production"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@opencode-ai/util": "workspace:*",
+    "@opencode-ai/shared": "workspace:*",
     "@opencode-ai/ui": "workspace:*",
     "@opencode-ai/ui": "workspace:*",
     "aws4fetch": "^1.0.20",
     "aws4fetch": "^1.0.20",
     "@pierre/diffs": "catalog:",
     "@pierre/diffs": "catalog:",

+ 2 - 2
packages/enterprise/src/core/share.ts

@@ -1,6 +1,6 @@
 import { Message, Model, Part, Session, SnapshotFileDiff } from "@opencode-ai/sdk/v2"
 import { Message, Model, Part, Session, SnapshotFileDiff } from "@opencode-ai/sdk/v2"
-import { fn } from "@opencode-ai/util/fn"
-import { iife } from "@opencode-ai/util/iife"
+import { fn } from "@opencode-ai/shared/util/fn"
+import { iife } from "@opencode-ai/shared/util/iife"
 import z from "zod"
 import z from "zod"
 import { Storage } from "./storage"
 import { Storage } from "./storage"
 
 

+ 1 - 1
packages/enterprise/src/core/storage.ts

@@ -1,5 +1,5 @@
 import { AwsClient } from "aws4fetch"
 import { AwsClient } from "aws4fetch"
-import { lazy } from "@opencode-ai/util/lazy"
+import { lazy } from "@opencode-ai/shared/util/lazy"
 
 
 export namespace Storage {
 export namespace Storage {
   export interface Adapter {
   export interface Adapter {

+ 3 - 3
packages/enterprise/src/routes/share/[shareID].tsx

@@ -10,9 +10,9 @@ import { Share } from "~/core/share"
 import { Logo, Mark } from "@opencode-ai/ui/logo"
 import { Logo, Mark } from "@opencode-ai/ui/logo"
 import { IconButton } from "@opencode-ai/ui/icon-button"
 import { IconButton } from "@opencode-ai/ui/icon-button"
 import { ProviderIcon } from "@opencode-ai/ui/provider-icon"
 import { ProviderIcon } from "@opencode-ai/ui/provider-icon"
-import { iife } from "@opencode-ai/util/iife"
-import { Binary } from "@opencode-ai/util/binary"
-import { NamedError } from "@opencode-ai/util/error"
+import { iife } from "@opencode-ai/shared/util/iife"
+import { Binary } from "@opencode-ai/shared/util/binary"
+import { NamedError } from "@opencode-ai/shared/util/error"
 import { DateTime } from "luxon"
 import { DateTime } from "luxon"
 import { createStore } from "solid-js/store"
 import { createStore } from "solid-js/store"
 import z from "zod"
 import z from "zod"

+ 1 - 1
packages/enterprise/test/core/share.test.ts

@@ -1,7 +1,7 @@
 import { describe, expect, test, afterAll } from "bun:test"
 import { describe, expect, test, afterAll } from "bun:test"
 import { Share } from "../../src/core/share"
 import { Share } from "../../src/core/share"
 import { Storage } from "../../src/core/storage"
 import { Storage } from "../../src/core/storage"
-import { Identifier } from "@opencode-ai/util/identifier"
+import { Identifier } from "@opencode-ai/shared/util/identifier"
 
 
 describe.concurrent("core.share", () => {
 describe.concurrent("core.share", () => {
   test("should create a share", async () => {
   test("should create a share", async () => {

+ 6 - 6
packages/extensions/zed/extension.toml

@@ -1,7 +1,7 @@
 id = "opencode"
 id = "opencode"
 name = "OpenCode"
 name = "OpenCode"
 description = "The open source coding agent."
 description = "The open source coding agent."
-version = "1.4.4"
+version = "1.4.6"
 schema_version = 1
 schema_version = 1
 authors = ["Anomaly"]
 authors = ["Anomaly"]
 repository = "https://github.com/anomalyco/opencode"
 repository = "https://github.com/anomalyco/opencode"
@@ -11,26 +11,26 @@ name = "OpenCode"
 icon = "./icons/opencode.svg"
 icon = "./icons/opencode.svg"
 
 
 [agent_servers.opencode.targets.darwin-aarch64]
 [agent_servers.opencode.targets.darwin-aarch64]
-archive = "https://github.com/anomalyco/opencode/releases/download/v1.4.4/opencode-darwin-arm64.zip"
+archive = "https://github.com/anomalyco/opencode/releases/download/v1.4.6/opencode-darwin-arm64.zip"
 cmd = "./opencode"
 cmd = "./opencode"
 args = ["acp"]
 args = ["acp"]
 
 
 [agent_servers.opencode.targets.darwin-x86_64]
 [agent_servers.opencode.targets.darwin-x86_64]
-archive = "https://github.com/anomalyco/opencode/releases/download/v1.4.4/opencode-darwin-x64.zip"
+archive = "https://github.com/anomalyco/opencode/releases/download/v1.4.6/opencode-darwin-x64.zip"
 cmd = "./opencode"
 cmd = "./opencode"
 args = ["acp"]
 args = ["acp"]
 
 
 [agent_servers.opencode.targets.linux-aarch64]
 [agent_servers.opencode.targets.linux-aarch64]
-archive = "https://github.com/anomalyco/opencode/releases/download/v1.4.4/opencode-linux-arm64.tar.gz"
+archive = "https://github.com/anomalyco/opencode/releases/download/v1.4.6/opencode-linux-arm64.tar.gz"
 cmd = "./opencode"
 cmd = "./opencode"
 args = ["acp"]
 args = ["acp"]
 
 
 [agent_servers.opencode.targets.linux-x86_64]
 [agent_servers.opencode.targets.linux-x86_64]
-archive = "https://github.com/anomalyco/opencode/releases/download/v1.4.4/opencode-linux-x64.tar.gz"
+archive = "https://github.com/anomalyco/opencode/releases/download/v1.4.6/opencode-linux-x64.tar.gz"
 cmd = "./opencode"
 cmd = "./opencode"
 args = ["acp"]
 args = ["acp"]
 
 
 [agent_servers.opencode.targets.windows-x86_64]
 [agent_servers.opencode.targets.windows-x86_64]
-archive = "https://github.com/anomalyco/opencode/releases/download/v1.4.4/opencode-windows-x64.zip"
+archive = "https://github.com/anomalyco/opencode/releases/download/v1.4.6/opencode-windows-x64.zip"
 cmd = "./opencode.exe"
 cmd = "./opencode.exe"
 args = ["acp"]
 args = ["acp"]

+ 1 - 1
packages/function/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@opencode-ai/function",
   "name": "@opencode-ai/function",
-  "version": "1.4.4",
+  "version": "1.4.6",
   "$schema": "https://json.schemastore.org/package.json",
   "$schema": "https://json.schemastore.org/package.json",
   "private": true,
   "private": true,
   "type": "module",
   "type": "module",

+ 6 - 4
packages/opencode/package.json

@@ -1,6 +1,6 @@
 {
 {
   "$schema": "https://json.schemastore.org/package.json",
   "$schema": "https://json.schemastore.org/package.json",
-  "version": "1.4.4",
+  "version": "1.4.6",
   "name": "opencode",
   "name": "opencode",
   "type": "module",
   "type": "module",
   "license": "MIT",
   "license": "MIT",
@@ -44,6 +44,7 @@
     "@effect/language-service": "0.84.2",
     "@effect/language-service": "0.84.2",
     "@octokit/webhooks-types": "7.6.1",
     "@octokit/webhooks-types": "7.6.1",
     "@opencode-ai/script": "workspace:*",
     "@opencode-ai/script": "workspace:*",
+    "@opencode-ai/shared": "workspace:*",
     "@parcel/watcher-darwin-arm64": "2.5.1",
     "@parcel/watcher-darwin-arm64": "2.5.1",
     "@parcel/watcher-darwin-x64": "2.5.1",
     "@parcel/watcher-darwin-x64": "2.5.1",
     "@parcel/watcher-linux-arm64-glibc": "2.5.1",
     "@parcel/watcher-linux-arm64-glibc": "2.5.1",
@@ -112,14 +113,15 @@
     "@octokit/rest": "catalog:",
     "@octokit/rest": "catalog:",
     "@openauthjs/openauth": "catalog:",
     "@openauthjs/openauth": "catalog:",
     "@opencode-ai/plugin": "workspace:*",
     "@opencode-ai/plugin": "workspace:*",
-    "@opencode-ai/server": "workspace:*",
     "@opencode-ai/script": "workspace:*",
     "@opencode-ai/script": "workspace:*",
     "@opencode-ai/sdk": "workspace:*",
     "@opencode-ai/sdk": "workspace:*",
-    "@opencode-ai/util": "workspace:*",
+    "@opencode-ai/server": "workspace:*",
+    "@openrouter/ai-sdk-provider": "2.5.1",
+    "@opentelemetry/api": "1.9.0",
+    "@opentelemetry/context-async-hooks": "2.6.1",
     "@opentelemetry/exporter-trace-otlp-http": "0.214.0",
     "@opentelemetry/exporter-trace-otlp-http": "0.214.0",
     "@opentelemetry/sdk-trace-base": "2.6.1",
     "@opentelemetry/sdk-trace-base": "2.6.1",
     "@opentelemetry/sdk-trace-node": "2.6.1",
     "@opentelemetry/sdk-trace-node": "2.6.1",
-    "@openrouter/ai-sdk-provider": "2.5.1",
     "@opentui/core": "0.1.99",
     "@opentui/core": "0.1.99",
     "@opentui/solid": "0.1.99",
     "@opentui/solid": "0.1.99",
     "@parcel/watcher": "2.5.1",
     "@parcel/watcher": "2.5.1",

+ 310 - 0
packages/opencode/specs/effect/instance-context.md

@@ -0,0 +1,310 @@
+# Instance context migration
+
+Practical plan for retiring the promise-backed / ALS-backed `Instance` helper in `src/project/instance.ts` and moving instance selection fully into Effect-provided scope.
+
+## Goal
+
+End state:
+
+- request, CLI, TUI, and tool entrypoints shift into an instance through Effect, not `Instance.provide(...)`
+- Effect code reads the current instance from `InstanceRef` or its eventual replacement, not from ALS-backed sync getters
+- per-directory boot, caching, and disposal are scoped Effect resources, not a module-level `Map<string, Promise<InstanceContext>>`
+- ALS remains only as a temporary bridge for native callback APIs that fire outside the Effect fiber tree
+
+## Current split
+
+Today `src/project/instance.ts` still owns two separate concerns:
+
+- ambient current-instance context through `LocalContext` / `AsyncLocalStorage`
+- per-directory boot and deduplication through `cache: Map<string, Promise<InstanceContext>>`
+
+At the same time, the Effect side already exists:
+
+- `src/effect/instance-ref.ts` provides `InstanceRef` and `WorkspaceRef`
+- `src/effect/run-service.ts` already attaches those refs when a runtime starts inside an active instance ALS context
+- `src/effect/instance-state.ts` already prefers `InstanceRef` and only falls back to ALS when needed
+
+That means the migration is not "invent instance context in Effect". The migration is "stop relying on the legacy helper as the primary source of truth".
+
+## End state shape
+
+Near-term target shape:
+
+```ts
+InstanceScope.with({ directory, workspaceID }, effect)
+```
+
+Responsibilities of `InstanceScope.with(...)`:
+
+- resolve `directory`, `project`, and `worktree`
+- acquire or reuse the scoped per-directory instance environment
+- provide `InstanceRef` and `WorkspaceRef`
+- run the caller's Effect inside that environment
+
+Code inside the boundary should then do one of these:
+
+```ts
+const ctx = yield * InstanceState.context
+const dir = yield * InstanceState.directory
+```
+
+Long-term, once `InstanceState` itself is replaced by keyed layers / `LayerMap`, those reads can move to an `InstanceContext` service without changing the outer migration order.
+
+## Migration phases
+
+### Phase 1: stop expanding the legacy surface
+
+Rules for all new code:
+
+- do not add new `Instance.directory`, `Instance.worktree`, `Instance.project`, or `Instance.current` reads inside Effect code
+- do not add new `Instance.provide(...)` boundaries unless there is no Effect-native seam yet
+- use `InstanceState.context`, `InstanceState.directory`, or an explicit `ctx` parameter inside Effect code
+
+Success condition:
+
+- the file inventory below only shrinks from here
+
+### Phase 2: remove direct sync getter reads from Effect services
+
+Convert Effect services first, before replacing the top-level boundary. These modules already run inside Effect and mostly need `yield* InstanceState.context` or a yielded `ctx` instead of ambient sync access.
+
+Primary batch, highest payoff:
+
+- `src/file/index.ts`
+- `src/lsp/server.ts`
+- `src/worktree/index.ts`
+- `src/file/watcher.ts`
+- `src/format/formatter.ts`
+- `src/session/index.ts`
+- `src/project/vcs.ts`
+
+Mechanical replacement rule:
+
+- `Instance.directory` -> `ctx.directory` or `yield* InstanceState.directory`
+- `Instance.worktree` -> `ctx.worktree`
+- `Instance.project` -> `ctx.project`
+
+Do not thread strings manually through every public method if the service already has access to Effect context.
+
+### Phase 3: convert entry boundaries to provide instance refs directly
+
+After the service bodies stop assuming ALS, move the top-level boundaries to shift into Effect explicitly.
+
+Main boundaries:
+
+- HTTP server middleware and experimental `HttpApi` entrypoints
+- CLI commands
+- TUI worker / attach / thread entrypoints
+- tool execution entrypoints
+
+These boundaries should become Effect-native wrappers that:
+
+- decode directory / workspace inputs
+- resolve the instance context once
+- provide `InstanceRef` and `WorkspaceRef`
+- run the requested Effect
+
+At that point `Instance.provide(...)` becomes a legacy adapter instead of the normal code path.
+
+### Phase 4: replace promise boot cache with scoped instance runtime
+
+Once boundaries and services both rely on Effect context, replace the module-level promise cache in `src/project/instance.ts`.
+
+Target replacement:
+
+- keyed scoped runtime or keyed layer acquisition for each directory
+- reuse via `ScopedCache`, `LayerMap`, or another keyed Effect resource manager
+- cleanup performed by scope finalizers instead of `disposeAll()` iterating a Promise map
+
+This phase should absorb the current responsibilities of:
+
+- `cache` in `src/project/instance.ts`
+- `boot(...)`
+- most of `disposeInstance(...)`
+- manual `reload(...)` / `disposeAll()` fan-out logic
+
+### Phase 5: shrink ALS to callback bridges only
+
+Keep ALS only where a library invokes callbacks outside the Effect fiber tree and we still need to call code that reads instance context synchronously.
+
+Known bridge cases today:
+
+- `src/file/watcher.ts`
+- `src/session/llm.ts`
+- some LSP and plugin callback paths
+
+If those libraries become fully wrapped in Effect services, the remaining `Instance.bind(...)` uses can disappear too.
+
+### Phase 6: delete the legacy sync API
+
+Only after earlier phases land:
+
+- remove broad use of `Instance.current`, `Instance.directory`, `Instance.worktree`, `Instance.project`
+- reduce `src/project/instance.ts` to a thin compatibility shim or delete it entirely
+- remove the ALS fallback from `InstanceState.context`
+
+## Inventory of direct legacy usage
+
+Direct legacy usage means any source file that still calls one of:
+
+- `Instance.current`
+- `Instance.directory`
+- `Instance.worktree`
+- `Instance.project`
+- `Instance.provide(...)`
+- `Instance.bind(...)`
+- `Instance.restore(...)`
+- `Instance.reload(...)`
+- `Instance.dispose()` / `Instance.disposeAll()`
+
+Current total: `54` files in `packages/opencode/src`.
+
+### Core bridge and plumbing
+
+These files define or adapt the current bridge. They should change last, after callers have moved.
+
+- `src/project/instance.ts`
+- `src/effect/run-service.ts`
+- `src/effect/instance-state.ts`
+- `src/project/bootstrap.ts`
+- `src/config/config.ts`
+
+Migration rule:
+
+- keep these as compatibility glue until the outer boundaries and inner services stop depending on ALS
+
+### HTTP and server boundaries
+
+These are the current request-entry seams that still create or consume instance context through the legacy helper.
+
+- `src/server/instance/middleware.ts`
+- `src/server/instance/index.ts`
+- `src/server/instance/project.ts`
+- `src/server/instance/workspace.ts`
+- `src/server/instance/file.ts`
+- `src/server/instance/experimental.ts`
+- `src/server/instance/global.ts`
+
+Migration rule:
+
+- move these to explicit Effect entrypoints that provide `InstanceRef` / `WorkspaceRef`
+- do not move these first; first reduce the number of downstream handlers and services that still expect ambient ALS
+
+### CLI and TUI boundaries
+
+These commands still enter an instance through `Instance.provide(...)` or read sync getters directly.
+
+- `src/cli/bootstrap.ts`
+- `src/cli/cmd/agent.ts`
+- `src/cli/cmd/debug/agent.ts`
+- `src/cli/cmd/debug/ripgrep.ts`
+- `src/cli/cmd/github.ts`
+- `src/cli/cmd/import.ts`
+- `src/cli/cmd/mcp.ts`
+- `src/cli/cmd/models.ts`
+- `src/cli/cmd/plug.ts`
+- `src/cli/cmd/pr.ts`
+- `src/cli/cmd/providers.ts`
+- `src/cli/cmd/stats.ts`
+- `src/cli/cmd/tui/attach.ts`
+- `src/cli/cmd/tui/plugin/runtime.ts`
+- `src/cli/cmd/tui/thread.ts`
+- `src/cli/cmd/tui/worker.ts`
+
+Migration rule:
+
+- converge these on one shared `withInstance(...)` Effect entry helper instead of open-coded `Instance.provide(...)`
+- after that helper is proven, inline the legacy implementation behind an Effect-native scope provider
+
+### Tool boundary code
+
+These tools mostly use direct getters for path resolution and repo-relative display logic.
+
+- `src/tool/apply_patch.ts`
+- `src/tool/bash.ts`
+- `src/tool/edit.ts`
+- `src/tool/lsp.ts`
+- `src/tool/multiedit.ts`
+- `src/tool/plan.ts`
+- `src/tool/read.ts`
+- `src/tool/write.ts`
+
+Migration rule:
+
+- expose the current instance as an explicit Effect dependency for tool execution
+- keep path logic local; avoid introducing another global singleton for tool state
+
+### Effect services still reading ambient instance state
+
+These modules are already the best near-term migration targets because they are in Effect code but still read sync getters from the legacy helper.
+
+- `src/agent/agent.ts`
+- `src/config/tui-migrate.ts`
+- `src/file/index.ts`
+- `src/file/watcher.ts`
+- `src/format/formatter.ts`
+- `src/lsp/client.ts`
+- `src/lsp/index.ts`
+- `src/lsp/server.ts`
+- `src/mcp/index.ts`
+- `src/project/vcs.ts`
+- `src/provider/provider.ts`
+- `src/pty/index.ts`
+- `src/session/index.ts`
+- `src/session/instruction.ts`
+- `src/session/llm.ts`
+- `src/session/system.ts`
+- `src/sync/index.ts`
+- `src/worktree/index.ts`
+
+Migration rule:
+
+- replace direct getter reads with `yield* InstanceState.context` or a yielded `ctx`
+- isolate `Instance.bind(...)` callers and convert only the truly callback-driven edges to bridge mode
+
+### Highest-churn hotspots
+
+Current highest direct-usage counts by file:
+
+- `src/file/index.ts` - `18`
+- `src/lsp/server.ts` - `14`
+- `src/worktree/index.ts` - `12`
+- `src/file/watcher.ts` - `9`
+- `src/cli/cmd/mcp.ts` - `8`
+- `src/format/formatter.ts` - `8`
+- `src/tool/apply_patch.ts` - `8`
+- `src/cli/cmd/github.ts` - `7`
+
+These files should drive the first measurable burn-down.
+
+## Recommended implementation order
+
+1. Migrate direct getter reads inside Effect services, starting with `file`, `lsp`, `worktree`, `format`, and `session`.
+2. Add one shared Effect-native boundary helper for CLI / tool / HTTP entrypoints so we stop open-coding `Instance.provide(...)`.
+3. Move experimental `HttpApi` entrypoints to that helper so the new server stack proves the pattern.
+4. Convert remaining CLI and tool boundaries.
+5. Replace the promise cache with a keyed scoped runtime or keyed layer map.
+6. Delete ALS fallback paths once only callback bridges still depend on them.
+
+## Definition of done
+
+This migration is done when all of the following are true:
+
+- new requests and commands enter an instance by providing Effect context, not ALS
+- Effect services no longer read `Instance.directory`, `Instance.worktree`, `Instance.project`, or `Instance.current`
+- `Instance.provide(...)` is gone from normal request / CLI / tool execution
+- per-directory boot and disposal are handled by scoped Effect resources
+- `Instance.bind(...)` is either gone or confined to a tiny set of native callback adapters
+
+## Tracker and worktree
+
+Active tracker items:
+
+- `lh7l73` - overall `HttpApi` migration
+- `yobwlk` - remove direct `Instance.*` reads inside Effect services
+- `7irl1e` - replace `InstanceState` / legacy instance caching with keyed Effect layers
+
+Dedicated worktree for this transition:
+
+- path: `/Users/kit/code/open-source/opencode-worktrees/instance-effect-shift`
+- branch: `kit/instance-effect-shift`

+ 4 - 0
packages/opencode/specs/effect/migration.md

@@ -13,6 +13,10 @@ Use `makeRuntime` (from `src/effect/run-service.ts`) to create a per-service `Ma
 
 
 Rule of thumb: if two open directories should not share one copy of the service, it needs `InstanceState`.
 Rule of thumb: if two open directories should not share one copy of the service, it needs `InstanceState`.
 
 
+## Instance context transition
+
+See `instance-context.md` for the phased plan to remove the legacy ALS / promise-backed `Instance` helper and move request / CLI / tool boundaries onto Effect-provided instance scope.
+
 ## Service shape
 ## Service shape
 
 
 Every service follows the same pattern — a single namespace with the service definition, layer, `runPromise`, and async facade functions:
 Every service follows the same pattern — a single namespace with the service definition, layer, `runPromise`, and async facade functions:

+ 1 - 1
packages/opencode/src/acp/agent.ts

@@ -34,7 +34,7 @@ import {
 import { Log } from "../util/log"
 import { Log } from "../util/log"
 import { pathToFileURL } from "url"
 import { pathToFileURL } from "url"
 import { Filesystem } from "../util/filesystem"
 import { Filesystem } from "../util/filesystem"
-import { Hash } from "../util/hash"
+import { Hash } from "@opencode-ai/shared/util/hash"
 import { ACPSessionManager } from "./session"
 import { ACPSessionManager } from "./session"
 import type { ACPConfig } from "./types"
 import type { ACPConfig } from "./types"
 import { Provider } from "../provider/provider"
 import { Provider } from "../provider/provider"

+ 1 - 1
packages/opencode/src/auth/index.ts

@@ -2,7 +2,7 @@ import path from "path"
 import { Effect, Layer, Record, Result, Schema, Context } from "effect"
 import { Effect, Layer, Record, Result, Schema, Context } from "effect"
 import { zod } from "@/util/effect-zod"
 import { zod } from "@/util/effect-zod"
 import { Global } from "../global"
 import { Global } from "../global"
-import { AppFileSystem } from "../filesystem"
+import { AppFileSystem } from "@opencode-ai/shared/filesystem"
 
 
 export const OAUTH_DUMMY_KEY = "opencode-oauth-dummy-key"
 export const OAUTH_DUMMY_KEY = "opencode-oauth-dummy-key"
 
 

+ 3 - 2
packages/opencode/src/bus/index.ts

@@ -1,6 +1,6 @@
 import z from "zod"
 import z from "zod"
 import { Effect, Exit, Layer, PubSub, Scope, Context, Stream } from "effect"
 import { Effect, Exit, Layer, PubSub, Scope, Context, Stream } from "effect"
-import { EffectLogger } from "@/effect/logger"
+import { EffectBridge } from "@/effect/bridge"
 import { Log } from "../util/log"
 import { Log } from "../util/log"
 import { BusEvent } from "./bus-event"
 import { BusEvent } from "./bus-event"
 import { GlobalBus } from "./global"
 import { GlobalBus } from "./global"
@@ -128,6 +128,7 @@ export namespace Bus {
       function on<T>(pubsub: PubSub.PubSub<T>, type: string, callback: (event: T) => unknown) {
       function on<T>(pubsub: PubSub.PubSub<T>, type: string, callback: (event: T) => unknown) {
         return Effect.gen(function* () {
         return Effect.gen(function* () {
           log.info("subscribing", { type })
           log.info("subscribing", { type })
+          const bridge = yield* EffectBridge.make()
           const scope = yield* Scope.make()
           const scope = yield* Scope.make()
           const subscription = yield* Scope.provide(scope)(PubSub.subscribe(pubsub))
           const subscription = yield* Scope.provide(scope)(PubSub.subscribe(pubsub))
 
 
@@ -147,7 +148,7 @@ export namespace Bus {
 
 
           return () => {
           return () => {
             log.info("unsubscribing", { type })
             log.info("unsubscribing", { type })
-            Effect.runFork(Scope.close(scope, Exit.void).pipe(Effect.provide(EffectLogger.layer)))
+            bridge.fork(Scope.close(scope, Exit.void))
           }
           }
         })
         })
       }
       }

+ 6 - 6
packages/opencode/src/cli/cmd/tui/context/sync.tsx

@@ -22,7 +22,7 @@ import { createStore, produce, reconcile } from "solid-js/store"
 import { useProject } from "@tui/context/project"
 import { useProject } from "@tui/context/project"
 import { useEvent } from "@tui/context/event"
 import { useEvent } from "@tui/context/event"
 import { useSDK } from "@tui/context/sdk"
 import { useSDK } from "@tui/context/sdk"
-import { Binary } from "@opencode-ai/util/binary"
+import { Binary } from "@opencode-ai/shared/util/binary"
 import { createSimpleContext } from "./helper"
 import { createSimpleContext } from "./helper"
 import type { Snapshot } from "@/snapshot"
 import type { Snapshot } from "@/snapshot"
 import { useExit } from "./exit"
 import { useExit } from "./exit"
@@ -336,7 +336,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
 
 
         case "lsp.updated": {
         case "lsp.updated": {
           const workspace = project.workspace.current()
           const workspace = project.workspace.current()
-          sdk.client.lsp.status({ workspace }).then((x) => setStore("lsp", x.data!))
+          sdk.client.lsp.status({ workspace }).then((x) => setStore("lsp", x.data ?? []))
           break
           break
         }
         }
 
 
@@ -419,14 +419,14 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
             ...(args.continue ? [] : [sessionListPromise.then((sessions) => setStore("session", reconcile(sessions)))]),
             ...(args.continue ? [] : [sessionListPromise.then((sessions) => setStore("session", reconcile(sessions)))]),
             consoleStatePromise.then((consoleState) => setStore("console_state", reconcile(consoleState))),
             consoleStatePromise.then((consoleState) => setStore("console_state", reconcile(consoleState))),
             sdk.client.command.list({ workspace }).then((x) => setStore("command", reconcile(x.data ?? []))),
             sdk.client.command.list({ workspace }).then((x) => setStore("command", reconcile(x.data ?? []))),
-            sdk.client.lsp.status({ workspace }).then((x) => setStore("lsp", reconcile(x.data!))),
-            sdk.client.mcp.status({ workspace }).then((x) => setStore("mcp", reconcile(x.data!))),
+            sdk.client.lsp.status({ workspace }).then((x) => setStore("lsp", reconcile(x.data ?? []))),
+            sdk.client.mcp.status({ workspace }).then((x) => setStore("mcp", reconcile(x.data ?? {}))),
             sdk.client.experimental.resource
             sdk.client.experimental.resource
               .list({ workspace })
               .list({ workspace })
               .then((x) => setStore("mcp_resource", reconcile(x.data ?? {}))),
               .then((x) => setStore("mcp_resource", reconcile(x.data ?? {}))),
-            sdk.client.formatter.status({ workspace }).then((x) => setStore("formatter", reconcile(x.data!))),
+            sdk.client.formatter.status({ workspace }).then((x) => setStore("formatter", reconcile(x.data ?? []))),
             sdk.client.session.status({ workspace }).then((x) => {
             sdk.client.session.status({ workspace }).then((x) => {
-              setStore("session_status", reconcile(x.data!))
+              setStore("session_status", reconcile(x.data ?? {}))
             }),
             }),
             sdk.client.provider.auth({ workspace }).then((x) => setStore("provider_auth", reconcile(x.data ?? {}))),
             sdk.client.provider.auth({ workspace }).then((x) => setStore("provider_auth", reconcile(x.data ?? {}))),
             sdk.client.vcs.get({ workspace }).then((x) => setStore("vcs", reconcile(x.data))),
             sdk.client.vcs.get({ workspace }).then((x) => setStore("vcs", reconcile(x.data))),

+ 1 - 1
packages/opencode/src/cli/cmd/tui/context/theme.tsx

@@ -2,7 +2,7 @@ import { CliRenderEvents, SyntaxStyle, RGBA, type TerminalColors } from "@opentu
 import path from "path"
 import path from "path"
 import { createEffect, createMemo, onCleanup, onMount } from "solid-js"
 import { createEffect, createMemo, onCleanup, onMount } from "solid-js"
 import { createSimpleContext } from "./helper"
 import { createSimpleContext } from "./helper"
-import { Glob } from "../../../../util/glob"
+import { Glob } from "@opencode-ai/shared/util/glob"
 import aura from "./theme/aura.json" with { type: "json" }
 import aura from "./theme/aura.json" with { type: "json" }
 import ayu from "./theme/ayu.json" with { type: "json" }
 import ayu from "./theme/ayu.json" with { type: "json" }
 import catppuccin from "./theme/catppuccin.json" with { type: "json" }
 import catppuccin from "./theme/catppuccin.json" with { type: "json" }

+ 1 - 1
packages/opencode/src/cli/cmd/tui/plugin/runtime.ts

@@ -34,7 +34,7 @@ import { hasTheme, upsertTheme } from "../context/theme"
 import { Global } from "@/global"
 import { Global } from "@/global"
 import { Filesystem } from "@/util/filesystem"
 import { Filesystem } from "@/util/filesystem"
 import { Process } from "@/util/process"
 import { Process } from "@/util/process"
-import { Flock } from "@/util/flock"
+import { Flock } from "@opencode-ai/shared/util/flock"
 import { Flag } from "@/flag/flag"
 import { Flag } from "@/flag/flag"
 import { INTERNAL_TUI_PLUGINS, type InternalTuiPlugin } from "./internal"
 import { INTERNAL_TUI_PLUGINS, type InternalTuiPlugin } from "./internal"
 import { setupSlots, Slot as View } from "./slots"
 import { setupSlots, Slot as View } from "./slots"

+ 1 - 1
packages/opencode/src/cli/ui.ts

@@ -1,6 +1,6 @@
 import z from "zod"
 import z from "zod"
 import { EOL } from "os"
 import { EOL } from "os"
-import { NamedError } from "@opencode-ai/util/error"
+import { NamedError } from "@opencode-ai/shared/util/error"
 import { logo as glyphs } from "./logo"
 import { logo as glyphs } from "./logo"
 
 
 export namespace UI {
 export namespace UI {

+ 3 - 3
packages/opencode/src/command/index.ts

@@ -1,9 +1,9 @@
 import { BusEvent } from "@/bus/bus-event"
 import { BusEvent } from "@/bus/bus-event"
 import { InstanceState } from "@/effect/instance-state"
 import { InstanceState } from "@/effect/instance-state"
+import { EffectBridge } from "@/effect/bridge"
 import type { InstanceContext } from "@/project/instance"
 import type { InstanceContext } from "@/project/instance"
 import { SessionID, MessageID } from "@/session/schema"
 import { SessionID, MessageID } from "@/session/schema"
 import { Effect, Layer, Context } from "effect"
 import { Effect, Layer, Context } from "effect"
-import { EffectLogger } from "@/effect/logger"
 import z from "zod"
 import z from "zod"
 import { Config } from "../config/config"
 import { Config } from "../config/config"
 import { MCP } from "../mcp"
 import { MCP } from "../mcp"
@@ -82,6 +82,7 @@ export namespace Command {
 
 
       const init = Effect.fn("Command.state")(function* (ctx: InstanceContext) {
       const init = Effect.fn("Command.state")(function* (ctx: InstanceContext) {
         const cfg = yield* config.get()
         const cfg = yield* config.get()
+        const bridge = yield* EffectBridge.make()
         const commands: Record<string, Info> = {}
         const commands: Record<string, Info> = {}
 
 
         commands[Default.INIT] = {
         commands[Default.INIT] = {
@@ -125,7 +126,7 @@ export namespace Command {
             source: "mcp",
             source: "mcp",
             description: prompt.description,
             description: prompt.description,
             get template() {
             get template() {
-              return Effect.runPromise(
+              return bridge.promise(
                 mcp
                 mcp
                   .getPrompt(
                   .getPrompt(
                     prompt.client,
                     prompt.client,
@@ -141,7 +142,6 @@ export namespace Command {
                           .map((message) => (message.content.type === "text" ? message.content.text : ""))
                           .map((message) => (message.content.type === "text" ? message.content.text : ""))
                           .join("\n") || "",
                           .join("\n") || "",
                     ),
                     ),
-                    Effect.provide(EffectLogger.layer),
                   ),
                   ),
               )
               )
             },
             },

+ 5 - 5
packages/opencode/src/config/config.ts

@@ -7,7 +7,7 @@ import z from "zod"
 import { mergeDeep, pipe, unique } from "remeda"
 import { mergeDeep, pipe, unique } from "remeda"
 import { Global } from "../global"
 import { Global } from "../global"
 import fsNode from "fs/promises"
 import fsNode from "fs/promises"
-import { NamedError } from "@opencode-ai/util/error"
+import { NamedError } from "@opencode-ai/shared/util/error"
 import { Flag } from "../flag/flag"
 import { Flag } from "../flag/flag"
 import { Auth } from "../auth"
 import { Auth } from "../auth"
 import { Env } from "../env"
 import { Env } from "../env"
@@ -26,17 +26,17 @@ import { existsSync } from "fs"
 import { Bus } from "@/bus"
 import { Bus } from "@/bus"
 import { GlobalBus } from "@/bus/global"
 import { GlobalBus } from "@/bus/global"
 import { Event } from "../server/event"
 import { Event } from "../server/event"
-import { Glob } from "../util/glob"
+import { Glob } from "@opencode-ai/shared/util/glob"
 import { Account } from "@/account"
 import { Account } from "@/account"
 import { isRecord } from "@/util/record"
 import { isRecord } from "@/util/record"
 import { ConfigPaths } from "./paths"
 import { ConfigPaths } from "./paths"
 import type { ConsoleState } from "./console-state"
 import type { ConsoleState } from "./console-state"
-import { AppFileSystem } from "@/filesystem"
+import { AppFileSystem } from "@opencode-ai/shared/filesystem"
 import { InstanceState } from "@/effect/instance-state"
 import { InstanceState } from "@/effect/instance-state"
 import { Context, Duration, Effect, Exit, Fiber, Layer, Option } from "effect"
 import { Context, Duration, Effect, Exit, Fiber, Layer, Option } from "effect"
-import { Flock } from "@/util/flock"
+import { Flock } from "@opencode-ai/shared/util/flock"
 import { isPathPluginSpec, parsePluginSpecifier, resolvePathPluginTarget } from "@/plugin/shared"
 import { isPathPluginSpec, parsePluginSpecifier, resolvePathPluginTarget } from "@/plugin/shared"
-import { Npm } from "@/npm"
+import { Npm } from "../npm"
 import { InstanceRef } from "@/effect/instance-ref"
 import { InstanceRef } from "@/effect/instance-ref"
 
 
 export namespace Config {
 export namespace Config {

+ 1 - 1
packages/opencode/src/config/markdown.ts

@@ -1,4 +1,4 @@
-import { NamedError } from "@opencode-ai/util/error"
+import { NamedError } from "@opencode-ai/shared/util/error"
 import matter from "gray-matter"
 import matter from "gray-matter"
 import { z } from "zod"
 import { z } from "zod"
 import { Filesystem } from "../util/filesystem"
 import { Filesystem } from "../util/filesystem"

+ 1 - 1
packages/opencode/src/config/paths.ts

@@ -2,7 +2,7 @@ import path from "path"
 import os from "os"
 import os from "os"
 import z from "zod"
 import z from "zod"
 import { type ParseError as JsoncParseError, parse as parseJsonc, printParseErrorCode } from "jsonc-parser"
 import { type ParseError as JsoncParseError, parse as parseJsonc, printParseErrorCode } from "jsonc-parser"
-import { NamedError } from "@opencode-ai/util/error"
+import { NamedError } from "@opencode-ai/shared/util/error"
 import { Filesystem } from "@/util/filesystem"
 import { Filesystem } from "@/util/filesystem"
 import { Flag } from "@/flag/flag"
 import { Flag } from "@/flag/flag"
 import { Global } from "@/global"
 import { Global } from "@/global"

+ 1 - 1
packages/opencode/src/config/tui.ts

@@ -13,7 +13,7 @@ import { Global } from "@/global"
 import { Filesystem } from "@/util/filesystem"
 import { Filesystem } from "@/util/filesystem"
 import { InstanceState } from "@/effect/instance-state"
 import { InstanceState } from "@/effect/instance-state"
 import { makeRuntime } from "@/effect/run-service"
 import { makeRuntime } from "@/effect/run-service"
-import { AppFileSystem } from "@/filesystem"
+import { AppFileSystem } from "@opencode-ai/shared/filesystem"
 
 
 export namespace TuiConfig {
 export namespace TuiConfig {
   const log = Log.create({ service: "tui.config" })
   const log = Log.create({ service: "tui.config" })

+ 4 - 0
packages/opencode/src/control-plane/workspace-context.ts

@@ -12,6 +12,10 @@ export const WorkspaceContext = {
     return context.provide({ workspaceID: input.workspaceID as string }, () => input.fn())
     return context.provide({ workspaceID: input.workspaceID as string }, () => input.fn())
   },
   },
 
 
+  restore<R>(workspaceID: string, fn: () => R): R {
+    return context.provide({ workspaceID }, fn)
+  },
+
   get workspaceID() {
   get workspaceID() {
     try {
     try {
       return context.use().workspaceID
       return context.use().workspaceID

+ 238 - 22
packages/opencode/src/control-plane/workspace.ts

@@ -1,20 +1,27 @@
 import z from "zod"
 import z from "zod"
 import { setTimeout as sleep } from "node:timers/promises"
 import { setTimeout as sleep } from "node:timers/promises"
 import { fn } from "@/util/fn"
 import { fn } from "@/util/fn"
-import { Database, eq } from "@/storage/db"
+import { Database, asc, eq } from "@/storage/db"
 import { Project } from "@/project/project"
 import { Project } from "@/project/project"
 import { BusEvent } from "@/bus/bus-event"
 import { BusEvent } from "@/bus/bus-event"
 import { GlobalBus } from "@/bus/global"
 import { GlobalBus } from "@/bus/global"
 import { SyncEvent } from "@/sync"
 import { SyncEvent } from "@/sync"
+import { EventTable } from "@/sync/event.sql"
+import { Flag } from "@/flag/flag"
 import { Log } from "@/util/log"
 import { Log } from "@/util/log"
 import { Filesystem } from "@/util/filesystem"
 import { Filesystem } from "@/util/filesystem"
 import { ProjectID } from "@/project/schema"
 import { ProjectID } from "@/project/schema"
-import { Slug } from "@opencode-ai/util/slug"
+import { Slug } from "@opencode-ai/shared/util/slug"
 import { WorkspaceTable } from "./workspace.sql"
 import { WorkspaceTable } from "./workspace.sql"
 import { getAdaptor } from "./adaptors"
 import { getAdaptor } from "./adaptors"
 import { WorkspaceInfo } from "./types"
 import { WorkspaceInfo } from "./types"
 import { WorkspaceID } from "./schema"
 import { WorkspaceID } from "./schema"
 import { parseSSE } from "./sse"
 import { parseSSE } from "./sse"
+import { Session } from "@/session"
+import { SessionTable } from "@/session/session.sql"
+import { SessionID } from "@/session/schema"
+import { errorData } from "@/util/error"
+import { AppRuntime } from "@/effect/app-runtime"
 
 
 export namespace Workspace {
 export namespace Workspace {
   export const Info = WorkspaceInfo.meta({
   export const Info = WorkspaceInfo.meta({
@@ -29,6 +36,13 @@ export namespace Workspace {
   })
   })
   export type ConnectionStatus = z.infer<typeof ConnectionStatus>
   export type ConnectionStatus = z.infer<typeof ConnectionStatus>
 
 
+  const Restore = z.object({
+    workspaceID: WorkspaceID.zod,
+    sessionID: SessionID.zod,
+    total: z.number().int().min(0),
+    step: z.number().int().min(0),
+  })
+
   export const Event = {
   export const Event = {
     Ready: BusEvent.define(
     Ready: BusEvent.define(
       "workspace.ready",
       "workspace.ready",
@@ -42,6 +56,7 @@ export namespace Workspace {
         message: z.string(),
         message: z.string(),
       }),
       }),
     ),
     ),
+    Restore: BusEvent.define("workspace.restore", Restore),
     Status: BusEvent.define("workspace.status", ConnectionStatus),
     Status: BusEvent.define("workspace.status", ConnectionStatus),
   }
   }
 
 
@@ -102,11 +117,170 @@ export namespace Workspace {
     return info
     return info
   })
   })
 
 
+  const SessionRestoreInput = z.object({
+    workspaceID: WorkspaceID.zod,
+    sessionID: SessionID.zod,
+  })
+
+  export const sessionRestore = fn(SessionRestoreInput, async (input) => {
+    log.info("session restore requested", {
+      workspaceID: input.workspaceID,
+      sessionID: input.sessionID,
+    })
+    try {
+      const space = await get(input.workspaceID)
+      if (!space) throw new Error(`Workspace not found: ${input.workspaceID}`)
+
+      const adaptor = await getAdaptor(space.projectID, space.type)
+      const target = await adaptor.target(space)
+
+      // Need to switch the workspace of the session
+      SyncEvent.run(Session.Event.Updated, {
+        sessionID: input.sessionID,
+        info: {
+          workspaceID: input.workspaceID,
+        },
+      })
+
+      const rows = Database.use((db) =>
+        db
+          .select({
+            id: EventTable.id,
+            aggregateID: EventTable.aggregate_id,
+            seq: EventTable.seq,
+            type: EventTable.type,
+            data: EventTable.data,
+          })
+          .from(EventTable)
+          .where(eq(EventTable.aggregate_id, input.sessionID))
+          .orderBy(asc(EventTable.seq))
+          .all(),
+      )
+      if (rows.length === 0) throw new Error(`No events found for session: ${input.sessionID}`)
+
+      const all = rows
+
+      const size = 10
+      const sets = Array.from({ length: Math.ceil(all.length / size) }, (_, i) => all.slice(i * size, (i + 1) * size))
+      const total = sets.length
+      log.info("session restore prepared", {
+        workspaceID: input.workspaceID,
+        sessionID: input.sessionID,
+        workspaceType: space.type,
+        directory: space.directory,
+        target: target.type === "remote" ? String(route(target.url, "/sync/replay")) : target.directory,
+        events: all.length,
+        batches: total,
+        first: all[0]?.seq,
+        last: all.at(-1)?.seq,
+      })
+      GlobalBus.emit("event", {
+        directory: "global",
+        workspace: input.workspaceID,
+        payload: {
+          type: Event.Restore.type,
+          properties: {
+            workspaceID: input.workspaceID,
+            sessionID: input.sessionID,
+            total,
+            step: 0,
+          },
+        },
+      })
+      for (const [i, events] of sets.entries()) {
+        log.info("session restore batch starting", {
+          workspaceID: input.workspaceID,
+          sessionID: input.sessionID,
+          step: i + 1,
+          total,
+          events: events.length,
+          first: events[0]?.seq,
+          last: events.at(-1)?.seq,
+          target: target.type === "remote" ? String(route(target.url, "/sync/replay")) : target.directory,
+        })
+        if (target.type === "local") {
+          SyncEvent.replayAll(events)
+          log.info("session restore batch replayed locally", {
+            workspaceID: input.workspaceID,
+            sessionID: input.sessionID,
+            step: i + 1,
+            total,
+            events: events.length,
+          })
+        } else {
+          const url = route(target.url, "/sync/replay")
+          const headers = new Headers(target.headers)
+          headers.set("content-type", "application/json")
+          const res = await fetch(url, {
+            method: "POST",
+            headers,
+            body: JSON.stringify({
+              directory: space.directory ?? "",
+              events,
+            }),
+          })
+          if (!res.ok) {
+            const body = await res.text()
+            log.error("session restore batch failed", {
+              workspaceID: input.workspaceID,
+              sessionID: input.sessionID,
+              step: i + 1,
+              total,
+              status: res.status,
+              body,
+            })
+            throw new Error(
+              `Failed to replay session ${input.sessionID} into workspace ${input.workspaceID}: HTTP ${res.status} ${body}`,
+            )
+          }
+          log.info("session restore batch posted", {
+            workspaceID: input.workspaceID,
+            sessionID: input.sessionID,
+            step: i + 1,
+            total,
+            status: res.status,
+          })
+        }
+        GlobalBus.emit("event", {
+          directory: "global",
+          workspace: input.workspaceID,
+          payload: {
+            type: Event.Restore.type,
+            properties: {
+              workspaceID: input.workspaceID,
+              sessionID: input.sessionID,
+              total,
+              step: i + 1,
+            },
+          },
+        })
+      }
+
+      log.info("session restore complete", {
+        workspaceID: input.workspaceID,
+        sessionID: input.sessionID,
+        batches: total,
+      })
+
+      return {
+        total,
+      }
+    } catch (err) {
+      log.error("session restore failed", {
+        workspaceID: input.workspaceID,
+        sessionID: input.sessionID,
+        error: errorData(err),
+      })
+      throw err
+    }
+  })
+
   export function list(project: Project.Info) {
   export function list(project: Project.Info) {
     const rows = Database.use((db) =>
     const rows = Database.use((db) =>
       db.select().from(WorkspaceTable).where(eq(WorkspaceTable.project_id, project.id)).all(),
       db.select().from(WorkspaceTable).where(eq(WorkspaceTable.project_id, project.id)).all(),
     )
     )
     const spaces = rows.map(fromRow).sort((a, b) => a.id.localeCompare(b.id))
     const spaces = rows.map(fromRow).sort((a, b) => a.id.localeCompare(b.id))
+
     for (const space of spaces) startSync(space)
     for (const space of spaces) startSync(space)
     return spaces
     return spaces
   }
   }
@@ -120,13 +294,25 @@ export namespace Workspace {
   })
   })
 
 
   export const remove = fn(WorkspaceID.zod, async (id) => {
   export const remove = fn(WorkspaceID.zod, async (id) => {
+    const sessions = Database.use((db) =>
+      db.select({ id: SessionTable.id }).from(SessionTable).where(eq(SessionTable.workspace_id, id)).all(),
+    )
+    for (const session of sessions) {
+      await AppRuntime.runPromise(Session.Service.use((svc) => svc.remove(session.id)))
+    }
+
     const row = Database.use((db) => db.select().from(WorkspaceTable).where(eq(WorkspaceTable.id, id)).get())
     const row = Database.use((db) => db.select().from(WorkspaceTable).where(eq(WorkspaceTable.id, id)).get())
+
     if (row) {
     if (row) {
       stopSync(id)
       stopSync(id)
 
 
       const info = fromRow(row)
       const info = fromRow(row)
-      const adaptor = await getAdaptor(info.projectID, row.type)
-      adaptor.remove(info)
+      try {
+        const adaptor = await getAdaptor(info.projectID, row.type)
+        await adaptor.remove(info)
+      } catch (err) {
+        log.error("adaptor not available when removing workspace", { type: row.type })
+      }
       Database.use((db) => db.delete(WorkspaceTable).where(eq(WorkspaceTable.id, id)).run())
       Database.use((db) => db.delete(WorkspaceTable).where(eq(WorkspaceTable.id, id)).run())
       return info
       return info
     }
     }
@@ -156,51 +342,81 @@ export namespace Workspace {
 
 
   const log = Log.create({ service: "workspace-sync" })
   const log = Log.create({ service: "workspace-sync" })
 
 
-  async function workspaceEventLoop(space: Info, signal: AbortSignal) {
-    log.info("starting sync: " + space.id)
+  function route(url: string | URL, path: string) {
+    const next = new URL(url)
+    next.pathname = `${next.pathname.replace(/\/$/, "")}${path}`
+    next.search = ""
+    next.hash = ""
+    return next
+  }
 
 
+  async function syncWorkspace(space: Info, signal: AbortSignal) {
     while (!signal.aborted) {
     while (!signal.aborted) {
-      log.info("connecting to sync: " + space.id)
+      log.info("connecting to global sync", { workspace: space.name })
 
 
-      setStatus(space.id, "connecting")
       const adaptor = await getAdaptor(space.projectID, space.type)
       const adaptor = await getAdaptor(space.projectID, space.type)
       const target = await adaptor.target(space)
       const target = await adaptor.target(space)
 
 
       if (target.type === "local") return
       if (target.type === "local") return
 
 
-      const res = await fetch(target.url + "/sync/event", { method: "GET", signal }).catch((err: unknown) => {
-        setStatus(space.id, "error", String(err))
+      const res = await fetch(route(target.url, "/global/event"), {
+        method: "GET",
+        headers: target.headers,
+        signal,
+      }).catch((err: unknown) => {
+        setStatus(space.id, "error")
+
+        log.info("failed to connect to global sync", {
+          workspace: space.name,
+          error: err,
+        })
         return undefined
         return undefined
       })
       })
-      if (!res || !res.ok || !res.body) {
-        log.info("failed to connect to sync: " + res?.status)
 
 
-        setStatus(space.id, "error", res ? `HTTP ${res.status}` : "no response")
+      if (!res || !res.ok || !res.body) {
+        log.info("failed to connect to global sync", { workspace: space.name })
+        setStatus(space.id, "error")
         await sleep(1000)
         await sleep(1000)
         continue
         continue
       }
       }
+
+      log.info("global sync connected", { workspace: space.name })
       setStatus(space.id, "connected")
       setStatus(space.id, "connected")
-      await parseSSE(res.body, signal, (evt) => {
-        const event = evt as SyncEvent.SerializedEvent
 
 
+      await parseSSE(res.body, signal, (evt: any) => {
         try {
         try {
-          if (!event.type.startsWith("server.")) {
-            SyncEvent.replay(event)
+          if (!("payload" in evt)) return
+
+          if (evt.payload.type === "sync") {
+            // This name -> type is temporary
+            SyncEvent.replay({ ...evt.payload, type: evt.payload.name } as SyncEvent.SerializedEvent)
           }
           }
+
+          GlobalBus.emit("event", {
+            directory: evt.directory,
+            project: evt.project,
+            workspace: space.id,
+            payload: evt.payload,
+          })
         } catch (err) {
         } catch (err) {
-          log.warn("failed to replay sync event", {
+          log.info("failed to replay global event", {
             workspaceID: space.id,
             workspaceID: space.id,
             error: err,
             error: err,
           })
           })
         }
         }
       })
       })
+
+      log.info("disconnected from global sync: " + space.id)
       setStatus(space.id, "disconnected")
       setStatus(space.id, "disconnected")
-      log.info("disconnected to sync: " + space.id)
-      await sleep(250)
+
+      // TODO: Implement exponential backoff
+      await sleep(1000)
     }
     }
   }
   }
 
 
   function startSync(space: Info) {
   function startSync(space: Info) {
+    if (!Flag.OPENCODE_EXPERIMENTAL_WORKSPACES) return
+
     if (space.type === "worktree") {
     if (space.type === "worktree") {
       void Filesystem.exists(space.directory!).then((exists) => {
       void Filesystem.exists(space.directory!).then((exists) => {
         setStatus(space.id, exists ? "connected" : "error", exists ? undefined : "directory does not exist")
         setStatus(space.id, exists ? "connected" : "error", exists ? undefined : "directory does not exist")
@@ -213,9 +429,9 @@ export namespace Workspace {
     aborts.set(space.id, abort)
     aborts.set(space.id, abort)
     setStatus(space.id, "disconnected")
     setStatus(space.id, "disconnected")
 
 
-    void workspaceEventLoop(space, abort.signal).catch((error) => {
+    void syncWorkspace(space, abort.signal).catch((error) => {
       setStatus(space.id, "error", String(error))
       setStatus(space.id, "error", String(error))
-      log.warn("workspace sync listener failed", {
+      log.warn("workspace listener failed", {
         workspaceID: space.id,
         workspaceID: space.id,
         error,
         error,
       })
       })

+ 1 - 1
packages/opencode/src/effect/app-runtime.ts

@@ -2,7 +2,7 @@ import { Layer, ManagedRuntime } from "effect"
 import { attach, memoMap } from "./run-service"
 import { attach, memoMap } from "./run-service"
 import { Observability } from "./observability"
 import { Observability } from "./observability"
 
 
-import { AppFileSystem } from "@/filesystem"
+import { AppFileSystem } from "@opencode-ai/shared/filesystem"
 import { Bus } from "@/bus"
 import { Bus } from "@/bus"
 import { Auth } from "@/auth"
 import { Auth } from "@/auth"
 import { Account } from "@/account"
 import { Account } from "@/account"

+ 49 - 0
packages/opencode/src/effect/bridge.ts

@@ -0,0 +1,49 @@
+import { Effect, Fiber } from "effect"
+import { WorkspaceContext } from "@/control-plane/workspace-context"
+import { Instance, type InstanceContext } from "@/project/instance"
+import { LocalContext } from "@/util/local-context"
+import { InstanceRef, WorkspaceRef } from "./instance-ref"
+import { attachWith } from "./run-service"
+
+export namespace EffectBridge {
+  export interface Shape {
+    readonly promise: <A, E, R>(effect: Effect.Effect<A, E, R>) => Promise<A>
+    readonly fork: <A, E, R>(effect: Effect.Effect<A, E, R>) => Fiber.Fiber<A, E>
+  }
+
+  function restore<R>(instance: InstanceContext | undefined, workspace: string | undefined, fn: () => R): R {
+    if (instance && workspace !== undefined) {
+      return WorkspaceContext.restore(workspace, () => Instance.restore(instance, fn))
+    }
+    if (instance) return Instance.restore(instance, fn)
+    if (workspace !== undefined) return WorkspaceContext.restore(workspace, fn)
+    return fn()
+  }
+
+  export function make(): Effect.Effect<Shape> {
+    return Effect.gen(function* () {
+      const ctx = yield* Effect.context()
+      const value = yield* InstanceRef
+      const instance =
+        value ??
+        (() => {
+          try {
+            return Instance.current
+          } catch (err) {
+            if (!(err instanceof LocalContext.NotFound)) throw err
+          }
+        })()
+      const workspace = (yield* WorkspaceRef) ?? WorkspaceContext.workspaceID
+      const attach = <A, E, R>(effect: Effect.Effect<A, E, R>) => attachWith(effect, { instance, workspace })
+      const wrap = <A, E, R>(effect: Effect.Effect<A, E, R>) =>
+        attach(effect).pipe(Effect.provide(ctx)) as Effect.Effect<A, E, never>
+
+      return {
+        promise: <A, E, R>(effect: Effect.Effect<A, E, R>) =>
+          restore(instance, workspace, () => Effect.runPromise(wrap(effect))),
+        fork: <A, E, R>(effect: Effect.Effect<A, E, R>) =>
+          restore(instance, workspace, () => Effect.runFork(wrap(effect))),
+      } satisfies Shape
+    })
+  }
+}

+ 14 - 2
packages/opencode/src/effect/observability.ts

@@ -12,8 +12,8 @@ export namespace Observability {
   const headers = Flag.OTEL_EXPORTER_OTLP_HEADERS
   const headers = Flag.OTEL_EXPORTER_OTLP_HEADERS
     ? Flag.OTEL_EXPORTER_OTLP_HEADERS.split(",").reduce(
     ? Flag.OTEL_EXPORTER_OTLP_HEADERS.split(",").reduce(
         (acc, x) => {
         (acc, x) => {
-          const [key, value] = x.split("=")
-          acc[key] = value
+          const [key, ...value] = x.split("=")
+          acc[key] = value.join("=")
           return acc
           return acc
         },
         },
         {} as Record<string, string>,
         {} as Record<string, string>,
@@ -46,6 +46,18 @@ export namespace Observability {
     const OTLP = await import("@opentelemetry/exporter-trace-otlp-http")
     const OTLP = await import("@opentelemetry/exporter-trace-otlp-http")
     const SdkBase = await import("@opentelemetry/sdk-trace-base")
     const SdkBase = await import("@opentelemetry/sdk-trace-base")
 
 
+    // @effect/opentelemetry creates a NodeTracerProvider but never calls
+    // register(), so the global @opentelemetry/api context manager stays
+    // as the no-op default. Non-Effect code (like the AI SDK) that calls
+    // tracer.startActiveSpan() relies on context.active() to find the
+    // parent span — without a real context manager every span starts a
+    // new trace. Registering AsyncLocalStorageContextManager fixes this.
+    const { AsyncLocalStorageContextManager } = await import("@opentelemetry/context-async-hooks")
+    const { context } = await import("@opentelemetry/api")
+    const mgr = new AsyncLocalStorageContextManager()
+    mgr.enable()
+    context.setGlobalContextManager(mgr)
+
     return NodeSdk.layer(() => ({
     return NodeSdk.layer(() => ({
       resource,
       resource,
       spanProcessor: new SdkBase.BatchSpanProcessor(
       spanProcessor: new SdkBase.BatchSpanProcessor(

+ 20 - 3
packages/opencode/src/effect/run-service.ts

@@ -5,14 +5,31 @@ import { LocalContext } from "@/util/local-context"
 import { InstanceRef, WorkspaceRef } from "./instance-ref"
 import { InstanceRef, WorkspaceRef } from "./instance-ref"
 import { Observability } from "./observability"
 import { Observability } from "./observability"
 import { WorkspaceContext } from "@/control-plane/workspace-context"
 import { WorkspaceContext } from "@/control-plane/workspace-context"
+import type { InstanceContext } from "@/project/instance"
 
 
 export const memoMap = Layer.makeMemoMapUnsafe()
 export const memoMap = Layer.makeMemoMapUnsafe()
 
 
+type Refs = {
+  instance?: InstanceContext
+  workspace?: string
+}
+
+export function attachWith<A, E, R>(effect: Effect.Effect<A, E, R>, refs: Refs): Effect.Effect<A, E, R> {
+  if (!refs.instance && !refs.workspace) return effect
+  if (!refs.instance) return effect.pipe(Effect.provideService(WorkspaceRef, refs.workspace))
+  if (!refs.workspace) return effect.pipe(Effect.provideService(InstanceRef, refs.instance))
+  return effect.pipe(
+    Effect.provideService(InstanceRef, refs.instance),
+    Effect.provideService(WorkspaceRef, refs.workspace),
+  )
+}
+
 export function attach<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> {
 export function attach<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> {
   try {
   try {
-    const ctx = Instance.current
-    const workspaceID = WorkspaceContext.workspaceID
-    return effect.pipe(Effect.provideService(InstanceRef, ctx), Effect.provideService(WorkspaceRef, workspaceID))
+    return attachWith(effect, {
+      instance: Instance.current,
+      workspace: WorkspaceContext.workspaceID,
+    })
   } catch (err) {
   } catch (err) {
     if (!(err instanceof LocalContext.NotFound)) throw err
     if (!(err instanceof LocalContext.NotFound)) throw err
   }
   }

+ 0 - 19
packages/opencode/src/env/index.ts

@@ -1,6 +1,5 @@
 import { Context, Effect, Layer } from "effect"
 import { Context, Effect, Layer } from "effect"
 import { InstanceState } from "@/effect/instance-state"
 import { InstanceState } from "@/effect/instance-state"
-import { makeRuntime } from "@/effect/run-service"
 
 
 export namespace Env {
 export namespace Env {
   type State = Record<string, string | undefined>
   type State = Record<string, string | undefined>
@@ -35,22 +34,4 @@ export namespace Env {
   )
   )
 
 
   export const defaultLayer = layer
   export const defaultLayer = layer
-
-  const rt = makeRuntime(Service, defaultLayer)
-
-  export function get(key: string) {
-    return rt.runSync((svc) => svc.get(key))
-  }
-
-  export function all() {
-    return rt.runSync((svc) => svc.all())
-  }
-
-  export function set(key: string, value: string) {
-    return rt.runSync((svc) => svc.set(key, value))
-  }
-
-  export function remove(key: string) {
-    return rt.runSync((svc) => svc.remove(key))
-  }
 }
 }

Некоторые файлы не были показаны из-за большого количества измененных файлов