@eddyskywalker/dsh-chatgpt-subscription 0.54.0 → 0.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +148 -1268
  3. package/lib/client.js +398 -23
  4. package/lib/client.js.map +1 -1
  5. package/lib/{entry-progress-updates-BEkdyDZU.js → entry-progress-updates-CxQewio9.js} +4 -2
  6. package/lib/index.js +1089 -212
  7. package/lib/plan-mode.js +3 -7
  8. package/lib/progress-updates.js +1 -1
  9. package/lib/tool-result-pruner.js +1 -1
  10. package/lib/types/client/common/host-locale-mirror.d.ts +24 -0
  11. package/lib/types/client/common/host-locale-mirror.d.ts.map +1 -0
  12. package/lib/types/client/hub/HubOverview.d.ts.map +1 -1
  13. package/lib/types/client/hub/providers.d.ts +18 -1
  14. package/lib/types/client/hub/providers.d.ts.map +1 -1
  15. package/lib/types/client/index.d.ts.map +1 -1
  16. package/lib/types/client/locales-ru/hub.d.ts.map +1 -1
  17. package/lib/types/client/locales-ru/index.d.ts +2 -3
  18. package/lib/types/client/locales-ru/index.d.ts.map +1 -1
  19. package/lib/types/client/locales-ru/progress-updates.d.ts.map +1 -1
  20. package/lib/types/client/locales.d.ts +27 -1
  21. package/lib/types/client/locales.d.ts.map +1 -1
  22. package/lib/types/client/minimax-code/commands-contract.d.ts +1 -1
  23. package/lib/types/client/progress-updates/locales.d.ts +5 -2
  24. package/lib/types/client/progress-updates/locales.d.ts.map +1 -1
  25. package/lib/types/client/progress-updates/settings-binding.d.ts +1 -1
  26. package/lib/types/client/progress-updates/settings-binding.d.ts.map +1 -1
  27. package/lib/types/client/progress-updates/settings-section.d.ts.map +1 -1
  28. package/lib/types/client/subagent/SubagentCard.d.ts.map +1 -1
  29. package/lib/types/client/subagent/locales.d.ts +14 -2
  30. package/lib/types/client/subagent/locales.d.ts.map +1 -1
  31. package/lib/types/client/subagent/styles.d.ts +1 -1
  32. package/lib/types/client/subagent/styles.d.ts.map +1 -1
  33. package/lib/types/client/subagent/subagent-card-controller.d.ts +26 -3
  34. package/lib/types/client/subagent/subagent-card-controller.d.ts.map +1 -1
  35. package/lib/types/compat.d.ts +1 -1
  36. package/lib/types/entry-plan-mode.d.ts +3 -7
  37. package/lib/types/entry-plan-mode.d.ts.map +1 -1
  38. package/lib/types/entry-tool-result-pruner.d.ts +1 -1
  39. package/lib/types/host/adapter.d.ts.map +1 -1
  40. package/lib/types/host/agent-preset.d.ts +5 -0
  41. package/lib/types/host/agent-preset.d.ts.map +1 -1
  42. package/lib/types/host/antigravity/adapter.d.ts.map +1 -1
  43. package/lib/types/host/claude/adapter.d.ts.map +1 -1
  44. package/lib/types/host/cline-pass/adapter.d.ts.map +1 -1
  45. package/lib/types/host/codex-account-pool.d.ts.map +1 -1
  46. package/lib/types/host/command-code/adapter.d.ts.map +1 -1
  47. package/lib/types/host/common/account-pool.d.ts.map +1 -1
  48. package/lib/types/host/common/i18n/en.d.ts +9 -0
  49. package/lib/types/host/common/i18n/en.d.ts.map +1 -0
  50. package/lib/types/host/common/i18n/index.d.ts +13 -0
  51. package/lib/types/host/common/i18n/index.d.ts.map +1 -0
  52. package/lib/types/host/common/i18n/provider-name.d.ts +10 -0
  53. package/lib/types/host/common/i18n/provider-name.d.ts.map +1 -0
  54. package/lib/types/host/common/i18n/ru.d.ts +10 -0
  55. package/lib/types/host/common/i18n/ru.d.ts.map +1 -0
  56. package/lib/types/host/common/i18n/runtime.d.ts +54 -0
  57. package/lib/types/host/common/i18n/runtime.d.ts.map +1 -0
  58. package/lib/types/host/common/i18n/t.d.ts +38 -0
  59. package/lib/types/host/common/i18n/t.d.ts.map +1 -0
  60. package/lib/types/host/common/i18n/zh.d.ts +167 -0
  61. package/lib/types/host/common/i18n/zh.d.ts.map +1 -0
  62. package/lib/types/host/common/llm-compat.d.ts +3 -1
  63. package/lib/types/host/common/llm-compat.d.ts.map +1 -1
  64. package/lib/types/host/glm-coding-plan/adapter.d.ts.map +1 -1
  65. package/lib/types/host/glm-coding-plan/client.d.ts.map +1 -1
  66. package/lib/types/host/glm-coding-plan/oauth.d.ts.map +1 -1
  67. package/lib/types/host/glm-coding-plan/routes.d.ts.map +1 -1
  68. package/lib/types/host/kimi-code/adapter.d.ts.map +1 -1
  69. package/lib/types/host/kimi-code/repeat-breaker.d.ts +1 -1
  70. package/lib/types/host/minimax-code/adapter.d.ts.map +1 -1
  71. package/lib/types/host/ollama/adapter.d.ts.map +1 -1
  72. package/lib/types/host/opendesign/adapter.d.ts.map +1 -1
  73. package/lib/types/host/plan-mode-cache-guard.d.ts.map +1 -1
  74. package/lib/types/host/preferences.d.ts.map +1 -1
  75. package/lib/types/host/progress-updates/prompt.d.ts +1 -1
  76. package/lib/types/host/progress-updates/prompt.d.ts.map +1 -1
  77. package/lib/types/host/qoder/account-pool.d.ts.map +1 -1
  78. package/lib/types/host/qoder/adapter.d.ts.map +1 -1
  79. package/lib/types/host/qoder/client.d.ts.map +1 -1
  80. package/lib/types/host/qoder/oauth.d.ts.map +1 -1
  81. package/lib/types/host/qoder/routes.d.ts.map +1 -1
  82. package/lib/types/host/qoder/token-store.d.ts.map +1 -1
  83. package/lib/types/host/routes.d.ts.map +1 -1
  84. package/lib/types/host/step-code/account-pool.d.ts.map +1 -1
  85. package/lib/types/host/step-code/adapter.d.ts.map +1 -1
  86. package/lib/types/host/step-code/oauth.d.ts.map +1 -1
  87. package/lib/types/host/step-code/routes.d.ts.map +1 -1
  88. package/lib/types/host/step-code/token-store.d.ts.map +1 -1
  89. package/lib/types/host/subagent-model-authorization.d.ts +34 -16
  90. package/lib/types/host/subagent-model-authorization.d.ts.map +1 -1
  91. package/lib/types/host/subagent-route-audit.d.ts +6 -1
  92. package/lib/types/host/subagent-route-audit.d.ts.map +1 -1
  93. package/lib/types/host/workbuddy/account-pool.d.ts.map +1 -1
  94. package/lib/types/host/workbuddy/adapter.d.ts.map +1 -1
  95. package/lib/types/host/workbuddy/oauth.d.ts.map +1 -1
  96. package/lib/types/index.d.ts +2 -2
  97. package/lib/types/index.d.ts.map +1 -1
  98. package/lib/types/shared/contracts.d.ts +19 -0
  99. package/lib/types/shared/contracts.d.ts.map +1 -1
  100. package/lib/types/shared/i18n-contracts.d.ts +35 -0
  101. package/lib/types/shared/i18n-contracts.d.ts.map +1 -0
  102. package/lib/types/shared/preferences.d.ts +22 -1
  103. package/lib/types/shared/preferences.d.ts.map +1 -1
  104. package/locale/progress-updates/ru.json +6 -0
  105. package/package.json +46 -43
  106. package/presets/dispatch/README.md +6 -5
  107. package/presets/dispatch/agent.cordis.yml +18 -14
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as resolveProgressUpdatesSettings, n as attachProgressSettings } from "./entry-progress-updates-BEkdyDZU.js";
1
+ import { a as resolveProgressUpdatesSettings, n as attachProgressSettings } from "./entry-progress-updates-CxQewio9.js";
2
2
  import { attachPlanModePipelineSettings, resolvePlanModePipelineEnabled } from "./plan-mode-pipeline.js";
3
3
  import { DEFAULT_SKIP_PROVIDERS, PRUNER_SERVICE_NAME, resolveSkipProviders, shouldSkipPruningForSession } from "./tool-result-pruner.js";
4
4
  import { PLAN_PROJECTION_KEY, createPlanNotice } from "./plan-mode.js";
@@ -26,6 +26,662 @@ import { URL as URL$1, URLSearchParams as URLSearchParams$1, fileURLToPath } fro
26
26
  import { ProxyAgent, fetch as fetch$1 } from "undici";
27
27
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
28
28
  import { gzipSync } from "node:zlib";
29
+ //#region src/shared/i18n-contracts.ts
30
+ /**
31
+ * Language ids this plugin speaks, and the one parser that decides which one a
32
+ * tag means.
33
+ *
34
+ * The Host has no locale service of its own: the browser decides the active
35
+ * language and the Host only learns it because the client mirrors it back. So
36
+ * both halves must agree on one normalization rule, and this module is it —
37
+ * shared, dependency-free and identical on both sides of the wire.
38
+ * @module dsh-chatgpt-subscription/i18n-contracts
39
+ */
40
+ /** Every language this plugin can answer in, in the order a picker shows them. */
41
+ const SUPPORTED_LOCALES = [
42
+ "zh",
43
+ "en",
44
+ "ru"
45
+ ];
46
+ /**
47
+ * Reduce a BCP 47 tag (or anything a caller offers) to one supported language.
48
+ *
49
+ * `zh-CN`, `zh_TW` and `ZH` are all `zh`; `ru-RU` is `ru`; an unsupported
50
+ * language (`fr`, `ja`) and a missing value both fall back to
51
+ * {@link DEFAULT_LOCALE} rather than throwing — a language hint is never worth
52
+ * failing a request over.
53
+ *
54
+ * @param tag - Candidate tag from a URL, a header, a settings document or an event.
55
+ * @returns The supported language to answer in.
56
+ */
57
+ function normalizeLocale(tag) {
58
+ if (typeof tag !== "string") return "zh";
59
+ const base = tag.trim().toLowerCase().split(/[-_]/)[0];
60
+ return SUPPORTED_LOCALES.find((id) => id === base) ?? "zh";
61
+ }
62
+ //#endregion
63
+ //#region src/host/common/i18n/runtime.ts
64
+ /**
65
+ * The one place the Host remembers which language it is answering in.
66
+ *
67
+ * The Host has no locale service: the browser resolves the active language
68
+ * (explicit preference, else the browser's own), and this plugin's client
69
+ * mirrors that resolved value back over its own route. Everything the Host
70
+ * says on its own — a provider name, a quota failure, a progress update —
71
+ * reads the language from here at the moment it speaks, so a switch reaches
72
+ * text that was composed long after the page loaded.
73
+ *
74
+ * Nothing is persisted: the client re-mirrors on every page load, and the
75
+ * default keeps a Host that has never been mirrored on the wording it shipped
76
+ * with. A second client with a different language wins the race described by
77
+ * 'last write wins'; that is a documented limitation, not a bug to scale into
78
+ * a per-session registry.
79
+ * @module dsh-chatgpt-subscription/host/i18n/runtime
80
+ */
81
+ /** In-memory current language plus its change notification. */
82
+ var HostLocaleRuntime = class {
83
+ current = "zh";
84
+ listeners = /* @__PURE__ */ new Set();
85
+ /** The language every Host-side composer should answer in right now. */
86
+ get() {
87
+ return this.current;
88
+ }
89
+ /**
90
+ * Adopt a language hint; unsupported values collapse to the default.
91
+ *
92
+ * @param tag - Any tag a caller offers (a route body, a settings value).
93
+ * @returns The language now in force after normalization.
94
+ */
95
+ set(tag) {
96
+ const next = normalizeLocale(tag);
97
+ if (next === this.current) return next;
98
+ this.current = next;
99
+ for (const listener of [...this.listeners]) listener();
100
+ return next;
101
+ }
102
+ /**
103
+ * Observe later language changes.
104
+ *
105
+ * @param listener - Called after {@link set} actually changed the language.
106
+ * @returns Unsubscribe.
107
+ */
108
+ subscribe(listener) {
109
+ this.listeners.add(listener);
110
+ return () => {
111
+ this.listeners.delete(listener);
112
+ };
113
+ }
114
+ };
115
+ let installed;
116
+ /**
117
+ * Hand the runtime to this module.
118
+ *
119
+ * Adapters and routes read the language through {@link currentLocale} instead
120
+ * of threading a runtime through thirteen constructors, and a test that never
121
+ * installs one keeps the plugin's original Chinese wording.
122
+ *
123
+ * @param runtime - The runtime the plugin entry owns, or `undefined` to detach.
124
+ */
125
+ function installHostLocale(runtime) {
126
+ installed = runtime;
127
+ }
128
+ /** The language in force, or {@link DEFAULT_LOCALE} when nothing is installed. */
129
+ function currentLocale() {
130
+ return installed?.get() ?? "zh";
131
+ }
132
+ /** The installed runtime, when the plugin entry has wired one. */
133
+ function hostLocaleRuntime() {
134
+ return installed;
135
+ }
136
+ //#endregion
137
+ //#region src/host/common/i18n/en.ts
138
+ const en = {
139
+ "provider.codex-chatgpt": "ChatGPT Subscription",
140
+ "provider.claude": "Claude Subscription",
141
+ "provider.workbuddy": "WorkBuddy (CodeBuddy Subscription)",
142
+ "provider.glm-coding-plan": "GLM (ZCode Account)",
143
+ "provider.minimax-code": "MiniMax Code (Coding Subscription)",
144
+ "provider.qoder": "Qoder Subscription",
145
+ "provider.step-code": "Step Code (Step Plan Subscription)",
146
+ "pool.maxAccounts": "The {provider} account pool holds at most {max} accounts; delete one that is no longer used first.",
147
+ "pool.notSignedIn": "No {provider} account is signed in; add one on the settings page first.",
148
+ "pool.allNeedSignIn": "All {count} {provider} accounts have to sign in again.",
149
+ "pool.credentialRejected": "The credential of the {provider} account was rejected; sign in again.",
150
+ "pool.allUnavailable": "All {count} {provider} accounts are unavailable right now, and none is cooling down.",
151
+ "pool.allCoolingDown": "All {count} {provider} accounts are rate limited or cooling down (429). The earliest clears in about {minutes} minutes.",
152
+ "codex.refresherNotReady": "The ChatGPT credential refresh service is not ready yet",
153
+ "codex.notSignedIn": "No ChatGPT account is signed in; add and sign in to one under Settings → Subscription services → ChatGPT.",
154
+ "codex.accountGone": "That ChatGPT account is no longer in the pool",
155
+ "antigravity.quotaExhausted": "The Antigravity account quota is exhausted or the request is rate limited (429 RESOURCE_EXHAUSTED). Check the remaining quota and the reset countdown on the plugin settings page. Raw response: {body}",
156
+ "antigravity.rateLimitedNoReset": "Antigravity returned 429 (RESOURCE_EXHAUSTED) without a reset time, so this is treated as an immediate rate limit: the account quota is not considered exhausted and the account is not cooled down. Raw response: {body}",
157
+ "wb.oauth.loginInitFailed": "{provider} sign-in could not start (HTTP {status}): {detail}",
158
+ "wb.oauth.loginMissingState": "{provider} sign-in response is missing state or authUrl",
159
+ "wb.oauth.loginPollInvalid": "{provider} sign-in poll returned an invalid payload",
160
+ "wb.oauth.loginFailed": "{provider} sign-in failed: {detail}",
161
+ "wb.oauth.loginMissingToken": "{provider} sign-in response is missing the access token",
162
+ "wb.oauth.loginPollFailed": "{provider} sign-in poll failed (HTTP {status}): {detail}",
163
+ "wb.oauth.loginPollNotJson": "{provider} sign-in poll returned a non-JSON response",
164
+ "wb.oauth.waitingBrowser": "Waiting for the browser authorization…",
165
+ "wb.oauth.waitingBrowserElapsed": "Waiting for the browser authorization… ({seconds}s)",
166
+ "wb.oauth.authorized": "Authorization complete",
167
+ "wb.oauth.loginTimeout": "The sign-in timed out; add the account again.",
168
+ "wb.pool.pausedDefault": "The account pool is paused.",
169
+ "wb.pool.accountLabel": "Account {position}",
170
+ "wb.pool.paused": "The {provider} account pool is paused: {reason}. It resumes automatically in about {minutes} minutes; an account restricted upstream has to sign in again before it rejoins the rotation.",
171
+ "wb.pool.notAccountScoped": "The {provider} pool only records account-scoped restrictions ({expected}), but received business code {code}; 11128 and 11158 are not account-level refusals and must be handled by the protocol layer.",
172
+ "wb.pool.upstreamRefused": "Upstream refused {count} different accounts with {code} within {minutes} minutes",
173
+ "wb.pool.desktopAccountUndeletable": "A desktop account belongs to the CodeBuddy client: it can be hidden, never deleted.",
174
+ "qo.modelResolveAborted": "{provider} model resolution was cancelled",
175
+ "qo.requestAborted": "{provider} request was cancelled",
176
+ "qo.requestFailed": "{provider} request failed: {detail}",
177
+ "qo.emptyBody": "{provider} returned an empty response body",
178
+ "qo.noBrowserOutsideGlobal": "{provider} does not offer browser sign-in outside the global deployment",
179
+ "qo.devicePollFailed": "{provider} device poll failed (HTTP {status}){detail}",
180
+ "qo.devicePollNotJson": "{provider} device poll did not return a JSON object",
181
+ "qo.devicePollNoToken": "{provider} device poll returned 200 without a token",
182
+ "qo.patEmpty": "The {provider} PAT is empty.",
183
+ "qo.noRefreshToken": "This {provider} credential carries no refresh token; only signing in again renews it.",
184
+ "qo.cnNoBrowserLogin": "The {provider} China site does not support browser sign-in; use a PAT ({patPage}) or import the local qodercli sign-in.",
185
+ "qo.waitingBrowserPoll": "Waiting for the browser authorization… (polled every {seconds}s)",
186
+ "qo.loginTimeout": "{provider} sign-in timed out: the browser authorization did not complete in time.",
187
+ "qo.authorized": "Authorization complete",
188
+ "qo.cancelled": "The operation was cancelled",
189
+ "qo.poolPayloadInvalid": "The {provider} pool payload is invalid",
190
+ "qo.poolEmpty": "The {provider} account pool has no accounts.",
191
+ "qo.userinfoFailed": "{provider} userinfo request failed (HTTP {status}){detail}",
192
+ "qo.userinfoNotJson": "{provider} userinfo response is not a JSON object",
193
+ "qo.patExchangeNotJson": "{provider} PAT exchange response is not a JSON object",
194
+ "qo.patExchangeNoToken": "{provider} PAT exchange response carries no token",
195
+ "qo.refreshFailed": "{provider} token refresh failed (HTTP {status})",
196
+ "qo.refreshNotJson": "{provider} token refresh response is not a JSON object",
197
+ "qo.refreshNoToken": "{provider} token refresh response carries no token",
198
+ "qo.quotaHttp": "The quota endpoint answered HTTP {status}{detail}",
199
+ "qo.quotaNoBucket": "The quota response carried no bucket this build recognises (upstream may have changed).",
200
+ "qo.poolNotInstalled": "The account pool is not installed.",
201
+ "qo.unknownStrategy": "Unknown rotation strategy.",
202
+ "qo.unknownAccountAction": "Unknown account action: {action}",
203
+ "qo.pastePat": "Paste a Personal Access Token (pt-...).",
204
+ "qo.notSignedIn": "No {provider} account is signed in yet.",
205
+ "qo.catalogHttp": "The catalog endpoint answered HTTP {status}",
206
+ "qo.credentialFieldInvalid": "{provider} credential field is invalid: {key}",
207
+ "qo.credentialPayloadInvalid": "The {provider} credential payload is invalid",
208
+ "qo.credentialNoToken": "The {provider} credential has no accessToken",
209
+ "qo.credentialRegionInvalid": "The {provider} credential region is invalid",
210
+ "qo.storeUnsupportedPlatform": "{label} credential storage supports Windows, macOS and Linux only.",
211
+ "qo.encryptedWriteVerifyFailed": "Writing the encrypted {provider} credential failed verification",
212
+ "qo.modelSettingsWriteFailed": "Writing the {provider} model settings failed: the stored choice differs from what was just written",
213
+ "sc.poolAccountFieldInvalid": "{provider} pool account field is invalid: {key}",
214
+ "sc.poolCredentialInvalid": "The {provider} pool credential is invalid",
215
+ "sc.poolCredentialNoAccess": "The {provider} pool credential has no access field",
216
+ "sc.poolCredentialProfileInvalid": "The {provider} pool credential profile is invalid",
217
+ "sc.poolPayloadInvalid": "The {provider} pool payload is invalid",
218
+ "sc.poolEmpty": "The {provider} account pool has no accounts.",
219
+ "sc.modelResolveAborted": "{provider} model resolution was cancelled",
220
+ "sc.requestAborted": "{provider} request was cancelled",
221
+ "sc.requestFailed": "{provider} request failed: {detail}",
222
+ "sc.noResponse": "{provider} returned no response at all",
223
+ "sc.emptyBody": "{provider} returned an empty response body",
224
+ "sc.poolNotInstalled": "The account pool is not installed.",
225
+ "sc.unknownStrategy": "Unknown rotation strategy.",
226
+ "sc.unknownAccountAction": "Unknown account action: {action}",
227
+ "sc.pastePlatformKey": "Paste a Platform API Key.",
228
+ "sc.missingAccount": "Fill in the account.",
229
+ "sc.missingPassword": "Fill in the password.",
230
+ "sc.unknownQuotaCredentialMode": "Unknown quota-credential submission mode: {mode}",
231
+ "sc.notSignedIn": "No {provider} account is signed in yet.",
232
+ "sc.catalogHttp": "The catalog endpoint answered HTTP {status}",
233
+ "sc.loginPhaseFailed": "{provider} sign-in {phase} {detail}",
234
+ "sc.loginRequestTimeout": "{provider} sign-in request timed out",
235
+ "sc.authorizeUrlInvalid": "The {provider} authorization URL is not a valid URL: {value}",
236
+ "sc.authorizeUrlNotHttps": "The {provider} authorization URL must use https",
237
+ "sc.authorizeUrlHasCredentials": "The {provider} authorization URL must not carry a user name or password",
238
+ "sc.cancelled": "The operation was cancelled",
239
+ "sc.loginTimeout": "{provider} sign-in timed out: the browser authorization did not complete in time.",
240
+ "sc.pollTokenEmpty": "The {provider} sign-in poll_token must not be empty",
241
+ "sc.loginNoApiKey": "{provider} signed in but returned no api_key",
242
+ "sc.apiKeyEmpty": "The {provider} API key is empty.",
243
+ "sc.waitingBrowserPoll": "Waiting for the browser authorization… (polled every {seconds}s)",
244
+ "sc.authorized": "Authorization complete",
245
+ "sc.credentialFieldInvalid": "{provider} credential field is invalid: {key}",
246
+ "sc.credentialPayloadInvalid": "The {provider} credential payload is invalid",
247
+ "sc.credentialNoApiKey": "The {provider} credential has no apiKey",
248
+ "sc.credentialProfileInvalid": "The {provider} credential profile is invalid",
249
+ "sc.storeUnsupportedPlatform": "{label} credential storage supports Windows, macOS and Linux only.",
250
+ "sc.encryptedWriteVerifyFailed": "Writing the encrypted {provider} credential failed verification",
251
+ "sc.quotaCredentialPayloadInvalid": "The {provider} quota credential payload is invalid",
252
+ "sc.quotaCredentialNoToken": "The {provider} quota credential has no Oasis-Token",
253
+ "sc.quotaCredentialNoDeviceId": "The {provider} quota credential has no Oasis-Webid",
254
+ "sc.quotaCredentialWriteVerifyFailed": "Writing the {provider} quota credential failed verification",
255
+ "sc.modelSettingsWriteFailed": "Writing the {provider} model settings failed: the stored choice differs from what was just written",
256
+ "glm.quotaNeedsKey": "The {provider} quota endpoint needs a Coding Plan Key (the bare value, no Bearer); an empty credential never becomes an authenticated request.",
257
+ "glm.catalogNotJson": "The model catalog {provider} returned is not readable JSON: {url}",
258
+ "glm.quotaNeedsKeyShort": "Reading the {provider} quota needs a Coding Plan Key (the bare value, no Bearer).",
259
+ "glm.quotaUnreachable": "The quota endpoint is unreachable: {detail}",
260
+ "glm.quotaHttp": "The quota query failed (HTTP {status})",
261
+ "glm.quotaNotJson": "The quota query did not return JSON.",
262
+ "glm.quotaNoWindow": "Upstream returned no quota window this build can show.",
263
+ "glm.cooldownUntilReset": "{provider} 429: the usage window resets at {at}",
264
+ "glm.cooldownRetryAfter": "{provider} 429: upstream asks to retry in {seconds} seconds",
265
+ "glm.cooldownNoReset": "{provider} 429: upstream gave no reset time, so this cools down for 5 minutes",
266
+ "glm.modelResolveAborted": "{provider} model resolution was cancelled",
267
+ "glm.requestAborted": "{provider} request was cancelled",
268
+ "glm.requestFailed": "{provider} request failed: {detail}",
269
+ "glm.noResponse": "{provider} returned no response at all",
270
+ "glm.emptyBody": "{provider} returned an empty response body",
271
+ "glm.anthropicEmpty": "The Anthropic surface of {provider} returned nothing",
272
+ "glm.waitingBrowser": "Waiting for you to finish the authorization in the browser…",
273
+ "glm.connectingUpstream": "Could not reach upstream; retrying…",
274
+ "glm.upstreamUnavailable": "Upstream is temporarily unavailable (HTTP {status}); retrying…",
275
+ "glm.upstreamRetryLater": "Upstream asks to retry later (HTTP {status}); retrying…",
276
+ "glm.pollRejected": "ZCode sign-in poll was rejected (HTTP {status}): {url}",
277
+ "glm.unparsableRetry": "Upstream returned a response this build cannot parse; retrying…",
278
+ "glm.pollBusinessCode": "ZCode sign-in poll returned business error code {code}{detail}",
279
+ "glm.readyNoToken": "The ready response carries no access_token; retrying…",
280
+ "glm.sessionCancelled": "This sign-in was cancelled or has expired; start it again.",
281
+ "glm.loginTimeout": "Sign-in timed out: upstream did not complete the authorization before {at}.",
282
+ "glm.noSession": "There is no GLM sign-in in progress to complete.",
283
+ "glm.authorizationDenied": "Authorization was denied: {denial}",
284
+ "glm.notAuthorizationCode": "This is neither an authorization code nor a complete callback link (it carries no code parameter).",
285
+ "glm.callbackReceived": "Callback received; confirming with upstream…",
286
+ "glm.poolNotInstalled": "The account pool is not installed.",
287
+ "glm.unknownStrategy": "Unknown rotation strategy.",
288
+ "glm.unknownAccountAction": "Unknown account action: {action}",
289
+ "glm.pasteCallback": "Paste the callback link or the authorization code.",
290
+ "glm.noLoginInProgress": "No sign-in is in progress; start one first.",
291
+ "glm.notSignedIn": "No {provider} account is signed in yet."
292
+ };
293
+ //#endregion
294
+ //#region src/host/common/i18n/ru.ts
295
+ const ru = {
296
+ "provider.codex-chatgpt": "Codex (подписка ChatGPT)",
297
+ "provider.claude": "Claude (подписка)",
298
+ "provider.workbuddy": "WorkBuddy (подписка CodeBuddy)",
299
+ "provider.glm-coding-plan": "GLM (аккаунт ZCode)",
300
+ "provider.minimax-code": "MiniMax Code (подписка для кода)",
301
+ "provider.qoder": "Qoder (подписка)",
302
+ "provider.step-code": "Step Code (подписка Step Plan)",
303
+ "pool.maxAccounts": "Пул аккаунтов {provider} вмещает не больше {max}; сначала удалите неиспользуемый аккаунт.",
304
+ "pool.notSignedIn": "Вход в аккаунт {provider} не выполнен; сначала добавьте его на странице настроек.",
305
+ "pool.allNeedSignIn": "Всем аккаунтам {provider} ({count}) нужно войти заново.",
306
+ "pool.credentialRejected": "Учётные данные аккаунта {provider} отклонены; войдите заново.",
307
+ "pool.allUnavailable": "Все аккаунты {provider} ({count}) сейчас недоступны, и ни один не в режиме ожидания.",
308
+ "pool.allCoolingDown": "Все аккаунты {provider} ({count}) ограничены по квоте или в режиме ожидания (429). Ближайший освободится примерно через {minutes} мин.",
309
+ "codex.refresherNotReady": "Служба обновления учётных данных ChatGPT ещё не готова",
310
+ "codex.notSignedIn": "Вход в аккаунт ChatGPT не выполнен; добавьте и войдите в аккаунт в разделе «Настройки → Подписки → ChatGPT».",
311
+ "codex.accountGone": "Этого аккаунта ChatGPT больше нет в пуле",
312
+ "antigravity.quotaExhausted": "Квота аккаунта Antigravity исчерпана или запрос ограничен (429 RESOURCE_EXHAUSTED). Проверьте остаток квоты и таймер сброса на странице настроек плагина. Исходный ответ: {body}",
313
+ "antigravity.rateLimitedNoReset": "Antigravity вернул 429 (RESOURCE_EXHAUSTED) без времени сброса, поэтому это считается мгновенным ограничением: квота аккаунта не исчерпана, и аккаунт не переводится в ожидание. Исходный ответ: {body}",
314
+ "wb.oauth.loginInitFailed": "{provider}: не удалось начать вход (HTTP {status}): {detail}",
315
+ "wb.oauth.loginMissingState": "{provider}: в ответе на вход нет state или authUrl",
316
+ "wb.oauth.loginPollInvalid": "{provider}: недопустимый ответ опроса входа",
317
+ "wb.oauth.loginFailed": "{provider}: вход не выполнен: {detail}",
318
+ "wb.oauth.loginMissingToken": "{provider}: в ответе на вход нет access token",
319
+ "wb.oauth.loginPollFailed": "{provider}: опрос входа завершился ошибкой (HTTP {status}): {detail}",
320
+ "wb.oauth.loginPollNotJson": "{provider}: опрос входа вернул ответ не в формате JSON",
321
+ "wb.oauth.waitingBrowser": "Ожидаем авторизацию в браузере…",
322
+ "wb.oauth.waitingBrowserElapsed": "Ожидаем авторизацию в браузере… ({seconds} с)",
323
+ "wb.oauth.authorized": "Авторизация завершена",
324
+ "wb.oauth.loginTimeout": "Вход не выполнен вовремя; добавьте аккаунт заново.",
325
+ "wb.pool.pausedDefault": "Пул аккаунтов приостановлен.",
326
+ "wb.pool.accountLabel": "Аккаунт {position}",
327
+ "wb.pool.paused": "Пул аккаунтов {provider} приостановлен: {reason}. Он возобновится примерно через {minutes} мин; аккаунту, ограниченному на стороне сервиса, нужно войти заново, прежде чем он вернётся в ротацию.",
328
+ "wb.pool.notAccountScoped": "Пул {provider} фиксирует только ограничения уровня аккаунта ({expected}), но получен бизнес-код {code}; 11128 и 11158 не являются отказами уровня аккаунта и должны обрабатываться на уровне протокола.",
329
+ "wb.pool.upstreamRefused": "Сервис отказал {count} разным аккаунтам с кодом {code} за {minutes} мин",
330
+ "wb.pool.desktopAccountUndeletable": "Настольный аккаунт принадлежит клиенту CodeBuddy: его можно скрыть, но нельзя удалить.",
331
+ "qo.modelResolveAborted": "{provider}: разрешение модели отменено",
332
+ "qo.requestAborted": "{provider}: запрос отменён",
333
+ "qo.requestFailed": "{provider}: запрос не выполнен: {detail}",
334
+ "qo.emptyBody": "{provider} вернул пустое тело ответа",
335
+ "qo.noBrowserOutsideGlobal": "{provider}: вход через браузер доступен только в глобальном развёртывании",
336
+ "qo.devicePollFailed": "{provider}: опрос устройства не удался (HTTP {status}){detail}",
337
+ "qo.devicePollNotJson": "{provider}: опрос устройства вернул не объект JSON",
338
+ "qo.devicePollNoToken": "{provider}: опрос устройства вернул 200 без токена",
339
+ "qo.patEmpty": "PAT {provider} пуст.",
340
+ "qo.noRefreshToken": "В этих учётных данных {provider} нет токена обновления; продлить их можно только повторным входом.",
341
+ "qo.cnNoBrowserLogin": "Китайский сайт {provider} не поддерживает вход через браузер; используйте PAT ({patPage}) или импортируйте локальный вход qodercli.",
342
+ "qo.waitingBrowserPoll": "Ожидаем авторизацию в браузере… (опрос каждые {seconds} с)",
343
+ "qo.loginTimeout": "{provider}: время входа истекло — авторизацию в браузере не завершили вовремя.",
344
+ "qo.authorized": "Авторизация завершена",
345
+ "qo.cancelled": "Операция отменена",
346
+ "qo.poolPayloadInvalid": "Недопустимые данные пула {provider}",
347
+ "qo.poolEmpty": "В пуле аккаунтов {provider} нет аккаунтов.",
348
+ "qo.userinfoFailed": "{provider}: запрос userinfo не удался (HTTP {status}){detail}",
349
+ "qo.userinfoNotJson": "{provider}: ответ userinfo не является объектом JSON",
350
+ "qo.patExchangeNotJson": "{provider}: ответ обмена PAT не является объектом JSON",
351
+ "qo.patExchangeNoToken": "{provider}: в ответе обмена PAT нет токена",
352
+ "qo.refreshFailed": "{provider}: обновление токена не удалось (HTTP {status})",
353
+ "qo.refreshNotJson": "{provider}: ответ обновления токена не является объектом JSON",
354
+ "qo.refreshNoToken": "{provider}: в ответе обновления токена нет токена",
355
+ "qo.quotaHttp": "Эндпоинт квоты ответил HTTP {status}{detail}",
356
+ "qo.quotaNoBucket": "В ответе о квоте нет известного этой сборке сегмента (возможно, сервис изменился).",
357
+ "qo.poolNotInstalled": "Пул аккаунтов не установлен.",
358
+ "qo.unknownStrategy": "Неизвестная стратегия ротации.",
359
+ "qo.unknownAccountAction": "Неизвестное действие с аккаунтом: {action}",
360
+ "qo.pastePat": "Вставьте Personal Access Token (pt-...).",
361
+ "qo.notSignedIn": "Вход в аккаунт {provider} ещё не выполнен.",
362
+ "qo.catalogHttp": "Эндпоинт каталога ответил HTTP {status}",
363
+ "qo.credentialFieldInvalid": "{provider}: недопустимое поле учётных данных: {key}",
364
+ "qo.credentialPayloadInvalid": "Недопустимые данные учётных данных {provider}",
365
+ "qo.credentialNoToken": "В учётных данных {provider} нет accessToken",
366
+ "qo.credentialRegionInvalid": "Недопустимый регион в учётных данных {provider}",
367
+ "qo.storeUnsupportedPlatform": "Хранилище учётных данных {label} поддерживает только Windows, macOS и Linux.",
368
+ "qo.encryptedWriteVerifyFailed": "Запись зашифрованных учётных данных {provider} не прошла проверку",
369
+ "qo.modelSettingsWriteFailed": "Запись настроек моделей {provider} не удалась: сохранённый выбор отличается от только что записанного",
370
+ "sc.poolAccountFieldInvalid": "{provider}: недопустимое поле аккаунта пула: {key}",
371
+ "sc.poolCredentialInvalid": "Недопустимые учётные данные пула {provider}",
372
+ "sc.poolCredentialNoAccess": "В учётных данных пула {provider} нет поля access",
373
+ "sc.poolCredentialProfileInvalid": "Недопустимый профиль учётных данных пула {provider}",
374
+ "sc.poolPayloadInvalid": "Недопустимые данные пула {provider}",
375
+ "sc.poolEmpty": "В пуле аккаунтов {provider} нет аккаунтов.",
376
+ "sc.modelResolveAborted": "{provider}: разрешение модели отменено",
377
+ "sc.requestAborted": "{provider}: запрос отменён",
378
+ "sc.requestFailed": "{provider}: запрос не выполнен: {detail}",
379
+ "sc.noResponse": "{provider} не вернул ответ",
380
+ "sc.emptyBody": "{provider} вернул пустое тело ответа",
381
+ "sc.poolNotInstalled": "Пул аккаунтов не установлен.",
382
+ "sc.unknownStrategy": "Неизвестная стратегия ротации.",
383
+ "sc.unknownAccountAction": "Неизвестное действие с аккаунтом: {action}",
384
+ "sc.pastePlatformKey": "Вставьте Platform API Key.",
385
+ "sc.missingAccount": "Укажите аккаунт.",
386
+ "sc.missingPassword": "Укажите пароль.",
387
+ "sc.unknownQuotaCredentialMode": "Неизвестный способ передачи учётных данных квоты: {mode}",
388
+ "sc.notSignedIn": "Вход в аккаунт {provider} ещё не выполнен.",
389
+ "sc.catalogHttp": "Эндпоинт каталога ответил HTTP {status}",
390
+ "sc.loginPhaseFailed": "{provider}: вход {phase} {detail}",
391
+ "sc.loginRequestTimeout": "{provider}: запрос входа не выполнен вовремя",
392
+ "sc.authorizeUrlInvalid": "URL авторизации {provider} не является допустимым URL: {value}",
393
+ "sc.authorizeUrlNotHttps": "URL авторизации {provider} должен использовать https",
394
+ "sc.authorizeUrlHasCredentials": "URL авторизации {provider} не должен содержать имя пользователя или пароль",
395
+ "sc.cancelled": "Операция отменена",
396
+ "sc.loginTimeout": "{provider}: время входа истекло — авторизацию в браузере не завершили вовремя.",
397
+ "sc.pollTokenEmpty": "poll_token входа {provider} не может быть пустым",
398
+ "sc.loginNoApiKey": "{provider} выполнил вход, но не вернул api_key",
399
+ "sc.apiKeyEmpty": "API-ключ {provider} пуст.",
400
+ "sc.waitingBrowserPoll": "Ожидаем авторизацию в браузере… (опрос каждые {seconds} с)",
401
+ "sc.authorized": "Авторизация завершена",
402
+ "sc.credentialFieldInvalid": "{provider}: недопустимое поле учётных данных: {key}",
403
+ "sc.credentialPayloadInvalid": "Недопустимые данные учётных данных {provider}",
404
+ "sc.credentialNoApiKey": "В учётных данных {provider} нет apiKey",
405
+ "sc.credentialProfileInvalid": "Недопустимый профиль учётных данных {provider}",
406
+ "sc.storeUnsupportedPlatform": "Хранилище учётных данных {label} поддерживает только Windows, macOS и Linux.",
407
+ "sc.encryptedWriteVerifyFailed": "Запись зашифрованных учётных данных {provider} не прошла проверку",
408
+ "sc.quotaCredentialPayloadInvalid": "Недопустимые данные учётных данных квоты {provider}",
409
+ "sc.quotaCredentialNoToken": "В учётных данных квоты {provider} нет Oasis-Token",
410
+ "sc.quotaCredentialNoDeviceId": "В учётных данных квоты {provider} нет Oasis-Webid",
411
+ "sc.quotaCredentialWriteVerifyFailed": "Запись учётных данных квоты {provider} не прошла проверку",
412
+ "sc.modelSettingsWriteFailed": "Запись настроек моделей {provider} не удалась: сохранённый выбор отличается от только что записанного",
413
+ "glm.quotaNeedsKey": "Эндпоинту квоты {provider} нужен Coding Plan Key (само значение, без Bearer); пустые учётные данные не станут аутентифицированным запросом.",
414
+ "glm.catalogNotJson": "Каталог моделей, который вернул {provider}, не является читаемым JSON: {url}",
415
+ "glm.quotaNeedsKeyShort": "Для чтения квоты {provider} нужен Coding Plan Key (само значение, без Bearer).",
416
+ "glm.quotaUnreachable": "Эндпоинт квоты недоступен: {detail}",
417
+ "glm.quotaHttp": "Запрос квоты не выполнен (HTTP {status})",
418
+ "glm.quotaNotJson": "Запрос квоты вернул не JSON.",
419
+ "glm.quotaNoWindow": "Сервис не вернул окно квоты, которое эта сборка умеет показывать.",
420
+ "glm.cooldownUntilReset": "{provider} 429: окно использования сбрасывается в {at}",
421
+ "glm.cooldownRetryAfter": "{provider} 429: сервис просит повторить через {seconds} с",
422
+ "glm.cooldownNoReset": "{provider} 429: сервис не указал время сброса, поэтому ожидание 5 минут",
423
+ "glm.modelResolveAborted": "{provider}: разрешение модели отменено",
424
+ "glm.requestAborted": "{provider}: запрос отменён",
425
+ "glm.requestFailed": "{provider}: запрос не выполнен: {detail}",
426
+ "glm.noResponse": "{provider} не вернул ответ",
427
+ "glm.emptyBody": "{provider} вернул пустое тело ответа",
428
+ "glm.anthropicEmpty": "Anthropic-интерфейс {provider} ничего не вернул",
429
+ "glm.waitingBrowser": "Ждём завершения авторизации в браузере…",
430
+ "glm.connectingUpstream": "Не удалось подключиться к сервису; повторяем…",
431
+ "glm.upstreamUnavailable": "Сервис временно недоступен (HTTP {status}); повторяем…",
432
+ "glm.upstreamRetryLater": "Сервис просит повторить позже (HTTP {status}); повторяем…",
433
+ "glm.pollRejected": "Опрос входа ZCode отклонён (HTTP {status}): {url}",
434
+ "glm.unparsableRetry": "Сервис вернул ответ, который эта сборка не может разобрать; повторяем…",
435
+ "glm.pollBusinessCode": "Опрос входа ZCode вернул бизнес-код ошибки {code}{detail}",
436
+ "glm.readyNoToken": "В ответе готовности нет access_token; повторяем…",
437
+ "glm.sessionCancelled": "Этот вход отменён или истёк; начните его заново.",
438
+ "glm.loginTimeout": "Время входа истекло: сервис не завершил авторизацию до {at}.",
439
+ "glm.noSession": "Сейчас нет незавершённого входа GLM.",
440
+ "glm.authorizationDenied": "В авторизации отказано: {denial}",
441
+ "glm.notAuthorizationCode": "Это не код авторизации и не полная ссылка обратного вызова (в ней нет параметра code).",
442
+ "glm.callbackReceived": "Обратный вызов получен; подтверждаем у сервиса…",
443
+ "glm.poolNotInstalled": "Пул аккаунтов не установлен.",
444
+ "glm.unknownStrategy": "Неизвестная стратегия ротации.",
445
+ "glm.unknownAccountAction": "Неизвестное действие с аккаунтом: {action}",
446
+ "glm.pasteCallback": "Вставьте ссылку обратного вызова или код авторизации.",
447
+ "glm.noLoginInProgress": "Сейчас нет входа в процессе; сначала начните его.",
448
+ "glm.notSignedIn": "Вход в аккаунт {provider} ещё не выполнен."
449
+ };
450
+ //#endregion
451
+ //#region src/host/common/i18n/zh.ts
452
+ /**
453
+ * Chinese copy for everything the Host says on its own.
454
+ *
455
+ * The key set here is the source of truth: `en` and `ru` are typed against
456
+ * `keyof typeof zh`, so a key added here fails to compile until both other
457
+ * languages carry it too. Values keep the exact wording the plugin shipped
458
+ * before it spoke three languages — `zh` is the default locale, and a
459
+ * regression in Chinese is a regression for every existing install.
460
+ */
461
+ const zh = {
462
+ "provider.codex-chatgpt": "Codex(ChatGPT 订阅)",
463
+ "provider.claude": "Claude(订阅)",
464
+ "provider.workbuddy": "WorkBuddy(CodeBuddy 订阅)",
465
+ "provider.glm-coding-plan": "GLM(ZCode 账号)",
466
+ "provider.minimax-code": "MiniMax Code(编程订阅)",
467
+ "provider.qoder": "Qoder(订阅)",
468
+ "provider.step-code": "Step Code(Step Plan 订阅)",
469
+ "pool.maxAccounts": "{provider} 号池最多支持 {max} 个账号,请先删除不再使用的账号。",
470
+ "pool.notSignedIn": "未登录 {provider} 账号,请先在设置页添加账号。",
471
+ "pool.allNeedSignIn": "全部 {count} 个 {provider} 账号均需要重新登录。",
472
+ "pool.credentialRejected": "{provider} 账号的凭据已被拒绝,需要重新登录。",
473
+ "pool.allUnavailable": "全部 {count} 个 {provider} 账号当前都不可用,且没有处于冷却中的账号。",
474
+ "pool.allCoolingDown": "全部 {count} 个 {provider} 账号均处于配额限制或冷却中 (429)。最短预计在 {minutes} 分钟后解除冷却。",
475
+ "codex.refresherNotReady": "ChatGPT 凭据刷新服务尚未就绪",
476
+ "codex.notSignedIn": "未登录 ChatGPT 账号,请在「设置 → 订阅服务 → ChatGPT」中添加并登录账号。",
477
+ "codex.accountGone": "ChatGPT 账号已不在号池中",
478
+ "antigravity.quotaExhausted": "Antigravity 账号配额已耗尽或请求受限 (429 RESOURCE_EXHAUSTED)。请在插件设置页查看配额剩余百分比及重置倒计时。原始响应: {body}",
479
+ "antigravity.rateLimitedNoReset": "Antigravity 上游返回 429 (RESOURCE_EXHAUSTED) 但未给出重置时间,因此按瞬时限流处理,不视为账号配额耗尽,也不会冷却该账号。原始响应: {body}",
480
+ "wb.oauth.loginInitFailed": "{provider} 登录初始化失败(HTTP {status}):{detail}",
481
+ "wb.oauth.loginMissingState": "{provider} 登录响应缺少 state 或 authUrl",
482
+ "wb.oauth.loginPollInvalid": "{provider} 登录轮询响应无效",
483
+ "wb.oauth.loginFailed": "{provider} 登录失败:{detail}",
484
+ "wb.oauth.loginMissingToken": "{provider} 登录成功响应缺少 access token",
485
+ "wb.oauth.loginPollFailed": "{provider} 登录轮询失败(HTTP {status}):{detail}",
486
+ "wb.oauth.loginPollNotJson": "{provider} 登录轮询返回了非 JSON 响应",
487
+ "wb.oauth.waitingBrowser": "等待浏览器授权…",
488
+ "wb.oauth.waitingBrowserElapsed": "等待浏览器授权…({seconds} 秒)",
489
+ "wb.oauth.authorized": "授权完成",
490
+ "wb.oauth.loginTimeout": "登录超时,请重新添加账号。",
491
+ "wb.pool.pausedDefault": "号池已暂停。",
492
+ "wb.pool.accountLabel": "账号 {position}",
493
+ "wb.pool.paused": "{provider} 号池已暂停:{reason} 预计 {minutes} 分钟后自动恢复;被上游限制的账号需要重新登录后才能回到轮换。",
494
+ "wb.pool.notAccountScoped": "{provider} 号池只记录账号级限制({expected}),收到业务码 {code};11128 与 11158 不是账号级拒绝,必须由协议层分别处理。",
495
+ "wb.pool.upstreamRefused": "上游以 {code} 在 {minutes} 分钟内拒绝了 {count} 个不同账号",
496
+ "wb.pool.desktopAccountUndeletable": "桌面账号由 CodeBuddy 客户端所有,只能隐藏,不能删除。",
497
+ "qo.modelResolveAborted": "{provider} 模型解析已取消",
498
+ "qo.requestAborted": "{provider} 请求已取消",
499
+ "qo.requestFailed": "{provider} 请求失败:{detail}",
500
+ "qo.emptyBody": "{provider} 返回了空响应体",
501
+ "qo.noBrowserOutsideGlobal": "{provider} 全球区以外的部署不支持浏览器登录",
502
+ "qo.devicePollFailed": "{provider} 设备轮询失败(HTTP {status}){detail}",
503
+ "qo.devicePollNotJson": "{provider} 设备轮询响应不是 JSON 对象",
504
+ "qo.devicePollNoToken": "{provider} 设备轮询的 200 响应里没有 token",
505
+ "qo.patEmpty": "{provider} 的 PAT 是空的。",
506
+ "qo.noRefreshToken": "{provider} 的这份凭据没有刷新令牌,只有重新登录才能续期。",
507
+ "qo.cnNoBrowserLogin": "{provider} 中国站不支持浏览器登录,请改用 PAT({patPage})或导入本机 qodercli 登录态。",
508
+ "qo.waitingBrowserPoll": "等待浏览器授权…(每 {seconds} 秒查询一次)",
509
+ "qo.loginTimeout": "{provider} 登录超时:没有在有效期内完成浏览器授权。",
510
+ "qo.authorized": "授权完成",
511
+ "qo.cancelled": "操作已取消",
512
+ "qo.poolPayloadInvalid": "{provider} 号池载荷无效",
513
+ "qo.poolEmpty": "{provider} 号池中没有账号。",
514
+ "qo.userinfoFailed": "{provider} userinfo 请求失败(HTTP {status}){detail}",
515
+ "qo.userinfoNotJson": "{provider} userinfo 响应不是 JSON 对象",
516
+ "qo.patExchangeNotJson": "{provider} PAT 兑换响应不是 JSON 对象",
517
+ "qo.patExchangeNoToken": "{provider} PAT 兑换响应里没有 token",
518
+ "qo.refreshFailed": "{provider} 令牌刷新失败(HTTP {status})",
519
+ "qo.refreshNotJson": "{provider} 令牌刷新响应不是 JSON 对象",
520
+ "qo.refreshNoToken": "{provider} 令牌刷新响应里没有 token",
521
+ "qo.quotaHttp": "额度接口返回 HTTP {status}{detail}",
522
+ "qo.quotaNoBucket": "额度响应里没有认识的额度桶(上游可能改版)。",
523
+ "qo.poolNotInstalled": "账号池未安装。",
524
+ "qo.unknownStrategy": "未知的轮转策略。",
525
+ "qo.unknownAccountAction": "未知的账号操作:{action}",
526
+ "qo.pastePat": "请粘贴一个 Personal Access Token(pt-...)。",
527
+ "qo.notSignedIn": "还没有登录 {provider} 账号。",
528
+ "qo.catalogHttp": "目录接口返回 HTTP {status}",
529
+ "qo.credentialFieldInvalid": "{provider} 凭据字段无效:{key}",
530
+ "qo.credentialPayloadInvalid": "{provider} 凭据载荷无效",
531
+ "qo.credentialNoToken": "{provider} 凭据缺少 accessToken",
532
+ "qo.credentialRegionInvalid": "{provider} 凭据的 region 无效",
533
+ "qo.storeUnsupportedPlatform": "{label} 凭据存储只支持 Windows、macOS 或 Linux。",
534
+ "qo.encryptedWriteVerifyFailed": "{provider} 加密凭据写入校验失败",
535
+ "qo.modelSettingsWriteFailed": "{provider} 模型设置写入失败:落盘的选择与刚写入的不一致",
536
+ "sc.poolAccountFieldInvalid": "{provider} 号池账号字段无效:{key}",
537
+ "sc.poolCredentialInvalid": "{provider} 号池凭据无效",
538
+ "sc.poolCredentialNoAccess": "{provider} 号池凭据缺少 access",
539
+ "sc.poolCredentialProfileInvalid": "{provider} 号池凭据的 profile 无效",
540
+ "sc.poolPayloadInvalid": "{provider} 号池载荷无效",
541
+ "sc.poolEmpty": "{provider} 号池中没有账号。",
542
+ "sc.modelResolveAborted": "{provider} 模型解析已取消",
543
+ "sc.requestAborted": "{provider} 请求已取消",
544
+ "sc.requestFailed": "{provider} 请求失败:{detail}",
545
+ "sc.noResponse": "{provider} 没有返回任何响应",
546
+ "sc.emptyBody": "{provider} 返回了空响应体",
547
+ "sc.poolNotInstalled": "账号池未安装。",
548
+ "sc.unknownStrategy": "未知的轮转策略。",
549
+ "sc.unknownAccountAction": "未知的账号操作:{action}",
550
+ "sc.pastePlatformKey": "请粘贴一个 Platform API Key。",
551
+ "sc.missingAccount": "请填写账号。",
552
+ "sc.missingPassword": "请填写密码。",
553
+ "sc.unknownQuotaCredentialMode": "未知的额度凭据提交方式:{mode}",
554
+ "sc.notSignedIn": "还没有登录 {provider} 账号。",
555
+ "sc.catalogHttp": "目录接口返回 HTTP {status}",
556
+ "sc.loginPhaseFailed": "{provider} 登录 {phase} {detail}",
557
+ "sc.loginRequestTimeout": "{provider} 登录请求超时",
558
+ "sc.authorizeUrlInvalid": "{provider} 的授权地址不是合法 URL:{value}",
559
+ "sc.authorizeUrlNotHttps": "{provider} 的授权地址必须使用 https",
560
+ "sc.authorizeUrlHasCredentials": "{provider} 的授权地址不得包含用户名或密码",
561
+ "sc.cancelled": "操作已取消",
562
+ "sc.loginTimeout": "{provider} 登录超时:没有在有效期内完成浏览器授权。",
563
+ "sc.pollTokenEmpty": "{provider} 登录的 poll_token 不能为空",
564
+ "sc.loginNoApiKey": "{provider} 登录成功但没有拿到 api_key",
565
+ "sc.apiKeyEmpty": "{provider} API Key 是空的。",
566
+ "sc.waitingBrowserPoll": "等待浏览器授权…(每 {seconds} 秒查询一次)",
567
+ "sc.authorized": "授权完成",
568
+ "sc.credentialFieldInvalid": "{provider} 凭据字段无效:{key}",
569
+ "sc.credentialPayloadInvalid": "{provider} 凭据载荷无效",
570
+ "sc.credentialNoApiKey": "{provider} 凭据缺少 apiKey",
571
+ "sc.credentialProfileInvalid": "{provider} 凭据的 profile 无效",
572
+ "sc.storeUnsupportedPlatform": "{label} 凭据存储只支持 Windows、macOS 或 Linux。",
573
+ "sc.encryptedWriteVerifyFailed": "{provider} 加密凭据写入校验失败",
574
+ "sc.quotaCredentialPayloadInvalid": "{provider} 额度凭据载荷无效",
575
+ "sc.quotaCredentialNoToken": "{provider} 额度凭据缺少 Oasis-Token",
576
+ "sc.quotaCredentialNoDeviceId": "{provider} 额度凭据缺少 Oasis-Webid",
577
+ "sc.quotaCredentialWriteVerifyFailed": "{provider} 额度凭据写入校验失败",
578
+ "sc.modelSettingsWriteFailed": "{provider} 模型设置写入失败:落盘的选择与刚写入的不一致",
579
+ "glm.quotaNeedsKey": "{provider} 的配额接口需要一把 Coding Plan Key(裸值,不加 Bearer);空凭据不会变成一个能通过鉴权的请求。",
580
+ "glm.catalogNotJson": "{provider} 返回的模型目录不是可读的 JSON:{url}",
581
+ "glm.quotaNeedsKeyShort": "{provider} 的配额读取需要一把 Coding Plan Key(裸值,不加 Bearer)。",
582
+ "glm.quotaUnreachable": "配额接口不可达:{detail}",
583
+ "glm.quotaHttp": "配额查询失败(HTTP {status})",
584
+ "glm.quotaNotJson": "配额查询返回的不是 JSON。",
585
+ "glm.quotaNoWindow": "上游没有返回可显示的额度窗口。",
586
+ "glm.cooldownUntilReset": "{provider} 429:用量窗口将于 {at} 重置",
587
+ "glm.cooldownRetryAfter": "{provider} 429:上游要求 {seconds} 秒后再试",
588
+ "glm.cooldownNoReset": "{provider} 429:上游未给重置时刻,按 5 分钟冷却",
589
+ "glm.modelResolveAborted": "{provider} 模型解析已取消",
590
+ "glm.requestAborted": "{provider} 请求已取消",
591
+ "glm.requestFailed": "{provider} 请求失败:{detail}",
592
+ "glm.noResponse": "{provider} 没有返回任何响应",
593
+ "glm.emptyBody": "{provider} 返回了空响应体",
594
+ "glm.anthropicEmpty": "{provider} 的 Anthropic 面没有返回任何内容",
595
+ "glm.waitingBrowser": "等待你在浏览器里完成授权…",
596
+ "glm.connectingUpstream": "连接上游失败,正在重试…",
597
+ "glm.upstreamUnavailable": "上游暂时不可用(HTTP {status}),正在重试…",
598
+ "glm.upstreamRetryLater": "上游要求稍后再试(HTTP {status}),正在重试…",
599
+ "glm.pollRejected": "ZCode 登录轮询被拒绝(HTTP {status}):{url}",
600
+ "glm.unparsableRetry": "上游返回了无法解析的响应,正在重试…",
601
+ "glm.pollBusinessCode": "ZCode 登录轮询返回业务错误码 {code}{detail}",
602
+ "glm.readyNoToken": "就绪响应缺少 access_token,正在重试…",
603
+ "glm.sessionCancelled": "这次登录已经取消或已经过期,请重新发起登录。",
604
+ "glm.loginTimeout": "登录超时:上游在 {at} 之前没有完成授权。",
605
+ "glm.noSession": "当前没有进行中的 GLM 登录流程可供补全。",
606
+ "glm.authorizationDenied": "授权被拒绝:{denial}",
607
+ "glm.notAuthorizationCode": "这看起来不是授权码,也不是完整的回调链接(里面没有 code 参数)。",
608
+ "glm.callbackReceived": "已收到回调,正在向上游确认…",
609
+ "glm.poolNotInstalled": "账号池未安装。",
610
+ "glm.unknownStrategy": "未知的轮转策略。",
611
+ "glm.unknownAccountAction": "未知的账号操作:{action}",
612
+ "glm.pasteCallback": "请粘贴回调链接或授权码。",
613
+ "glm.noLoginInProgress": "当前没有进行中的登录流程,请先点击登录。",
614
+ "glm.notSignedIn": "还没有登录 {provider} 账号。"
615
+ };
616
+ //#endregion
617
+ //#region src/host/common/i18n/t.ts
618
+ const DICTIONARIES = {
619
+ zh,
620
+ en,
621
+ ru
622
+ };
623
+ /**
624
+ * Copy for one key in one language, with `{name}` placeholders filled.
625
+ *
626
+ * @param locale - Language to answer in.
627
+ * @param key - Key from the Chinese source dictionary.
628
+ * @param params - Values for the placeholders the template declares.
629
+ * @returns The rendered copy; a key missing from a language falls back to Chinese.
630
+ */
631
+ function translate$2(locale, key, params) {
632
+ return interpolate((DICTIONARIES[locale] ?? zh)[key] ?? zh[key] ?? key, params);
633
+ }
634
+ /**
635
+ * Copy for one key in the language currently in force.
636
+ *
637
+ * @param key - Key from the Chinese source dictionary.
638
+ * @param params - Values for the placeholders the template declares.
639
+ * @returns The rendered copy.
640
+ */
641
+ function t(key, params) {
642
+ return translate$2(currentLocale(), key, params);
643
+ }
644
+ /**
645
+ * Fill `{name}` placeholders; an absent parameter leaves its placeholder alone
646
+ * so a mis-wired call is visible rather than silently blank.
647
+ *
648
+ * @param template - Copy carrying placeholders.
649
+ * @param params - Values by placeholder name.
650
+ * @returns The rendered copy.
651
+ */
652
+ function interpolate(template, params) {
653
+ if (params === void 0) return template;
654
+ return template.replace(/\{([A-Za-z0-9_.-]+)\}/g, (whole, name) => {
655
+ const value = params[name];
656
+ if (value === void 0 || value === null) return whole;
657
+ return String(value);
658
+ });
659
+ }
660
+ //#endregion
661
+ //#region src/host/common/i18n/provider-name.ts
662
+ /** Provider id to the key that names it. */
663
+ const NAME_KEYS = /* @__PURE__ */ new Map([
664
+ ["codex-chatgpt", "provider.codex-chatgpt"],
665
+ ["claude-subscription", "provider.claude"],
666
+ ["workbuddy-subscription", "provider.workbuddy"],
667
+ ["glm-coding-plan", "provider.glm-coding-plan"],
668
+ ["minimax-code", "provider.minimax-code"],
669
+ ["qoder", "provider.qoder"],
670
+ ["step-code", "provider.step-code"]
671
+ ]);
672
+ /**
673
+ * The name one provider registers under, in the language in force.
674
+ *
675
+ * @param providerId - Id the harness asked about.
676
+ * @param fallback - The adapter's own neutral name, used when this build has no
677
+ * translation for the id (a provider this table does not know).
678
+ * @returns Localized display name, or `fallback`.
679
+ */
680
+ function localizedProviderName(providerId, fallback) {
681
+ const key = NAME_KEYS.get(providerId);
682
+ return key === void 0 ? fallback : t(key);
683
+ }
684
+ //#endregion
29
685
  //#region src/host/common/output-reservation.ts
30
686
  /**
31
687
  * Keep fixed defaults only when they fit DSH compaction-basic's default policy.
@@ -151,7 +807,7 @@ const ROUTE_PREFIX$5 = "/api/dsh-chatgpt-subscription";
151
807
  * `test/responses-client.test.ts` asserts the two agree, so a release that
152
808
  * forgets this constant fails the suite instead of shipping quietly.
153
809
  */
154
- const PLUGIN_VERSION = "0.54.0";
810
+ const PLUGIN_VERSION = "0.56.0";
155
811
  const CODEX_CHATGPT_PROVIDER_ID = "codex-chatgpt";
156
812
  const CODEX_API_BASE = "https://chatgpt.com/backend-api/codex";
157
813
  const CODEX_RESPONSES_URL = `${CODEX_API_BASE}/responses`;
@@ -997,7 +1653,7 @@ var CodexChatGptAdapter = class extends LlmAdapter {
997
1653
  providerInfo(provider) {
998
1654
  return {
999
1655
  id: provider,
1000
- name: PROVIDER_NAME$12
1656
+ name: localizedProviderName(provider, PROVIDER_NAME$12)
1001
1657
  };
1002
1658
  }
1003
1659
  providerRetryPolicy() {
@@ -2420,7 +3076,10 @@ var AccountPoolCore = class {
2420
3076
  const key = this.hooks.dedupeKey?.(credentials);
2421
3077
  const existingIndex = key === void 0 ? -1 : data.accounts.findIndex((account) => this.hooks.dedupeKey?.(account.credentials) === key);
2422
3078
  const maxAccounts = this.hooks.maxAccounts ?? 20;
2423
- if (existingIndex < 0 && data.accounts.length >= maxAccounts) throw new Error(`${this.hooks.displayName} 号池最多支持 ${maxAccounts} 个账号,请先删除不再使用的账号。`);
3079
+ if (existingIndex < 0 && data.accounts.length >= maxAccounts) throw new Error(t("pool.maxAccounts", {
3080
+ provider: this.hooks.displayName,
3081
+ max: maxAccounts
3082
+ }));
2424
3083
  const existing = existingIndex >= 0 ? data.accounts[existingIndex] : void 0;
2425
3084
  const id = existing === void 0 ? this.hooks.accountId?.(credentials) ?? `acc_${randomBytes(6).toString("hex")}` : existing.id;
2426
3085
  const isPrimary = data.accounts.length === 0 || existing?.isPrimary === true;
@@ -2580,9 +3239,12 @@ var AccountPoolCore = class {
2580
3239
  */
2581
3240
  async getCredentialAccount(fetchFn = fetch, forceRefresh = false) {
2582
3241
  const data = await this.read();
2583
- if (data.accounts.length === 0) throw new Error(this.hooks.emptyMessage ?? `未登录 ${this.hooks.displayName} 账号,请先在设置页添加账号。`);
3242
+ if (data.accounts.length === 0) throw new Error(this.hooks.emptyMessage ?? t("pool.notSignedIn", { provider: this.hooks.displayName }));
2584
3243
  const usable = data.accounts.filter((account) => this.isCredentialUsable(account));
2585
- if (usable.length === 0) throw new LlmError(`全部 ${data.accounts.length} 个 ${this.hooks.displayName} 账号均需要重新登录。`, "AUTH", { status: 401 });
3244
+ if (usable.length === 0) throw new LlmError(t("pool.allNeedSignIn", {
3245
+ count: data.accounts.length,
3246
+ provider: this.hooks.displayName
3247
+ }), "AUTH", { status: 401 });
2586
3248
  const selected = this.selectAccount(usable, data);
2587
3249
  const account = await this.freshAccount(selected, fetchFn, forceRefresh);
2588
3250
  return {
@@ -2636,8 +3298,8 @@ var AccountPoolCore = class {
2636
3298
  async credentialFor(accountId, fetchFn, force, expected) {
2637
3299
  const data = await this.read();
2638
3300
  const target = accountId === void 0 ? data.accounts.find((account) => account.id === data.activeAccountId) ?? data.accounts.find((account) => account.isPrimary) ?? data.accounts[0] : data.accounts.find((account) => account.id === accountId);
2639
- if (target === void 0) throw new LlmError(this.hooks.emptyMessage ?? `未登录 ${this.hooks.displayName} 账号,请先在设置页添加账号。`, "AUTH");
2640
- if (!this.isCredentialUsable(target)) throw new LlmError(`${this.hooks.displayName} 账号的凭据已被拒绝,需要重新登录。`, "AUTH", { status: 401 });
3301
+ if (target === void 0) throw new LlmError(this.hooks.emptyMessage ?? t("pool.notSignedIn", { provider: this.hooks.displayName }), "AUTH");
3302
+ if (!this.isCredentialUsable(target)) throw new LlmError(t("pool.credentialRejected", { provider: this.hooks.displayName }), "AUTH", { status: 401 });
2641
3303
  if (expected !== void 0 && !isDeepStrictEqual(expected, target.credentials)) return target.credentials;
2642
3304
  return (await this.freshAccount(target, fetchFn, force)).credentials;
2643
3305
  }
@@ -2659,7 +3321,7 @@ var AccountPoolCore = class {
2659
3321
  let launch;
2660
3322
  const plan = await this.serialize(async () => {
2661
3323
  const current = (await this.loadPoolData()).accounts.find((account) => account.id === target.id);
2662
- if (current === void 0 || !this.isCredentialUsable(current)) throw new PoolAccountUnavailableError(this.hooks.emptyMessage ?? "未登录 " + this.hooks.displayName + " 账号,请先在设置页添加账号。", "AUTH");
3324
+ if (current === void 0 || !this.isCredentialUsable(current)) throw new PoolAccountUnavailableError(this.hooks.emptyMessage ?? t("pool.notSignedIn", { provider: this.hooks.displayName }), "AUTH");
2663
3325
  if (!isDeepStrictEqual(current.credentials, target.credentials)) return { account: current };
2664
3326
  if (!this.hooks.refresh || !force && !this.shouldRefreshCredential(current, Date.now())) return { account: current };
2665
3327
  const key = JSON.stringify([this.operationKey, current.id]);
@@ -2731,8 +3393,8 @@ var AccountPoolCore = class {
2731
3393
  return account;
2732
3394
  }
2733
3395
  assertUsableAccount(account) {
2734
- if (account === void 0) throw new PoolAccountUnavailableError(this.hooks.emptyMessage ?? "未登录 " + this.hooks.displayName + " 账号,请先在设置页添加账号。", "AUTH");
2735
- if (!this.isCredentialUsable(account)) throw new PoolAccountUnavailableError(this.hooks.displayName + " 账号的凭据已被拒绝,需要重新登录。", "AUTH", { status: 401 });
3396
+ if (account === void 0) throw new PoolAccountUnavailableError(this.hooks.emptyMessage ?? t("pool.notSignedIn", { provider: this.hooks.displayName }), "AUTH");
3397
+ if (!this.isCredentialUsable(account)) throw new PoolAccountUnavailableError(t("pool.credentialRejected", { provider: this.hooks.displayName }), "AUTH", { status: 401 });
2736
3398
  }
2737
3399
  /** Whether one account's credential must be refreshed before it is handed out. */
2738
3400
  shouldRefreshCredential(account, now) {
@@ -2784,9 +3446,19 @@ var AccountPoolCore = class {
2784
3446
  allUnavailableError(data, now) {
2785
3447
  let shortest = Infinity;
2786
3448
  for (const account of data.accounts) if (account.cooldownUntil !== void 0 && account.cooldownUntil > now) shortest = Math.min(shortest, account.cooldownUntil - now);
2787
- if (!data.accounts.some((account) => this.isCredentialUsable(account))) return new LlmError(this.hooks.allAuthFailedMessage?.(data.accounts.length) ?? `全部 ${data.accounts.length} 个 ${this.hooks.displayName} 账号均需要重新登录。`, "AUTH", { status: 401 });
3449
+ if (!data.accounts.some((account) => this.isCredentialUsable(account))) return new LlmError(this.hooks.allAuthFailedMessage?.(data.accounts.length) ?? t("pool.allNeedSignIn", {
3450
+ count: data.accounts.length,
3451
+ provider: this.hooks.displayName
3452
+ }), "AUTH", { status: 401 });
2788
3453
  const waitMinutes = Number.isFinite(shortest) ? Math.ceil(shortest / 6e4) : null;
2789
- return new LlmError(this.hooks.allUnavailableMessage?.(data.accounts.length, waitMinutes) ?? (waitMinutes === null ? `全部 ${data.accounts.length} 个 ${this.hooks.displayName} 账号当前都不可用,且没有处于冷却中的账号。` : `全部 ${data.accounts.length} 个 ${this.hooks.displayName} 账号均处于配额限制或冷却中 (429)。最短预计在 ${waitMinutes} 分钟后解除冷却。`), "RATE_LIMIT", { status: 429 });
3454
+ return new LlmError(this.hooks.allUnavailableMessage?.(data.accounts.length, waitMinutes) ?? (waitMinutes === null ? t("pool.allUnavailable", {
3455
+ count: data.accounts.length,
3456
+ provider: this.hooks.displayName
3457
+ }) : t("pool.allCoolingDown", {
3458
+ count: data.accounts.length,
3459
+ provider: this.hooks.displayName,
3460
+ minutes: waitMinutes
3461
+ })), "RATE_LIMIT", { status: 429 });
2790
3462
  }
2791
3463
  /**
2792
3464
  * Pick the account for the next request, refreshing its credential when it is
@@ -2802,7 +3474,7 @@ var AccountPoolCore = class {
2802
3474
  */
2803
3475
  async getEffectiveAccount(excludeIds, fetchFn = fetch, forceRefresh = false, options) {
2804
3476
  const data = await this.read();
2805
- if (data.accounts.length === 0) throw new Error(this.hooks.emptyMessage ?? `未登录 ${this.hooks.displayName} 账号,请先在设置页添加账号。`);
3477
+ if (data.accounts.length === 0) throw new Error(this.hooks.emptyMessage ?? t("pool.notSignedIn", { provider: this.hooks.displayName }));
2806
3478
  const now = Date.now();
2807
3479
  const eligible = data.accounts.filter((account) => this.isEligible(account, now, excludeIds));
2808
3480
  if (eligible.length === 0) throw this.allUnavailableError(data, now);
@@ -4607,7 +5279,7 @@ var CodexAccountPool = class extends AccountPoolCore {
4607
5279
  refresh: async (credentials) => {
4608
5280
  if (isAdoptedCodexPoolCredential(credentials)) throw new CodexAdoptedCredentialError(isAdoptedCodexCredentialExpired(credentials) ? ADOPTED_CODEX_CREDENTIAL_EXPIRED_HINT : ADOPTED_NEVER_REFRESHED_MESSAGE$1);
4609
5281
  const refresher = ref.current;
4610
- if (refresher === void 0) throw new Error("ChatGPT 凭据刷新服务尚未就绪");
5282
+ if (refresher === void 0) throw new Error(t("codex.refresherNotReady"));
4611
5283
  return refresher.refreshAccount(credentials);
4612
5284
  },
4613
5285
  authRejectedReason: (credentials) => codexAuthRejectedReason(credentials),
@@ -4657,7 +5329,7 @@ var CodexAccountPool = class extends AccountPoolCore {
4657
5329
  } : {}
4658
5330
  };
4659
5331
  },
4660
- emptyMessage: "未登录 ChatGPT 账号,请在「设置 → 订阅服务 → ChatGPT」中添加并登录账号。",
5332
+ emptyMessage: t("codex.notSignedIn"),
4661
5333
  ...options.backend === void 0 ? {} : { backend: options.backend },
4662
5334
  ...options.keyring === void 0 ? {} : { keyring: options.keyring },
4663
5335
  ...options.maxAccounts === void 0 ? {} : { maxAccounts: options.maxAccounts }
@@ -4707,8 +5379,8 @@ var CodexAccountPool = class extends AccountPoolCore {
4707
5379
  */
4708
5380
  async refreshAccountNow(accountId) {
4709
5381
  const account = (await this.read()).accounts.find((entry) => entry.id === accountId);
4710
- if (account === void 0) throw new Error("ChatGPT 账号已不在号池中");
4711
- if (this.refresherRef.current === void 0) throw new Error("ChatGPT 凭据刷新服务尚未就绪");
5382
+ if (account === void 0) throw new Error(t("codex.accountGone"));
5383
+ if (this.refresherRef.current === void 0) throw new Error(t("codex.refresherNotReady"));
4712
5384
  return this.renewCredential(accountId, fetch, account.credentials);
4713
5385
  }
4714
5386
  /**
@@ -9315,7 +9987,7 @@ var AntigravityAdapter = class extends LlmAdapter {
9315
9987
  providerInfo(provider) {
9316
9988
  return {
9317
9989
  id: provider,
9318
- name: PROVIDER_NAME$11
9990
+ name: localizedProviderName(provider, PROVIDER_NAME$11)
9319
9991
  };
9320
9992
  }
9321
9993
  providerRetryPolicy() {}
@@ -9550,8 +10222,8 @@ var AntigravityAdapter = class extends LlmAdapter {
9550
10222
  if (response === void 0) throw new LlmError(`Antigravity request failed before any endpoint answered: ${(transportError instanceof Error ? transportError.message : transportError === void 0 ? "" : String(transportError)) || "No response"}`, "TRANSPORT", transportError === void 0 ? {} : { cause: transportError });
9551
10223
  const status = response.status;
9552
10224
  if (status === 429) {
9553
- if (retryDelayMs(response.headers, errText) !== void 0) throw new LlmError(`Antigravity 账号配额已耗尽或请求受限 (429 RESOURCE_EXHAUSTED)。请在插件设置页查看配额剩余百分比及重置倒计时。原始响应: ${errText || "No response"}`, "RATE_LIMIT", { status: 429 });
9554
- throw new LlmError(`Antigravity 上游返回 429 (RESOURCE_EXHAUSTED) 但未给出重置时间,因此按瞬时限流处理,不视为账号配额耗尽,也不会冷却该账号。原始响应: ${upstreamBodyExcerpt(errText) || "No response"}`, "SERVER", { status: 429 });
10225
+ if (retryDelayMs(response.headers, errText) !== void 0) throw new LlmError(t("antigravity.quotaExhausted", { body: errText || "No response" }), "RATE_LIMIT", { status: 429 });
10226
+ throw new LlmError(t("antigravity.rateLimitedNoReset", { body: upstreamBodyExcerpt(errText) || "No response" }), "SERVER", { status: 429 });
9555
10227
  }
9556
10228
  if (status >= 500) throw new LlmError(`Antigravity upstream server error (${status}): ${errText || "No response"}`, "SERVER", { status });
9557
10229
  throw new LlmError(`Antigravity API error (${status}): ${errText || "No response"}`, isHttpContextOverflow(status, errText) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR", { status });
@@ -11436,7 +12108,9 @@ const DEFAULT_PREFERENCES = {
11436
12108
  customProxyUrl: null,
11437
12109
  compactionRoute: null,
11438
12110
  subagentDefaultModels: [],
11439
- subagentModelsByMainModel: {}
12111
+ subagentModelsByMainModel: {},
12112
+ subagentDefaultAllowParentFork: false,
12113
+ subagentAllowParentForkByMainModel: {}
11440
12114
  };
11441
12115
  const SEARCH_PROVIDER_CODEX = "codex";
11442
12116
  function isSearchProviderPreference(value) {
@@ -11550,6 +12224,36 @@ function mergeSubagentModelsByMainModel(current, patch) {
11550
12224
  }
11551
12225
  return merged;
11552
12226
  }
12227
+ /**
12228
+ * Merge one `subagentAllowParentForkByMainModel` patch into the stored map.
12229
+ *
12230
+ * `null` clears one key so that main model falls back to
12231
+ * `subagentDefaultAllowParentFork`; a boolean sets an explicit per-main-model
12232
+ * override (`true` OR `false`, since overriding a `true` global default back to
12233
+ * `false` for one main model is legitimate).
12234
+ * @param current - Map already stored in the preferences document.
12235
+ * @param patch - Incoming patch from a settings card or a route body.
12236
+ * @returns the merged map, or null when any key or value is malformed.
12237
+ */
12238
+ function mergeSubagentAllowParentForkByMainModel(current, patch) {
12239
+ const patchRecord = asRecord$19(patch);
12240
+ if (patchRecord === void 0) return null;
12241
+ const merged = {};
12242
+ if (current !== void 0) {
12243
+ for (const [k, v] of Object.entries(current)) if (typeof v === "boolean" && isValidMainModelKey(k)) merged[k.trim()] = v;
12244
+ }
12245
+ for (const [rawKey, rawValue] of Object.entries(patchRecord)) {
12246
+ const key = rawKey.trim();
12247
+ if (!isValidMainModelKey(key)) return null;
12248
+ if (rawValue === null) {
12249
+ delete merged[key];
12250
+ continue;
12251
+ }
12252
+ if (typeof rawValue !== "boolean") return null;
12253
+ merged[key] = rawValue;
12254
+ }
12255
+ return merged;
12256
+ }
11553
12257
  //#endregion
11554
12258
  //#region src/host/common/legacy-preferences.ts
11555
12259
  /**
@@ -11751,7 +12455,9 @@ function registerPreferenceStore(settings) {
11751
12455
  model: z$1.string()
11752
12456
  }), z$1.const(null)]).default(DEFAULT_PREFERENCES.compactionRoute ?? null),
11753
12457
  subagentDefaultModels: subagentModelRoutes.default([]),
11754
- subagentModelsByMainModel: z$1.dict(subagentModelRoutes).default({})
12458
+ subagentModelsByMainModel: z$1.dict(subagentModelRoutes).default({}),
12459
+ subagentDefaultAllowParentFork: z$1.boolean().default(DEFAULT_PREFERENCES.subagentDefaultAllowParentFork ?? false),
12460
+ subagentAllowParentForkByMainModel: z$1.dict(z$1.boolean()).default({})
11755
12461
  });
11756
12462
  if (!hasRegister(settings)) {
11757
12463
  const fileStore = new FilePreferencesStore(schema, preferencesPath(), readLegacyPreferences);
@@ -11819,6 +12525,15 @@ var SettingsPreferenceStore = class {
11819
12525
  if (merged === null) throw new PreferenceError("Unsupported subagentModelsByMainModel preference.");
11820
12526
  normalized.subagentModelsByMainModel = merged;
11821
12527
  }
12528
+ if (patch.subagentDefaultAllowParentFork !== void 0) {
12529
+ if (typeof patch.subagentDefaultAllowParentFork !== "boolean") throw new PreferenceError("Unsupported subagentDefaultAllowParentFork preference.");
12530
+ normalized.subagentDefaultAllowParentFork = patch.subagentDefaultAllowParentFork;
12531
+ }
12532
+ if (patch.subagentAllowParentForkByMainModel !== void 0) {
12533
+ const merged = mergeSubagentAllowParentForkByMainModel(this.scope.get().subagentAllowParentForkByMainModel, patch.subagentAllowParentForkByMainModel);
12534
+ if (merged === null) throw new PreferenceError("Unsupported subagentAllowParentForkByMainModel preference.");
12535
+ normalized.subagentAllowParentForkByMainModel = merged;
12536
+ }
11822
12537
  if (patch.customProxyUrl !== void 0) if (patch.customProxyUrl !== null) {
11823
12538
  const trimmed = patch.customProxyUrl.trim();
11824
12539
  if (trimmed.length > 0 && !/^https?:\/\//i.test(trimmed) && !/^socks5?:\/\//i.test(trimmed)) normalized.customProxyUrl = `http://${trimmed}`;
@@ -14521,6 +15236,15 @@ function registerRoutes(ctx, oauth, usage, preferences, proxyManager, searchSwit
14521
15236
  };
14522
15237
  try {
14523
15238
  switch (url.pathname) {
15239
+ case `${ROUTE_PREFIX$5}/i18n/locale`: {
15240
+ const runtime = hostLocaleRuntime();
15241
+ const tag = field(body, "locale");
15242
+ json(response, {
15243
+ ok: true,
15244
+ value: { locale: runtime === void 0 ? currentLocale() : runtime.set(tag ?? void 0) }
15245
+ });
15246
+ return;
15247
+ }
14524
15248
  case `${ROUTE_PREFIX$5}/login/start`:
14525
15249
  json(response, {
14526
15250
  ok: true,
@@ -14849,6 +15573,14 @@ function readPreferencesUpdate(value, current) {
14849
15573
  if (mergeSubagentModelsByMainModel(current.subagentModelsByMainModel, value.subagentModelsByMainModel) === null) throw new PreferenceError("subagentModelsByMainModel must map \"provider/model\" keys to arrays of { provider, model } routes, or null to clear one.");
14850
15574
  patch.subagentModelsByMainModel = value.subagentModelsByMainModel;
14851
15575
  }
15576
+ if ("subagentDefaultAllowParentFork" in value) {
15577
+ if (typeof value.subagentDefaultAllowParentFork !== "boolean") throw new PreferenceError("subagentDefaultAllowParentFork must be a boolean.");
15578
+ patch.subagentDefaultAllowParentFork = value.subagentDefaultAllowParentFork;
15579
+ }
15580
+ if ("subagentAllowParentForkByMainModel" in value) {
15581
+ if (mergeSubagentAllowParentForkByMainModel(current.subagentAllowParentForkByMainModel, value.subagentAllowParentForkByMainModel) === null) throw new PreferenceError("subagentAllowParentForkByMainModel must map \"provider/model\" keys to booleans, or null to clear one.");
15582
+ patch.subagentAllowParentForkByMainModel = value.subagentAllowParentForkByMainModel;
15583
+ }
14852
15584
  if ("contextWindowOverrides" in value) {
14853
15585
  if (!isRecord$62(value.contextWindowOverrides)) throw new PreferenceError("contextWindowOverrides must be an object.");
14854
15586
  const overrides = {};
@@ -22471,7 +23203,7 @@ var CommandCodeAdapter = class extends LlmAdapter {
22471
23203
  providerInfo(provider) {
22472
23204
  return {
22473
23205
  id: provider,
22474
- name: PROVIDER_NAME$10
23206
+ name: localizedProviderName(provider, PROVIDER_NAME$10)
22475
23207
  };
22476
23208
  }
22477
23209
  providerRetryPolicy() {
@@ -25083,7 +25815,7 @@ var OllamaAdapter = class extends LlmAdapter {
25083
25815
  providerInfo(provider) {
25084
25816
  return {
25085
25817
  id: provider,
25086
- name: PROVIDER_NAME$9
25818
+ name: localizedProviderName(provider, PROVIDER_NAME$9)
25087
25819
  };
25088
25820
  }
25089
25821
  providerRetryPolicy() {
@@ -35947,7 +36679,7 @@ var KimiCodeAdapter = class extends LlmAdapter {
35947
36679
  providerInfo(provider) {
35948
36680
  return {
35949
36681
  id: provider,
35950
- name: PROVIDER_NAME$8
36682
+ name: localizedProviderName(provider, PROVIDER_NAME$8)
35951
36683
  };
35952
36684
  }
35953
36685
  providerRetryPolicy() {
@@ -43289,7 +44021,7 @@ var MinimaxCodeAdapter = class extends LlmAdapter {
43289
44021
  providerInfo(provider) {
43290
44022
  return {
43291
44023
  id: provider,
43292
- name: PROVIDER_NAME$7
44024
+ name: localizedProviderName(provider, PROVIDER_NAME$7)
43293
44025
  };
43294
44026
  }
43295
44027
  providerRetryPolicy() {
@@ -54289,7 +55021,7 @@ var ClaudeAdapter = class ClaudeAdapter extends LlmAdapter {
54289
55021
  providerInfo(provider) {
54290
55022
  return {
54291
55023
  id: provider,
54292
- name: PROVIDER_NAME
55024
+ name: localizedProviderName(provider, PROVIDER_NAME)
54293
55025
  };
54294
55026
  }
54295
55027
  providerRetryPolicy() {
@@ -60091,7 +60823,7 @@ function glmOpenAiProbeHeaders(codingPlanKey) {
60091
60823
  */
60092
60824
  function quotaRequestHeaders$1(codingPlanKey) {
60093
60825
  const key = codingPlanKey.trim();
60094
- if (key === "") throw new Error(failure$1("的配额接口需要一把 Coding Plan Key(裸值,不加 Bearer);空凭据不会变成一个能通过鉴权的请求。"));
60826
+ if (key === "") throw new Error(failure$1(t("glm.quotaNeedsKey", { provider: PROVIDER_NAME$1 })));
60095
60827
  return {
60096
60828
  "content-type": "application/json",
60097
60829
  accept: "application/json",
@@ -60179,7 +60911,10 @@ async function fetchCatalog(region, codingPlanKey, options = {}) {
60179
60911
  try {
60180
60912
  payload = JSON.parse(text);
60181
60913
  } catch {
60182
- throw new Error(failure$1("返回的模型目录不是可读的 JSON:" + url));
60914
+ throw new Error(failure$1(t("glm.catalogNotJson", {
60915
+ provider: PROVIDER_NAME$1,
60916
+ url
60917
+ })));
60183
60918
  }
60184
60919
  return parseCatalogListing(payload, region);
60185
60920
  }
@@ -60434,7 +61169,7 @@ async function fetchSubscriptionPlan(region, codingPlanKey, options = {}) {
60434
61169
  * 所以它同步抛出,与「上游读失败返回 `error`」那条路径分开。
60435
61170
  */
60436
61171
  async function fetchGlmQuota(region, codingPlanKey, options = {}) {
60437
- if (codingPlanKey.trim() === "") throw new Error(failure$1("的配额读取需要一把 Coding Plan Key(裸值,不加 Bearer)。"));
61172
+ if (codingPlanKey.trim() === "") throw new Error(failure$1(t("glm.quotaNeedsKeyShort", { provider: PROVIDER_NAME$1 })));
60438
61173
  const accountId = options.accountId;
60439
61174
  const cached = quotaEntryFor(accountId);
60440
61175
  if (options.force !== true && cached !== null && Date.now() - cached.at < 12e4) return {
@@ -60460,7 +61195,7 @@ async function fetchGlmQuota(region, codingPlanKey, options = {}) {
60460
61195
  } catch (error) {
60461
61196
  return {
60462
61197
  snapshot: null,
60463
- error: failure$1("配额接口不可达:" + (error instanceof Error ? error.message : String(error))),
61198
+ error: failure$1(t("glm.quotaUnreachable", { detail: error instanceof Error ? error.message : String(error) })),
60464
61199
  fromCache: false
60465
61200
  };
60466
61201
  }
@@ -60469,7 +61204,7 @@ async function fetchGlmQuota(region, codingPlanKey, options = {}) {
60469
61204
  const detail = summarize(text);
60470
61205
  return {
60471
61206
  snapshot: null,
60472
- error: failure$1("配额查询失败(HTTP " + response.status + ")") + (detail === "" ? "" : ":" + detail),
61207
+ error: failure$1(t("glm.quotaHttp", { status: response.status })) + (detail === "" ? "" : ":" + detail),
60473
61208
  fromCache: false
60474
61209
  };
60475
61210
  }
@@ -60479,7 +61214,7 @@ async function fetchGlmQuota(region, codingPlanKey, options = {}) {
60479
61214
  } catch {
60480
61215
  return {
60481
61216
  snapshot: null,
60482
- error: failure$1("配额查询返回的不是 JSON。"),
61217
+ error: failure$1(t("glm.quotaNotJson")),
60483
61218
  fromCache: false
60484
61219
  };
60485
61220
  }
@@ -60492,7 +61227,7 @@ async function fetchGlmQuota(region, codingPlanKey, options = {}) {
60492
61227
  });
60493
61228
  if (snapshot === null) return {
60494
61229
  snapshot: null,
60495
- error: failure$1("上游没有返回可显示的额度窗口。"),
61230
+ error: failure$1(t("glm.quotaNoWindow")),
60496
61231
  fromCache: false
60497
61232
  };
60498
61233
  return {
@@ -61482,18 +62217,24 @@ function glmCooldownDecision(input) {
61482
62217
  if (resetsAt !== void 0) return {
61483
62218
  cooldown: true,
61484
62219
  durationMs: Math.max(3e4, resetsAt - Date.now()),
61485
- reason: "GLM(ZCode 账号) 429:用量窗口将于 " + new Date(resetsAt).toISOString() + " 重置"
62220
+ reason: t("glm.cooldownUntilReset", {
62221
+ provider: PROVIDER_NAME$1,
62222
+ at: new Date(resetsAt).toISOString()
62223
+ })
61486
62224
  };
61487
62225
  const after = input.headers === void 0 ? void 0 : retryAfterMs$1(input.headers);
61488
62226
  if (after !== void 0 && after > 0) return {
61489
62227
  cooldown: true,
61490
62228
  durationMs: after,
61491
- reason: "GLM(ZCode 账号) 429:上游要求 " + Math.ceil(after / 1e3) + " 秒后再试"
62229
+ reason: t("glm.cooldownRetryAfter", {
62230
+ provider: PROVIDER_NAME$1,
62231
+ seconds: Math.ceil(after / 1e3)
62232
+ })
61492
62233
  };
61493
62234
  return {
61494
62235
  cooldown: true,
61495
62236
  durationMs: GLM_POOL_COOLDOWN_MS,
61496
- reason: "GLM(ZCode 账号) 429:上游未给重置时刻,按 5 分钟冷却"
62237
+ reason: t("glm.cooldownNoReset", { provider: PROVIDER_NAME$1 })
61497
62238
  };
61498
62239
  }
61499
62240
  /**
@@ -61560,7 +62301,7 @@ var GlmCodingPlanAdapter = class extends LlmAdapter {
61560
62301
  providerInfo(provider) {
61561
62302
  return {
61562
62303
  id: provider,
61563
- name: PROVIDER_NAME$1
62304
+ name: localizedProviderName(provider, PROVIDER_NAME$1)
61564
62305
  };
61565
62306
  }
61566
62307
  providerRetryPolicy() {
@@ -61619,7 +62360,7 @@ var GlmCodingPlanAdapter = class extends LlmAdapter {
61619
62360
  }));
61620
62361
  }
61621
62362
  async resolveModel(provider, model, signal) {
61622
- if (signal?.aborted) throw new LlmError("GLM(ZCode 账号) 模型解析已取消", "ABORTED");
62363
+ if (signal?.aborted) throw new LlmError(t("glm.modelResolveAborted", { provider: PROVIDER_NAME$1 }), "ABORTED");
61623
62364
  const settings = await this.settings();
61624
62365
  const region = (await this.credentialFor().catch(() => null))?.credentials.codingPlan.region ?? "intl";
61625
62366
  const entry = resolveGlmModel(model, this.catalog(region));
@@ -61688,8 +62429,11 @@ var GlmCodingPlanAdapter = class extends LlmAdapter {
61688
62429
  });
61689
62430
  activity?.pulse();
61690
62431
  } catch (error) {
61691
- if (signal.aborted) throw new LlmError("GLM(ZCode 账号) 请求已取消", "ABORTED", { cause: error });
61692
- throw new LlmError("GLM(ZCode 账号) 请求失败:" + (error instanceof Error ? error.message : String(error)), "TRANSPORT", { cause: error });
62432
+ if (signal.aborted) throw new LlmError(t("glm.requestAborted", { provider: PROVIDER_NAME$1 }), "ABORTED", { cause: error });
62433
+ throw new LlmError(t("glm.requestFailed", {
62434
+ provider: PROVIDER_NAME$1,
62435
+ detail: error instanceof Error ? error.message : String(error)
62436
+ }), "TRANSPORT", { cause: error });
61693
62437
  }
61694
62438
  if (response.ok) break;
61695
62439
  const detail = await response.text().catch(() => "");
@@ -61726,8 +62470,8 @@ var GlmCodingPlanAdapter = class extends LlmAdapter {
61726
62470
  throw failure;
61727
62471
  }
61728
62472
  const settled = plan;
61729
- if (response === void 0) throw new LlmError("GLM(ZCode 账号) 没有返回任何响应", "PROVIDER_ERROR");
61730
- if (response.body === null) throw new LlmError("GLM(ZCode 账号) 返回了空响应体", "PROVIDER_ERROR");
62473
+ if (response === void 0) throw new LlmError(t("glm.noResponse", { provider: PROVIDER_NAME$1 }), "PROVIDER_ERROR");
62474
+ if (response.body === null) throw new LlmError(t("glm.emptyBody", { provider: PROVIDER_NAME$1 }), "PROVIDER_ERROR");
61731
62475
  const reader = response.body.getReader();
61732
62476
  const decoder = new TextDecoder();
61733
62477
  let buffer = "";
@@ -61750,7 +62494,7 @@ var GlmCodingPlanAdapter = class extends LlmAdapter {
61750
62494
  buffer += decoder.decode();
61751
62495
  if (buffer.trim() !== "") for (const line of buffer.split("\n")) for (const chunk of processGlmAnthropicStreamLine(line, state)) yield chunk;
61752
62496
  if (state.finished) return;
61753
- if (!glmStreamHasContent(state)) throw new LlmError("GLM(ZCode 账号) 的 Anthropic 面没有返回任何内容", "PROVIDER_ERROR");
62497
+ if (!glmStreamHasContent(state)) throw new LlmError(t("glm.anthropicEmpty", { provider: PROVIDER_NAME$1 }), "PROVIDER_ERROR");
61754
62498
  assertGlmStreamComplete(state);
61755
62499
  for (const chunk of closeGlmAnthropicStream(state)) yield chunk;
61756
62500
  } finally {
@@ -62308,42 +63052,48 @@ async function pollCliFlow(flow, options = {}) {
62308
63052
  if (options.signal?.aborted === true) throw error;
62309
63053
  return {
62310
63054
  kind: "pending",
62311
- progress: "连接上游失败,正在重试…"
63055
+ progress: t("glm.connectingUpstream")
62312
63056
  };
62313
63057
  }
62314
63058
  const payload = await response.json().catch(() => void 0);
62315
63059
  if (response.status >= 500) return {
62316
63060
  kind: "pending",
62317
- progress: "上游暂时不可用(HTTP " + response.status + "),正在重试…"
63061
+ progress: t("glm.upstreamUnavailable", { status: response.status })
62318
63062
  };
62319
63063
  if (!response.ok) {
62320
63064
  if (response.status === 408 || response.status === 429) return {
62321
63065
  kind: "pending",
62322
- progress: "上游要求稍后再试(HTTP " + response.status + "),正在重试…"
63066
+ progress: t("glm.upstreamRetryLater", { status: response.status })
62323
63067
  };
62324
- throw new GlmLoginFatalError("ZCode 登录轮询被拒绝(HTTP " + response.status + "):" + url);
63068
+ throw new GlmLoginFatalError(t("glm.pollRejected", {
63069
+ status: response.status,
63070
+ url
63071
+ }));
62325
63072
  }
62326
63073
  const root = asRecord$4(payload);
62327
63074
  if (root === void 0) return {
62328
63075
  kind: "pending",
62329
- progress: "上游返回了无法解析的响应,正在重试…"
63076
+ progress: t("glm.unparsableRetry")
62330
63077
  };
62331
63078
  const code = readEnvelopeCode(root);
62332
63079
  if (code !== void 0 && code !== 0 && code !== "0") {
62333
63080
  const message = asString$11(root.msg) ?? asString$11(root.message);
62334
- throw new GlmLoginFatalError("ZCode 登录轮询返回业务错误码 " + String(code) + (message === void 0 ? "" : ":" + message));
63081
+ throw new GlmLoginFatalError(t("glm.pollBusinessCode", {
63082
+ code: String(code),
63083
+ detail: message === void 0 ? "" : ":" + message
63084
+ }));
62335
63085
  }
62336
63086
  const body = unwrapBody(root, [CLI_READY_FIELDS$1.status, CLI_READY_FIELDS$1.user]);
62337
63087
  const status = body === void 0 ? void 0 : asString$11(body[CLI_READY_FIELDS$1.status]);
62338
63088
  if (status === CLI_PENDING_STATUS) return {
62339
63089
  kind: "pending",
62340
- progress: "等待你在浏览器里完成授权…"
63090
+ progress: t("glm.waitingBrowser")
62341
63091
  };
62342
63092
  if (status === "ready") {
62343
63093
  const credentials = parseReadyCredentials(root, flow.region, Date.now());
62344
63094
  if (credentials === null) return {
62345
63095
  kind: "pending",
62346
- progress: "就绪响应缺少 access_token,正在重试…"
63096
+ progress: t("glm.readyNoToken")
62347
63097
  };
62348
63098
  return {
62349
63099
  kind: "ready",
@@ -62415,7 +63165,7 @@ async function beginWebLogin$5(options = {}) {
62415
63165
  startedAt: now,
62416
63166
  expiresAt: init.expiresAt,
62417
63167
  pollIntervalSec: init.pollIntervalSec,
62418
- progress: "等待你在浏览器里完成授权…"
63168
+ progress: t("glm.waitingBrowser")
62419
63169
  }
62420
63170
  };
62421
63171
  loginSessions.set(loginId, session);
@@ -62459,7 +63209,7 @@ async function pollWebLogin$1(loginId, options = {}) {
62459
63209
  loginId,
62460
63210
  credentials: null,
62461
63211
  status: "error",
62462
- error: "这次登录已经取消或已经过期,请重新发起登录。",
63212
+ error: t("glm.sessionCancelled"),
62463
63213
  retryable: false
62464
63214
  };
62465
63215
  if (now >= session.deadline) {
@@ -62469,7 +63219,7 @@ async function pollWebLogin$1(loginId, options = {}) {
62469
63219
  ...session.status,
62470
63220
  status: "error",
62471
63221
  progress: void 0,
62472
- error: "登录超时:上游在 " + new Date(session.deadline).toISOString() + " 之前没有完成授权。",
63222
+ error: t("glm.loginTimeout", { at: new Date(session.deadline).toISOString() }),
62473
63223
  retryable: false
62474
63224
  };
62475
63225
  return snapshot(session);
@@ -62583,7 +63333,7 @@ function extractAuthorizationError(raw) {
62583
63333
  function submitLoginCode(raw, options = {}) {
62584
63334
  const id = options.loginId ?? latestLoginId;
62585
63335
  const session = id === null || id === void 0 ? void 0 : loginSessions.get(id);
62586
- if (session === void 0 || session.status.status !== "pending") throw new Error("当前没有进行中的 GLM 登录流程可供补全。");
63336
+ if (session === void 0 || session.status.status !== "pending") throw new Error(t("glm.noSession"));
62587
63337
  const denial = extractAuthorizationError(raw);
62588
63338
  if (denial !== "") {
62589
63339
  loginSessions.delete(session.loginId);
@@ -62592,18 +63342,18 @@ function submitLoginCode(raw, options = {}) {
62592
63342
  ...session.status,
62593
63343
  status: "error",
62594
63344
  progress: void 0,
62595
- error: "授权被拒绝:" + denial,
63345
+ error: t("glm.authorizationDenied", { denial }),
62596
63346
  retryable: false
62597
63347
  };
62598
63348
  return snapshot(session);
62599
63349
  }
62600
63350
  const code = extractAuthorizationCode(raw);
62601
- if (code === "") throw new Error("这看起来不是授权码,也不是完整的回调链接(里面没有 code 参数)。");
63351
+ if (code === "") throw new Error(t("glm.notAuthorizationCode"));
62602
63352
  session.manualCode = code;
62603
63353
  session.nextPollAt = 0;
62604
63354
  session.status = {
62605
63355
  ...session.status,
62606
- progress: "已收到回调,正在向上游确认…"
63356
+ progress: t("glm.callbackReceived")
62607
63357
  };
62608
63358
  return snapshot(session);
62609
63359
  }
@@ -62913,7 +63663,7 @@ function registerGlmCodingPlanRoutes(ctx, settings, options = {}) {
62913
63663
  if (!isSameOriginMutation(request)) return sendCrossOrigin$2(response);
62914
63664
  if (accountPool === void 0) return sendJson$5(response, 400, {
62915
63665
  ok: false,
62916
- error: "账号池未安装。"
63666
+ error: t("glm.poolNotInstalled")
62917
63667
  });
62918
63668
  const body = await readRequestJson$5(request);
62919
63669
  const action = typeof body.action === "string" ? body.action : "";
@@ -62921,7 +63671,7 @@ function registerGlmCodingPlanRoutes(ctx, settings, options = {}) {
62921
63671
  const strategy = body.strategy;
62922
63672
  if (strategy !== "sequential" && strategy !== "round-robin" && strategy !== "sticky") return sendJson$5(response, 400, {
62923
63673
  ok: false,
62924
- error: "未知的轮转策略。"
63674
+ error: t("glm.unknownStrategy")
62925
63675
  });
62926
63676
  await accountPool.setStrategy(strategy);
62927
63677
  return sendJson$5(response, 200, {
@@ -62950,7 +63700,7 @@ function registerGlmCodingPlanRoutes(ctx, settings, options = {}) {
62950
63700
  break;
62951
63701
  default: return sendJson$5(response, 400, {
62952
63702
  ok: false,
62953
- error: "未知的账号操作:" + action
63703
+ error: t("glm.unknownAccountAction", { action })
62954
63704
  });
62955
63705
  }
62956
63706
  return sendJson$5(response, 200, {
@@ -63040,12 +63790,12 @@ function registerGlmCodingPlanRoutes(ctx, settings, options = {}) {
63040
63790
  const raw = typeof body.code === "string" ? body.code : "";
63041
63791
  if (raw.trim() === "") return sendJson$5(response, 400, {
63042
63792
  ok: false,
63043
- error: "请粘贴回调链接或授权码。"
63793
+ error: t("glm.pasteCallback")
63044
63794
  });
63045
63795
  const current = latestLogin ?? getWebLoginStatus$3();
63046
63796
  if (current === null) return sendJson$5(response, 400, {
63047
63797
  ok: false,
63048
- error: "当前没有进行中的登录流程,请先点击登录。"
63798
+ error: t("glm.noLoginInProgress")
63049
63799
  });
63050
63800
  let submitted;
63051
63801
  try {
@@ -63119,7 +63869,7 @@ async function probeConnection$3(accountPool, fetchFn) {
63119
63869
  account: null,
63120
63870
  model: null,
63121
63871
  checkedAt,
63122
- error: "还没有登录 GLM(ZCode 账号) 账号。"
63872
+ error: t("glm.notSignedIn", { provider: PROVIDER_NAME$1 })
63123
63873
  };
63124
63874
  const region = target.credentials.codingPlan.region;
63125
63875
  const started = Date.now();
@@ -65607,7 +66357,10 @@ function asFiniteNumber$1(value) {
65607
66357
  function optionalString$7(record, key) {
65608
66358
  const value = record[key];
65609
66359
  if (value === void 0 || value === null) return void 0;
65610
- if (typeof value !== "string") throw new Error("Step Code 凭据字段无效:" + key);
66360
+ if (typeof value !== "string") throw new Error(t("sc.credentialFieldInvalid", {
66361
+ provider: "Step Code",
66362
+ key
66363
+ }));
65611
66364
  return value;
65612
66365
  }
65613
66366
  function isOrigin$1(value) {
@@ -65625,11 +66378,11 @@ function isOrigin$1(value) {
65625
66378
  * 猜错的代价是一次拿国区凭据去打国际区端点的明确鉴权失败,排查成本远高于让它重新登录。
65626
66379
  */
65627
66380
  function parseStepCodeCredentials$1(value) {
65628
- if (!isRecord$30(value)) throw new Error("Step Code 凭据载荷无效");
66381
+ if (!isRecord$30(value)) throw new Error(t("sc.credentialPayloadInvalid", { provider: "Step Code" }));
65629
66382
  const apiKey = asString$9(value.apiKey);
65630
- if (apiKey === void 0) throw new Error("Step Code 凭据缺少 apiKey");
66383
+ if (apiKey === void 0) throw new Error(t("sc.credentialNoApiKey", { provider: "Step Code" }));
65631
66384
  const profile = normalizeProfile(value.profile);
65632
- if (profile === void 0) throw new Error("Step Code 凭据的 profile 无效");
66385
+ if (profile === void 0) throw new Error(t("sc.credentialProfileInvalid", { provider: "Step Code" }));
65633
66386
  const origin = isOrigin$1(value.origin) ? value.origin : isAdoptedSnapshot$1(value) ? "adopt" : "browser";
65634
66387
  const credentials = {
65635
66388
  apiKey,
@@ -65720,7 +66473,7 @@ function createCredentialBackend$3(filePath, parse, label) {
65720
66473
  if (process.platform === "win32") return new WindowsDpapiCredentialStore(filePath + ".dpapi", parse);
65721
66474
  if (process.platform === "darwin") return new MacKeychainCredentialStore(PROVIDER_ID$6, credentialAccount$3(filePath), parse);
65722
66475
  if (process.platform === "linux") return new SecretServiceCredentialStore(PROVIDER_ID$6, credentialAccount$3(filePath), parse);
65723
- throw new Error(label + " 凭据存储只支持 Windows、macOS 或 Linux。");
66476
+ throw new Error(t("sc.storeUnsupportedPlatform", { label }));
65724
66477
  }
65725
66478
  const credentialOperations$1 = /* @__PURE__ */ new Map();
65726
66479
  function serialize$1(key, operation) {
@@ -65763,7 +66516,7 @@ var StepCodeCredentialStore = class {
65763
66516
  return serialize$1(this.filePath, async () => {
65764
66517
  const normalized = parseStepCodeCredentials$1(credentials);
65765
66518
  await this.backend.save(normalized);
65766
- if (!isDeepStrictEqual(await this.backend.load(), normalized)) throw new Error("Step Code 加密凭据写入校验失败");
66519
+ if (!isDeepStrictEqual(await this.backend.load(), normalized)) throw new Error(t("sc.encryptedWriteVerifyFailed", { provider: "Step Code" }));
65767
66520
  });
65768
66521
  }
65769
66522
  delete() {
@@ -65772,11 +66525,11 @@ var StepCodeCredentialStore = class {
65772
66525
  };
65773
66526
  /** 校验并归一化一份落盘的额度凭据。缺 token 或 deviceId 一律拒绝——少一个就是一次必然的鉴权失败。 */
65774
66527
  function parseStepCodeQuotaCredential(value) {
65775
- if (!isRecord$30(value)) throw new Error("Step Code 额度凭据载荷无效");
66528
+ if (!isRecord$30(value)) throw new Error(t("sc.quotaCredentialPayloadInvalid", { provider: "Step Code" }));
65776
66529
  const token = asString$9(value.token);
65777
- if (token === void 0) throw new Error("Step Code 额度凭据缺少 Oasis-Token");
66530
+ if (token === void 0) throw new Error(t("sc.quotaCredentialNoToken", { provider: "Step Code" }));
65778
66531
  const deviceId = asString$9(value.deviceId);
65779
- if (deviceId === void 0) throw new Error("Step Code 额度凭据缺少 Oasis-Webid");
66532
+ if (deviceId === void 0) throw new Error(t("sc.quotaCredentialNoDeviceId", { provider: "Step Code" }));
65780
66533
  return {
65781
66534
  token,
65782
66535
  deviceId,
@@ -65809,7 +66562,7 @@ var StepCodeQuotaCredentialStore = class {
65809
66562
  return serialize$1(this.filePath, async () => {
65810
66563
  const normalized = parseStepCodeQuotaCredential(credential);
65811
66564
  await this.backend.save(normalized);
65812
- if (!isDeepStrictEqual(await this.backend.load(), normalized)) throw new Error("Step Code 额度凭据写入校验失败");
66565
+ if (!isDeepStrictEqual(await this.backend.load(), normalized)) throw new Error(t("sc.quotaCredentialWriteVerifyFailed", { provider: "Step Code" }));
65813
66566
  });
65814
66567
  }
65815
66568
  delete() {
@@ -65892,7 +66645,7 @@ var StepCodeModelSettingsStore = class {
65892
66645
  const temporary = this.filePath + ".tmp." + Date.now();
65893
66646
  await fs.writeFile(temporary, JSON.stringify(settings, null, 2) + "\n", "utf8");
65894
66647
  await fs.rename(temporary, this.filePath);
65895
- if (!isDeepStrictEqual(parseStepCodeModelSettings(JSON.parse(await fs.readFile(this.filePath, "utf8"))), settings)) throw new Error("Step Code 模型设置写入失败:落盘的选择与刚写入的不一致");
66648
+ if (!isDeepStrictEqual(parseStepCodeModelSettings(JSON.parse(await fs.readFile(this.filePath, "utf8"))), settings)) throw new Error(t("sc.modelSettingsWriteFailed", { provider: "Step Code" }));
65896
66649
  }
65897
66650
  /**
65898
66651
  * 在与凭据写入同一条按路径排队的锁里做「读-改-写」。
@@ -66137,7 +66890,7 @@ var StepCodeAdapter = class extends LlmAdapter {
66137
66890
  providerInfo(provider) {
66138
66891
  return {
66139
66892
  id: provider,
66140
- name: PROVIDER_NAME$6
66893
+ name: localizedProviderName(provider, PROVIDER_NAME$6)
66141
66894
  };
66142
66895
  }
66143
66896
  providerRetryPolicy() {
@@ -66203,7 +66956,7 @@ var StepCodeAdapter = class extends LlmAdapter {
66203
66956
  }));
66204
66957
  }
66205
66958
  async resolveModel(provider, model, signal) {
66206
- if (signal?.aborted) throw new LlmError("Step Code(Step Plan 订阅) 模型解析已取消", "ABORTED");
66959
+ if (signal?.aborted) throw new LlmError(t("sc.modelResolveAborted", { provider: PROVIDER_NAME$6 }), "ABORTED");
66207
66960
  const settings = await this.settings();
66208
66961
  const picked = await this.credentialFor().catch(() => null);
66209
66962
  const catalog = this.catalog(picked?.credentials.profile);
@@ -66270,8 +67023,11 @@ var StepCodeAdapter = class extends LlmAdapter {
66270
67023
  });
66271
67024
  activity?.pulse();
66272
67025
  } catch (error) {
66273
- if (signal.aborted) throw new LlmError("Step Code(Step Plan 订阅) 请求已取消", "ABORTED", { cause: error });
66274
- throw new LlmError("Step Code(Step Plan 订阅) 请求失败:" + (error instanceof Error ? error.message : String(error)), "TRANSPORT", { cause: error });
67026
+ if (signal.aborted) throw new LlmError(t("sc.requestAborted", { provider: PROVIDER_NAME$6 }), "ABORTED", { cause: error });
67027
+ throw new LlmError(t("sc.requestFailed", {
67028
+ provider: PROVIDER_NAME$6,
67029
+ detail: error instanceof Error ? error.message : String(error)
67030
+ }), "TRANSPORT", { cause: error });
66275
67031
  }
66276
67032
  if (response.ok) break;
66277
67033
  const detail = await response.text().catch(() => "");
@@ -66294,8 +67050,8 @@ var StepCodeAdapter = class extends LlmAdapter {
66294
67050
  }
66295
67051
  throw failure;
66296
67052
  }
66297
- if (response === void 0) throw new LlmError("Step Code(Step Plan 订阅) 没有返回任何响应", "PROVIDER_ERROR");
66298
- if (response.body === null) throw new LlmError("Step Code(Step Plan 订阅) 返回了空响应体", "PROVIDER_ERROR");
67053
+ if (response === void 0) throw new LlmError(t("sc.noResponse", { provider: PROVIDER_NAME$6 }), "PROVIDER_ERROR");
67054
+ if (response.body === null) throw new LlmError(t("sc.emptyBody", { provider: PROVIDER_NAME$6 }), "PROVIDER_ERROR");
66299
67055
  const reader = response.body.getReader();
66300
67056
  const decoder = new TextDecoder();
66301
67057
  const state = createStreamState$2();
@@ -66404,7 +67160,11 @@ function isRetryableStepCodeLoginError(error) {
66404
67160
  }
66405
67161
  /** protocol 类错误:形状/字段值不合协议,不重试。 */
66406
67162
  function protocolError(phase, detail, cause) {
66407
- return new StepCodeLoginRequestError("protocol", "Step Code(Step Plan 订阅) 登录 " + phase + " " + detail, { ...cause === void 0 ? {} : { cause } });
67163
+ return new StepCodeLoginRequestError("protocol", t("sc.loginPhaseFailed", {
67164
+ provider: PROVIDER_NAME$6,
67165
+ phase,
67166
+ detail
67167
+ }), { ...cause === void 0 ? {} : { cause } });
66408
67168
  }
66409
67169
  /** 成功体里的 `desc` 去控制字符后截断到 MAX_ERROR_DETAIL_LENGTH(逐字 login-client.ts:342-346)。 */
66410
67170
  function envelopeDetail(payload) {
@@ -66442,10 +67202,13 @@ function parseAuthBase(value) {
66442
67202
  try {
66443
67203
  url = new URL(value);
66444
67204
  } catch {
66445
- throw new Error("Step Code(Step Plan 订阅) 的授权地址不是合法 URL:" + value);
67205
+ throw new Error(t("sc.authorizeUrlInvalid", {
67206
+ provider: PROVIDER_NAME$6,
67207
+ value
67208
+ }));
66446
67209
  }
66447
- if (url.protocol !== "https:") throw new Error("Step Code(Step Plan 订阅) 的授权地址必须使用 https");
66448
- if (url.username !== "" || url.password !== "") throw new Error("Step Code(Step Plan 订阅) 的授权地址不得包含用户名或密码");
67210
+ if (url.protocol !== "https:") throw new Error(t("sc.authorizeUrlNotHttps", { provider: PROVIDER_NAME$6 }));
67211
+ if (url.username !== "" || url.password !== "") throw new Error(t("sc.authorizeUrlHasCredentials", { provider: PROVIDER_NAME$6 }));
66449
67212
  return url;
66450
67213
  }
66451
67214
  /**
@@ -66506,7 +67269,7 @@ async function withLoginTimeout(timeoutMs, signal, timeoutError, run) {
66506
67269
  }
66507
67270
  function abortReasonOf(signal) {
66508
67271
  const reason = signal.reason;
66509
- return reason instanceof Error ? reason : /* @__PURE__ */ new Error("操作已取消");
67272
+ return reason instanceof Error ? reason : new Error(t("sc.cancelled"));
66510
67273
  }
66511
67274
  /** 可被取消的 sleep(逐字 utils/sleep.ts 的语义)。 */
66512
67275
  function sleep$1(ms, signal) {
@@ -66543,9 +67306,9 @@ function sleep$1(ms, signal) {
66543
67306
  * 服务端会用 200 携带业务错误)。
66544
67307
  */
66545
67308
  async function request(input) {
66546
- return withLoginTimeout(LOGIN_REQUEST_TIMEOUT_MS$1, input.signal, () => new StepCodeLoginRequestError("transport", "Step Code(Step Plan 订阅) 登录请求超时"), async (signal) => {
67309
+ return withLoginTimeout(LOGIN_REQUEST_TIMEOUT_MS$1, input.signal, () => new StepCodeLoginRequestError("transport", t("sc.loginRequestTimeout", { provider: PROVIDER_NAME$6 })), async (signal) => {
66547
67310
  const pollToken = input.pollToken.trim();
66548
- if (pollToken === "") throw new Error("Step Code(Step Plan 订阅) 登录的 poll_token 不能为空");
67311
+ if (pollToken === "") throw new Error(t("sc.pollTokenEmpty", { provider: PROVIDER_NAME$6 }));
66549
67312
  const fetchFn = input.fetchFn ?? fetch;
66550
67313
  let response;
66551
67314
  try {
@@ -66689,7 +67452,7 @@ async function pollStepCodeCliLogin(input) {
66689
67452
  * 不可重试的直接抛出。
66690
67453
  */
66691
67454
  async function waitForStepCodeLogin(input) {
66692
- const timeoutError = () => /* @__PURE__ */ new Error("Step Code(Step Plan 订阅) 登录超时:没有在有效期内完成浏览器授权。");
67455
+ const timeoutError = () => new Error(t("sc.loginTimeout", { provider: PROVIDER_NAME$6 }));
66693
67456
  const serverRemaining = input.init.expiresAt * 1e3 - Date.now();
66694
67457
  const localRemaining = input.localDeadline === void 0 ? Infinity : input.localDeadline - Date.now();
66695
67458
  const remaining = Math.min(serverRemaining, localRemaining);
@@ -66724,7 +67487,7 @@ async function waitForStepCodeLogin(input) {
66724
67487
  /** 从一次成功登录的结果造出凭据(uid 不合格时已经被丢掉,这里只做装配)。 */
66725
67488
  function stepCodeCredentialFromLogin(profile, ready) {
66726
67489
  const apiKey = ready.apiKey.trim();
66727
- if (apiKey === "") throw new Error("Step Code(Step Plan 订阅) 登录成功但没有拿到 api_key");
67490
+ if (apiKey === "") throw new Error(t("sc.loginNoApiKey", { provider: PROVIDER_NAME$6 }));
66728
67491
  const uid = readBoundedUid$1(ready.uid);
66729
67492
  return {
66730
67493
  type: "oauth",
@@ -66743,7 +67506,7 @@ function stepCodeCredentialFromLogin(profile, ready) {
66743
67506
  */
66744
67507
  function stepCodeCredentialFromApiKey(profile, apiKey, uid) {
66745
67508
  const trimmed = apiKey.trim();
66746
- if (trimmed === "") throw new Error("Step Code(Step Plan 订阅) API Key 是空的。");
67509
+ if (trimmed === "") throw new Error(t("sc.apiKeyEmpty", { provider: PROVIDER_NAME$6 }));
66747
67510
  const bounded = readBoundedUid$1(uid);
66748
67511
  return {
66749
67512
  type: "oauth",
@@ -66815,7 +67578,7 @@ async function beginStepCodeLogin(profile, options = {}) {
66815
67578
  startedAt,
66816
67579
  expiresAt,
66817
67580
  pollIntervalSec: init.pollIntervalSec,
66818
- progress: "等待浏览器授权…(每 " + init.pollIntervalSec + " 秒查询一次)"
67581
+ progress: t("sc.waitingBrowserPoll", { seconds: init.pollIntervalSec })
66819
67582
  };
66820
67583
  (async () => {
66821
67584
  try {
@@ -66839,7 +67602,7 @@ async function beginStepCodeLogin(profile, options = {}) {
66839
67602
  completedAt: Date.now(),
66840
67603
  expiresAt,
66841
67604
  pollIntervalSec: init.pollIntervalSec,
66842
- progress: "授权完成",
67605
+ progress: t("sc.authorized"),
66843
67606
  ...ready.uid === void 0 ? {} : { uid: ready.uid }
66844
67607
  };
66845
67608
  } catch (error) {
@@ -66939,7 +67702,10 @@ function projectAccount$1(input) {
66939
67702
  function optionalString$6(record, key) {
66940
67703
  const value = record[key];
66941
67704
  if (value === void 0 || value === null) return void 0;
66942
- if (typeof value !== "string") throw new Error("Step Code(Step Plan 订阅) 号池账号字段无效:" + key);
67705
+ if (typeof value !== "string") throw new Error(t("sc.poolAccountFieldInvalid", {
67706
+ provider: PROVIDER_NAME$6,
67707
+ key
67708
+ }));
66943
67709
  return value;
66944
67710
  }
66945
67711
  /**
@@ -66950,11 +67716,11 @@ function optionalString$6(record, key) {
66950
67716
  * 当成可路由的账号打出去。
66951
67717
  */
66952
67718
  function parseStepCodeCredentials(value) {
66953
- if (!isRecord$28(value)) throw new Error("Step Code(Step Plan 订阅) 号池凭据无效");
67719
+ if (!isRecord$28(value)) throw new Error(t("sc.poolCredentialInvalid", { provider: PROVIDER_NAME$6 }));
66954
67720
  const access = typeof value.access === "string" ? value.access.trim() : "";
66955
- if (access === "") throw new Error("Step Code(Step Plan 订阅) 号池凭据缺少 access");
67721
+ if (access === "") throw new Error(t("sc.poolCredentialNoAccess", { provider: PROVIDER_NAME$6 }));
66956
67722
  const profile = normalizeProfile(value.profile);
66957
- if (profile === void 0) throw new Error("Step Code(Step Plan 订阅) 号池凭据的 profile 无效");
67723
+ if (profile === void 0) throw new Error(t("sc.poolCredentialProfileInvalid", { provider: PROVIDER_NAME$6 }));
66958
67724
  const uidRaw = typeof value.uid === "string" ? value.uid.trim() : "";
66959
67725
  const uid = uidRaw.length > 64 || !UID_PATTERN.test(uidRaw) ? "" : uidRaw;
66960
67726
  return {
@@ -66977,7 +67743,7 @@ function parseStepCodeCredentials(value) {
66977
67743
  * 抛错等于让一行坏数据带走整个池。
66978
67744
  */
66979
67745
  function parseStepCodePoolData(value) {
66980
- if (!isRecord$28(value)) throw new Error("Step Code(Step Plan 订阅) 号池载荷无效");
67746
+ if (!isRecord$28(value)) throw new Error(t("sc.poolPayloadInvalid", { provider: PROVIDER_NAME$6 }));
66981
67747
  const accounts = [];
66982
67748
  for (const item of Array.isArray(value.accounts) ? value.accounts : []) {
66983
67749
  if (!isRecord$28(item) || typeof item.id !== "string") continue;
@@ -67127,7 +67893,7 @@ var StepCodeAccountPool = class extends AccountPoolCore {
67127
67893
  const target = data.accounts.find((account) => account.id === data.activeAccountId) ?? data.accounts.find((account) => account.isPrimary) ?? data.accounts[0];
67128
67894
  if (target === void 0) {
67129
67895
  await this.getFreshCredential(void 0, fetchFn);
67130
- throw new Error("Step Code(Step Plan 订阅) 号池中没有账号。");
67896
+ throw new Error(t("sc.poolEmpty", { provider: PROVIDER_NAME$6 }));
67131
67897
  }
67132
67898
  return {
67133
67899
  accountId: target.id,
@@ -67858,7 +68624,7 @@ function registerStepCodeRoutes(ctx, settings, options = {}) {
67858
68624
  if (!isSameOriginMutation(request)) return sendCrossOrigin$1(response);
67859
68625
  if (accountPool === void 0) return sendJson$4(response, 400, {
67860
68626
  ok: false,
67861
- error: "账号池未安装。"
68627
+ error: t("sc.poolNotInstalled")
67862
68628
  });
67863
68629
  const body = await readRequestJson$4(request);
67864
68630
  const action = typeof body.action === "string" ? body.action : "";
@@ -67866,7 +68632,7 @@ function registerStepCodeRoutes(ctx, settings, options = {}) {
67866
68632
  const strategy = body.strategy;
67867
68633
  if (strategy !== "sequential" && strategy !== "round-robin" && strategy !== "sticky") return sendJson$4(response, 400, {
67868
68634
  ok: false,
67869
- error: "未知的轮转策略。"
68635
+ error: t("sc.unknownStrategy")
67870
68636
  });
67871
68637
  await accountPool.setStrategy(strategy);
67872
68638
  return sendJson$4(response, 200, {
@@ -67895,7 +68661,7 @@ function registerStepCodeRoutes(ctx, settings, options = {}) {
67895
68661
  break;
67896
68662
  default: return sendJson$4(response, 400, {
67897
68663
  ok: false,
67898
- error: "未知的账号操作:" + action
68664
+ error: t("sc.unknownAccountAction", { action })
67899
68665
  });
67900
68666
  }
67901
68667
  return sendJson$4(response, 200, {
@@ -67942,7 +68708,7 @@ function registerStepCodeRoutes(ctx, settings, options = {}) {
67942
68708
  const apiKey = typeof body.apiKey === "string" ? body.apiKey : "";
67943
68709
  if (apiKey.trim() === "") return sendJson$4(response, 400, {
67944
68710
  ok: false,
67945
- error: "请粘贴一个 Platform API Key。"
68711
+ error: t("sc.pastePlatformKey")
67946
68712
  });
67947
68713
  const credentials = stepCodeCredentialFromApiKey(profileFromBody(body), apiKey);
67948
68714
  await savePastedCredential(credentials);
@@ -68000,11 +68766,11 @@ function registerStepCodeRoutes(ctx, settings, options = {}) {
68000
68766
  const password = typeof body.password === "string" ? body.password : "";
68001
68767
  if (account === "") return sendJson$4(response, 400, {
68002
68768
  ok: false,
68003
- error: "请填写账号。"
68769
+ error: t("sc.missingAccount")
68004
68770
  });
68005
68771
  if (password === "") return sendJson$4(response, 400, {
68006
68772
  ok: false,
68007
- error: "请填写密码。"
68773
+ error: t("sc.missingPassword")
68008
68774
  });
68009
68775
  const signed = await attempt(() => signInOasisQuotaCredential({
68010
68776
  profile,
@@ -68047,7 +68813,7 @@ function registerStepCodeRoutes(ctx, settings, options = {}) {
68047
68813
  quotaCredential = stored;
68048
68814
  } else return sendJson$4(response, 400, {
68049
68815
  ok: false,
68050
- error: "未知的额度凭据提交方式:" + mode
68816
+ error: t("sc.unknownQuotaCredentialMode", { mode })
68051
68817
  });
68052
68818
  await quotaRefresh.run(() => refreshQuota(true));
68053
68819
  return sendJson$4(response, 200, {
@@ -68093,7 +68859,7 @@ async function probeConnection$2(accountPool, fetchFn, env) {
68093
68859
  account: null,
68094
68860
  model: null,
68095
68861
  checkedAt,
68096
- error: "还没有登录 Step Code(Step Plan 订阅) 账号。"
68862
+ error: t("sc.notSignedIn", { provider: PROVIDER_NAME$6 })
68097
68863
  };
68098
68864
  const credentials = upstreamCredentialOf$2(target.credentials);
68099
68865
  const started = Date.now();
@@ -68111,7 +68877,7 @@ async function probeConnection$2(accountPool, fetchFn, env) {
68111
68877
  account: null,
68112
68878
  model: null,
68113
68879
  checkedAt,
68114
- error: "目录接口返回 HTTP " + response.status + (detail === "" ? "" : ":" + stepCodeErrorDetail(detail, 160))
68880
+ error: t("sc.catalogHttp", { status: response.status }) + (detail === "" ? "" : ":" + stepCodeErrorDetail(detail, 160))
68115
68881
  };
68116
68882
  }
68117
68883
  const entries = parseStepModelCatalog(await response.json().catch(() => void 0));
@@ -70640,7 +71406,7 @@ var ClinePassAdapter = class extends LlmAdapter {
70640
71406
  providerInfo(provider) {
70641
71407
  return {
70642
71408
  id: provider,
70643
- name: PROVIDER_NAME$5
71409
+ name: localizedProviderName(provider, PROVIDER_NAME$5)
70644
71410
  };
70645
71411
  }
70646
71412
  providerRetryPolicy() {
@@ -75407,7 +76173,10 @@ function asFiniteNumber(value) {
75407
76173
  function optionalString$3(record, key) {
75408
76174
  const value = record[key];
75409
76175
  if (value === void 0 || value === null) return void 0;
75410
- if (typeof value !== "string") throw new Error("Qoder 凭据字段无效:" + key);
76176
+ if (typeof value !== "string") throw new Error(t("qo.credentialFieldInvalid", {
76177
+ provider: "Qoder",
76178
+ key
76179
+ }));
75411
76180
  return value;
75412
76181
  }
75413
76182
  function isOrigin(value) {
@@ -75424,10 +76193,10 @@ function isOrigin(value) {
75424
76193
  * 拿一区的凭据去打另一区的端点,一次明确的鉴权失败,排查成本远高于重新登录。
75425
76194
  */
75426
76195
  function parseQoderCredentials(value) {
75427
- if (!isRecord$23(value)) throw new Error("Qoder 凭据载荷无效");
76196
+ if (!isRecord$23(value)) throw new Error(t("qo.credentialPayloadInvalid", { provider: "Qoder" }));
75428
76197
  const accessToken = asString$8(value.accessToken);
75429
- if (accessToken === void 0) throw new Error("Qoder 凭据缺少 accessToken");
75430
- if (!isQoderRegion(value.region)) throw new Error("Qoder 凭据的 region 无效");
76198
+ if (accessToken === void 0) throw new Error(t("qo.credentialNoToken", { provider: "Qoder" }));
76199
+ if (!isQoderRegion(value.region)) throw new Error(t("qo.credentialRegionInvalid", { provider: "Qoder" }));
75431
76200
  const origin = isOrigin(value.origin) ? value.origin : isAdoptedSnapshot(value) ? "adopt" : "device";
75432
76201
  const credentials = {
75433
76202
  accessToken,
@@ -75521,7 +76290,7 @@ function createCredentialBackend$1(filePath, parse, label) {
75521
76290
  if (process.platform === "win32") return new WindowsDpapiCredentialStore(filePath + ".dpapi", parse);
75522
76291
  if (process.platform === "darwin") return new MacKeychainCredentialStore(PROVIDER_ID$4, credentialAccount$1(filePath), parse);
75523
76292
  if (process.platform === "linux") return new SecretServiceCredentialStore(PROVIDER_ID$4, credentialAccount$1(filePath), parse);
75524
- throw new Error(label + " 凭据存储只支持 Windows、macOS 或 Linux。");
76293
+ throw new Error(t("qo.storeUnsupportedPlatform", { label }));
75525
76294
  }
75526
76295
  const credentialOperations = /* @__PURE__ */ new Map();
75527
76296
  function serialize(key, operation) {
@@ -75559,7 +76328,7 @@ var QoderCredentialStore = class {
75559
76328
  return serialize(this.filePath, async () => {
75560
76329
  const normalized = parseQoderCredentials(credentials);
75561
76330
  await this.backend.save(normalized);
75562
- if (!isDeepStrictEqual(await this.backend.load(), normalized)) throw new Error("Qoder 加密凭据写入校验失败");
76331
+ if (!isDeepStrictEqual(await this.backend.load(), normalized)) throw new Error(t("qo.encryptedWriteVerifyFailed", { provider: "Qoder" }));
75563
76332
  });
75564
76333
  }
75565
76334
  delete() {
@@ -75670,7 +76439,7 @@ var QoderModelSettingsStore = class {
75670
76439
  const temporary = this.filePath + ".tmp." + Date.now();
75671
76440
  await fs.writeFile(temporary, JSON.stringify(document, null, 2) + "\n", "utf8");
75672
76441
  await fs.rename(temporary, this.filePath);
75673
- if (!isDeepStrictEqual(parseQoderModelSettings(JSON.parse(await fs.readFile(this.filePath, "utf8"))), document)) throw new Error("Qoder 模型设置写入失败:落盘的选择与刚写入的不一致");
76442
+ if (!isDeepStrictEqual(parseQoderModelSettings(JSON.parse(await fs.readFile(this.filePath, "utf8"))), document)) throw new Error(t("qo.modelSettingsWriteFailed", { provider: "Qoder" }));
75674
76443
  }
75675
76444
  /** 在与凭据写入同一条按路径排队的锁里做「读-改-写」。 */
75676
76445
  updateSettings(patch) {
@@ -76409,10 +77178,14 @@ async function fetchQoderUserInfo(accessToken, region, options = {}) {
76409
77178
  });
76410
77179
  if (!response.ok) {
76411
77180
  const detail = qoderErrorDetail(await response.text().catch(() => ""), 160);
76412
- throw new Error("Qoder(订阅) userinfo 请求失败(HTTP " + response.status + ")" + (detail === "" ? "" : ":" + detail));
77181
+ throw new Error(t("qo.userinfoFailed", {
77182
+ provider: PROVIDER_NAME$4,
77183
+ status: response.status,
77184
+ detail: detail === "" ? "" : ":" + detail
77185
+ }));
76413
77186
  }
76414
77187
  const payload = await response.json().catch(() => void 0);
76415
- if (!isRecord$22(payload)) throw new Error("Qoder(订阅) userinfo 响应不是 JSON 对象");
77188
+ if (!isRecord$22(payload)) throw new Error(t("qo.userinfoNotJson", { provider: PROVIDER_NAME$4 }));
76416
77189
  const tags = Array.isArray(payload.organization_tags) ? payload.organization_tags.filter((tag) => typeof tag === "string" && tag !== "") : void 0;
76417
77190
  return {
76418
77191
  userID: asText$1(payload.id) ?? asText$1(payload.uid) ?? "",
@@ -76481,9 +77254,9 @@ async function exchangeQoderJobToken(personalToken, region, options = {}) {
76481
77254
  throw new QoderPatExchangeError("Qoder(订阅) PAT 兑换失败(HTTP " + response.status + ")" + (detail === "" ? "" : ":" + detail), response.status, region);
76482
77255
  }
76483
77256
  const payload = await response.json().catch(() => void 0);
76484
- if (!isRecord$22(payload)) throw new Error("Qoder(订阅) PAT 兑换响应不是 JSON 对象");
77257
+ if (!isRecord$22(payload)) throw new Error(t("qo.patExchangeNotJson", { provider: PROVIDER_NAME$4 }));
76485
77258
  const token = asText$1(payload.token);
76486
- if (token === void 0) throw new Error("Qoder(订阅) PAT 兑换响应里没有 token");
77259
+ if (token === void 0) throw new Error(t("qo.patExchangeNoToken", { provider: PROVIDER_NAME$4 }));
76487
77260
  return {
76488
77261
  token,
76489
77262
  refreshToken: asText$1(payload.refresh_token) ?? null,
@@ -76509,14 +77282,17 @@ async function refreshQoderAccessToken(credentials, region, options = {}) {
76509
77282
  signal: timeoutSignal$1(options.signal, DISCOVERY_TIMEOUT_MS$1)
76510
77283
  });
76511
77284
  if (!response.ok) {
76512
- const error = /* @__PURE__ */ new Error("Qoder(订阅) 令牌刷新失败(HTTP " + response.status + ")");
77285
+ const error = new Error(t("qo.refreshFailed", {
77286
+ provider: PROVIDER_NAME$4,
77287
+ status: response.status
77288
+ }));
76513
77289
  error.status = response.status;
76514
77290
  throw error;
76515
77291
  }
76516
77292
  const payload = await response.json().catch(() => void 0);
76517
- if (!isRecord$22(payload)) throw new Error("Qoder(订阅) 令牌刷新响应不是 JSON 对象");
77293
+ if (!isRecord$22(payload)) throw new Error(t("qo.refreshNotJson", { provider: PROVIDER_NAME$4 }));
76518
77294
  const token = asText$1(payload.token);
76519
- if (token === void 0) throw new Error("Qoder(订阅) 令牌刷新响应里没有 token");
77295
+ if (token === void 0) throw new Error(t("qo.refreshNoToken", { provider: PROVIDER_NAME$4 }));
76520
77296
  return {
76521
77297
  token,
76522
77298
  refreshToken: asText$1(payload.refresh_token) ?? credentials.refreshToken,
@@ -76609,13 +77385,16 @@ async function loadQoderQuota(credentials, options = {}) {
76609
77385
  const detail = qoderErrorDetail(await response.text().catch(() => ""), 160);
76610
77386
  return {
76611
77387
  ok: false,
76612
- error: "额度接口返回 HTTP " + response.status + (detail === "" ? "" : ":" + detail)
77388
+ error: t("qo.quotaHttp", {
77389
+ status: response.status,
77390
+ detail: detail === "" ? "" : ":" + detail
77391
+ })
76613
77392
  };
76614
77393
  }
76615
77394
  const snapshot = normalizeQoderQuotaSnapshot(await response.json().catch(() => void 0), credentials.region);
76616
77395
  if (snapshot === void 0) return {
76617
77396
  ok: false,
76618
- error: "额度响应里没有认识的额度桶(上游可能改版)。"
77397
+ error: t("qo.quotaNoBucket")
76619
77398
  };
76620
77399
  quotaCacheByAccount.set(cacheKey, {
76621
77400
  snapshot,
@@ -77849,7 +78628,7 @@ var QoderAdapter = class extends LlmAdapter {
77849
78628
  providerInfo(provider) {
77850
78629
  return {
77851
78630
  id: provider,
77852
- name: PROVIDER_NAME$4
78631
+ name: localizedProviderName(provider, PROVIDER_NAME$4)
77853
78632
  };
77854
78633
  }
77855
78634
  providerRetryPolicy() {
@@ -77905,7 +78684,7 @@ var QoderAdapter = class extends LlmAdapter {
77905
78684
  }));
77906
78685
  }
77907
78686
  async resolveModel(provider, model, signal) {
77908
- if (signal?.aborted) throw new LlmError("Qoder(订阅) 模型解析已取消", "ABORTED");
78687
+ if (signal?.aborted) throw new LlmError(t("qo.modelResolveAborted", { provider: PROVIDER_NAME$4 }), "ABORTED");
77909
78688
  const settings = await this.settings();
77910
78689
  const region = (await this.credentialFor().catch(() => null))?.credentials.region ?? "global";
77911
78690
  const catalog = this.catalog(region);
@@ -78052,8 +78831,11 @@ var QoderAdapter = class extends LlmAdapter {
78052
78831
  });
78053
78832
  activity?.pulse();
78054
78833
  } catch (error) {
78055
- if (signal.aborted) throw new LlmError("Qoder(订阅) 请求已取消", "ABORTED", { cause: error });
78056
- throw new LlmError("Qoder(订阅) 请求失败:" + (error instanceof Error ? error.message : String(error)), "TRANSPORT", { cause: error });
78834
+ if (signal.aborted) throw new LlmError(t("qo.requestAborted", { provider: PROVIDER_NAME$4 }), "ABORTED", { cause: error });
78835
+ throw new LlmError(t("qo.requestFailed", {
78836
+ provider: PROVIDER_NAME$4,
78837
+ detail: error instanceof Error ? error.message : String(error)
78838
+ }), "TRANSPORT", { cause: error });
78057
78839
  }
78058
78840
  if (!response.ok) {
78059
78841
  const detail = await response.text().catch(() => "");
@@ -78061,7 +78843,7 @@ var QoderAdapter = class extends LlmAdapter {
78061
78843
  if (await handlePreContentFailure(failure, response.headers)) continue;
78062
78844
  throw failure;
78063
78845
  }
78064
- if (response.body === null) throw new LlmError("Qoder(订阅) 返回了空响应体", "PROVIDER_ERROR");
78846
+ if (response.body === null) throw new LlmError(t("qo.emptyBody", { provider: PROVIDER_NAME$4 }), "PROVIDER_ERROR");
78065
78847
  const reader = response.body.getReader();
78066
78848
  const decoder = new TextDecoder();
78067
78849
  const state = createQoderStreamState();
@@ -78159,7 +78941,7 @@ function createQoderDeviceParams(env = process.env) {
78159
78941
  */
78160
78942
  function qoderDeviceAuthorizeUrl(params) {
78161
78943
  const page = REGION_HOSTS$1.global.deviceAuthorizePage;
78162
- if (page === null) throw new Error("Qoder(订阅) 全球区以外的部署不支持浏览器登录");
78944
+ if (page === null) throw new Error(t("qo.noBrowserOutsideGlobal", { provider: PROVIDER_NAME$4 }));
78163
78945
  const url = new URL(page);
78164
78946
  url.searchParams.set("challenge", params.challenge);
78165
78947
  url.searchParams.set("challenge_method", "S256");
@@ -78201,18 +78983,22 @@ async function pollQoderDeviceToken(params, options = {}) {
78201
78983
  const detail = qoderErrorDetail(await response.text().catch(() => ""), 160);
78202
78984
  return {
78203
78985
  state: "failed",
78204
- reason: "Qoder(订阅) 设备轮询失败(HTTP " + response.status + ")" + (detail === "" ? "" : ":" + detail)
78986
+ reason: t("qo.devicePollFailed", {
78987
+ provider: PROVIDER_NAME$4,
78988
+ status: response.status,
78989
+ detail: detail === "" ? "" : ":" + detail
78990
+ })
78205
78991
  };
78206
78992
  }
78207
78993
  const payload = await response.json().catch(() => void 0);
78208
78994
  if (!isRecord$20(payload)) return {
78209
78995
  state: "failed",
78210
- reason: "Qoder(订阅) 设备轮询响应不是 JSON 对象"
78996
+ reason: t("qo.devicePollNotJson", { provider: PROVIDER_NAME$4 })
78211
78997
  };
78212
78998
  const token = asText(payload.token);
78213
78999
  if (token === void 0) return {
78214
79000
  state: "failed",
78215
- reason: "Qoder(订阅) 设备轮询的 200 响应里没有 token"
79001
+ reason: t("qo.devicePollNoToken", { provider: PROVIDER_NAME$4 })
78216
79002
  };
78217
79003
  return {
78218
79004
  state: "ready",
@@ -78279,7 +79065,7 @@ async function qoderCredentialsFromDevicePoll(ready, machineId, options = {}) {
78279
79065
  */
78280
79066
  async function qoderCredentialsFromPat(personalToken, region, options = {}) {
78281
79067
  const pat = personalToken.trim();
78282
- if (pat === "") throw new Error("Qoder(订阅) 的 PAT 是空的。");
79068
+ if (pat === "") throw new Error(t("qo.patEmpty", { provider: PROVIDER_NAME$4 }));
78283
79069
  if (!pat.startsWith("pt-")) throw new Error("Qoder(订阅) 的 PAT 格式不对:它必须以 `pt-` 开头,粘贴时不要带引号或多余空白。令牌在 https://qoder.com/account/integrations(中国站是 https://qoder.com.cn/account/integrations)生成。");
78284
79070
  const candidates = [region, ...QODER_REGIONS.filter((other) => other !== region)];
78285
79071
  let resolved = region;
@@ -78363,7 +79149,7 @@ async function refreshQoderCredential(credentials, fetchFn = fetch) {
78363
79149
  } : {}
78364
79150
  };
78365
79151
  if (credentials.refreshToken === null || credentials.refreshToken === "") {
78366
- const error = /* @__PURE__ */ new Error("Qoder(订阅) 的这份凭据没有刷新令牌,只有重新登录才能续期。");
79152
+ const error = new Error(t("qo.noRefreshToken", { provider: PROVIDER_NAME$4 }));
78367
79153
  error.status = 401;
78368
79154
  throw error;
78369
79155
  }
@@ -78404,7 +79190,7 @@ function sleep(ms, signal) {
78404
79190
  clearTimeout(timer);
78405
79191
  cleanup();
78406
79192
  const reason = signal.reason;
78407
- reject(reason instanceof Error ? reason : /* @__PURE__ */ new Error("操作已取消"));
79193
+ reject(reason instanceof Error ? reason : new Error(t("qo.cancelled")));
78408
79194
  }
78409
79195
  if (signal.aborted) {
78410
79196
  onAbort();
@@ -78429,7 +79215,10 @@ async function beginQoderLogin(region, options = {}) {
78429
79215
  region,
78430
79216
  startedAt,
78431
79217
  completedAt: Date.now(),
78432
- error: "Qoder(订阅) 中国站不支持浏览器登录,请改用 PAT(" + REGION_HOSTS$1.cn.patPage + ")或导入本机 qodercli 登录态。",
79218
+ error: t("qo.cnNoBrowserLogin", {
79219
+ provider: PROVIDER_NAME$4,
79220
+ patPage: REGION_HOSTS$1.cn.patPage
79221
+ }),
78433
79222
  retryable: false
78434
79223
  };
78435
79224
  return getQoderLoginStatus();
@@ -78447,13 +79236,13 @@ async function beginQoderLogin(region, options = {}) {
78447
79236
  startedAt,
78448
79237
  expiresAt: deadline,
78449
79238
  pollIntervalSec: DEVICE_POLL_INTERVAL_MS / 1e3,
78450
- progress: "等待浏览器授权…(每 2 秒查询一次)"
79239
+ progress: t("qo.waitingBrowserPoll", { seconds: DEVICE_POLL_INTERVAL_MS / 1e3 })
78451
79240
  };
78452
79241
  (async () => {
78453
79242
  try {
78454
79243
  for (;;) {
78455
79244
  active.signal.throwIfAborted();
78456
- if (Date.now() >= deadline) throw new Error("Qoder(订阅) 登录超时:没有在有效期内完成浏览器授权。");
79245
+ if (Date.now() >= deadline) throw new Error(t("qo.loginTimeout", { provider: PROVIDER_NAME$4 }));
78457
79246
  const result = await pollQoderDeviceToken({
78458
79247
  nonce: params.nonce,
78459
79248
  verifier: params.verifier
@@ -78476,7 +79265,7 @@ async function beginQoderLogin(region, options = {}) {
78476
79265
  completedAt: Date.now(),
78477
79266
  expiresAt: deadline,
78478
79267
  pollIntervalSec: DEVICE_POLL_INTERVAL_MS / 1e3,
78479
- progress: "授权完成",
79268
+ progress: t("qo.authorized"),
78480
79269
  ...credentials.uid === null ? {} : { uid: credentials.uid }
78481
79270
  };
78482
79271
  return;
@@ -78579,7 +79368,7 @@ function projectAccount(input) {
78579
79368
  * 抛错等于让一行坏数据带走整个池。
78580
79369
  */
78581
79370
  function parseQoderPoolData(value) {
78582
- if (!isRecord$19(value)) throw new Error("Qoder(订阅) 号池载荷无效");
79371
+ if (!isRecord$19(value)) throw new Error(t("qo.poolPayloadInvalid", { provider: PROVIDER_NAME$4 }));
78583
79372
  const accounts = [];
78584
79373
  for (const item of Array.isArray(value.accounts) ? value.accounts : []) {
78585
79374
  if (!isRecord$19(item) || typeof item.id !== "string") continue;
@@ -78724,7 +79513,7 @@ var QoderAccountPool = class extends AccountPoolCore {
78724
79513
  const target = data.accounts.find((account) => account.id === data.activeAccountId) ?? data.accounts.find((account) => account.isPrimary) ?? data.accounts[0];
78725
79514
  if (target === void 0) {
78726
79515
  await this.getFreshCredential(void 0, fetchFn);
78727
- throw new Error("Qoder(订阅) 号池中没有账号。");
79516
+ throw new Error(t("qo.poolEmpty", { provider: PROVIDER_NAME$4 }));
78728
79517
  }
78729
79518
  return {
78730
79519
  accountId: target.id,
@@ -79352,7 +80141,7 @@ function registerQoderRoutes(ctx, settings, options = {}) {
79352
80141
  if (!isSameOriginMutation(request)) return sendCrossOrigin(response);
79353
80142
  if (accountPool === void 0) return sendJson$2(response, 400, {
79354
80143
  ok: false,
79355
- error: "账号池未安装。"
80144
+ error: t("qo.poolNotInstalled")
79356
80145
  });
79357
80146
  const body = await readRequestJson$2(request);
79358
80147
  const action = typeof body.action === "string" ? body.action : "";
@@ -79360,7 +80149,7 @@ function registerQoderRoutes(ctx, settings, options = {}) {
79360
80149
  const strategy = body.strategy;
79361
80150
  if (strategy !== "sequential" && strategy !== "round-robin" && strategy !== "sticky") return sendJson$2(response, 400, {
79362
80151
  ok: false,
79363
- error: "未知的轮转策略。"
80152
+ error: t("qo.unknownStrategy")
79364
80153
  });
79365
80154
  await accountPool.setStrategy(strategy);
79366
80155
  return sendJson$2(response, 200, {
@@ -79389,7 +80178,7 @@ function registerQoderRoutes(ctx, settings, options = {}) {
79389
80178
  break;
79390
80179
  default: return sendJson$2(response, 400, {
79391
80180
  ok: false,
79392
- error: "未知的账号操作:" + action
80181
+ error: t("qo.unknownAccountAction", { action })
79393
80182
  });
79394
80183
  }
79395
80184
  return sendJson$2(response, 200, {
@@ -79432,7 +80221,7 @@ function registerQoderRoutes(ctx, settings, options = {}) {
79432
80221
  const token = typeof body.token === "string" ? body.token : "";
79433
80222
  if (token.trim() === "") return sendJson$2(response, 400, {
79434
80223
  ok: false,
79435
- error: "请粘贴一个 Personal Access Token(pt-...)。"
80224
+ error: t("qo.pastePat")
79436
80225
  });
79437
80226
  const credentials = await qoderCredentialsFromPat(token, regionFromBody(body), {
79438
80227
  fetchFn,
@@ -79578,7 +80367,7 @@ async function probeConnection$1(accountPool, fetchFn, env) {
79578
80367
  account: null,
79579
80368
  model: null,
79580
80369
  checkedAt,
79581
- error: "还没有登录 Qoder(订阅) 账号。"
80370
+ error: t("qo.notSignedIn", { provider: PROVIDER_NAME$4 })
79582
80371
  };
79583
80372
  const credentials = upstreamCredentialOf(target.credentials);
79584
80373
  const started = Date.now();
@@ -79602,7 +80391,7 @@ async function probeConnection$1(accountPool, fetchFn, env) {
79602
80391
  account: null,
79603
80392
  model: null,
79604
80393
  checkedAt,
79605
- error: "目录接口返回 HTTP " + response.status + (detail === "" ? "" : ":" + detail.replace(/[\p{Cc}\p{Cf}]/gu, "").trim().slice(0, 160))
80394
+ error: t("qo.catalogHttp", { status: response.status }) + (detail === "" ? "" : ":" + detail.replace(/[\p{Cc}\p{Cf}]/gu, "").trim().slice(0, 160))
79606
80395
  };
79607
80396
  }
79608
80397
  const entries = parseQoderModelListing(await response.json().catch(() => void 0), credentials.region);
@@ -82579,7 +83368,7 @@ var OpenDesignAdapter = class extends LlmAdapter {
82579
83368
  providerInfo(provider) {
82580
83369
  return {
82581
83370
  id: provider,
82582
- name: PROVIDER_NAME$2
83371
+ name: localizedProviderName(provider, PROVIDER_NAME$2)
82583
83372
  };
82584
83373
  }
82585
83374
  providerRetryPolicy() {
@@ -84825,6 +85614,12 @@ const DEFAULT_DELEGATION_TOOLS = ["subagent"];
84825
85614
  */
84826
85615
  const DEFAULT_SUBAGENT_INHERIT_TOOLS = ["subagent_fork", "spawn_teammate"];
84827
85616
  /**
85617
+ * Inherit-mode tools that fork the caller's own conversation context on the
85618
+ * caller's own route (as opposed to multi-agent team spawning such as
85619
+ * `spawn_teammate`). Only these tools are unlocked by `allowParentFork`.
85620
+ */
85621
+ const DEFAULT_PARENT_FORK_TOOLS = ["subagent_fork"];
85622
+ /**
84828
85623
  * Read one deployment event field as a string.
84829
85624
  * @param value - Candidate field value from a durable event.
84830
85625
  * @returns the string value, or undefined for any other type.
@@ -84966,6 +85761,11 @@ const lockedRootMainRoutes = /* @__PURE__ */ new WeakMap();
84966
85761
  */
84967
85762
  const lockedRootAllowedRoutes = /* @__PURE__ */ new WeakMap();
84968
85763
  /**
85764
+ * Authorized `allowParentFork` posture per root Session, locked on first evaluation
85765
+ * alongside {@link lockedRootAllowedRoutes} so one Session is governed by one policy.
85766
+ */
85767
+ const lockedRootAllowParentFork = /* @__PURE__ */ new WeakMap();
85768
+ /**
84969
85769
  * Narrow one candidate route pair into an exact route.
84970
85770
  * @param provider - Candidate provider id.
84971
85771
  * @param model - Candidate model id.
@@ -85300,6 +86100,30 @@ function mainModelRoutesFor(agent, sessions, preference, baseRoutes, lockSnapsho
85300
86100
  return resolved;
85301
86101
  }
85302
86102
  /**
86103
+ * Resolve whether `subagent_fork` is authorized to inherit the root main model's
86104
+ * own route even when that route is absent from the cold-spawn allowlist.
86105
+ * @param agent - Calling agent.
86106
+ * @param preference - Current Host preference, when composed.
86107
+ * @param sessions - Session registry used for ancestor lookup.
86108
+ * @param lockSnapshot - Freeze the resolved posture for this Session now.
86109
+ * @returns whether same-route parent forking is authorized for the Session's main model.
86110
+ */
86111
+ function effectiveAllowParentFork(agent, preference, sessions, lockSnapshot = false) {
86112
+ if (preference !== void 0 && !preference.enabled) return true;
86113
+ const inherited = inheritedRouteOf(agent);
86114
+ const { rootSession, mainRoute } = resolveRootSessionAndMainRoute(agent, sessions, inherited, lockSnapshot);
86115
+ const lockable = typeof rootSession === "object" && rootSession !== null;
86116
+ const locked = lockable ? lockedRootAllowParentFork.get(rootSession) : void 0;
86117
+ if (!(locked !== void 0 ? locked : (() => {
86118
+ const specific = mainRoute === void 0 ? void 0 : preference?.allowParentForkByMainModel?.[`${mainRoute.provider}/${mainRoute.model}`];
86119
+ const resolved = typeof specific === "boolean" ? specific : preference?.defaultAllowParentFork === true;
86120
+ if (lockable && (lockSnapshot || headerRouteOf(rootSession) !== void 0)) lockedRootAllowParentFork.set(rootSession, resolved);
86121
+ return resolved;
86122
+ })())) return false;
86123
+ if (inherited.provider === void 0 || inherited.model === void 0 || mainRoute === void 0) return false;
86124
+ return inherited.provider === mainRoute.provider && inherited.model === mainRoute.model;
86125
+ }
86126
+ /**
85303
86127
  * State a Session's routing posture in the `list_subagent_models` result.
85304
86128
  *
85305
86129
  * Calling `list_subagent_models({})` upstream returns only provider names
@@ -85310,20 +86134,17 @@ function mainModelRoutesFor(agent, sessions, preference, baseRoutes, lockSnapsho
85310
86134
  * authorized route in the form `subagent` expects, eliminating any reason to
85311
86135
  * search local config files or source code for the allowlist.
85312
86136
  *
85313
- * The empty case states the opposite fact rather than staying silent, because
85314
- * silence is what makes a model infer that a mounted tool implies enforcement.
85315
- * It does not: the tool row and the route parameters are static, while whether
85316
- * anything is enforced is decided by the allowlist the Session recorded. The
85317
- * two facts differ, so the model has to be able to read the second one instead
85318
- * of deriving it from the first.
86137
+ * The empty case distinguishes an absent Session allowlist from the host's own
86138
+ * delegation policy. On 0.2.2 the latter still limits explicit selection to the
86139
+ * parent route, so calling this posture "unrestricted" would be false.
85319
86140
  * @param output - Original text returned by `list_subagent_models`.
85320
86141
  * @param allowed - Routes the calling Session authorizes, empty when none is in force.
85321
86142
  * @returns the output with the Session routing posture appended.
85322
86143
  */
85323
86144
  function enrichListSubagentModelsOutput(output, allowed) {
85324
86145
  if (allowed.length === 0) {
85325
- if (output.includes("No allowlist is in force for this Session: subagent routing is unrestricted, no route is validated against any list, and omitting provider/model is legitimate rather than a rule breach.")) return output;
85326
- return output.trim().length === 0 ? UNRESTRICTED_ROUTING_NOTICE : `${output}\n\n${UNRESTRICTED_ROUTING_NOTICE}`;
86146
+ if (output.includes("No allowlist is in force for this Session. Omitting provider/model follows the delegation tool's normal inheritance/default behavior; explicit selection may still be limited to the parent route by the host.")) return output;
86147
+ return output.trim().length === 0 ? NO_ALLOWLIST_ROUTING_NOTICE : `${output}\n\n${NO_ALLOWLIST_ROUTING_NOTICE}`;
85327
86148
  }
85328
86149
  const header = "Authorized child routes for this Session (already filtered by the Session allowlist; only these routes are accepted, and `provider` and `model` must be passed as separate fields):";
85329
86150
  if (output.includes(header)) return output;
@@ -85402,44 +86223,47 @@ function filterListSubagentModelsOutput(output, allowed) {
85402
86223
  function mergePreferenceOverrides(base, overrides) {
85403
86224
  const hasDefault = overrides?.defaultAllowedModels !== void 0;
85404
86225
  const hasByMain = overrides?.byMainModel !== void 0;
86226
+ const hasDefaultFork = overrides?.defaultAllowParentFork !== void 0;
86227
+ const hasForkByMain = overrides?.allowParentForkByMainModel !== void 0;
85405
86228
  if (base === void 0) {
85406
- if (!hasDefault && !hasByMain) return void 0;
86229
+ if (!hasDefault && !hasByMain && !hasDefaultFork && !hasForkByMain) return void 0;
85407
86230
  return {
85408
86231
  enabled: true,
85409
86232
  allowedModels: overrides?.defaultAllowedModels ?? [],
85410
86233
  ...hasDefault ? { defaultAllowedModels: overrides?.defaultAllowedModels } : {},
85411
- ...hasByMain ? { byMainModel: overrides?.byMainModel } : {}
86234
+ ...hasByMain ? { byMainModel: overrides?.byMainModel } : {},
86235
+ ...hasDefaultFork ? { defaultAllowParentFork: overrides?.defaultAllowParentFork } : {},
86236
+ ...hasForkByMain ? { allowParentForkByMainModel: overrides?.allowParentForkByMainModel } : {}
85412
86237
  };
85413
86238
  }
85414
- if (!hasDefault && !hasByMain) return base;
86239
+ if (!hasDefault && !hasByMain && !hasDefaultFork && !hasForkByMain) return base;
85415
86240
  return {
85416
86241
  ...base,
85417
86242
  ...hasDefault ? { defaultAllowedModels: overrides?.defaultAllowedModels } : {},
85418
- ...hasByMain ? { byMainModel: overrides?.byMainModel } : {}
86243
+ ...hasByMain ? { byMainModel: overrides?.byMainModel } : {},
86244
+ ...hasDefaultFork ? { defaultAllowParentFork: overrides?.defaultAllowParentFork } : {},
86245
+ ...hasForkByMain ? { allowParentForkByMainModel: overrides?.allowParentForkByMainModel } : {}
85419
86246
  };
85420
86247
  }
85421
86248
  /**
85422
86249
  * The statement appended to `list_subagent_models` when no allowlist governs the
85423
86250
  * calling Session.
85424
86251
  *
85425
- * Two facts, and nothing more: nothing is enforced, and omitting the route is
85426
- * legitimate here. It deliberately does not recommend a setting. This notice is
86252
+ * It distinguishes an absent Session allowlist from the host's own inheritance
86253
+ * or parent-route rules, and deliberately does not recommend a setting. This notice is
85427
86254
  * attached for every Session the plugin's authorization listener reaches—which
85428
86255
  * includes sessions with no interest in the dispatch preset—so a sentence telling
85429
86256
  * the reader to go enable model selection would be noise in most of them, and a
85430
86257
  * model that reads it as an instruction will repeat it in an unrelated summary.
85431
86258
  */
85432
- const UNRESTRICTED_ROUTING_NOTICE = "No allowlist is in force for this Session: subagent routing is unrestricted, no route is validated against any list, and omitting provider/model is legitimate rather than a rule breach.";
86259
+ const NO_ALLOWLIST_ROUTING_NOTICE = "No allowlist is in force for this Session. Omitting provider/model follows the delegation tool's normal inheritance/default behavior; explicit selection may still be limited to the parent route by the host.";
85433
86260
  /**
85434
86261
  * Rewrite the upstream `list_subagent_models` and `subagent` tool/parameter
85435
86262
  * descriptions when the calling Session enforces an allowlist.
85436
86263
  *
85437
- * Upstream `dsh-tool-subagent` ships static descriptions stating that
85438
- * `"Catalog membership is advisory: an adapter may accept an unlisted model id."`
85439
- * and `"Child LLM selection is optional. Omit provider, model, and reasoning_effort..."`.
85440
- * In an allowlist-governed Session both statements are false and actively
85441
- * mislead the dispatcher into either omitting `provider`/`model` or distrusting
85442
- * `list_subagent_models` and hunting through local files for the "real" allowlist.
86264
+ * Upstream releases before 0.2.2 call selection optional and catalog membership
86265
+ * advisory; 0.2.2 instead says omitted values use child defaults. In an
86266
+ * allowlist-governed Session those statements would contradict execution.
85443
86267
  * @param text - Tool description, parameter description, or rendered `tools:sdk` section text.
85444
86268
  * @param allowed - Routes the calling Session authorizes.
85445
86269
  * @returns the text with the misleading upstream sentences replaced by the Session's exact policy.
@@ -85447,7 +86271,8 @@ const UNRESTRICTED_ROUTING_NOTICE = "No allowlist is in force for this Session:
85447
86271
  function rewriteAuthorizedToolDescriptions(text, allowed) {
85448
86272
  if (allowed.length === 0 || text.length === 0) return text;
85449
86273
  const routes = authorizedRoutesText(allowed);
85450
- return text.replaceAll("Catalog membership is advisory: an adapter may accept an unlisted model id.", `Output is already filtered to this Session's allowlist (${routes}); only these authorized provider/model routes are accepted.`).replace(/Child LLM selection is optional\.\s*Omit `?provider`?, `?model`?, and `?reasoning_effort`? to use configured child defaults and (?:inherit compatible missing values from the parent Agent|this provider's route defaults)\./g, `Child LLM selection is required in this Session: pass an authorized \`provider\` and \`model\` from \`list_subagent_models\` (${routes}) as separate fields; omitting either field is rejected.`).replace(/Supply together with model; omit both to use configured child defaults or (?:inherit the parent route|this provider's route defaults)\.|Omit to use the configured child default or inherit from the parent Agent\./g, `Required in this Session: pass an authorized provider id from list_subagent_models (${routes}).`).replace(/Supply together with provider; omit both to use configured child defaults or (?:inherit the parent route|this provider's route defaults)\.|Omit to use the configured child default or inherit when the child provider matches the parent provider\./g, "Required in this Session: pass the authorized model id (without the provider/ prefix) for the selected provider.");
86274
+ const required = `Child LLM selection is required in this Session: pass an authorized \`provider\` and \`model\` from \`list_subagent_models\` (${routes}) as separate fields; omitting either field is rejected.`;
86275
+ return text.replaceAll("Catalog membership is advisory: an adapter may accept an unlisted model id.", `Output is already filtered to this Session's allowlist (${routes}); only these authorized provider/model routes are accepted.`).replace(/Child LLM selection is optional\.\s*Omit `?provider`?, `?model`?, and `?reasoning_effort`? to use configured child defaults and (?:inherit compatible missing values from the parent Agent|this provider's route defaults)\./g, required).replace(/Supply `provider` and `model` together\. Omitted values use child defaults, falling back to (?:this backend's route defaults|compatible parent values)\./g, required).replace(/Supply together with model; omit both to use configured child defaults or (?:inherit the parent route|this provider's route defaults)\.|Omit to use the configured child default or inherit from the parent Agent\./g, `Required in this Session: pass an authorized provider id from list_subagent_models (${routes}).`).replace(/Supply together with provider; omit both to use configured child defaults or (?:inherit the parent route|this provider's route defaults)\.|Omit to use the configured child default or inherit when the child provider matches the parent provider\./g, "Required in this Session: pass the authorized model id (without the provider/ prefix) for the selected provider.").replaceAll("Child LLM provider id.", `Required in this Session: pass an authorized provider id from list_subagent_models (${routes}).`).replaceAll("Model id within that provider.", "Required in this Session: pass the authorized model id (without the provider/ prefix) for the selected provider.");
85451
86276
  }
85452
86277
  /**
85453
86278
  * Rewrite one assembled prompt's `tools:sdk` section and native tool schemas
@@ -85527,7 +86352,7 @@ function rewriteAuthorizedPromptAssembly(assembly, allowed, toolNames = DEFAULT_
85527
86352
  * @param inheritToolNames - Delegation tools that start a child on the caller's own route.
85528
86353
  * @returns a denial reason, or undefined to leave the call untouched.
85529
86354
  */
85530
- function delegationDenialReason(agent, toolName, args, preference, sessions, toolNames = DEFAULT_DELEGATION_TOOLS, scope = "session", inheritToolNames = [], declaresRouteParameters, lockSnapshot = true) {
86355
+ function delegationDenialReason(agent, toolName, args, preference, sessions, toolNames = DEFAULT_DELEGATION_TOOLS, scope = "session", inheritToolNames = [], declaresRouteParameters, lockSnapshot = true, parentForkToolNames = DEFAULT_PARENT_FORK_TOOLS) {
85531
86356
  const mode = delegationModeOf([...toolNames.map((name) => ({
85532
86357
  name,
85533
86358
  mode: "explicit"
@@ -85542,7 +86367,8 @@ function delegationDenialReason(agent, toolName, args, preference, sessions, too
85542
86367
  const requestedProvider = asString$6(request["provider"]);
85543
86368
  const requestedModel = asString$6(request["model"]);
85544
86369
  if (mode === "inherit") {
85545
- if (requestedProvider !== void 0 && requestedModel !== void 0) return inheritOverrideReason(toolName, requestedProvider, requestedModel);
86370
+ if (requestedProvider !== void 0 || requestedModel !== void 0) return inheritOverrideReason(toolName, requestedProvider ?? "", requestedModel ?? "");
86371
+ if (parentForkToolNames.includes(toolName) && effectiveAllowParentFork(agent, preference, sessions, lockSnapshot)) return;
85546
86372
  return inheritedRouteDenial(agent, toolName, allowed);
85547
86373
  }
85548
86374
  if (declaresRouteParameters?.(agent, toolName) === false) {
@@ -89580,14 +90406,16 @@ function routeAllowed(allowed, route) {
89580
90406
  * @param parent - the parent session to audit.
89581
90407
  * @param sessions - registry used to resolve children and parents.
89582
90408
  * @param allowed - routes the parent Session authorized, when it recorded any.
90409
+ * @param options - optional parent-fork exemption matching the live guard.
89583
90410
  * @returns violations, ordered as the children were discovered.
89584
90411
  */
89585
- function auditChildRoutes(parent, sessions, allowed) {
90412
+ function auditChildRoutes(parent, sessions, allowed, options) {
89586
90413
  if (allowed === void 0 || allowed.length === 0) return [];
89587
90414
  const violations = [];
89588
90415
  for (const finding of childRoutesOf(parent, sessions)) {
89589
90416
  const effective = effectiveRouteOf(finding, sessions);
89590
90417
  if (routeAllowed(allowed, effective)) continue;
90418
+ if (options?.allowParentFork === true && finding.provider === "fork" && effective.sameAsParent) continue;
89591
90419
  violations.push({
89592
90420
  finding,
89593
90421
  route: {
@@ -91287,6 +92115,8 @@ const PRESET_REGISTRY_PACKAGE = "@deepseek-ai/dsh-agent-preset";
91287
92115
  * registers `{{cwd}}` as a `systemPrompt` variable.
91288
92116
  */
91289
92117
  const WORKING_DIRECTORY_PACKAGE = "@deepseek-ai/dsh-working-directory";
92118
+ /** The standalone PTC executor introduced when tool presentation split into executor plugins. */
92119
+ const PTC_EXECUTOR_PACKAGE = "@deepseek-ai/dsh-tool-executor-ptc";
91290
92120
  /** The id the `dispatch` preset is selectable under. */
91291
92121
  const DISPATCH_PRESET_ID = "dispatch";
91292
92122
  /**
@@ -91313,11 +92143,11 @@ const DISPATCH_PRESET = {
91313
92143
  prefix: `[Role Identification] If your first user message is a task brief (rather than a direct request from the human user), you are a subagent: the coordinator-facing rules in R0, R0.5, R-G, R1, R2, R4, R5, and R-W do not apply to you. You are the executor—plan, execute, and self-verify strictly within your task boundary, and report concrete evidence back to the dispatcher; R3 remains in effect.
91314
92144
  - [Standing Subagent Contract] Unless overridden by the brief, every subagent inherits these standing limits: retry attempts at most 3 total per brief; file edits bounded strictly to the declared Boundary module or files; read, search, verification, and test commands unlimited within that boundary; no per-cycle banking (all limits are single-run task totals, and unused allowance is not banked).
91315
92145
  - [Subagent Report Protocol] Every subagent completion report states status: ready | hand_back | blocked | failed | dropped, a summary, and evidence (diffs, test commands and outputs, before/after captures for UI). A status: hand_back report adds a one-sentence hand_back_reason naming the out-of-boundary file/interface or broken premise, and mutates no file outside Boundary.
91316
- - [Coordinator-Only Tools] ask_user_question, enter_plan_mode, leave_plan_mode, exit_plan_mode, create_goal, update_goal, and present are coordinator-only: a subagent call is hard-blocked at execution time (DELEGATED_CALLER), while declarations remain visible to preserve the provider’s content-prefix cache (notably Kimi Code’s). Never call them as a subagent; escalate via status: hand_back or status: blocked. The bridge’s enforcement is generation-graded (see R9), so never rely on the rejection.
92146
+ - [Coordinator-Only Tools] ask_user_question, enter_plan_mode, leave_plan_mode, exit_plan_mode, create_goal, update_goal, and present are coordinator-only: a subagent call is hard-blocked at execution time (DELEGATED_CALLER), while declarations remain visible to preserve the provider’s content-prefix cache. Never call them as a subagent; escalate via status: hand_back or status: blocked. The bridge’s enforcement is generation-graded (see R9), so never rely on the rejection.
91317
92147
  - [Dispatch Ledger] Call dispatch_ledger {action:"self"} once before your first delegation — it prints the v2 mandate protocol at the tail of its result — and follow that protocol verbatim for every dispatch, report, and steer.
91318
92148
 
91319
- [Coordinator Identity] You are the Dispatch Agent for this session. Your deliverables are plans, task briefs, review verdicts, and delivery summaries—not code written on someone else's behalf.
91320
- [Execution Pipeline] R0.5 Compatibility Gate (once per new session) -> R0 Complexity Triage -> (L2) R-G Clarification Interview -> Planning -> R2 Model Routing -> R5 Task Brief Dispatch -> R-W Turn Boundary Wait -> R6 Review & Acceptance.
92149
+ [Coordinator Identity] You are the Lead & Dispatch Agent: converge requirements, plan architecture, select R1 topology (Lead-Core / Hybrid / Fan-out), orchestrate subagents where ROI is positive, and own final acceptance.
92150
+ [Execution Pipeline] R0.5 Gate -> R0 Triage -> (L2) R-G Interview -> R9 Plan -> R1 Topology -> (if delegating: R2 Routing -> R5 Brief -> R-W Wait) -> R6 Acceptance.
91321
92151
 
91322
92152
  ## R0.5 · Compatibility Gate (Once per New Session, Before R0)
91323
92153
  Dispatch Mode is **incompatible** with Agent Teams and deliberately provides no fallback path: Agent Teams replaces send_message, list_agents, and interrupt_agent with team-scoped registrations, leaving spawned subagents invisible and unreachable.
@@ -91332,7 +92162,7 @@ Criterion: whether spawn_teammate and wait_agent exist (in PTC mode: tools.spawn
91332
92162
  Upon receiving a task, determine its tier by semantic impact and uncertainty first, write one line stating "Tier + Rationale", and run the matching workflow:
91333
92163
  - L0 Simple / Single-point: single-file or single-point edit; unambiguous; reversible; no parallelism value. -> Execute directly and report; no interview or subagents.
91334
92164
  - L1 Moderate: unambiguous module-local work; edits at most 5 files (5 is a cap, not a range and not a target) with no cross-module contract break; at most 2 open points; limited parallelism gain. -> Ask at most 2 key questions (no full interview; 2 is the cap) -> brief plan -> execute yourself or dispatch 1 subagent.
91335
- - L2 Complex / Multi-step: cross-module or interface-contract changes, unsettled product/UI decisions, or independent subtasks suitable for parallel execution. -> Run full workflow: Clarification Interview -> Full Plan -> Parallel Subagents -> Layered Acceptance.
92165
+ - L2 Complex / Multi-step: cross-module/contract changes, unsettled product/UI decisions, or multi-part work. -> Full governance: R-G Interview -> R9 Plan & Approval -> execute via R1 topology -> R6 Acceptance.
91336
92166
  - [Stop by Impact, Not by Effort] Within an assigned module or interface boundary, a subagent fixes all affected call sites, types, and tests needed for a self-contained result. It pauses and reports status: hand_back immediately when a change would break an external caller’s contract, alter cross-module responsibilities, or require an unsettled product or UI design decision—even when that change is a single line.
91337
92167
  When in doubt, clarify before escalating; if complexity grows mid-task, stop, re-triage, and inform the user.
91338
92168
 
@@ -91344,8 +92174,11 @@ When in doubt, clarify before escalating; if complexity grows mid-task, stop, re
91344
92174
  - G5 Convergence: End the interview only when the frontier is empty and the user explicitly confirms shared understanding.
91345
92175
  - G6 Prohibited: Answering your own questions, making product/design decisions for the user, skipping the interview, or treating a casual remark as full sign-off.
91346
92176
 
91347
- ## R1 · Responsibility Boundary (Layered by Tier)
91348
- For L2 tasks, execute work yourself only in these seven categories: (1) Planning & decomposition; (2) Dispatching tasks; (3) Review; (4) Acceptance verification; (5) Documentation & delivery summary; (6) Tasks subagents cannot perform; (7) Independent parallel-module implementation sharing no files, unfinished interfaces, or acceptance dependencies with active subagents. For L0/L1 tasks, execute directly.
92177
+ ## R1 · Execution Topology & Boundary (Coupling × Fan-out ROI)
92178
+ L0/L1: execute directly (or 1 subagent for L1). L2: R-G, R9, and R6 are mandatory; pick topology in the plan by coupling vs. parallel ROI (tightly coupled code is never barred from direct execution):
92179
+ - Lead-Core: tightly coupled cross-module/contract changes or sequential chains where splitting duplicates reads or causes hand_back loops. -> Implement directly in continuous steps (track in todo_write, no self-briefs) and run R6 verification.
92180
+ - Hybrid: unsettled shared contracts/seams plus orthogonal downstream work. -> Implement & freeze core seams yourself first, then delegate orthogonal adapters/tests/noisy exploration per R2/R5 (or subagent_fork for warm-context isolation).
92181
+ - Fan-out: >=3 orthogonal subtasks with disjoint files, settled interfaces, and clear parallel/routing gain. -> Coordinate (plan, R2/R5 dispatch, R6 review/acceptance, docs, non-delegable or disjoint parallel modules); never edit an active child's Boundary.
91349
92182
 
91350
92183
  ## R2 · Model Routing (Check Availability First, Then Decide How to Dispatch)
91351
92184
  Check whether list_subagent_models exists (in PTC mode: tools.list_subagent_models). The tool row and provider/model/reasoning_effort parameters are mounted statically, so they are present even in a session that authorized no route at all. Read that fact instead of inferring it from the tool's output:
@@ -91353,9 +92186,9 @@ Check whether list_subagent_models exists (in PTC mode: tools.list_subagent_mode
91353
92186
  - [State: Listed] Output ends with "Authorized child routes for this Session": enforcement is active.
91354
92187
  - The sole source of truth for the allowlist is list_subagent_models: call list_subagent_models({}) to list authorized providers, and call list_subagent_models({ provider }) to list authorized models under that provider; trust its output directly without cross-checking local config files or workspace code (even if upstream tool text says "Catalog membership is advisory", the runtime output is already filtered to this session's allowlist).
91355
92188
  - Before every dispatch, write route: <provider>/<model> (+ reasoning_effort when applicable) and pass split provider and model (model without the <provider>/ prefix).
91356
- - [State: Unlisted] Output states no allowlist is in force: routing is unrestricted; omitting provider/model is legitimate. State once in your delivery summary that routing is unrestricted because no allowlist was recorded. Never claim per-task routing is in force here.
92189
+ - [State: Unlisted] Output states no allowlist is in force: no Session allowlist is recorded; omitting provider/model follows the tool's normal inheritance/default behavior. On Harness >=0.2.2, explicit selection may still be limited to the parent route; follow the tool result rather than claiming routing is unrestricted. State once in your delivery summary that no Session allowlist was recorded. Never claim per-task routing is in force here.
91357
92190
  - [State: Unmounted] list_subagent_models is absent and subagent exposes no route fields: subagents inherit your route; omit the route: line.
91358
- - subagent_fork shares the parent route and KV cache; its admission is decided by the route the calling session is actually running, so it still works when list_subagent_models is absent: try subagent_fork once and read the denial if rejected. Keep model selection consistent across tasks of the same kind within a batch.
92191
+ - subagent_fork shares the parent route and KV cache; its admission is decided by the route the calling session is actually running (including same-model fork authorization), so it still works when list_subagent_models is absent: try subagent_fork once and read the denial if rejected. Keep model selection consistent across tasks of the same kind within a batch.
91359
92192
 
91360
92193
  ## R3 · Subagent Autonomy & R4 · Subagent Role
91361
92194
  A subagent has full authority to plan, execute, and self-verify within its assigned module; do not edit its files while it works. Subagents use DSH's default subagent role; model selection belongs solely to the Dispatch Agent.
@@ -91369,8 +92202,8 @@ Every task brief covers six elements: Goal / Boundary (which files or modules ma
91369
92202
  ## R6 · Review & Acceptance
91370
92203
  Two layers: subagent self-check -> your independent review (reading diffs, running tests, checking each criterion). The completion notification is a post-hoc signal: it tells you a child stopped, not that the work passed.
91371
92204
  - Re-dispatch budget per brief: 1 first attempt + at most 2 re-dispatches = at most 3 runs total. Count runs, not failures; the number belongs in the task list item for that brief (R7), not in your memory. Only after the third run fails, transition to R8 Fallback.
91372
- - [Non-Penalized hand_back] A subagent that stops cleanly before mutating any out-of-boundary file and reports status: hand_back with a valid hand_back_reason is a scope routing event, not an execution failure, and does not increment the brief’s 3-run failure counter. When re-scoping or answering a child’s hand_back or blocked report, prefer continuing the existing child with send_message({ agent_id }) over spawning a fresh subagent to preserve its warm prefix cache—especially on kimi-code.
91373
- - [Noticed but not handled] Every defect found in review: the defect goes back out on a re-dispatch with evidence or go to the user via ask_user_question (R-W). Writing it into the delivery summary and shipping anyway is not an available outcome.
92205
+ - [Non-Penalized hand_back] A subagent that stops cleanly before mutating any out-of-boundary file and reports status: hand_back with a valid hand_back_reason is a scope routing event, not an execution failure, and does not increment the brief’s 3-run failure counter. When re-scoping or answering a child’s hand_back or blocked report, prefer continuing the existing child with send_message({ agent_id }) over spawning a fresh subagent to preserve its warm prefix cache.
92206
+ - [Noticed but not handled] Every defect found in review: the defect goes back out on a re-dispatch with evidence or go to the user via ask_user_question (R-W); on Lead-Core/Hybrid core, fix and re-verify before delivery. Writing it into the delivery summary and shipping anyway is not an available outcome.
91374
92207
  - [UI Visual Evidence Gate] For any task or subtask that changes visible UI or GUI layout, styling, or components, acceptance requires both Before and After visual evidence—screenshots or live DOM/rendered captures—taken under the same scenario, viewport, and theme. After-only evidence fails R6 review.
91375
92208
 
91376
92209
  ## R-W · Turn Boundary (Waiting / Goals / Questions)
@@ -91384,7 +92217,7 @@ Maintain the task list (in todo_write, not create_goal; see R-W), decision log,
91384
92217
  - [Clause Deletion Test] Keep complete engineering evidence in internal review verification, but before sending the final user-facing delivery summary, ask of each clause whether deleting it would prevent the user from understanding the outcome, risk, or required action—if not, omit it.
91385
92218
 
91386
92219
  ## R8 · Fallback
91387
- Fallback is a task-scoped, non-session-wide exception: it covers only the single task that triggered it. Execute a task yourself only on evidence of: L0/L1 task; subagent tools unmounted (R2 [State: Unmounted]—An unmounted tool is the only routing condition that permits fallback); non-delegable task; or the same task brief has still not passed review after its third run under R6. Fix trigger conditions on hard rejections (on active child limit -> wait and re-dispatch; on subagent model selection -> pass an explicit authorized route). When the next task begins, always return to R0 to triage anew.
92220
+ Fallback is a task-scoped, non-session-wide exception for delegated briefs: it covers only the single task that triggered it. Outside planned direct execution (L0/L1, R1 Lead-Core, or Hybrid core), execute a task yourself only on evidence of: subagent tools unmounted (R2 [State: Unmounted]—An unmounted tool is the only routing condition that permits fallback); non-delegable task; or the same task brief has still not passed review after its third run under R6. Fix trigger conditions on hard rejections (on active child limit -> wait and re-dispatch; on subagent model selection -> pass an explicit authorized route). When the next task begins, always return to R0 to triage anew.
91388
92221
 
91389
92222
  ## R9 · Plan Pipeline (Converged Interview -> Plan Mode -> Plan -> Approval)
91390
92223
  - Trigger: only for L2 once R-G has converged. Call enter_plan_mode immediately once that holds, as the sole action of that step. Read-only exploration and the decision-complete plan belong to the next turn, and exit_plan_mode must be the sole and final tool call of the turn that submits the plan.
@@ -91459,7 +92292,7 @@ Fallback is a task-scoped, non-session-wide exception: it covers only the single
91459
92292
 
91460
92293
  [Read-Only Exploration & Clarification Interview] Inspect the repository first using non-mutating reads, searches, and static checks, preferring existing functions, utilities, and patterns; never edit or write files, mutate config, run formatters/codegen that rewrite tracked files, commit, or otherwise enact the plan. To verify repository facts (such as where code lives or how current behavior works), explore read-only yourself or dispatch read-only subagents per R2 (using the routes returned directly by list_subagent_models) without blocking unrelated frontier questions. Before drafting the plan, settle requirements with the user per R0 and R-G: for L2 tasks, work the R-G design tree in rounds—ask the entire current frontier in one ask_user_question call (numbered, titled, with your recommended answer marked first), wait for the answers, and recompute the frontier until it is empty (every branch visited, nothing left silently assumed) and the user explicitly confirms shared understanding; for L0/L1 tasks, keep the interview to at most 2 questions, the ones that actually change the outcome. When a technical, naming, layout, or styling choice can be derived from an established reference in the repository or in AGENTS.md (target_basis: existing-standard), treat it as a repository fact: follow the existing standard and do not ask the user; reserve ask_user_question for unsettled product or design decisions with no established precedent.
91461
92294
 
91462
- [Plan Completeness] Make the plan decision-complete: state the goal and success criteria; group implementation changes by subsystem; specify public API, schema, and data-flow changes; and cover edge cases, failure modes, test strategy, acceptance criteria, and explicit assumptions. Keep it concise enough to scan quickly while detailed enough that an executor or subagent can implement it without making further design decisions. When the plan changes visible UI or GUI layout, styling, or components, it names the Before and After visual evidence acceptance will require (same scenario, viewport, and theme); After-only evidence does not pass review.
92295
+ [Plan Completeness] Make the plan decision-complete: state the goal, success criteria, and R1 execution topology (Lead-Core, Hybrid, or Fan-out with subtask boundaries); group implementation changes by subsystem; specify public API, schema, and data-flow changes; and cover edge cases, failure modes, test strategy, acceptance criteria, and explicit assumptions. Keep it concise enough to scan quickly while detailed enough that an executor or subagent can implement it without making further design decisions. When the plan changes visible UI or GUI layout, styling, or components, it names the Before and After visual evidence acceptance will require (same scenario, viewport, and theme); After-only evidence does not pass review.
91463
92296
 
91464
92297
  [Plan Approval] When ready, call exit_plan_mode with the complete plan Markdown starting with a # Title heading, making exit_plan_mode the sole and final tool call of that turn: implementation or dispatch happens only in subsequent turns after approval. Never paste the final plan into a normal chat response or ask "Should I proceed?" in prose or via ask_user_question. If the user rejects the plan, fold in their feedback and resubmit via exit_plan_mode; if the approval channel is unavailable or aborted, stay in Plan Mode and ask the user to switch modes manually—never start implementing on your own.` }
91465
92298
  }, {
@@ -91615,13 +92448,17 @@ Fallback is a task-scoped, non-session-wide exception: it covers only the single
91615
92448
  * and remove its standalone `./list-agents` export. That row is omitted only when
91616
92449
  * the export is absent; older harnesses keep it because their main entry does not
91617
92450
  * register the tool.
92451
+ *
92452
+ * When the standalone PTC executor exists, it replaces the deprecated
92453
+ * agent-tool-presentation compatibility row and its `{ mode: 'ptc' }` config.
91618
92454
  * @param resolves - whether a bare specifier resolves in this installation.
91619
92455
  * @returns the preset definition for the running harness generation.
91620
92456
  */
91621
92457
  function resolveDispatchPreset(resolves = resolvesFromHere) {
91622
92458
  const hasWorkingDirectory = resolves(WORKING_DIRECTORY_PACKAGE);
91623
92459
  const hasLegacyListAgents = resolves("@deepseek-ai/dsh-tool-subagent-control/list-agents");
91624
- if (!hasWorkingDirectory && hasLegacyListAgents) return DISPATCH_PRESET;
92460
+ const hasPtcExecutor = resolves(PTC_EXECUTOR_PACKAGE);
92461
+ if (!hasWorkingDirectory && hasLegacyListAgents && !hasPtcExecutor) return DISPATCH_PRESET;
91625
92462
  return {
91626
92463
  ...DISPATCH_PRESET,
91627
92464
  plugins: DISPATCH_PRESET.plugins.map((row) => {
@@ -91629,6 +92466,14 @@ function resolveDispatchPreset(resolves = resolvesFromHere) {
91629
92466
  ...row,
91630
92467
  config: row.config.filter((nested) => nested.id !== "tool-subagent-list-agents")
91631
92468
  };
92469
+ if (row.id === "tool-presentation" && hasPtcExecutor) {
92470
+ const { config: _omitted, ...rest } = row;
92471
+ return {
92472
+ ...rest,
92473
+ id: "tool-executor-ptc",
92474
+ name: PTC_EXECUTOR_PACKAGE
92475
+ };
92476
+ }
91632
92477
  if (row.id !== "persona" || !hasWorkingDirectory || typeof row.config !== "object" || row.config === null) return row;
91633
92478
  const { suffix: _omitted, ...rest } = row.config;
91634
92479
  return {
@@ -99531,7 +100376,7 @@ var WorkBuddyAdapter = class extends LlmAdapter {
99531
100376
  providerInfo(provider) {
99532
100377
  return {
99533
100378
  id: provider,
99534
- name: PROVIDER_NAME$3
100379
+ name: localizedProviderName(provider, PROVIDER_NAME$3)
99535
100380
  };
99536
100381
  }
99537
100382
  providerRetryPolicy() {
@@ -100171,7 +101016,7 @@ function parseWorkBuddyPoolState(value) {
100171
101016
  if (typeof raw.pause === "object" && raw.pause !== null && !Array.isArray(raw.pause)) {
100172
101017
  const record = raw.pause;
100173
101018
  if (typeof record.pausedSince === "number" && Number.isFinite(record.pausedSince) && typeof record.pausedUntil === "number" && Number.isFinite(record.pausedUntil)) pause = {
100174
- reason: typeof record.reason === "string" ? record.reason : "号池已暂停。",
101019
+ reason: typeof record.reason === "string" ? record.reason : t("wb.pool.pausedDefault"),
100175
101020
  pausedSince: record.pausedSince,
100176
101021
  pausedUntil: record.pausedUntil,
100177
101022
  triggeredBy: Array.isArray(record.triggeredBy) ? record.triggeredBy.filter((id) => typeof id === "string") : []
@@ -100303,7 +101148,7 @@ function backendFromDomain(domain) {
100303
101148
  * which is the case that used to be reported as "the account shows 账号 1".
100304
101149
  */
100305
101150
  function defaultAliasFor(credentials, position) {
100306
- return credentials.nickname || credentials.uin || credentials.uid || `账号 ${position}`;
101151
+ return credentials.nickname || credentials.uin || credentials.uid || t("wb.pool.accountLabel", { position });
100307
101152
  }
100308
101153
  /**
100309
101154
  * A meter's consumed share, from whichever fraction this line measured.
@@ -100493,7 +101338,11 @@ var WorkBuddyAccountPool = class extends AccountPoolCore {
100493
101338
  /** The error every selection raises while the pool is paused. */
100494
101339
  pausedError(pause, now = Date.now()) {
100495
101340
  const minutes = Math.max(1, Math.ceil((pause.pausedUntil - now) / 6e4));
100496
- return new WorkBuddyPoolPausedError(`${PROVIDER_NAME$3} 号池已暂停:${pause.reason} 预计 ${minutes} 分钟后自动恢复;被上游限制的账号需要重新登录后才能回到轮换。`, pause.pausedUntil);
101341
+ return new WorkBuddyPoolPausedError(t("wb.pool.paused", {
101342
+ provider: PROVIDER_NAME$3,
101343
+ reason: pause.reason,
101344
+ minutes
101345
+ }), pause.pausedUntil);
100497
101346
  }
100498
101347
  /**
100499
101348
  * Record an account-scoped refusal reported by the protocol worker.
@@ -100520,7 +101369,11 @@ var WorkBuddyAccountPool = class extends AccountPoolCore {
100520
101369
  * log instead of silently barring a healthy account.
100521
101370
  */
100522
101371
  async markAccountRestriction(accountId, restriction) {
100523
- if (restriction.code !== 11140) throw new Error(`${PROVIDER_NAME$3} 号池只记录账号级限制(${WORKBUDDY_RESTRICTED_ACCOUNT_CODE}),收到业务码 ${restriction.code};11128 与 11158 不是账号级拒绝,必须由协议层分别处理。`);
101372
+ if (restriction.code !== 11140) throw new Error(t("wb.pool.notAccountScoped", {
101373
+ provider: PROVIDER_NAME$3,
101374
+ expected: WORKBUDDY_RESTRICTED_ACCOUNT_CODE,
101375
+ code: restriction.code
101376
+ }));
100524
101377
  const now = Date.now();
100525
101378
  const record = {
100526
101379
  code: restriction.code,
@@ -100537,7 +101390,11 @@ var WorkBuddyAccountPool = class extends AccountPoolCore {
100537
101390
  if (others.length > 0) {
100538
101391
  const windowMinutes = Math.round(WORKBUDDY_RESTRICTION_ESCALATION_WINDOW_MS / 6e4);
100539
101392
  state.pause = {
100540
- reason: `上游以 ${restriction.code} 在 ${windowMinutes} 分钟内拒绝了 ${others.length + 1} 个不同账号`,
101393
+ reason: t("wb.pool.upstreamRefused", {
101394
+ code: restriction.code,
101395
+ minutes: windowMinutes,
101396
+ count: others.length + 1
101397
+ }),
100541
101398
  pausedSince: now,
100542
101399
  pausedUntil: now + WORKBUDDY_POOL_PAUSE_MS,
100543
101400
  triggeredBy: Object.keys(state.restrictions)
@@ -100853,7 +101710,7 @@ var WorkBuddyAccountPool = class extends AccountPoolCore {
100853
101710
  * the user their account was deleted. Hiding is the supported action there.
100854
101711
  */
100855
101712
  deleteAccountFromPool(data, accountId) {
100856
- if (data.accounts.find((account) => account.id === accountId)?.source === "desktop") throw new Error("桌面账号由 CodeBuddy 客户端所有,只能隐藏,不能删除。");
101713
+ if (data.accounts.find((account) => account.id === accountId)?.source === "desktop") throw new Error(t("wb.pool.desktopAccountUndeletable"));
100857
101714
  super.deleteAccountFromPool(data, accountId);
100858
101715
  }
100859
101716
  };
@@ -100930,10 +101787,14 @@ async function requestLoginState(region, fetchFn = fetch, signal) {
100930
101787
  } catch {
100931
101788
  root = void 0;
100932
101789
  }
100933
- if (!response.ok || root?.code !== 0 || !isRecord$1(root.data)) throw new Error(`${PROVIDER_NAME$3} 登录初始化失败(HTTP ${response.status}):${stringOf(root ?? {}, "msg") ?? text.slice(0, 160)}`);
101790
+ if (!response.ok || root?.code !== 0 || !isRecord$1(root.data)) throw new Error(t("wb.oauth.loginInitFailed", {
101791
+ provider: PROVIDER_NAME$3,
101792
+ status: response.status,
101793
+ detail: stringOf(root ?? {}, "msg") ?? text.slice(0, 160)
101794
+ }));
100934
101795
  const state = stringOf(root.data, "state");
100935
101796
  const authUrl = stringOf(root.data, "authUrl");
100936
- if (!state || !authUrl) throw new Error(`${PROVIDER_NAME$3} 登录响应缺少 state 或 authUrl`);
101797
+ if (!state || !authUrl) throw new Error(t("wb.oauth.loginMissingState", { provider: PROVIDER_NAME$3 }));
100937
101798
  return {
100938
101799
  state,
100939
101800
  authUrl,
@@ -100943,15 +101804,18 @@ async function requestLoginState(region, fetchFn = fetch, signal) {
100943
101804
  }
100944
101805
  /** Parse the successful token-poll shape while accepting the two observed wrappers. */
100945
101806
  function parseLoginCredential(payload, attempt) {
100946
- if (!isRecord$1(payload)) throw new Error(`${PROVIDER_NAME$3} 登录轮询响应无效`);
101807
+ if (!isRecord$1(payload)) throw new Error(t("wb.oauth.loginPollInvalid", { provider: PROVIDER_NAME$3 }));
100947
101808
  const code = numberOf(payload, "code");
100948
101809
  if (code === 11217) return null;
100949
- if (code !== 0) throw new Error(`${PROVIDER_NAME$3} 登录失败:${stringOf(payload, "msg") ?? `code ${String(code)}`}`);
101810
+ if (code !== 0) throw new Error(t("wb.oauth.loginFailed", {
101811
+ provider: PROVIDER_NAME$3,
101812
+ detail: stringOf(payload, "msg") ?? `code ${String(code)}`
101813
+ }));
100950
101814
  const data = isRecord$1(payload.data) ? payload.data : payload;
100951
101815
  const auth = isRecord$1(data.auth) ? data.auth : data;
100952
101816
  const account = isRecord$1(data.account) ? data.account : isRecord$1(auth.account) ? auth.account : isRecord$1(data.user) ? data.user : isRecord$1(auth.user) ? auth.user : {};
100953
101817
  const accessToken = stringOf(auth, "accessToken") ?? stringOf(auth, "access_token") ?? stringOf(data, "token");
100954
- if (!accessToken) throw new Error(`${PROVIDER_NAME$3} 登录成功响应缺少 access token`);
101818
+ if (!accessToken) throw new Error(t("wb.oauth.loginMissingToken", { provider: PROVIDER_NAME$3 }));
100955
101819
  const domain = stringOf(auth, "domain") ?? attempt.domain;
100956
101820
  const expiresIn = numberOf(auth, "expiresIn") ?? numberOf(auth, "expires_in");
100957
101821
  const expiresAt = numberOf(auth, "expiresAt") ?? numberOf(auth, "expires_at") ?? (expiresIn === void 0 ? Date.now() + 3600 * 1e3 : Date.now() + expiresIn * 1e3);
@@ -100978,12 +101842,16 @@ async function pollLogin(attempt, fetchFn = fetch, signal) {
100978
101842
  signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(2e4)]) : AbortSignal.timeout(2e4)
100979
101843
  });
100980
101844
  const text = await response.text().catch(() => "");
100981
- if (!response.ok) throw new Error(`${PROVIDER_NAME$3} 登录轮询失败(HTTP ${response.status}):${text.slice(0, 160)}`);
101845
+ if (!response.ok) throw new Error(t("wb.oauth.loginPollFailed", {
101846
+ provider: PROVIDER_NAME$3,
101847
+ status: response.status,
101848
+ detail: text.slice(0, 160)
101849
+ }));
100982
101850
  let payload;
100983
101851
  try {
100984
101852
  payload = JSON.parse(text);
100985
101853
  } catch {
100986
- throw new Error(`${PROVIDER_NAME$3} 登录轮询返回了非 JSON 响应`);
101854
+ throw new Error(t("wb.oauth.loginPollNotJson", { provider: PROVIDER_NAME$3 }));
100987
101855
  }
100988
101856
  return parseLoginCredential(payload, attempt);
100989
101857
  }
@@ -101021,7 +101889,7 @@ async function beginWebLogin$4(store, region, fetchFn = fetch, options = {}) {
101021
101889
  status: "pending",
101022
101890
  region,
101023
101891
  authUrl: attempt.authUrl,
101024
- progress: "等待浏览器授权…",
101892
+ progress: t("wb.oauth.waitingBrowser"),
101025
101893
  startedAt
101026
101894
  };
101027
101895
  (async () => {
@@ -101034,7 +101902,7 @@ async function beginWebLogin$4(store, region, fetchFn = fetch, options = {}) {
101034
101902
  if (credentials === null) {
101035
101903
  flow = {
101036
101904
  ...flow,
101037
- progress: `等待浏览器授权…(${Math.floor((Date.now() - startedAt) / 1e3)} 秒)`
101905
+ progress: t("wb.oauth.waitingBrowserElapsed", { seconds: Math.floor((Date.now() - startedAt) / 1e3) })
101038
101906
  };
101039
101907
  continue;
101040
101908
  }
@@ -101047,7 +101915,7 @@ async function beginWebLogin$4(store, region, fetchFn = fetch, options = {}) {
101047
101915
  accountId: workBuddyAccountId(resolved),
101048
101916
  startedAt,
101049
101917
  completedAt: Date.now(),
101050
- progress: "授权完成"
101918
+ progress: t("wb.oauth.authorized")
101051
101919
  };
101052
101920
  return;
101053
101921
  }
@@ -101056,7 +101924,7 @@ async function beginWebLogin$4(store, region, fetchFn = fetch, options = {}) {
101056
101924
  region,
101057
101925
  startedAt,
101058
101926
  completedAt: Date.now(),
101059
- error: "登录超时,请重新添加账号。"
101927
+ error: t("wb.oauth.loginTimeout")
101060
101928
  };
101061
101929
  } catch (error) {
101062
101930
  if (active.signal.aborted) return;
@@ -102166,7 +103034,8 @@ const Config = z$1.object({
102166
103034
  progressUpdatesLanguage: z$1.union([
102167
103035
  z$1.const("auto"),
102168
103036
  z$1.const("zh"),
102169
- z$1.const("en")
103037
+ z$1.const("en"),
103038
+ z$1.const("ru")
102170
103039
  ]).default("auto").volatile().description("进展更新的输出语言:auto 跟随对话语言,zh 中文,en 英文。"),
102171
103040
  planModePipeline: z$1.boolean().default(true).volatile().description("启用计划模式管线:允许调度模式在澄清访谈收敛后用 enter_plan_mode 进入计划模式,放弃规划时用 leave_plan_mode 退出。"),
102172
103041
  dispatchExecutionGuard: z$1.boolean().default(true).volatile().description("启用调度执行守卫:在执行期拦截子代理越权调用主控专用工具,并拦截等待子代理期间的纯 sleep 空等命令;不修改工具声明面,零损耗保护 Kimi 缓存。"),
@@ -102185,6 +103054,8 @@ const inject = [
102185
103054
  "loader"
102186
103055
  ];
102187
103056
  function apply(ctx, pluginConfig = {}) {
103057
+ installHostLocale(new HostLocaleRuntime());
103058
+ ctx.effect(() => () => installHostLocale(void 0), "dsh-chatgpt-subscription: host locale");
102188
103059
  const fetchConfiguration = resolveFetchConfiguration(pluginConfig);
102189
103060
  const poolStorageSettings = new PoolStorageSettings();
102190
103061
  poolStorageSettings.hydrate().catch(() => void 0);
@@ -102318,9 +103189,13 @@ function apply(ctx, pluginConfig = {}) {
102318
103189
  const current = preferences.status();
102319
103190
  const defaultAllowedModels = current.subagentDefaultModels ?? [];
102320
103191
  const byMainModel = current.subagentModelsByMainModel ?? {};
103192
+ const defaultAllowParentFork = current.subagentDefaultAllowParentFork;
103193
+ const allowParentForkByMainModel = current.subagentAllowParentForkByMainModel ?? {};
102321
103194
  return {
102322
103195
  ...defaultAllowedModels.length > 0 ? { defaultAllowedModels } : {},
102323
- ...Object.keys(byMainModel).length > 0 ? { byMainModel } : {}
103196
+ ...Object.keys(byMainModel).length > 0 ? { byMainModel } : {},
103197
+ ...defaultAllowParentFork === true ? { defaultAllowParentFork: true } : {},
103198
+ ...Object.keys(allowParentForkByMainModel).length > 0 ? { allowParentForkByMainModel } : {}
102324
103199
  };
102325
103200
  }
102326
103201
  });
@@ -102684,13 +103559,15 @@ function apply(ctx, pluginConfig = {}) {
102684
103559
  const override = mainRoute === void 0 ? void 0 : (current.subagentModelsByMainModel ?? {})[`${mainRoute.provider}/${mainRoute.model}`];
102685
103560
  const fallback = current.subagentDefaultModels ?? [];
102686
103561
  const allowed = audited === void 0 ? audited : override !== void 0 && override.length > 0 ? override : fallback.length > 0 ? fallback : audited;
103562
+ const forkOverride = mainRoute === void 0 ? void 0 : (current.subagentAllowParentForkByMainModel ?? {})[`${mainRoute.provider}/${mainRoute.model}`];
103563
+ const allowParentFork = typeof forkOverride === "boolean" ? forkOverride : current.subagentDefaultAllowParentFork === true;
102687
103564
  return Promise.resolve({
102688
103565
  sessionId,
102689
103566
  allowedModels: (allowed ?? []).map((route) => ({
102690
103567
  provider: route.provider,
102691
103568
  model: route.model
102692
103569
  })),
102693
- violations: auditChildRoutes(target, sessions, allowed).map((violation) => ({
103570
+ violations: auditChildRoutes(target, sessions, allowed, { allowParentFork }).map((violation) => ({
102694
103571
  childId: violation.finding.childId,
102695
103572
  parentId: violation.finding.parentId ?? null,
102696
103573
  provider: violation.finding.provider ?? null,
@@ -102974,4 +103851,4 @@ function apply(ctx, pluginConfig = {}) {
102974
103851
  }, "dsh-chatgpt-subscription: adapter, routes, and lifecycle");
102975
103852
  }
102976
103853
  //#endregion
102977
- export { AccountPoolCore, AccountPoolStore, AntigravityAdapter, CHANNEL_ALIASES, ADOPTED_CREDENTIAL_EXPIRED_HINT as CLAUDE_ADOPTED_CREDENTIAL_EXPIRED_HINT, API_BASE as CLAUDE_API_BASE, DEFAULT_VISIBLE_MODEL_IDS as CLAUDE_DEFAULT_VISIBLE_MODELS, FALLBACK_MODELS as CLAUDE_FALLBACK_MODELS, MESSAGES_PATH as CLAUDE_MESSAGES_PATH, CLAUDE_MODELS, CLAUDE_MODEL_IDS, PROVIDER_ID as CLAUDE_PROVIDER_ID, PROVIDER_NAME as CLAUDE_PROVIDER_NAME, QUOTA_CACHE_TTL_MS as CLAUDE_QUOTA_CACHE_TTL_MS, CLAUDE_REASONING_EFFORTS, ROUTE_PREFIX as CLAUDE_ROUTE_PREFIX, CLINE_PASS_API_KEY_ENV, DEFAULT_BASE_URL as CLINE_PASS_DEFAULT_BASE_URL, DEFAULT_MODELS as CLINE_PASS_DEFAULT_MODELS, MAX_UPSTREAMS as CLINE_PASS_MAX_UPSTREAMS, MODEL_CATALOG as CLINE_PASS_MODEL_CATALOG, POOL_COOLDOWN_MS as CLINE_PASS_POOL_COOLDOWN_MS, REASONING_EFFORTS as CLINE_PASS_REASONING_EFFORTS, CLINE_PASS_ROUTES, CLINE_PASS_ROUTE_PREFIX, CLINE_PASS_PROVIDER_ID as CLINE_PASS_ROUTE_PROVIDER_ID, CLINE_PASS_PROVIDER_NAME as CLINE_PASS_ROUTE_PROVIDER_NAME, ClaudeAccountPool, ClaudeAdapter, FileCredentialStore as ClaudeCredentialStore, FileModelSettingsStore as ClaudeModelSettingsStore, ClinePassAccountPool, ClinePassAdapter, FileCredentialStore$1 as ClinePassCredentialStore, ClinePassEngine, ClinePassModelSettingsStore, CodexAccountPool, CodexChatGptAdapter, CommandCodeAccountPool, CommandCodeAdapter, FileCredentialStore$2 as CommandCodeCredentialStore, FileModelSettingsStore$1 as CommandCodeModelSettingsStore, Config, DEFAULT_GUARD_OPTIONS, DEFAULT_SUBAGENT_INHERIT_TOOLS, FileCredentialStore$3 as FileCredentialStore, FileModelSettingsStore$2 as FileModelSettingsStore, GLM_CODING_PLAN_PREFERENCES_NAMESPACE, QUOTA_WINDOW_MINUTES as GLM_CODING_PLAN_QUOTA_WINDOW_MINUTES, GLM_CODING_PLAN_RETRY_POLICY_CONFIG, PROVIDER_ID$1 as GLM_CODING_PLAN_ROUTE_PROVIDER_ID, PROVIDER_NAME$1 as GLM_CODING_PLAN_ROUTE_PROVIDER_NAME, GLM_MODEL_CATALOG, GLM_MODEL_IDS, GLM_POOL_COOLDOWN_MS, GlmAdoptedCredentialRefreshError, GlmCodingPlanAccountPool, GlmCodingPlanAdapter, GlmCodingPlanCredentialStore, GlmCodingPlanModelSettingsStore, KIMI_CODE_MODELS, KIMI_CODE_RETRY_POLICY_CONFIG, KimiCodeAccountPool, KimiCodeAdapter, FileCredentialStore$4 as KimiCodeCredentialStore, FileModelSettingsStore$3 as KimiCodeModelSettingsStore, LinuxFileTokenStore, AGENT_LLM_PREFIX as MINIMAX_CODE_AGENT_LLM_PREFIX, DEFAULT_MAX_MESSAGE_BODY_BYTES as MINIMAX_CODE_MAX_MESSAGE_BODY_BYTES, MESSAGES_PATH$1 as MINIMAX_CODE_MESSAGES_PATH, MINIMAX_CODE_MODELS, PROBE_MODEL as MINIMAX_CODE_PROBE_MODEL, MINIMAX_CODE_PROVIDER_ID, MINIMAX_CODE_PROVIDER_NAME, MINIMAX_CODE_REASONING_EFFORTS, REGION_HOSTS as MINIMAX_CODE_REGION_HOSTS, MINIMAX_CODE_RETRY_POLICY_CONFIG, MINIMAX_CODE_ROUTE_PREFIX, MacKeychainTokenStore, MinimaxCodeAccountPool, MinimaxCodeAdapter, MinimaxCodeCheckinService, MinimaxCodeCredentialStore, MinimaxCodeModelSettingsStore, OAuthService, OPENDESIGN_API_KEY_ENV, OPENDESIGN_CONSOLE_URL, DEFAULT_BASE_URL$1 as OPENDESIGN_DEFAULT_BASE_URL, DEFAULT_CONTEXT_WINDOW as OPENDESIGN_DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_CONCURRENT_REQUESTS as OPENDESIGN_DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_MAX_TOKENS as OPENDESIGN_DEFAULT_MAX_TOKENS, DEFAULT_MODELS$1 as OPENDESIGN_DEFAULT_MODELS, DEFAULT_STREAM_IDLE_TIMEOUT_MS as OPENDESIGN_DEFAULT_STREAM_IDLE_TIMEOUT_MS, PROVIDER_ID$2 as OPENDESIGN_HOST_PROVIDER_ID, PROVIDER_NAME$2 as OPENDESIGN_HOST_PROVIDER_NAME, MODEL_CATALOG$1 as OPENDESIGN_MODEL_CATALOG, MODEL_PRICES_URL as OPENDESIGN_MODEL_PRICES_URL, NO_ANSWER_PHRASE as OPENDESIGN_NO_ANSWER_PHRASE, POOL_COOLDOWN_MS$1 as OPENDESIGN_POOL_COOLDOWN_MS, OPENDESIGN_PROVIDER_ID, OPENDESIGN_PROVIDER_NAME, REASONING_EFFORT_IDS as OPENDESIGN_REASONING_EFFORT_IDS, OPENDESIGN_ROUTES, OPENDESIGN_ROUTE_PREFIX, OpenDesignAccountPool, OpenDesignAdapter, FileCredentialStore$5 as OpenDesignCredentialStore, OpenDesignModelSettingsStore, ProxyManager, QODER_POOL_COOLDOWN_MS, QODER_PROVIDER_ID, QODER_PROVIDER_NAME, QODER_REGIONS, QODER_RETRY_POLICY_CONFIG, QODER_ROUTE_PREFIX, QoderAccountPool, QoderAdapter, QoderCredentialStore, QoderModelSettingsStore, RELAY_PROBE_ENV, RELAY_PROBE_FILE_ENV, RELAY_PROBE_FILE_NAME, RELAY_PROBE_MAX_BYTES, RELAY_SOURCE_KINDS, RESUME_HINT, RESUME_HINT_STRICT, RelayProbe, ResponsesClient, STEP_CODE_POOL_COOLDOWN_MS, STEP_CODE_PROFILES, STEP_CODE_PROVIDER_ID, STEP_CODE_PROVIDER_NAME, STEP_CODE_RETRY_POLICY_CONFIG, STEP_CODE_ROUTE_PREFIX, SUBAGENT_MODEL_SELECTION_NAMESPACE, SUBAGENT_POLICY_EVENT, SearchProviderSwitcher, StepCodeAccountPool, StepCodeAdapter, StepCodeCredentialRefreshError, StepCodeCredentialStore, StepCodeModelSettingsStore, StepCodeQuotaCredentialStore, UsageService, FALLBACK_MODELS$1 as WORKBUDDY_MODELS, WORKBUDDY_MODEL_IDS, WindowsDpapiTokenStore, WorkBuddyAdapter, WorkBuddyCheckinService, FileCredentialStore$6 as WorkBuddyCredentialStore, FileModelSettingsStore$4 as WorkBuddyModelSettingsStore, adoptZcodeSignIn as adoptGlmZcodeSignIn, adoptedPoolAccountKey, apply, assertRequestBodyFits as assertMinimaxCodeBodyFits, assertStreamComplete as assertMinimaxCodeStreamComplete, auditChildRoutes, auditedRoutesOf, authorizedRoutesFor, beginLogin as beginClaudeLogin, beginWebLogin as beginKimiCodeLogin, beginWebLogin$1 as beginMinimaxCodeLogin, beginWebLogin$2 as beginWebLogin, buildAttempts, buildClaudeModelOptions, buildClinePassBody, buildGlmRequestPlan, buildMinimaxCodeModelOptions, buildMinimaxRequest, buildOpenDesignBody, cachedQoderModelCatalog, cachedStepCodeModelCatalog, cancelLogin as cancelClaudeLogin, cancelWebLogin as cancelMinimaxCodeLogin, catalogModelOptions, channelNameFor, childRoutesOf, clampOutputToContext as clampMinimaxCodeOutputToContext, classifyFailure as classifyClaudeFailure, classifyKimiFailure, classifyMinimaxFailure, classifyUpstreamError, classifyFailure$1 as classifyWorkBuddyFailure, claudeCliVersion, claudeCodeCredentialPaths, claudeCodeCredentialPresence, codeForFailure as claudeCodeForFailure, credentialPath as claudeCredentialPath, defaultContextWindowFor as claudeDefaultContextWindow, maxOutputTokensFor as claudeMaxOutputTokens, claudeModelCanDisableThinking, modelSettingsPath as claudeModelSettingsPath, claudeModelSupportsImage, claudeModelSupportsTemperature, claudePoolPath, claudeReasoningEfforts, claudeThinkingMode, toLlmError as claudeToLlmError, clearCachedQuota, clearCachedCatalog as clearClaudeCatalog, clearCachedQuota$1 as clearClaudeQuota, clearCachedQuota$2 as clearCommandCodeQuota, clearCachedQuota$3 as clearKimiCodeQuota, clearCachedQuota$4 as clearMinimaxCodeQuota, clearCachedCatalog$1 as clearWorkBuddyCatalog, clearCachedQuota$5 as clearWorkBuddyQuota, clinePassAccountKey, clinePassAccountQuota, catalogEntry as clinePassCatalogEntry, chatCompletion as clinePassChatCompletion, chatURL as clinePassChatURL, credentialPath$1 as clinePassCredentialPath, defaultPin as clinePassDefaultPin, clinePassKnownModelIds, modelSettingsPath$1 as clinePassModelSettingsPath, clinePassPoolPath, clinePassVisibleModelIds, clinePassWindowDurationMins, clinePassWindowLabel, closeMinimaxStream, codexPoolPath, collapseScore, commandCodeAccountKey, credentialPath$2 as commandCodeCredentialPath, modelSettingsPath$2 as commandCodeModelSettingsPath, commandCodePoolPath, contextWindowForModel, convergeGlmEffort, createAntigravityImageTool, createClinePassLine, createClinePassStore, createCodexFetchProvider, createCodexImageTool, createCodexSearchProvider, createFileRelayProbeSink, createMinimaxCodeAccountsHandler, createMessage as createMinimaxCodeMessage, createPkcePair as createMinimaxCodePkcePair, createStreamState as createMinimaxCodeStreamState, createOpenDesignLine, createPlatformTokenStore, createSubagentAuthorization, credentialPath$3 as credentialPath, credentialsFromAdopt, credentialsFromCliLogin, defaultOpenDesignModelSettings, delegationDenialReason, delegationModeOf, describeCredentials as describeMinimaxCodeCredentials, detectSystemProxy, dshHomeDir, effectiveRouteOf, ensureAccessToken as ensureClaudeAccessToken, ensureAccessToken$1 as ensureKimiCodeAccessToken, ensureAccessToken$2 as ensureMinimaxCodeAccessToken, extractAvailableProviders, fetchAccountQuota, fetchAccountQuota$1 as fetchClaudeQuota, fetchGatewayCatalog as fetchClinePassGatewayCatalog, fetchOfficialModels as fetchClinePassOfficialModels, fetchUsageLimits as fetchClinePassUsageLimits, fetchAccountQuota$2 as fetchCommandCodeQuota, fetchGlmQuota, fetchAccountQuota$3 as fetchKimiCodeQuota, fetchUserInfo as fetchKimiCodeUserInfo, fetchTokenPlanQuota as fetchMinimaxCodeQuota, fetchGatewayCatalog$1 as fetchOpenDesignGatewayCatalog, fetchAccountQuota$4 as fetchWorkBuddyQuota, getCachedQuota as getCachedGlmCodingPlanQuota, getCachedQuota$1 as getCachedQuota, getLoginStatus as getClaudeLoginStatus, getCachedQuota$2 as getClaudeQuota, getClaudeWebStatus, getClinePassWebStatus, getWebLoginStatus as getCommandCodeLoginStatus, getCachedQuota$3 as getCommandCodeQuota, getCommandCodeWebStatus, getGlmCodingPlanStatus, getWebLoginStatus$1 as getKimiCodeLoginStatus, getCachedQuota$4 as getKimiCodeQuota, getKimiCodeWebStatus, getWebLogin as getMinimaxCodeLogin, getCachedQuota$5 as getMinimaxCodeQuota, getMinimaxCodeWebStatus, getOpenDesignWebStatus, getQoderStatus, getStepCodeStatus, getCachedQuota$6 as getWorkBuddyQuota, getWorkBuddyWebStatus, glmCatalogSize, authorizeUrl as glmCodingPlanAuthorizeUrl, catalogSize as glmCodingPlanCatalogCount, credentialPath$4 as glmCodingPlanCredentialPath, modelSettingsPath$3 as glmCodingPlanModelSettingsPath, modelsForRegion as glmCodingPlanModelsForRegion, glmCodingPlanPoolIdentity, glmCodingPlanPoolPath, glmCodingPlanPoolQuota, glmCodingPlanPoolStatus, glmCodingPlanSettingsSource, glmCooldownDecision, glmSubPathOf, inheritOverrideReason, inheritRouteDenialReason, inheritedRouteOf, inject, injectPrefs, installReasoningCollapseGuard, installRelayProbe, installSubagentModelAuthorization, isAdherenceOk, isAdoptedClaudeCredential, isAdoptedCredentialExpired, isAdoptedCredential as isAdoptedGlmCodingPlanCredential, isAdoptedZcodeCredential as isAdoptedGlmZcodeCredential, isAdoptedPoolCredential, isClaudeReasoningEffort, isClinePassPinMode, isGlmReasoningEffort, isMinimaxCodeReasoningEffort, isRefreshTokenRejected as isMinimaxCodeRefreshTokenRejected, isAuthenticationError as isOpenDesignAuthenticationError, isThinkingDisabledEffort, credentialPath$5 as kimiCodeCredentialPath, kimiCodeModelDef, modelSettingsPath$4 as kimiCodeModelSettingsPath, kimiCodePoolPath, listModelIds as listMinimaxCodeModelIds, loadCatalog as loadClaudeCatalog, loadProviderModels as loadCommandCodeModels, loadCatalog$1 as loadGlmCodingPlanCatalog, loadProviderModels$1 as loadKimiCodeModels, loadConfigCatalog as loadWorkBuddyModels, loginAndSave, mapCodexUsage, mapFinishReason, mapFinishReason$1 as mapOpenDesignFinishReason, mapUsage as mapOpenDesignUsage, mapUsage$1 as mapUsage, mergeGlmCodingPlanSettings, mergeUpstreams, accountFromCredentials as minimaxCodeAccountFromCredentials, accountHost as minimaxCodeAccountHost, agentBaseUrl as minimaxCodeAgentBaseUrl, authJsonPath as minimaxCodeAuthJsonPath, authStateJsonPath as minimaxCodeAuthStateJsonPath, catalogSize$1 as minimaxCodeCatalogSize, credentialIsFresh as minimaxCodeCredentialIsFresh, effortForModel as minimaxCodeEffortForModel, minimaxHomeDir as minimaxCodeHomeDir, maxMessageBodyBytes as minimaxCodeMaxMessageBodyBytes, maxOutputTokensFor$1 as minimaxCodeMaxOutputTokens, messagesUrl as minimaxCodeMessagesUrl, minimaxCodeModelDef, minimaxCodeModelIds, minimaxCodeModelName, modelRequestHeaders as minimaxCodeModelRequestHeaders, modelSettingsPath$5 as minimaxCodeModelSettingsPath, outputConfigFor as minimaxCodeOutputConfig, pluginCredentialPath as minimaxCodePluginCredentialPath, minimaxCodePoolIdentity, minimaxCodePoolPath, minimaxCodePoolStatus, quotaHostCandidates as minimaxCodeQuotaHostCandidates, quotaRequestHeaders as minimaxCodeQuotaRequestHeaders, subPathOf as minimaxCodeSubPathOf, tokenPlanRemainsUrl as minimaxCodeTokenPlanRemainsUrl, modelSettingsPath$6 as modelSettingsPath, normalizeDelegationToolNames, normalizeRegion as normalizeGlmCodingPlanRegion, normalizeInheritToolNames, normalizePinMode, normalizeRotationStrategy, normalizeSort, openChatStream as openClinePassChatStream, bearerFor as openDesignBearerFor, catalogEntry$1 as openDesignCatalogEntry, chatURL$1 as openDesignChatURL, credentialPath$6 as openDesignCredentialPath, credentialsIdentity as openDesignCredentialsIdentity, firstMessage as openDesignFirstMessage, openDesignKnownModelIds, modelSettingsPath$7 as openDesignModelSettingsPath, modelsURL as openDesignModelsURL, reasoningOf as openDesignReasoningOf, streamErrorCode as openDesignStreamErrorCode, openDesignVisibleModelIds, openChatStream$1 as openOpenDesignChatStream, opendesignAccountKey, opendesignPoolPath, parseAllowedRoutes, parseClaudeCredentialDocument, parseClaudeCredentials, parseClaudePoolData, parseUsagePayload as parseClaudeUsagePayload, parseClinePassCredentials, parseClinePassModelSettings, parseClinePassPoolData, parseCodexPoolData, parseCodexUsage, parseCommandCodePoolData, parseGlmCodingPlanCredentials, parseGlmCodingPlanPoolData, parseKimiCodePoolData, parseMinimaxCodeCredentials, parseMinimaxCodePoolData, parseTokenPlanQuota as parseMinimaxCodeQuota, parseAnthropicUsage as parseMinimaxCodeUsage, parseOpenDesignCredentials, parseOpenDesignModelSettings, parseOpenDesignPoolData, parseServerSentEvents as parseOpenDesignServerSentEvents, parseQoderCredentials, parseResponsesStream, parseRouting, parseServerSentEvents$1 as parseServerSentEvents, parseTier0, parseBilling as parseWorkBuddyBilling, parseConfigModels as parseWorkBuddyConfigModels, parseCredentialFile as parseWorkBuddyCredential, pinAdherence, pinWarnings, policyRoutesOf, pollWebLogin as pollMinimaxCodeLogin, probeConnection as probeClaudeConnection, processMinimaxStreamLine, qoderCatalogSize, credentialPath$7 as qoderCredentialPath, qoderCredentialsExpireAt, qoderCredentialsNeedRefresh, modelSettingsPath$8 as qoderModelSettingsPath, qoderPoolIdentity, qoderPoolPath, qoderPoolQuota, qoderPoolStatus, qoderPoolStatusSlice, qoderRefreshFailureStatus, qoderSettingsSource, qoderSubPathOf, readChildDescriptor, readClaudeCodeCredentials, readGlmResetAt, readQoderCacheStats, readStepCodeCacheStats, reasoningOf$1 as reasoningOf, redactToken as redactMinimaxCodeToken, refreshAntigravityToken, refreshAccessToken as refreshClaudeToken, refreshAccessToken$1 as refreshKimiCodeToken, refreshAccessToken$2 as refreshMinimaxCodeToken, refreshCredentials as refreshWorkBuddyCredentials, registerClaudePreferenceStore, registerClaudeRoutes, registerClinePassRoutes, registerCommandCodePreferenceStore, registerCommandCodeRoutes, registerGlmCodingPlanPreferenceStore, registerGlmCodingPlanRoutes, registerKimiCodePreferenceStore, registerKimiCodeRoutes, registerMinimaxCodePreferenceStore, registerMinimaxCodeRoutes, registerOpenDesignRoutes, registerQoderPreferenceStore, registerQoderRoutes, registerStepCodePreferenceStore, registerStepCodeRoutes, registerWorkBuddyPreferenceStore, registerWorkBuddyRoutes, relayProbeEnabled, relayProbeEnvFile, relayProbeEnvValue, relayProbeLogPath, rememberQoderCacheUsage, rememberStepCodeCacheUsage, requestDeviceAuthorization as requestKimiCodeDeviceAuthorization, requestDeviceAuthorization$1 as requestMinimaxCodeDeviceAuthorization, resetWebLogins as resetMinimaxCodeLogins, resolveEnabledModelIds as resolveClaudeEnabledModelIds, resolveLoginInput as resolveClaudeLoginInput, resolveClaudeModel, resolveGlmModel, resolveGuardOptions, resolveRegion as resolveKimiCodeRegion, resolveMinimaxCodeEnabledModelIds, resolveMinimaxCodeModelId, resolveQuotaCounts as resolveMinimaxCodeQuotaCounts, resolveModelInfo as resolveOpenDesignModelInfo, resolveOutputBudget as resolveOpenDesignOutputBudget, resolveWorkBuddyModel, revokeToken as revokeMinimaxCodeToken, saveApiKey as saveCommandCodeApiKey, scanCredentials as scanWorkBuddyCredentials, sendJSON as sendClinePassJSON, sendJSON$1 as sendOpenDesignJSON, serializeMessages, serializeMessages$1 as serializeOpenDesignMessages, setClaudeCliVersion, beginWebLogin$3 as startCommandCodeLogin, stepCodeCatalogSize, credentialPath$8 as stepCodeCredentialPath, stepCodeModelCatalogFrom, modelSettingsPath$9 as stepCodeModelSettingsPath, stepCodePoolIdentity, stepCodePoolPath, stepCodePoolQuota, stepCodePoolStatus, stepCodePoolStatusSlice, quotaCredentialPath as stepCodeQuotaCredentialPath, stepCodeSettingsSource, stepCodeSubPathOf, streamErrorCode$1 as streamErrorCode, subagentModelSelectionPreference, submitLoginInput as submitClaudeLoginInput, summarizeFailureBody as summarizeMinimaxCodeFailureBody, testConnection as testMinimaxCodeConnection, testApiKey as testOpenDesignApiKey, translate, translate$1 as translateOpenDesignStream, trimBase as trimClinePassBase, trimBase$1 as trimOpenDesignBase, unauthorizedRouteReason, validateAuthorizationScope, validateDelegationToolNames, validateInheritToolNames, verifyCodingPlanKey as verifyGlmCodingPlanKey, violationText, warmQoderCatalogOnStartup, withTimeout as withOpenDesignTimeout, modelSettingsPath$10 as workBuddyModelSettingsPath, modelsForRegion$1 as workBuddyModelsForRegion, zcodeCredentialsPath };
103854
+ export { AccountPoolCore, AccountPoolStore, AntigravityAdapter, CHANNEL_ALIASES, ADOPTED_CREDENTIAL_EXPIRED_HINT as CLAUDE_ADOPTED_CREDENTIAL_EXPIRED_HINT, API_BASE as CLAUDE_API_BASE, DEFAULT_VISIBLE_MODEL_IDS as CLAUDE_DEFAULT_VISIBLE_MODELS, FALLBACK_MODELS as CLAUDE_FALLBACK_MODELS, MESSAGES_PATH as CLAUDE_MESSAGES_PATH, CLAUDE_MODELS, CLAUDE_MODEL_IDS, PROVIDER_ID as CLAUDE_PROVIDER_ID, PROVIDER_NAME as CLAUDE_PROVIDER_NAME, QUOTA_CACHE_TTL_MS as CLAUDE_QUOTA_CACHE_TTL_MS, CLAUDE_REASONING_EFFORTS, ROUTE_PREFIX as CLAUDE_ROUTE_PREFIX, CLINE_PASS_API_KEY_ENV, DEFAULT_BASE_URL as CLINE_PASS_DEFAULT_BASE_URL, DEFAULT_MODELS as CLINE_PASS_DEFAULT_MODELS, MAX_UPSTREAMS as CLINE_PASS_MAX_UPSTREAMS, MODEL_CATALOG as CLINE_PASS_MODEL_CATALOG, POOL_COOLDOWN_MS as CLINE_PASS_POOL_COOLDOWN_MS, REASONING_EFFORTS as CLINE_PASS_REASONING_EFFORTS, CLINE_PASS_ROUTES, CLINE_PASS_ROUTE_PREFIX, CLINE_PASS_PROVIDER_ID as CLINE_PASS_ROUTE_PROVIDER_ID, CLINE_PASS_PROVIDER_NAME as CLINE_PASS_ROUTE_PROVIDER_NAME, ClaudeAccountPool, ClaudeAdapter, FileCredentialStore as ClaudeCredentialStore, FileModelSettingsStore as ClaudeModelSettingsStore, ClinePassAccountPool, ClinePassAdapter, FileCredentialStore$1 as ClinePassCredentialStore, ClinePassEngine, ClinePassModelSettingsStore, CodexAccountPool, CodexChatGptAdapter, CommandCodeAccountPool, CommandCodeAdapter, FileCredentialStore$2 as CommandCodeCredentialStore, FileModelSettingsStore$1 as CommandCodeModelSettingsStore, Config, DEFAULT_GUARD_OPTIONS, DEFAULT_PARENT_FORK_TOOLS, DEFAULT_SUBAGENT_INHERIT_TOOLS, FileCredentialStore$3 as FileCredentialStore, FileModelSettingsStore$2 as FileModelSettingsStore, GLM_CODING_PLAN_PREFERENCES_NAMESPACE, QUOTA_WINDOW_MINUTES as GLM_CODING_PLAN_QUOTA_WINDOW_MINUTES, GLM_CODING_PLAN_RETRY_POLICY_CONFIG, PROVIDER_ID$1 as GLM_CODING_PLAN_ROUTE_PROVIDER_ID, PROVIDER_NAME$1 as GLM_CODING_PLAN_ROUTE_PROVIDER_NAME, GLM_MODEL_CATALOG, GLM_MODEL_IDS, GLM_POOL_COOLDOWN_MS, GlmAdoptedCredentialRefreshError, GlmCodingPlanAccountPool, GlmCodingPlanAdapter, GlmCodingPlanCredentialStore, GlmCodingPlanModelSettingsStore, KIMI_CODE_MODELS, KIMI_CODE_RETRY_POLICY_CONFIG, KimiCodeAccountPool, KimiCodeAdapter, FileCredentialStore$4 as KimiCodeCredentialStore, FileModelSettingsStore$3 as KimiCodeModelSettingsStore, LinuxFileTokenStore, AGENT_LLM_PREFIX as MINIMAX_CODE_AGENT_LLM_PREFIX, DEFAULT_MAX_MESSAGE_BODY_BYTES as MINIMAX_CODE_MAX_MESSAGE_BODY_BYTES, MESSAGES_PATH$1 as MINIMAX_CODE_MESSAGES_PATH, MINIMAX_CODE_MODELS, PROBE_MODEL as MINIMAX_CODE_PROBE_MODEL, MINIMAX_CODE_PROVIDER_ID, MINIMAX_CODE_PROVIDER_NAME, MINIMAX_CODE_REASONING_EFFORTS, REGION_HOSTS as MINIMAX_CODE_REGION_HOSTS, MINIMAX_CODE_RETRY_POLICY_CONFIG, MINIMAX_CODE_ROUTE_PREFIX, MacKeychainTokenStore, MinimaxCodeAccountPool, MinimaxCodeAdapter, MinimaxCodeCheckinService, MinimaxCodeCredentialStore, MinimaxCodeModelSettingsStore, OAuthService, OPENDESIGN_API_KEY_ENV, OPENDESIGN_CONSOLE_URL, DEFAULT_BASE_URL$1 as OPENDESIGN_DEFAULT_BASE_URL, DEFAULT_CONTEXT_WINDOW as OPENDESIGN_DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_CONCURRENT_REQUESTS as OPENDESIGN_DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_MAX_TOKENS as OPENDESIGN_DEFAULT_MAX_TOKENS, DEFAULT_MODELS$1 as OPENDESIGN_DEFAULT_MODELS, DEFAULT_STREAM_IDLE_TIMEOUT_MS as OPENDESIGN_DEFAULT_STREAM_IDLE_TIMEOUT_MS, PROVIDER_ID$2 as OPENDESIGN_HOST_PROVIDER_ID, PROVIDER_NAME$2 as OPENDESIGN_HOST_PROVIDER_NAME, MODEL_CATALOG$1 as OPENDESIGN_MODEL_CATALOG, MODEL_PRICES_URL as OPENDESIGN_MODEL_PRICES_URL, NO_ANSWER_PHRASE as OPENDESIGN_NO_ANSWER_PHRASE, POOL_COOLDOWN_MS$1 as OPENDESIGN_POOL_COOLDOWN_MS, OPENDESIGN_PROVIDER_ID, OPENDESIGN_PROVIDER_NAME, REASONING_EFFORT_IDS as OPENDESIGN_REASONING_EFFORT_IDS, OPENDESIGN_ROUTES, OPENDESIGN_ROUTE_PREFIX, OpenDesignAccountPool, OpenDesignAdapter, FileCredentialStore$5 as OpenDesignCredentialStore, OpenDesignModelSettingsStore, ProxyManager, QODER_POOL_COOLDOWN_MS, QODER_PROVIDER_ID, QODER_PROVIDER_NAME, QODER_REGIONS, QODER_RETRY_POLICY_CONFIG, QODER_ROUTE_PREFIX, QoderAccountPool, QoderAdapter, QoderCredentialStore, QoderModelSettingsStore, RELAY_PROBE_ENV, RELAY_PROBE_FILE_ENV, RELAY_PROBE_FILE_NAME, RELAY_PROBE_MAX_BYTES, RELAY_SOURCE_KINDS, RESUME_HINT, RESUME_HINT_STRICT, RelayProbe, ResponsesClient, STEP_CODE_POOL_COOLDOWN_MS, STEP_CODE_PROFILES, STEP_CODE_PROVIDER_ID, STEP_CODE_PROVIDER_NAME, STEP_CODE_RETRY_POLICY_CONFIG, STEP_CODE_ROUTE_PREFIX, SUBAGENT_MODEL_SELECTION_NAMESPACE, SUBAGENT_POLICY_EVENT, SearchProviderSwitcher, StepCodeAccountPool, StepCodeAdapter, StepCodeCredentialRefreshError, StepCodeCredentialStore, StepCodeModelSettingsStore, StepCodeQuotaCredentialStore, UsageService, FALLBACK_MODELS$1 as WORKBUDDY_MODELS, WORKBUDDY_MODEL_IDS, WindowsDpapiTokenStore, WorkBuddyAdapter, WorkBuddyCheckinService, FileCredentialStore$6 as WorkBuddyCredentialStore, FileModelSettingsStore$4 as WorkBuddyModelSettingsStore, adoptZcodeSignIn as adoptGlmZcodeSignIn, adoptedPoolAccountKey, apply, assertRequestBodyFits as assertMinimaxCodeBodyFits, assertStreamComplete as assertMinimaxCodeStreamComplete, auditChildRoutes, auditedRoutesOf, authorizedRoutesFor, beginLogin as beginClaudeLogin, beginWebLogin as beginKimiCodeLogin, beginWebLogin$1 as beginMinimaxCodeLogin, beginWebLogin$2 as beginWebLogin, buildAttempts, buildClaudeModelOptions, buildClinePassBody, buildGlmRequestPlan, buildMinimaxCodeModelOptions, buildMinimaxRequest, buildOpenDesignBody, cachedQoderModelCatalog, cachedStepCodeModelCatalog, cancelLogin as cancelClaudeLogin, cancelWebLogin as cancelMinimaxCodeLogin, catalogModelOptions, channelNameFor, childRoutesOf, clampOutputToContext as clampMinimaxCodeOutputToContext, classifyFailure as classifyClaudeFailure, classifyKimiFailure, classifyMinimaxFailure, classifyUpstreamError, classifyFailure$1 as classifyWorkBuddyFailure, claudeCliVersion, claudeCodeCredentialPaths, claudeCodeCredentialPresence, codeForFailure as claudeCodeForFailure, credentialPath as claudeCredentialPath, defaultContextWindowFor as claudeDefaultContextWindow, maxOutputTokensFor as claudeMaxOutputTokens, claudeModelCanDisableThinking, modelSettingsPath as claudeModelSettingsPath, claudeModelSupportsImage, claudeModelSupportsTemperature, claudePoolPath, claudeReasoningEfforts, claudeThinkingMode, toLlmError as claudeToLlmError, clearCachedQuota, clearCachedCatalog as clearClaudeCatalog, clearCachedQuota$1 as clearClaudeQuota, clearCachedQuota$2 as clearCommandCodeQuota, clearCachedQuota$3 as clearKimiCodeQuota, clearCachedQuota$4 as clearMinimaxCodeQuota, clearCachedCatalog$1 as clearWorkBuddyCatalog, clearCachedQuota$5 as clearWorkBuddyQuota, clinePassAccountKey, clinePassAccountQuota, catalogEntry as clinePassCatalogEntry, chatCompletion as clinePassChatCompletion, chatURL as clinePassChatURL, credentialPath$1 as clinePassCredentialPath, defaultPin as clinePassDefaultPin, clinePassKnownModelIds, modelSettingsPath$1 as clinePassModelSettingsPath, clinePassPoolPath, clinePassVisibleModelIds, clinePassWindowDurationMins, clinePassWindowLabel, closeMinimaxStream, codexPoolPath, collapseScore, commandCodeAccountKey, credentialPath$2 as commandCodeCredentialPath, modelSettingsPath$2 as commandCodeModelSettingsPath, commandCodePoolPath, contextWindowForModel, convergeGlmEffort, createAntigravityImageTool, createClinePassLine, createClinePassStore, createCodexFetchProvider, createCodexImageTool, createCodexSearchProvider, createFileRelayProbeSink, createMinimaxCodeAccountsHandler, createMessage as createMinimaxCodeMessage, createPkcePair as createMinimaxCodePkcePair, createStreamState as createMinimaxCodeStreamState, createOpenDesignLine, createPlatformTokenStore, createSubagentAuthorization, credentialPath$3 as credentialPath, credentialsFromAdopt, credentialsFromCliLogin, defaultOpenDesignModelSettings, delegationDenialReason, delegationModeOf, describeCredentials as describeMinimaxCodeCredentials, detectSystemProxy, dshHomeDir, effectiveAllowParentFork, effectiveRouteOf, ensureAccessToken as ensureClaudeAccessToken, ensureAccessToken$1 as ensureKimiCodeAccessToken, ensureAccessToken$2 as ensureMinimaxCodeAccessToken, extractAvailableProviders, fetchAccountQuota, fetchAccountQuota$1 as fetchClaudeQuota, fetchGatewayCatalog as fetchClinePassGatewayCatalog, fetchOfficialModels as fetchClinePassOfficialModels, fetchUsageLimits as fetchClinePassUsageLimits, fetchAccountQuota$2 as fetchCommandCodeQuota, fetchGlmQuota, fetchAccountQuota$3 as fetchKimiCodeQuota, fetchUserInfo as fetchKimiCodeUserInfo, fetchTokenPlanQuota as fetchMinimaxCodeQuota, fetchGatewayCatalog$1 as fetchOpenDesignGatewayCatalog, fetchAccountQuota$4 as fetchWorkBuddyQuota, getCachedQuota as getCachedGlmCodingPlanQuota, getCachedQuota$1 as getCachedQuota, getLoginStatus as getClaudeLoginStatus, getCachedQuota$2 as getClaudeQuota, getClaudeWebStatus, getClinePassWebStatus, getWebLoginStatus as getCommandCodeLoginStatus, getCachedQuota$3 as getCommandCodeQuota, getCommandCodeWebStatus, getGlmCodingPlanStatus, getWebLoginStatus$1 as getKimiCodeLoginStatus, getCachedQuota$4 as getKimiCodeQuota, getKimiCodeWebStatus, getWebLogin as getMinimaxCodeLogin, getCachedQuota$5 as getMinimaxCodeQuota, getMinimaxCodeWebStatus, getOpenDesignWebStatus, getQoderStatus, getStepCodeStatus, getCachedQuota$6 as getWorkBuddyQuota, getWorkBuddyWebStatus, glmCatalogSize, authorizeUrl as glmCodingPlanAuthorizeUrl, catalogSize as glmCodingPlanCatalogCount, credentialPath$4 as glmCodingPlanCredentialPath, modelSettingsPath$3 as glmCodingPlanModelSettingsPath, modelsForRegion as glmCodingPlanModelsForRegion, glmCodingPlanPoolIdentity, glmCodingPlanPoolPath, glmCodingPlanPoolQuota, glmCodingPlanPoolStatus, glmCodingPlanSettingsSource, glmCooldownDecision, glmSubPathOf, inheritOverrideReason, inheritRouteDenialReason, inheritedRouteOf, inject, injectPrefs, installReasoningCollapseGuard, installRelayProbe, installSubagentModelAuthorization, isAdherenceOk, isAdoptedClaudeCredential, isAdoptedCredentialExpired, isAdoptedCredential as isAdoptedGlmCodingPlanCredential, isAdoptedZcodeCredential as isAdoptedGlmZcodeCredential, isAdoptedPoolCredential, isClaudeReasoningEffort, isClinePassPinMode, isGlmReasoningEffort, isMinimaxCodeReasoningEffort, isRefreshTokenRejected as isMinimaxCodeRefreshTokenRejected, isAuthenticationError as isOpenDesignAuthenticationError, isThinkingDisabledEffort, credentialPath$5 as kimiCodeCredentialPath, kimiCodeModelDef, modelSettingsPath$4 as kimiCodeModelSettingsPath, kimiCodePoolPath, listModelIds as listMinimaxCodeModelIds, loadCatalog as loadClaudeCatalog, loadProviderModels as loadCommandCodeModels, loadCatalog$1 as loadGlmCodingPlanCatalog, loadProviderModels$1 as loadKimiCodeModels, loadConfigCatalog as loadWorkBuddyModels, loginAndSave, mapCodexUsage, mapFinishReason, mapFinishReason$1 as mapOpenDesignFinishReason, mapUsage as mapOpenDesignUsage, mapUsage$1 as mapUsage, mergeGlmCodingPlanSettings, mergeUpstreams, accountFromCredentials as minimaxCodeAccountFromCredentials, accountHost as minimaxCodeAccountHost, agentBaseUrl as minimaxCodeAgentBaseUrl, authJsonPath as minimaxCodeAuthJsonPath, authStateJsonPath as minimaxCodeAuthStateJsonPath, catalogSize$1 as minimaxCodeCatalogSize, credentialIsFresh as minimaxCodeCredentialIsFresh, effortForModel as minimaxCodeEffortForModel, minimaxHomeDir as minimaxCodeHomeDir, maxMessageBodyBytes as minimaxCodeMaxMessageBodyBytes, maxOutputTokensFor$1 as minimaxCodeMaxOutputTokens, messagesUrl as minimaxCodeMessagesUrl, minimaxCodeModelDef, minimaxCodeModelIds, minimaxCodeModelName, modelRequestHeaders as minimaxCodeModelRequestHeaders, modelSettingsPath$5 as minimaxCodeModelSettingsPath, outputConfigFor as minimaxCodeOutputConfig, pluginCredentialPath as minimaxCodePluginCredentialPath, minimaxCodePoolIdentity, minimaxCodePoolPath, minimaxCodePoolStatus, quotaHostCandidates as minimaxCodeQuotaHostCandidates, quotaRequestHeaders as minimaxCodeQuotaRequestHeaders, subPathOf as minimaxCodeSubPathOf, tokenPlanRemainsUrl as minimaxCodeTokenPlanRemainsUrl, modelSettingsPath$6 as modelSettingsPath, normalizeDelegationToolNames, normalizeRegion as normalizeGlmCodingPlanRegion, normalizeInheritToolNames, normalizePinMode, normalizeRotationStrategy, normalizeSort, openChatStream as openClinePassChatStream, bearerFor as openDesignBearerFor, catalogEntry$1 as openDesignCatalogEntry, chatURL$1 as openDesignChatURL, credentialPath$6 as openDesignCredentialPath, credentialsIdentity as openDesignCredentialsIdentity, firstMessage as openDesignFirstMessage, openDesignKnownModelIds, modelSettingsPath$7 as openDesignModelSettingsPath, modelsURL as openDesignModelsURL, reasoningOf as openDesignReasoningOf, streamErrorCode as openDesignStreamErrorCode, openDesignVisibleModelIds, openChatStream$1 as openOpenDesignChatStream, opendesignAccountKey, opendesignPoolPath, parseAllowedRoutes, parseClaudeCredentialDocument, parseClaudeCredentials, parseClaudePoolData, parseUsagePayload as parseClaudeUsagePayload, parseClinePassCredentials, parseClinePassModelSettings, parseClinePassPoolData, parseCodexPoolData, parseCodexUsage, parseCommandCodePoolData, parseGlmCodingPlanCredentials, parseGlmCodingPlanPoolData, parseKimiCodePoolData, parseMinimaxCodeCredentials, parseMinimaxCodePoolData, parseTokenPlanQuota as parseMinimaxCodeQuota, parseAnthropicUsage as parseMinimaxCodeUsage, parseOpenDesignCredentials, parseOpenDesignModelSettings, parseOpenDesignPoolData, parseServerSentEvents as parseOpenDesignServerSentEvents, parseQoderCredentials, parseResponsesStream, parseRouting, parseServerSentEvents$1 as parseServerSentEvents, parseTier0, parseBilling as parseWorkBuddyBilling, parseConfigModels as parseWorkBuddyConfigModels, parseCredentialFile as parseWorkBuddyCredential, pinAdherence, pinWarnings, policyRoutesOf, pollWebLogin as pollMinimaxCodeLogin, probeConnection as probeClaudeConnection, processMinimaxStreamLine, qoderCatalogSize, credentialPath$7 as qoderCredentialPath, qoderCredentialsExpireAt, qoderCredentialsNeedRefresh, modelSettingsPath$8 as qoderModelSettingsPath, qoderPoolIdentity, qoderPoolPath, qoderPoolQuota, qoderPoolStatus, qoderPoolStatusSlice, qoderRefreshFailureStatus, qoderSettingsSource, qoderSubPathOf, readChildDescriptor, readClaudeCodeCredentials, readGlmResetAt, readQoderCacheStats, readStepCodeCacheStats, reasoningOf$1 as reasoningOf, redactToken as redactMinimaxCodeToken, refreshAntigravityToken, refreshAccessToken as refreshClaudeToken, refreshAccessToken$1 as refreshKimiCodeToken, refreshAccessToken$2 as refreshMinimaxCodeToken, refreshCredentials as refreshWorkBuddyCredentials, registerClaudePreferenceStore, registerClaudeRoutes, registerClinePassRoutes, registerCommandCodePreferenceStore, registerCommandCodeRoutes, registerGlmCodingPlanPreferenceStore, registerGlmCodingPlanRoutes, registerKimiCodePreferenceStore, registerKimiCodeRoutes, registerMinimaxCodePreferenceStore, registerMinimaxCodeRoutes, registerOpenDesignRoutes, registerQoderPreferenceStore, registerQoderRoutes, registerStepCodePreferenceStore, registerStepCodeRoutes, registerWorkBuddyPreferenceStore, registerWorkBuddyRoutes, relayProbeEnabled, relayProbeEnvFile, relayProbeEnvValue, relayProbeLogPath, rememberQoderCacheUsage, rememberStepCodeCacheUsage, requestDeviceAuthorization as requestKimiCodeDeviceAuthorization, requestDeviceAuthorization$1 as requestMinimaxCodeDeviceAuthorization, resetWebLogins as resetMinimaxCodeLogins, resolveEnabledModelIds as resolveClaudeEnabledModelIds, resolveLoginInput as resolveClaudeLoginInput, resolveClaudeModel, resolveGlmModel, resolveGuardOptions, resolveRegion as resolveKimiCodeRegion, resolveMinimaxCodeEnabledModelIds, resolveMinimaxCodeModelId, resolveQuotaCounts as resolveMinimaxCodeQuotaCounts, resolveModelInfo as resolveOpenDesignModelInfo, resolveOutputBudget as resolveOpenDesignOutputBudget, resolveWorkBuddyModel, revokeToken as revokeMinimaxCodeToken, saveApiKey as saveCommandCodeApiKey, scanCredentials as scanWorkBuddyCredentials, sendJSON as sendClinePassJSON, sendJSON$1 as sendOpenDesignJSON, serializeMessages, serializeMessages$1 as serializeOpenDesignMessages, setClaudeCliVersion, beginWebLogin$3 as startCommandCodeLogin, stepCodeCatalogSize, credentialPath$8 as stepCodeCredentialPath, stepCodeModelCatalogFrom, modelSettingsPath$9 as stepCodeModelSettingsPath, stepCodePoolIdentity, stepCodePoolPath, stepCodePoolQuota, stepCodePoolStatus, stepCodePoolStatusSlice, quotaCredentialPath as stepCodeQuotaCredentialPath, stepCodeSettingsSource, stepCodeSubPathOf, streamErrorCode$1 as streamErrorCode, subagentModelSelectionPreference, submitLoginInput as submitClaudeLoginInput, summarizeFailureBody as summarizeMinimaxCodeFailureBody, testConnection as testMinimaxCodeConnection, testApiKey as testOpenDesignApiKey, translate, translate$1 as translateOpenDesignStream, trimBase as trimClinePassBase, trimBase$1 as trimOpenDesignBase, unauthorizedRouteReason, validateAuthorizationScope, validateDelegationToolNames, validateInheritToolNames, verifyCodingPlanKey as verifyGlmCodingPlanKey, violationText, warmQoderCatalogOnStartup, withTimeout as withOpenDesignTimeout, modelSettingsPath$10 as workBuddyModelSettingsPath, modelsForRegion$1 as workBuddyModelsForRegion, zcodeCredentialsPath };