@eddyskywalker/dsh-chatgpt-subscription 0.54.0 → 0.55.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.
- package/CHANGELOG.md +12 -0
- package/lib/client.js +156 -6
- package/lib/client.js.map +1 -1
- package/lib/{entry-progress-updates-BEkdyDZU.js → entry-progress-updates-CxQewio9.js} +4 -2
- package/lib/index.js +933 -169
- package/lib/progress-updates.js +1 -1
- package/lib/types/client/common/host-locale-mirror.d.ts +24 -0
- package/lib/types/client/common/host-locale-mirror.d.ts.map +1 -0
- package/lib/types/client/hub/HubOverview.d.ts.map +1 -1
- package/lib/types/client/hub/providers.d.ts +18 -1
- package/lib/types/client/hub/providers.d.ts.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/locales-ru/hub.d.ts.map +1 -1
- package/lib/types/client/locales-ru/progress-updates.d.ts.map +1 -1
- package/lib/types/client/locales.d.ts +27 -1
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/progress-updates/locales.d.ts +5 -2
- package/lib/types/client/progress-updates/locales.d.ts.map +1 -1
- package/lib/types/client/progress-updates/settings-binding.d.ts +1 -1
- package/lib/types/client/progress-updates/settings-binding.d.ts.map +1 -1
- package/lib/types/client/progress-updates/settings-section.d.ts.map +1 -1
- package/lib/types/compat.d.ts +1 -1
- package/lib/types/host/adapter.d.ts.map +1 -1
- package/lib/types/host/antigravity/adapter.d.ts.map +1 -1
- package/lib/types/host/claude/adapter.d.ts.map +1 -1
- package/lib/types/host/cline-pass/adapter.d.ts.map +1 -1
- package/lib/types/host/codex-account-pool.d.ts.map +1 -1
- package/lib/types/host/command-code/adapter.d.ts.map +1 -1
- package/lib/types/host/common/account-pool.d.ts.map +1 -1
- package/lib/types/host/common/i18n/en.d.ts +9 -0
- package/lib/types/host/common/i18n/en.d.ts.map +1 -0
- package/lib/types/host/common/i18n/index.d.ts +13 -0
- package/lib/types/host/common/i18n/index.d.ts.map +1 -0
- package/lib/types/host/common/i18n/provider-name.d.ts +10 -0
- package/lib/types/host/common/i18n/provider-name.d.ts.map +1 -0
- package/lib/types/host/common/i18n/ru.d.ts +10 -0
- package/lib/types/host/common/i18n/ru.d.ts.map +1 -0
- package/lib/types/host/common/i18n/runtime.d.ts +54 -0
- package/lib/types/host/common/i18n/runtime.d.ts.map +1 -0
- package/lib/types/host/common/i18n/t.d.ts +38 -0
- package/lib/types/host/common/i18n/t.d.ts.map +1 -0
- package/lib/types/host/common/i18n/zh.d.ts +167 -0
- package/lib/types/host/common/i18n/zh.d.ts.map +1 -0
- package/lib/types/host/glm-coding-plan/adapter.d.ts.map +1 -1
- package/lib/types/host/glm-coding-plan/client.d.ts.map +1 -1
- package/lib/types/host/glm-coding-plan/oauth.d.ts.map +1 -1
- package/lib/types/host/glm-coding-plan/routes.d.ts.map +1 -1
- package/lib/types/host/kimi-code/adapter.d.ts.map +1 -1
- package/lib/types/host/minimax-code/adapter.d.ts.map +1 -1
- package/lib/types/host/ollama/adapter.d.ts.map +1 -1
- package/lib/types/host/opendesign/adapter.d.ts.map +1 -1
- package/lib/types/host/progress-updates/prompt.d.ts +1 -1
- package/lib/types/host/progress-updates/prompt.d.ts.map +1 -1
- package/lib/types/host/qoder/account-pool.d.ts.map +1 -1
- package/lib/types/host/qoder/adapter.d.ts.map +1 -1
- package/lib/types/host/qoder/client.d.ts.map +1 -1
- package/lib/types/host/qoder/oauth.d.ts.map +1 -1
- package/lib/types/host/qoder/routes.d.ts.map +1 -1
- package/lib/types/host/qoder/token-store.d.ts.map +1 -1
- package/lib/types/host/routes.d.ts.map +1 -1
- package/lib/types/host/step-code/account-pool.d.ts.map +1 -1
- package/lib/types/host/step-code/adapter.d.ts.map +1 -1
- package/lib/types/host/step-code/oauth.d.ts.map +1 -1
- package/lib/types/host/step-code/routes.d.ts.map +1 -1
- package/lib/types/host/step-code/token-store.d.ts.map +1 -1
- package/lib/types/host/workbuddy/account-pool.d.ts.map +1 -1
- package/lib/types/host/workbuddy/adapter.d.ts.map +1 -1
- package/lib/types/host/workbuddy/oauth.d.ts.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/shared/i18n-contracts.d.ts +35 -0
- package/lib/types/shared/i18n-contracts.d.ts.map +1 -0
- package/locale/progress-updates/ru.json +6 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as resolveProgressUpdatesSettings, n as attachProgressSettings } from "./entry-progress-updates-
|
|
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.
|
|
810
|
+
const PLUGIN_VERSION = "0.55.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(
|
|
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 ??
|
|
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(
|
|
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 ??
|
|
2640
|
-
if (!this.isCredentialUsable(target)) throw new LlmError(
|
|
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 ?? "
|
|
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 ?? "
|
|
2735
|
-
if (!this.isCredentialUsable(account)) throw new PoolAccountUnavailableError(this.hooks.displayName
|
|
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) ??
|
|
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 ?
|
|
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 ??
|
|
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("
|
|
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: "
|
|
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("
|
|
4711
|
-
if (this.refresherRef.current === void 0) throw new Error("
|
|
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(
|
|
9554
|
-
throw new LlmError(
|
|
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 });
|
|
@@ -14521,6 +15193,15 @@ function registerRoutes(ctx, oauth, usage, preferences, proxyManager, searchSwit
|
|
|
14521
15193
|
};
|
|
14522
15194
|
try {
|
|
14523
15195
|
switch (url.pathname) {
|
|
15196
|
+
case `${ROUTE_PREFIX$5}/i18n/locale`: {
|
|
15197
|
+
const runtime = hostLocaleRuntime();
|
|
15198
|
+
const tag = field(body, "locale");
|
|
15199
|
+
json(response, {
|
|
15200
|
+
ok: true,
|
|
15201
|
+
value: { locale: runtime === void 0 ? currentLocale() : runtime.set(tag ?? void 0) }
|
|
15202
|
+
});
|
|
15203
|
+
return;
|
|
15204
|
+
}
|
|
14524
15205
|
case `${ROUTE_PREFIX$5}/login/start`:
|
|
14525
15206
|
json(response, {
|
|
14526
15207
|
ok: true,
|
|
@@ -22471,7 +23152,7 @@ var CommandCodeAdapter = class extends LlmAdapter {
|
|
|
22471
23152
|
providerInfo(provider) {
|
|
22472
23153
|
return {
|
|
22473
23154
|
id: provider,
|
|
22474
|
-
name: PROVIDER_NAME$10
|
|
23155
|
+
name: localizedProviderName(provider, PROVIDER_NAME$10)
|
|
22475
23156
|
};
|
|
22476
23157
|
}
|
|
22477
23158
|
providerRetryPolicy() {
|
|
@@ -25083,7 +25764,7 @@ var OllamaAdapter = class extends LlmAdapter {
|
|
|
25083
25764
|
providerInfo(provider) {
|
|
25084
25765
|
return {
|
|
25085
25766
|
id: provider,
|
|
25086
|
-
name: PROVIDER_NAME$9
|
|
25767
|
+
name: localizedProviderName(provider, PROVIDER_NAME$9)
|
|
25087
25768
|
};
|
|
25088
25769
|
}
|
|
25089
25770
|
providerRetryPolicy() {
|
|
@@ -35947,7 +36628,7 @@ var KimiCodeAdapter = class extends LlmAdapter {
|
|
|
35947
36628
|
providerInfo(provider) {
|
|
35948
36629
|
return {
|
|
35949
36630
|
id: provider,
|
|
35950
|
-
name: PROVIDER_NAME$8
|
|
36631
|
+
name: localizedProviderName(provider, PROVIDER_NAME$8)
|
|
35951
36632
|
};
|
|
35952
36633
|
}
|
|
35953
36634
|
providerRetryPolicy() {
|
|
@@ -43289,7 +43970,7 @@ var MinimaxCodeAdapter = class extends LlmAdapter {
|
|
|
43289
43970
|
providerInfo(provider) {
|
|
43290
43971
|
return {
|
|
43291
43972
|
id: provider,
|
|
43292
|
-
name: PROVIDER_NAME$7
|
|
43973
|
+
name: localizedProviderName(provider, PROVIDER_NAME$7)
|
|
43293
43974
|
};
|
|
43294
43975
|
}
|
|
43295
43976
|
providerRetryPolicy() {
|
|
@@ -54289,7 +54970,7 @@ var ClaudeAdapter = class ClaudeAdapter extends LlmAdapter {
|
|
|
54289
54970
|
providerInfo(provider) {
|
|
54290
54971
|
return {
|
|
54291
54972
|
id: provider,
|
|
54292
|
-
name: PROVIDER_NAME
|
|
54973
|
+
name: localizedProviderName(provider, PROVIDER_NAME)
|
|
54293
54974
|
};
|
|
54294
54975
|
}
|
|
54295
54976
|
providerRetryPolicy() {
|
|
@@ -60091,7 +60772,7 @@ function glmOpenAiProbeHeaders(codingPlanKey) {
|
|
|
60091
60772
|
*/
|
|
60092
60773
|
function quotaRequestHeaders$1(codingPlanKey) {
|
|
60093
60774
|
const key = codingPlanKey.trim();
|
|
60094
|
-
if (key === "") throw new Error(failure$1("
|
|
60775
|
+
if (key === "") throw new Error(failure$1(t("glm.quotaNeedsKey", { provider: PROVIDER_NAME$1 })));
|
|
60095
60776
|
return {
|
|
60096
60777
|
"content-type": "application/json",
|
|
60097
60778
|
accept: "application/json",
|
|
@@ -60179,7 +60860,10 @@ async function fetchCatalog(region, codingPlanKey, options = {}) {
|
|
|
60179
60860
|
try {
|
|
60180
60861
|
payload = JSON.parse(text);
|
|
60181
60862
|
} catch {
|
|
60182
|
-
throw new Error(failure$1("
|
|
60863
|
+
throw new Error(failure$1(t("glm.catalogNotJson", {
|
|
60864
|
+
provider: PROVIDER_NAME$1,
|
|
60865
|
+
url
|
|
60866
|
+
})));
|
|
60183
60867
|
}
|
|
60184
60868
|
return parseCatalogListing(payload, region);
|
|
60185
60869
|
}
|
|
@@ -60434,7 +61118,7 @@ async function fetchSubscriptionPlan(region, codingPlanKey, options = {}) {
|
|
|
60434
61118
|
* 所以它同步抛出,与「上游读失败返回 `error`」那条路径分开。
|
|
60435
61119
|
*/
|
|
60436
61120
|
async function fetchGlmQuota(region, codingPlanKey, options = {}) {
|
|
60437
|
-
if (codingPlanKey.trim() === "") throw new Error(failure$1("
|
|
61121
|
+
if (codingPlanKey.trim() === "") throw new Error(failure$1(t("glm.quotaNeedsKeyShort", { provider: PROVIDER_NAME$1 })));
|
|
60438
61122
|
const accountId = options.accountId;
|
|
60439
61123
|
const cached = quotaEntryFor(accountId);
|
|
60440
61124
|
if (options.force !== true && cached !== null && Date.now() - cached.at < 12e4) return {
|
|
@@ -60460,7 +61144,7 @@ async function fetchGlmQuota(region, codingPlanKey, options = {}) {
|
|
|
60460
61144
|
} catch (error) {
|
|
60461
61145
|
return {
|
|
60462
61146
|
snapshot: null,
|
|
60463
|
-
error: failure$1("
|
|
61147
|
+
error: failure$1(t("glm.quotaUnreachable", { detail: error instanceof Error ? error.message : String(error) })),
|
|
60464
61148
|
fromCache: false
|
|
60465
61149
|
};
|
|
60466
61150
|
}
|
|
@@ -60469,7 +61153,7 @@ async function fetchGlmQuota(region, codingPlanKey, options = {}) {
|
|
|
60469
61153
|
const detail = summarize(text);
|
|
60470
61154
|
return {
|
|
60471
61155
|
snapshot: null,
|
|
60472
|
-
error: failure$1("
|
|
61156
|
+
error: failure$1(t("glm.quotaHttp", { status: response.status })) + (detail === "" ? "" : ":" + detail),
|
|
60473
61157
|
fromCache: false
|
|
60474
61158
|
};
|
|
60475
61159
|
}
|
|
@@ -60479,7 +61163,7 @@ async function fetchGlmQuota(region, codingPlanKey, options = {}) {
|
|
|
60479
61163
|
} catch {
|
|
60480
61164
|
return {
|
|
60481
61165
|
snapshot: null,
|
|
60482
|
-
error: failure$1("
|
|
61166
|
+
error: failure$1(t("glm.quotaNotJson")),
|
|
60483
61167
|
fromCache: false
|
|
60484
61168
|
};
|
|
60485
61169
|
}
|
|
@@ -60492,7 +61176,7 @@ async function fetchGlmQuota(region, codingPlanKey, options = {}) {
|
|
|
60492
61176
|
});
|
|
60493
61177
|
if (snapshot === null) return {
|
|
60494
61178
|
snapshot: null,
|
|
60495
|
-
error: failure$1("
|
|
61179
|
+
error: failure$1(t("glm.quotaNoWindow")),
|
|
60496
61180
|
fromCache: false
|
|
60497
61181
|
};
|
|
60498
61182
|
return {
|
|
@@ -61482,18 +62166,24 @@ function glmCooldownDecision(input) {
|
|
|
61482
62166
|
if (resetsAt !== void 0) return {
|
|
61483
62167
|
cooldown: true,
|
|
61484
62168
|
durationMs: Math.max(3e4, resetsAt - Date.now()),
|
|
61485
|
-
reason: "
|
|
62169
|
+
reason: t("glm.cooldownUntilReset", {
|
|
62170
|
+
provider: PROVIDER_NAME$1,
|
|
62171
|
+
at: new Date(resetsAt).toISOString()
|
|
62172
|
+
})
|
|
61486
62173
|
};
|
|
61487
62174
|
const after = input.headers === void 0 ? void 0 : retryAfterMs$1(input.headers);
|
|
61488
62175
|
if (after !== void 0 && after > 0) return {
|
|
61489
62176
|
cooldown: true,
|
|
61490
62177
|
durationMs: after,
|
|
61491
|
-
reason: "
|
|
62178
|
+
reason: t("glm.cooldownRetryAfter", {
|
|
62179
|
+
provider: PROVIDER_NAME$1,
|
|
62180
|
+
seconds: Math.ceil(after / 1e3)
|
|
62181
|
+
})
|
|
61492
62182
|
};
|
|
61493
62183
|
return {
|
|
61494
62184
|
cooldown: true,
|
|
61495
62185
|
durationMs: GLM_POOL_COOLDOWN_MS,
|
|
61496
|
-
reason: "
|
|
62186
|
+
reason: t("glm.cooldownNoReset", { provider: PROVIDER_NAME$1 })
|
|
61497
62187
|
};
|
|
61498
62188
|
}
|
|
61499
62189
|
/**
|
|
@@ -61560,7 +62250,7 @@ var GlmCodingPlanAdapter = class extends LlmAdapter {
|
|
|
61560
62250
|
providerInfo(provider) {
|
|
61561
62251
|
return {
|
|
61562
62252
|
id: provider,
|
|
61563
|
-
name: PROVIDER_NAME$1
|
|
62253
|
+
name: localizedProviderName(provider, PROVIDER_NAME$1)
|
|
61564
62254
|
};
|
|
61565
62255
|
}
|
|
61566
62256
|
providerRetryPolicy() {
|
|
@@ -61619,7 +62309,7 @@ var GlmCodingPlanAdapter = class extends LlmAdapter {
|
|
|
61619
62309
|
}));
|
|
61620
62310
|
}
|
|
61621
62311
|
async resolveModel(provider, model, signal) {
|
|
61622
|
-
if (signal?.aborted) throw new LlmError("
|
|
62312
|
+
if (signal?.aborted) throw new LlmError(t("glm.modelResolveAborted", { provider: PROVIDER_NAME$1 }), "ABORTED");
|
|
61623
62313
|
const settings = await this.settings();
|
|
61624
62314
|
const region = (await this.credentialFor().catch(() => null))?.credentials.codingPlan.region ?? "intl";
|
|
61625
62315
|
const entry = resolveGlmModel(model, this.catalog(region));
|
|
@@ -61688,8 +62378,11 @@ var GlmCodingPlanAdapter = class extends LlmAdapter {
|
|
|
61688
62378
|
});
|
|
61689
62379
|
activity?.pulse();
|
|
61690
62380
|
} catch (error) {
|
|
61691
|
-
if (signal.aborted) throw new LlmError("
|
|
61692
|
-
throw new LlmError("
|
|
62381
|
+
if (signal.aborted) throw new LlmError(t("glm.requestAborted", { provider: PROVIDER_NAME$1 }), "ABORTED", { cause: error });
|
|
62382
|
+
throw new LlmError(t("glm.requestFailed", {
|
|
62383
|
+
provider: PROVIDER_NAME$1,
|
|
62384
|
+
detail: error instanceof Error ? error.message : String(error)
|
|
62385
|
+
}), "TRANSPORT", { cause: error });
|
|
61693
62386
|
}
|
|
61694
62387
|
if (response.ok) break;
|
|
61695
62388
|
const detail = await response.text().catch(() => "");
|
|
@@ -61726,8 +62419,8 @@ var GlmCodingPlanAdapter = class extends LlmAdapter {
|
|
|
61726
62419
|
throw failure;
|
|
61727
62420
|
}
|
|
61728
62421
|
const settled = plan;
|
|
61729
|
-
if (response === void 0) throw new LlmError("
|
|
61730
|
-
if (response.body === null) throw new LlmError("
|
|
62422
|
+
if (response === void 0) throw new LlmError(t("glm.noResponse", { provider: PROVIDER_NAME$1 }), "PROVIDER_ERROR");
|
|
62423
|
+
if (response.body === null) throw new LlmError(t("glm.emptyBody", { provider: PROVIDER_NAME$1 }), "PROVIDER_ERROR");
|
|
61731
62424
|
const reader = response.body.getReader();
|
|
61732
62425
|
const decoder = new TextDecoder();
|
|
61733
62426
|
let buffer = "";
|
|
@@ -61750,7 +62443,7 @@ var GlmCodingPlanAdapter = class extends LlmAdapter {
|
|
|
61750
62443
|
buffer += decoder.decode();
|
|
61751
62444
|
if (buffer.trim() !== "") for (const line of buffer.split("\n")) for (const chunk of processGlmAnthropicStreamLine(line, state)) yield chunk;
|
|
61752
62445
|
if (state.finished) return;
|
|
61753
|
-
if (!glmStreamHasContent(state)) throw new LlmError("
|
|
62446
|
+
if (!glmStreamHasContent(state)) throw new LlmError(t("glm.anthropicEmpty", { provider: PROVIDER_NAME$1 }), "PROVIDER_ERROR");
|
|
61754
62447
|
assertGlmStreamComplete(state);
|
|
61755
62448
|
for (const chunk of closeGlmAnthropicStream(state)) yield chunk;
|
|
61756
62449
|
} finally {
|
|
@@ -62308,42 +63001,48 @@ async function pollCliFlow(flow, options = {}) {
|
|
|
62308
63001
|
if (options.signal?.aborted === true) throw error;
|
|
62309
63002
|
return {
|
|
62310
63003
|
kind: "pending",
|
|
62311
|
-
progress: "
|
|
63004
|
+
progress: t("glm.connectingUpstream")
|
|
62312
63005
|
};
|
|
62313
63006
|
}
|
|
62314
63007
|
const payload = await response.json().catch(() => void 0);
|
|
62315
63008
|
if (response.status >= 500) return {
|
|
62316
63009
|
kind: "pending",
|
|
62317
|
-
progress: "
|
|
63010
|
+
progress: t("glm.upstreamUnavailable", { status: response.status })
|
|
62318
63011
|
};
|
|
62319
63012
|
if (!response.ok) {
|
|
62320
63013
|
if (response.status === 408 || response.status === 429) return {
|
|
62321
63014
|
kind: "pending",
|
|
62322
|
-
progress: "
|
|
63015
|
+
progress: t("glm.upstreamRetryLater", { status: response.status })
|
|
62323
63016
|
};
|
|
62324
|
-
throw new GlmLoginFatalError("
|
|
63017
|
+
throw new GlmLoginFatalError(t("glm.pollRejected", {
|
|
63018
|
+
status: response.status,
|
|
63019
|
+
url
|
|
63020
|
+
}));
|
|
62325
63021
|
}
|
|
62326
63022
|
const root = asRecord$4(payload);
|
|
62327
63023
|
if (root === void 0) return {
|
|
62328
63024
|
kind: "pending",
|
|
62329
|
-
progress: "
|
|
63025
|
+
progress: t("glm.unparsableRetry")
|
|
62330
63026
|
};
|
|
62331
63027
|
const code = readEnvelopeCode(root);
|
|
62332
63028
|
if (code !== void 0 && code !== 0 && code !== "0") {
|
|
62333
63029
|
const message = asString$11(root.msg) ?? asString$11(root.message);
|
|
62334
|
-
throw new GlmLoginFatalError(
|
|
63030
|
+
throw new GlmLoginFatalError(t("glm.pollBusinessCode", {
|
|
63031
|
+
code: String(code),
|
|
63032
|
+
detail: message === void 0 ? "" : ":" + message
|
|
63033
|
+
}));
|
|
62335
63034
|
}
|
|
62336
63035
|
const body = unwrapBody(root, [CLI_READY_FIELDS$1.status, CLI_READY_FIELDS$1.user]);
|
|
62337
63036
|
const status = body === void 0 ? void 0 : asString$11(body[CLI_READY_FIELDS$1.status]);
|
|
62338
63037
|
if (status === CLI_PENDING_STATUS) return {
|
|
62339
63038
|
kind: "pending",
|
|
62340
|
-
progress: "
|
|
63039
|
+
progress: t("glm.waitingBrowser")
|
|
62341
63040
|
};
|
|
62342
63041
|
if (status === "ready") {
|
|
62343
63042
|
const credentials = parseReadyCredentials(root, flow.region, Date.now());
|
|
62344
63043
|
if (credentials === null) return {
|
|
62345
63044
|
kind: "pending",
|
|
62346
|
-
progress: "
|
|
63045
|
+
progress: t("glm.readyNoToken")
|
|
62347
63046
|
};
|
|
62348
63047
|
return {
|
|
62349
63048
|
kind: "ready",
|
|
@@ -62415,7 +63114,7 @@ async function beginWebLogin$5(options = {}) {
|
|
|
62415
63114
|
startedAt: now,
|
|
62416
63115
|
expiresAt: init.expiresAt,
|
|
62417
63116
|
pollIntervalSec: init.pollIntervalSec,
|
|
62418
|
-
progress: "
|
|
63117
|
+
progress: t("glm.waitingBrowser")
|
|
62419
63118
|
}
|
|
62420
63119
|
};
|
|
62421
63120
|
loginSessions.set(loginId, session);
|
|
@@ -62459,7 +63158,7 @@ async function pollWebLogin$1(loginId, options = {}) {
|
|
|
62459
63158
|
loginId,
|
|
62460
63159
|
credentials: null,
|
|
62461
63160
|
status: "error",
|
|
62462
|
-
error: "
|
|
63161
|
+
error: t("glm.sessionCancelled"),
|
|
62463
63162
|
retryable: false
|
|
62464
63163
|
};
|
|
62465
63164
|
if (now >= session.deadline) {
|
|
@@ -62469,7 +63168,7 @@ async function pollWebLogin$1(loginId, options = {}) {
|
|
|
62469
63168
|
...session.status,
|
|
62470
63169
|
status: "error",
|
|
62471
63170
|
progress: void 0,
|
|
62472
|
-
error: "
|
|
63171
|
+
error: t("glm.loginTimeout", { at: new Date(session.deadline).toISOString() }),
|
|
62473
63172
|
retryable: false
|
|
62474
63173
|
};
|
|
62475
63174
|
return snapshot(session);
|
|
@@ -62583,7 +63282,7 @@ function extractAuthorizationError(raw) {
|
|
|
62583
63282
|
function submitLoginCode(raw, options = {}) {
|
|
62584
63283
|
const id = options.loginId ?? latestLoginId;
|
|
62585
63284
|
const session = id === null || id === void 0 ? void 0 : loginSessions.get(id);
|
|
62586
|
-
if (session === void 0 || session.status.status !== "pending") throw new Error("
|
|
63285
|
+
if (session === void 0 || session.status.status !== "pending") throw new Error(t("glm.noSession"));
|
|
62587
63286
|
const denial = extractAuthorizationError(raw);
|
|
62588
63287
|
if (denial !== "") {
|
|
62589
63288
|
loginSessions.delete(session.loginId);
|
|
@@ -62592,18 +63291,18 @@ function submitLoginCode(raw, options = {}) {
|
|
|
62592
63291
|
...session.status,
|
|
62593
63292
|
status: "error",
|
|
62594
63293
|
progress: void 0,
|
|
62595
|
-
error: "
|
|
63294
|
+
error: t("glm.authorizationDenied", { denial }),
|
|
62596
63295
|
retryable: false
|
|
62597
63296
|
};
|
|
62598
63297
|
return snapshot(session);
|
|
62599
63298
|
}
|
|
62600
63299
|
const code = extractAuthorizationCode(raw);
|
|
62601
|
-
if (code === "") throw new Error("
|
|
63300
|
+
if (code === "") throw new Error(t("glm.notAuthorizationCode"));
|
|
62602
63301
|
session.manualCode = code;
|
|
62603
63302
|
session.nextPollAt = 0;
|
|
62604
63303
|
session.status = {
|
|
62605
63304
|
...session.status,
|
|
62606
|
-
progress: "
|
|
63305
|
+
progress: t("glm.callbackReceived")
|
|
62607
63306
|
};
|
|
62608
63307
|
return snapshot(session);
|
|
62609
63308
|
}
|
|
@@ -62913,7 +63612,7 @@ function registerGlmCodingPlanRoutes(ctx, settings, options = {}) {
|
|
|
62913
63612
|
if (!isSameOriginMutation(request)) return sendCrossOrigin$2(response);
|
|
62914
63613
|
if (accountPool === void 0) return sendJson$5(response, 400, {
|
|
62915
63614
|
ok: false,
|
|
62916
|
-
error: "
|
|
63615
|
+
error: t("glm.poolNotInstalled")
|
|
62917
63616
|
});
|
|
62918
63617
|
const body = await readRequestJson$5(request);
|
|
62919
63618
|
const action = typeof body.action === "string" ? body.action : "";
|
|
@@ -62921,7 +63620,7 @@ function registerGlmCodingPlanRoutes(ctx, settings, options = {}) {
|
|
|
62921
63620
|
const strategy = body.strategy;
|
|
62922
63621
|
if (strategy !== "sequential" && strategy !== "round-robin" && strategy !== "sticky") return sendJson$5(response, 400, {
|
|
62923
63622
|
ok: false,
|
|
62924
|
-
error: "
|
|
63623
|
+
error: t("glm.unknownStrategy")
|
|
62925
63624
|
});
|
|
62926
63625
|
await accountPool.setStrategy(strategy);
|
|
62927
63626
|
return sendJson$5(response, 200, {
|
|
@@ -62950,7 +63649,7 @@ function registerGlmCodingPlanRoutes(ctx, settings, options = {}) {
|
|
|
62950
63649
|
break;
|
|
62951
63650
|
default: return sendJson$5(response, 400, {
|
|
62952
63651
|
ok: false,
|
|
62953
|
-
error: "
|
|
63652
|
+
error: t("glm.unknownAccountAction", { action })
|
|
62954
63653
|
});
|
|
62955
63654
|
}
|
|
62956
63655
|
return sendJson$5(response, 200, {
|
|
@@ -63040,12 +63739,12 @@ function registerGlmCodingPlanRoutes(ctx, settings, options = {}) {
|
|
|
63040
63739
|
const raw = typeof body.code === "string" ? body.code : "";
|
|
63041
63740
|
if (raw.trim() === "") return sendJson$5(response, 400, {
|
|
63042
63741
|
ok: false,
|
|
63043
|
-
error: "
|
|
63742
|
+
error: t("glm.pasteCallback")
|
|
63044
63743
|
});
|
|
63045
63744
|
const current = latestLogin ?? getWebLoginStatus$3();
|
|
63046
63745
|
if (current === null) return sendJson$5(response, 400, {
|
|
63047
63746
|
ok: false,
|
|
63048
|
-
error: "
|
|
63747
|
+
error: t("glm.noLoginInProgress")
|
|
63049
63748
|
});
|
|
63050
63749
|
let submitted;
|
|
63051
63750
|
try {
|
|
@@ -63119,7 +63818,7 @@ async function probeConnection$3(accountPool, fetchFn) {
|
|
|
63119
63818
|
account: null,
|
|
63120
63819
|
model: null,
|
|
63121
63820
|
checkedAt,
|
|
63122
|
-
error: "
|
|
63821
|
+
error: t("glm.notSignedIn", { provider: PROVIDER_NAME$1 })
|
|
63123
63822
|
};
|
|
63124
63823
|
const region = target.credentials.codingPlan.region;
|
|
63125
63824
|
const started = Date.now();
|
|
@@ -65607,7 +66306,10 @@ function asFiniteNumber$1(value) {
|
|
|
65607
66306
|
function optionalString$7(record, key) {
|
|
65608
66307
|
const value = record[key];
|
|
65609
66308
|
if (value === void 0 || value === null) return void 0;
|
|
65610
|
-
if (typeof value !== "string") throw new Error("
|
|
66309
|
+
if (typeof value !== "string") throw new Error(t("sc.credentialFieldInvalid", {
|
|
66310
|
+
provider: "Step Code",
|
|
66311
|
+
key
|
|
66312
|
+
}));
|
|
65611
66313
|
return value;
|
|
65612
66314
|
}
|
|
65613
66315
|
function isOrigin$1(value) {
|
|
@@ -65625,11 +66327,11 @@ function isOrigin$1(value) {
|
|
|
65625
66327
|
* 猜错的代价是一次拿国区凭据去打国际区端点的明确鉴权失败,排查成本远高于让它重新登录。
|
|
65626
66328
|
*/
|
|
65627
66329
|
function parseStepCodeCredentials$1(value) {
|
|
65628
|
-
if (!isRecord$30(value)) throw new Error("Step Code
|
|
66330
|
+
if (!isRecord$30(value)) throw new Error(t("sc.credentialPayloadInvalid", { provider: "Step Code" }));
|
|
65629
66331
|
const apiKey = asString$9(value.apiKey);
|
|
65630
|
-
if (apiKey === void 0) throw new Error("Step Code
|
|
66332
|
+
if (apiKey === void 0) throw new Error(t("sc.credentialNoApiKey", { provider: "Step Code" }));
|
|
65631
66333
|
const profile = normalizeProfile(value.profile);
|
|
65632
|
-
if (profile === void 0) throw new Error("
|
|
66334
|
+
if (profile === void 0) throw new Error(t("sc.credentialProfileInvalid", { provider: "Step Code" }));
|
|
65633
66335
|
const origin = isOrigin$1(value.origin) ? value.origin : isAdoptedSnapshot$1(value) ? "adopt" : "browser";
|
|
65634
66336
|
const credentials = {
|
|
65635
66337
|
apiKey,
|
|
@@ -65720,7 +66422,7 @@ function createCredentialBackend$3(filePath, parse, label) {
|
|
|
65720
66422
|
if (process.platform === "win32") return new WindowsDpapiCredentialStore(filePath + ".dpapi", parse);
|
|
65721
66423
|
if (process.platform === "darwin") return new MacKeychainCredentialStore(PROVIDER_ID$6, credentialAccount$3(filePath), parse);
|
|
65722
66424
|
if (process.platform === "linux") return new SecretServiceCredentialStore(PROVIDER_ID$6, credentialAccount$3(filePath), parse);
|
|
65723
|
-
throw new Error(
|
|
66425
|
+
throw new Error(t("sc.storeUnsupportedPlatform", { label }));
|
|
65724
66426
|
}
|
|
65725
66427
|
const credentialOperations$1 = /* @__PURE__ */ new Map();
|
|
65726
66428
|
function serialize$1(key, operation) {
|
|
@@ -65763,7 +66465,7 @@ var StepCodeCredentialStore = class {
|
|
|
65763
66465
|
return serialize$1(this.filePath, async () => {
|
|
65764
66466
|
const normalized = parseStepCodeCredentials$1(credentials);
|
|
65765
66467
|
await this.backend.save(normalized);
|
|
65766
|
-
if (!isDeepStrictEqual(await this.backend.load(), normalized)) throw new Error("Step Code
|
|
66468
|
+
if (!isDeepStrictEqual(await this.backend.load(), normalized)) throw new Error(t("sc.encryptedWriteVerifyFailed", { provider: "Step Code" }));
|
|
65767
66469
|
});
|
|
65768
66470
|
}
|
|
65769
66471
|
delete() {
|
|
@@ -65772,11 +66474,11 @@ var StepCodeCredentialStore = class {
|
|
|
65772
66474
|
};
|
|
65773
66475
|
/** 校验并归一化一份落盘的额度凭据。缺 token 或 deviceId 一律拒绝——少一个就是一次必然的鉴权失败。 */
|
|
65774
66476
|
function parseStepCodeQuotaCredential(value) {
|
|
65775
|
-
if (!isRecord$30(value)) throw new Error("Step Code
|
|
66477
|
+
if (!isRecord$30(value)) throw new Error(t("sc.quotaCredentialPayloadInvalid", { provider: "Step Code" }));
|
|
65776
66478
|
const token = asString$9(value.token);
|
|
65777
|
-
if (token === void 0) throw new Error("Step Code
|
|
66479
|
+
if (token === void 0) throw new Error(t("sc.quotaCredentialNoToken", { provider: "Step Code" }));
|
|
65778
66480
|
const deviceId = asString$9(value.deviceId);
|
|
65779
|
-
if (deviceId === void 0) throw new Error("Step Code
|
|
66481
|
+
if (deviceId === void 0) throw new Error(t("sc.quotaCredentialNoDeviceId", { provider: "Step Code" }));
|
|
65780
66482
|
return {
|
|
65781
66483
|
token,
|
|
65782
66484
|
deviceId,
|
|
@@ -65809,7 +66511,7 @@ var StepCodeQuotaCredentialStore = class {
|
|
|
65809
66511
|
return serialize$1(this.filePath, async () => {
|
|
65810
66512
|
const normalized = parseStepCodeQuotaCredential(credential);
|
|
65811
66513
|
await this.backend.save(normalized);
|
|
65812
|
-
if (!isDeepStrictEqual(await this.backend.load(), normalized)) throw new Error("Step Code
|
|
66514
|
+
if (!isDeepStrictEqual(await this.backend.load(), normalized)) throw new Error(t("sc.quotaCredentialWriteVerifyFailed", { provider: "Step Code" }));
|
|
65813
66515
|
});
|
|
65814
66516
|
}
|
|
65815
66517
|
delete() {
|
|
@@ -65892,7 +66594,7 @@ var StepCodeModelSettingsStore = class {
|
|
|
65892
66594
|
const temporary = this.filePath + ".tmp." + Date.now();
|
|
65893
66595
|
await fs.writeFile(temporary, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
65894
66596
|
await fs.rename(temporary, this.filePath);
|
|
65895
|
-
if (!isDeepStrictEqual(parseStepCodeModelSettings(JSON.parse(await fs.readFile(this.filePath, "utf8"))), settings)) throw new Error("Step Code
|
|
66597
|
+
if (!isDeepStrictEqual(parseStepCodeModelSettings(JSON.parse(await fs.readFile(this.filePath, "utf8"))), settings)) throw new Error(t("sc.modelSettingsWriteFailed", { provider: "Step Code" }));
|
|
65896
66598
|
}
|
|
65897
66599
|
/**
|
|
65898
66600
|
* 在与凭据写入同一条按路径排队的锁里做「读-改-写」。
|
|
@@ -66137,7 +66839,7 @@ var StepCodeAdapter = class extends LlmAdapter {
|
|
|
66137
66839
|
providerInfo(provider) {
|
|
66138
66840
|
return {
|
|
66139
66841
|
id: provider,
|
|
66140
|
-
name: PROVIDER_NAME$6
|
|
66842
|
+
name: localizedProviderName(provider, PROVIDER_NAME$6)
|
|
66141
66843
|
};
|
|
66142
66844
|
}
|
|
66143
66845
|
providerRetryPolicy() {
|
|
@@ -66203,7 +66905,7 @@ var StepCodeAdapter = class extends LlmAdapter {
|
|
|
66203
66905
|
}));
|
|
66204
66906
|
}
|
|
66205
66907
|
async resolveModel(provider, model, signal) {
|
|
66206
|
-
if (signal?.aborted) throw new LlmError("
|
|
66908
|
+
if (signal?.aborted) throw new LlmError(t("sc.modelResolveAborted", { provider: PROVIDER_NAME$6 }), "ABORTED");
|
|
66207
66909
|
const settings = await this.settings();
|
|
66208
66910
|
const picked = await this.credentialFor().catch(() => null);
|
|
66209
66911
|
const catalog = this.catalog(picked?.credentials.profile);
|
|
@@ -66270,8 +66972,11 @@ var StepCodeAdapter = class extends LlmAdapter {
|
|
|
66270
66972
|
});
|
|
66271
66973
|
activity?.pulse();
|
|
66272
66974
|
} catch (error) {
|
|
66273
|
-
if (signal.aborted) throw new LlmError("
|
|
66274
|
-
throw new LlmError("
|
|
66975
|
+
if (signal.aborted) throw new LlmError(t("sc.requestAborted", { provider: PROVIDER_NAME$6 }), "ABORTED", { cause: error });
|
|
66976
|
+
throw new LlmError(t("sc.requestFailed", {
|
|
66977
|
+
provider: PROVIDER_NAME$6,
|
|
66978
|
+
detail: error instanceof Error ? error.message : String(error)
|
|
66979
|
+
}), "TRANSPORT", { cause: error });
|
|
66275
66980
|
}
|
|
66276
66981
|
if (response.ok) break;
|
|
66277
66982
|
const detail = await response.text().catch(() => "");
|
|
@@ -66294,8 +66999,8 @@ var StepCodeAdapter = class extends LlmAdapter {
|
|
|
66294
66999
|
}
|
|
66295
67000
|
throw failure;
|
|
66296
67001
|
}
|
|
66297
|
-
if (response === void 0) throw new LlmError("
|
|
66298
|
-
if (response.body === null) throw new LlmError("
|
|
67002
|
+
if (response === void 0) throw new LlmError(t("sc.noResponse", { provider: PROVIDER_NAME$6 }), "PROVIDER_ERROR");
|
|
67003
|
+
if (response.body === null) throw new LlmError(t("sc.emptyBody", { provider: PROVIDER_NAME$6 }), "PROVIDER_ERROR");
|
|
66299
67004
|
const reader = response.body.getReader();
|
|
66300
67005
|
const decoder = new TextDecoder();
|
|
66301
67006
|
const state = createStreamState$2();
|
|
@@ -66404,7 +67109,11 @@ function isRetryableStepCodeLoginError(error) {
|
|
|
66404
67109
|
}
|
|
66405
67110
|
/** protocol 类错误:形状/字段值不合协议,不重试。 */
|
|
66406
67111
|
function protocolError(phase, detail, cause) {
|
|
66407
|
-
return new StepCodeLoginRequestError("protocol", "
|
|
67112
|
+
return new StepCodeLoginRequestError("protocol", t("sc.loginPhaseFailed", {
|
|
67113
|
+
provider: PROVIDER_NAME$6,
|
|
67114
|
+
phase,
|
|
67115
|
+
detail
|
|
67116
|
+
}), { ...cause === void 0 ? {} : { cause } });
|
|
66408
67117
|
}
|
|
66409
67118
|
/** 成功体里的 `desc` 去控制字符后截断到 MAX_ERROR_DETAIL_LENGTH(逐字 login-client.ts:342-346)。 */
|
|
66410
67119
|
function envelopeDetail(payload) {
|
|
@@ -66442,10 +67151,13 @@ function parseAuthBase(value) {
|
|
|
66442
67151
|
try {
|
|
66443
67152
|
url = new URL(value);
|
|
66444
67153
|
} catch {
|
|
66445
|
-
throw new Error("
|
|
67154
|
+
throw new Error(t("sc.authorizeUrlInvalid", {
|
|
67155
|
+
provider: PROVIDER_NAME$6,
|
|
67156
|
+
value
|
|
67157
|
+
}));
|
|
66446
67158
|
}
|
|
66447
|
-
if (url.protocol !== "https:") throw new Error("
|
|
66448
|
-
if (url.username !== "" || url.password !== "") throw new Error("
|
|
67159
|
+
if (url.protocol !== "https:") throw new Error(t("sc.authorizeUrlNotHttps", { provider: PROVIDER_NAME$6 }));
|
|
67160
|
+
if (url.username !== "" || url.password !== "") throw new Error(t("sc.authorizeUrlHasCredentials", { provider: PROVIDER_NAME$6 }));
|
|
66449
67161
|
return url;
|
|
66450
67162
|
}
|
|
66451
67163
|
/**
|
|
@@ -66506,7 +67218,7 @@ async function withLoginTimeout(timeoutMs, signal, timeoutError, run) {
|
|
|
66506
67218
|
}
|
|
66507
67219
|
function abortReasonOf(signal) {
|
|
66508
67220
|
const reason = signal.reason;
|
|
66509
|
-
return reason instanceof Error ? reason :
|
|
67221
|
+
return reason instanceof Error ? reason : new Error(t("sc.cancelled"));
|
|
66510
67222
|
}
|
|
66511
67223
|
/** 可被取消的 sleep(逐字 utils/sleep.ts 的语义)。 */
|
|
66512
67224
|
function sleep$1(ms, signal) {
|
|
@@ -66543,9 +67255,9 @@ function sleep$1(ms, signal) {
|
|
|
66543
67255
|
* 服务端会用 200 携带业务错误)。
|
|
66544
67256
|
*/
|
|
66545
67257
|
async function request(input) {
|
|
66546
|
-
return withLoginTimeout(LOGIN_REQUEST_TIMEOUT_MS$1, input.signal, () => new StepCodeLoginRequestError("transport", "
|
|
67258
|
+
return withLoginTimeout(LOGIN_REQUEST_TIMEOUT_MS$1, input.signal, () => new StepCodeLoginRequestError("transport", t("sc.loginRequestTimeout", { provider: PROVIDER_NAME$6 })), async (signal) => {
|
|
66547
67259
|
const pollToken = input.pollToken.trim();
|
|
66548
|
-
if (pollToken === "") throw new Error("
|
|
67260
|
+
if (pollToken === "") throw new Error(t("sc.pollTokenEmpty", { provider: PROVIDER_NAME$6 }));
|
|
66549
67261
|
const fetchFn = input.fetchFn ?? fetch;
|
|
66550
67262
|
let response;
|
|
66551
67263
|
try {
|
|
@@ -66689,7 +67401,7 @@ async function pollStepCodeCliLogin(input) {
|
|
|
66689
67401
|
* 不可重试的直接抛出。
|
|
66690
67402
|
*/
|
|
66691
67403
|
async function waitForStepCodeLogin(input) {
|
|
66692
|
-
const timeoutError = () =>
|
|
67404
|
+
const timeoutError = () => new Error(t("sc.loginTimeout", { provider: PROVIDER_NAME$6 }));
|
|
66693
67405
|
const serverRemaining = input.init.expiresAt * 1e3 - Date.now();
|
|
66694
67406
|
const localRemaining = input.localDeadline === void 0 ? Infinity : input.localDeadline - Date.now();
|
|
66695
67407
|
const remaining = Math.min(serverRemaining, localRemaining);
|
|
@@ -66724,7 +67436,7 @@ async function waitForStepCodeLogin(input) {
|
|
|
66724
67436
|
/** 从一次成功登录的结果造出凭据(uid 不合格时已经被丢掉,这里只做装配)。 */
|
|
66725
67437
|
function stepCodeCredentialFromLogin(profile, ready) {
|
|
66726
67438
|
const apiKey = ready.apiKey.trim();
|
|
66727
|
-
if (apiKey === "") throw new Error("
|
|
67439
|
+
if (apiKey === "") throw new Error(t("sc.loginNoApiKey", { provider: PROVIDER_NAME$6 }));
|
|
66728
67440
|
const uid = readBoundedUid$1(ready.uid);
|
|
66729
67441
|
return {
|
|
66730
67442
|
type: "oauth",
|
|
@@ -66743,7 +67455,7 @@ function stepCodeCredentialFromLogin(profile, ready) {
|
|
|
66743
67455
|
*/
|
|
66744
67456
|
function stepCodeCredentialFromApiKey(profile, apiKey, uid) {
|
|
66745
67457
|
const trimmed = apiKey.trim();
|
|
66746
|
-
if (trimmed === "") throw new Error("
|
|
67458
|
+
if (trimmed === "") throw new Error(t("sc.apiKeyEmpty", { provider: PROVIDER_NAME$6 }));
|
|
66747
67459
|
const bounded = readBoundedUid$1(uid);
|
|
66748
67460
|
return {
|
|
66749
67461
|
type: "oauth",
|
|
@@ -66815,7 +67527,7 @@ async function beginStepCodeLogin(profile, options = {}) {
|
|
|
66815
67527
|
startedAt,
|
|
66816
67528
|
expiresAt,
|
|
66817
67529
|
pollIntervalSec: init.pollIntervalSec,
|
|
66818
|
-
progress: "
|
|
67530
|
+
progress: t("sc.waitingBrowserPoll", { seconds: init.pollIntervalSec })
|
|
66819
67531
|
};
|
|
66820
67532
|
(async () => {
|
|
66821
67533
|
try {
|
|
@@ -66839,7 +67551,7 @@ async function beginStepCodeLogin(profile, options = {}) {
|
|
|
66839
67551
|
completedAt: Date.now(),
|
|
66840
67552
|
expiresAt,
|
|
66841
67553
|
pollIntervalSec: init.pollIntervalSec,
|
|
66842
|
-
progress: "
|
|
67554
|
+
progress: t("sc.authorized"),
|
|
66843
67555
|
...ready.uid === void 0 ? {} : { uid: ready.uid }
|
|
66844
67556
|
};
|
|
66845
67557
|
} catch (error) {
|
|
@@ -66939,7 +67651,10 @@ function projectAccount$1(input) {
|
|
|
66939
67651
|
function optionalString$6(record, key) {
|
|
66940
67652
|
const value = record[key];
|
|
66941
67653
|
if (value === void 0 || value === null) return void 0;
|
|
66942
|
-
if (typeof value !== "string") throw new Error("
|
|
67654
|
+
if (typeof value !== "string") throw new Error(t("sc.poolAccountFieldInvalid", {
|
|
67655
|
+
provider: PROVIDER_NAME$6,
|
|
67656
|
+
key
|
|
67657
|
+
}));
|
|
66943
67658
|
return value;
|
|
66944
67659
|
}
|
|
66945
67660
|
/**
|
|
@@ -66950,11 +67665,11 @@ function optionalString$6(record, key) {
|
|
|
66950
67665
|
* 当成可路由的账号打出去。
|
|
66951
67666
|
*/
|
|
66952
67667
|
function parseStepCodeCredentials(value) {
|
|
66953
|
-
if (!isRecord$28(value)) throw new Error("
|
|
67668
|
+
if (!isRecord$28(value)) throw new Error(t("sc.poolCredentialInvalid", { provider: PROVIDER_NAME$6 }));
|
|
66954
67669
|
const access = typeof value.access === "string" ? value.access.trim() : "";
|
|
66955
|
-
if (access === "") throw new Error("
|
|
67670
|
+
if (access === "") throw new Error(t("sc.poolCredentialNoAccess", { provider: PROVIDER_NAME$6 }));
|
|
66956
67671
|
const profile = normalizeProfile(value.profile);
|
|
66957
|
-
if (profile === void 0) throw new Error("
|
|
67672
|
+
if (profile === void 0) throw new Error(t("sc.poolCredentialProfileInvalid", { provider: PROVIDER_NAME$6 }));
|
|
66958
67673
|
const uidRaw = typeof value.uid === "string" ? value.uid.trim() : "";
|
|
66959
67674
|
const uid = uidRaw.length > 64 || !UID_PATTERN.test(uidRaw) ? "" : uidRaw;
|
|
66960
67675
|
return {
|
|
@@ -66977,7 +67692,7 @@ function parseStepCodeCredentials(value) {
|
|
|
66977
67692
|
* 抛错等于让一行坏数据带走整个池。
|
|
66978
67693
|
*/
|
|
66979
67694
|
function parseStepCodePoolData(value) {
|
|
66980
|
-
if (!isRecord$28(value)) throw new Error("
|
|
67695
|
+
if (!isRecord$28(value)) throw new Error(t("sc.poolPayloadInvalid", { provider: PROVIDER_NAME$6 }));
|
|
66981
67696
|
const accounts = [];
|
|
66982
67697
|
for (const item of Array.isArray(value.accounts) ? value.accounts : []) {
|
|
66983
67698
|
if (!isRecord$28(item) || typeof item.id !== "string") continue;
|
|
@@ -67127,7 +67842,7 @@ var StepCodeAccountPool = class extends AccountPoolCore {
|
|
|
67127
67842
|
const target = data.accounts.find((account) => account.id === data.activeAccountId) ?? data.accounts.find((account) => account.isPrimary) ?? data.accounts[0];
|
|
67128
67843
|
if (target === void 0) {
|
|
67129
67844
|
await this.getFreshCredential(void 0, fetchFn);
|
|
67130
|
-
throw new Error("
|
|
67845
|
+
throw new Error(t("sc.poolEmpty", { provider: PROVIDER_NAME$6 }));
|
|
67131
67846
|
}
|
|
67132
67847
|
return {
|
|
67133
67848
|
accountId: target.id,
|
|
@@ -67858,7 +68573,7 @@ function registerStepCodeRoutes(ctx, settings, options = {}) {
|
|
|
67858
68573
|
if (!isSameOriginMutation(request)) return sendCrossOrigin$1(response);
|
|
67859
68574
|
if (accountPool === void 0) return sendJson$4(response, 400, {
|
|
67860
68575
|
ok: false,
|
|
67861
|
-
error: "
|
|
68576
|
+
error: t("sc.poolNotInstalled")
|
|
67862
68577
|
});
|
|
67863
68578
|
const body = await readRequestJson$4(request);
|
|
67864
68579
|
const action = typeof body.action === "string" ? body.action : "";
|
|
@@ -67866,7 +68581,7 @@ function registerStepCodeRoutes(ctx, settings, options = {}) {
|
|
|
67866
68581
|
const strategy = body.strategy;
|
|
67867
68582
|
if (strategy !== "sequential" && strategy !== "round-robin" && strategy !== "sticky") return sendJson$4(response, 400, {
|
|
67868
68583
|
ok: false,
|
|
67869
|
-
error: "
|
|
68584
|
+
error: t("sc.unknownStrategy")
|
|
67870
68585
|
});
|
|
67871
68586
|
await accountPool.setStrategy(strategy);
|
|
67872
68587
|
return sendJson$4(response, 200, {
|
|
@@ -67895,7 +68610,7 @@ function registerStepCodeRoutes(ctx, settings, options = {}) {
|
|
|
67895
68610
|
break;
|
|
67896
68611
|
default: return sendJson$4(response, 400, {
|
|
67897
68612
|
ok: false,
|
|
67898
|
-
error: "
|
|
68613
|
+
error: t("sc.unknownAccountAction", { action })
|
|
67899
68614
|
});
|
|
67900
68615
|
}
|
|
67901
68616
|
return sendJson$4(response, 200, {
|
|
@@ -67942,7 +68657,7 @@ function registerStepCodeRoutes(ctx, settings, options = {}) {
|
|
|
67942
68657
|
const apiKey = typeof body.apiKey === "string" ? body.apiKey : "";
|
|
67943
68658
|
if (apiKey.trim() === "") return sendJson$4(response, 400, {
|
|
67944
68659
|
ok: false,
|
|
67945
|
-
error: "
|
|
68660
|
+
error: t("sc.pastePlatformKey")
|
|
67946
68661
|
});
|
|
67947
68662
|
const credentials = stepCodeCredentialFromApiKey(profileFromBody(body), apiKey);
|
|
67948
68663
|
await savePastedCredential(credentials);
|
|
@@ -68000,11 +68715,11 @@ function registerStepCodeRoutes(ctx, settings, options = {}) {
|
|
|
68000
68715
|
const password = typeof body.password === "string" ? body.password : "";
|
|
68001
68716
|
if (account === "") return sendJson$4(response, 400, {
|
|
68002
68717
|
ok: false,
|
|
68003
|
-
error: "
|
|
68718
|
+
error: t("sc.missingAccount")
|
|
68004
68719
|
});
|
|
68005
68720
|
if (password === "") return sendJson$4(response, 400, {
|
|
68006
68721
|
ok: false,
|
|
68007
|
-
error: "
|
|
68722
|
+
error: t("sc.missingPassword")
|
|
68008
68723
|
});
|
|
68009
68724
|
const signed = await attempt(() => signInOasisQuotaCredential({
|
|
68010
68725
|
profile,
|
|
@@ -68047,7 +68762,7 @@ function registerStepCodeRoutes(ctx, settings, options = {}) {
|
|
|
68047
68762
|
quotaCredential = stored;
|
|
68048
68763
|
} else return sendJson$4(response, 400, {
|
|
68049
68764
|
ok: false,
|
|
68050
|
-
error: "
|
|
68765
|
+
error: t("sc.unknownQuotaCredentialMode", { mode })
|
|
68051
68766
|
});
|
|
68052
68767
|
await quotaRefresh.run(() => refreshQuota(true));
|
|
68053
68768
|
return sendJson$4(response, 200, {
|
|
@@ -68093,7 +68808,7 @@ async function probeConnection$2(accountPool, fetchFn, env) {
|
|
|
68093
68808
|
account: null,
|
|
68094
68809
|
model: null,
|
|
68095
68810
|
checkedAt,
|
|
68096
|
-
error: "
|
|
68811
|
+
error: t("sc.notSignedIn", { provider: PROVIDER_NAME$6 })
|
|
68097
68812
|
};
|
|
68098
68813
|
const credentials = upstreamCredentialOf$2(target.credentials);
|
|
68099
68814
|
const started = Date.now();
|
|
@@ -68111,7 +68826,7 @@ async function probeConnection$2(accountPool, fetchFn, env) {
|
|
|
68111
68826
|
account: null,
|
|
68112
68827
|
model: null,
|
|
68113
68828
|
checkedAt,
|
|
68114
|
-
error: "
|
|
68829
|
+
error: t("sc.catalogHttp", { status: response.status }) + (detail === "" ? "" : ":" + stepCodeErrorDetail(detail, 160))
|
|
68115
68830
|
};
|
|
68116
68831
|
}
|
|
68117
68832
|
const entries = parseStepModelCatalog(await response.json().catch(() => void 0));
|
|
@@ -70640,7 +71355,7 @@ var ClinePassAdapter = class extends LlmAdapter {
|
|
|
70640
71355
|
providerInfo(provider) {
|
|
70641
71356
|
return {
|
|
70642
71357
|
id: provider,
|
|
70643
|
-
name: PROVIDER_NAME$5
|
|
71358
|
+
name: localizedProviderName(provider, PROVIDER_NAME$5)
|
|
70644
71359
|
};
|
|
70645
71360
|
}
|
|
70646
71361
|
providerRetryPolicy() {
|
|
@@ -75407,7 +76122,10 @@ function asFiniteNumber(value) {
|
|
|
75407
76122
|
function optionalString$3(record, key) {
|
|
75408
76123
|
const value = record[key];
|
|
75409
76124
|
if (value === void 0 || value === null) return void 0;
|
|
75410
|
-
if (typeof value !== "string") throw new Error("
|
|
76125
|
+
if (typeof value !== "string") throw new Error(t("qo.credentialFieldInvalid", {
|
|
76126
|
+
provider: "Qoder",
|
|
76127
|
+
key
|
|
76128
|
+
}));
|
|
75411
76129
|
return value;
|
|
75412
76130
|
}
|
|
75413
76131
|
function isOrigin(value) {
|
|
@@ -75424,10 +76142,10 @@ function isOrigin(value) {
|
|
|
75424
76142
|
* 拿一区的凭据去打另一区的端点,一次明确的鉴权失败,排查成本远高于重新登录。
|
|
75425
76143
|
*/
|
|
75426
76144
|
function parseQoderCredentials(value) {
|
|
75427
|
-
if (!isRecord$23(value)) throw new Error("Qoder
|
|
76145
|
+
if (!isRecord$23(value)) throw new Error(t("qo.credentialPayloadInvalid", { provider: "Qoder" }));
|
|
75428
76146
|
const accessToken = asString$8(value.accessToken);
|
|
75429
|
-
if (accessToken === void 0) throw new Error("
|
|
75430
|
-
if (!isQoderRegion(value.region)) throw new Error("
|
|
76147
|
+
if (accessToken === void 0) throw new Error(t("qo.credentialNoToken", { provider: "Qoder" }));
|
|
76148
|
+
if (!isQoderRegion(value.region)) throw new Error(t("qo.credentialRegionInvalid", { provider: "Qoder" }));
|
|
75431
76149
|
const origin = isOrigin(value.origin) ? value.origin : isAdoptedSnapshot(value) ? "adopt" : "device";
|
|
75432
76150
|
const credentials = {
|
|
75433
76151
|
accessToken,
|
|
@@ -75521,7 +76239,7 @@ function createCredentialBackend$1(filePath, parse, label) {
|
|
|
75521
76239
|
if (process.platform === "win32") return new WindowsDpapiCredentialStore(filePath + ".dpapi", parse);
|
|
75522
76240
|
if (process.platform === "darwin") return new MacKeychainCredentialStore(PROVIDER_ID$4, credentialAccount$1(filePath), parse);
|
|
75523
76241
|
if (process.platform === "linux") return new SecretServiceCredentialStore(PROVIDER_ID$4, credentialAccount$1(filePath), parse);
|
|
75524
|
-
throw new Error(
|
|
76242
|
+
throw new Error(t("qo.storeUnsupportedPlatform", { label }));
|
|
75525
76243
|
}
|
|
75526
76244
|
const credentialOperations = /* @__PURE__ */ new Map();
|
|
75527
76245
|
function serialize(key, operation) {
|
|
@@ -75559,7 +76277,7 @@ var QoderCredentialStore = class {
|
|
|
75559
76277
|
return serialize(this.filePath, async () => {
|
|
75560
76278
|
const normalized = parseQoderCredentials(credentials);
|
|
75561
76279
|
await this.backend.save(normalized);
|
|
75562
|
-
if (!isDeepStrictEqual(await this.backend.load(), normalized)) throw new Error("Qoder
|
|
76280
|
+
if (!isDeepStrictEqual(await this.backend.load(), normalized)) throw new Error(t("qo.encryptedWriteVerifyFailed", { provider: "Qoder" }));
|
|
75563
76281
|
});
|
|
75564
76282
|
}
|
|
75565
76283
|
delete() {
|
|
@@ -75670,7 +76388,7 @@ var QoderModelSettingsStore = class {
|
|
|
75670
76388
|
const temporary = this.filePath + ".tmp." + Date.now();
|
|
75671
76389
|
await fs.writeFile(temporary, JSON.stringify(document, null, 2) + "\n", "utf8");
|
|
75672
76390
|
await fs.rename(temporary, this.filePath);
|
|
75673
|
-
if (!isDeepStrictEqual(parseQoderModelSettings(JSON.parse(await fs.readFile(this.filePath, "utf8"))), document)) throw new Error("Qoder
|
|
76391
|
+
if (!isDeepStrictEqual(parseQoderModelSettings(JSON.parse(await fs.readFile(this.filePath, "utf8"))), document)) throw new Error(t("qo.modelSettingsWriteFailed", { provider: "Qoder" }));
|
|
75674
76392
|
}
|
|
75675
76393
|
/** 在与凭据写入同一条按路径排队的锁里做「读-改-写」。 */
|
|
75676
76394
|
updateSettings(patch) {
|
|
@@ -76409,10 +77127,14 @@ async function fetchQoderUserInfo(accessToken, region, options = {}) {
|
|
|
76409
77127
|
});
|
|
76410
77128
|
if (!response.ok) {
|
|
76411
77129
|
const detail = qoderErrorDetail(await response.text().catch(() => ""), 160);
|
|
76412
|
-
throw new Error("
|
|
77130
|
+
throw new Error(t("qo.userinfoFailed", {
|
|
77131
|
+
provider: PROVIDER_NAME$4,
|
|
77132
|
+
status: response.status,
|
|
77133
|
+
detail: detail === "" ? "" : ":" + detail
|
|
77134
|
+
}));
|
|
76413
77135
|
}
|
|
76414
77136
|
const payload = await response.json().catch(() => void 0);
|
|
76415
|
-
if (!isRecord$22(payload)) throw new Error("
|
|
77137
|
+
if (!isRecord$22(payload)) throw new Error(t("qo.userinfoNotJson", { provider: PROVIDER_NAME$4 }));
|
|
76416
77138
|
const tags = Array.isArray(payload.organization_tags) ? payload.organization_tags.filter((tag) => typeof tag === "string" && tag !== "") : void 0;
|
|
76417
77139
|
return {
|
|
76418
77140
|
userID: asText$1(payload.id) ?? asText$1(payload.uid) ?? "",
|
|
@@ -76481,9 +77203,9 @@ async function exchangeQoderJobToken(personalToken, region, options = {}) {
|
|
|
76481
77203
|
throw new QoderPatExchangeError("Qoder(订阅) PAT 兑换失败(HTTP " + response.status + ")" + (detail === "" ? "" : ":" + detail), response.status, region);
|
|
76482
77204
|
}
|
|
76483
77205
|
const payload = await response.json().catch(() => void 0);
|
|
76484
|
-
if (!isRecord$22(payload)) throw new Error("
|
|
77206
|
+
if (!isRecord$22(payload)) throw new Error(t("qo.patExchangeNotJson", { provider: PROVIDER_NAME$4 }));
|
|
76485
77207
|
const token = asText$1(payload.token);
|
|
76486
|
-
if (token === void 0) throw new Error("
|
|
77208
|
+
if (token === void 0) throw new Error(t("qo.patExchangeNoToken", { provider: PROVIDER_NAME$4 }));
|
|
76487
77209
|
return {
|
|
76488
77210
|
token,
|
|
76489
77211
|
refreshToken: asText$1(payload.refresh_token) ?? null,
|
|
@@ -76509,14 +77231,17 @@ async function refreshQoderAccessToken(credentials, region, options = {}) {
|
|
|
76509
77231
|
signal: timeoutSignal$1(options.signal, DISCOVERY_TIMEOUT_MS$1)
|
|
76510
77232
|
});
|
|
76511
77233
|
if (!response.ok) {
|
|
76512
|
-
const error =
|
|
77234
|
+
const error = new Error(t("qo.refreshFailed", {
|
|
77235
|
+
provider: PROVIDER_NAME$4,
|
|
77236
|
+
status: response.status
|
|
77237
|
+
}));
|
|
76513
77238
|
error.status = response.status;
|
|
76514
77239
|
throw error;
|
|
76515
77240
|
}
|
|
76516
77241
|
const payload = await response.json().catch(() => void 0);
|
|
76517
|
-
if (!isRecord$22(payload)) throw new Error("
|
|
77242
|
+
if (!isRecord$22(payload)) throw new Error(t("qo.refreshNotJson", { provider: PROVIDER_NAME$4 }));
|
|
76518
77243
|
const token = asText$1(payload.token);
|
|
76519
|
-
if (token === void 0) throw new Error("
|
|
77244
|
+
if (token === void 0) throw new Error(t("qo.refreshNoToken", { provider: PROVIDER_NAME$4 }));
|
|
76520
77245
|
return {
|
|
76521
77246
|
token,
|
|
76522
77247
|
refreshToken: asText$1(payload.refresh_token) ?? credentials.refreshToken,
|
|
@@ -76609,13 +77334,16 @@ async function loadQoderQuota(credentials, options = {}) {
|
|
|
76609
77334
|
const detail = qoderErrorDetail(await response.text().catch(() => ""), 160);
|
|
76610
77335
|
return {
|
|
76611
77336
|
ok: false,
|
|
76612
|
-
error: "
|
|
77337
|
+
error: t("qo.quotaHttp", {
|
|
77338
|
+
status: response.status,
|
|
77339
|
+
detail: detail === "" ? "" : ":" + detail
|
|
77340
|
+
})
|
|
76613
77341
|
};
|
|
76614
77342
|
}
|
|
76615
77343
|
const snapshot = normalizeQoderQuotaSnapshot(await response.json().catch(() => void 0), credentials.region);
|
|
76616
77344
|
if (snapshot === void 0) return {
|
|
76617
77345
|
ok: false,
|
|
76618
|
-
error: "
|
|
77346
|
+
error: t("qo.quotaNoBucket")
|
|
76619
77347
|
};
|
|
76620
77348
|
quotaCacheByAccount.set(cacheKey, {
|
|
76621
77349
|
snapshot,
|
|
@@ -77849,7 +78577,7 @@ var QoderAdapter = class extends LlmAdapter {
|
|
|
77849
78577
|
providerInfo(provider) {
|
|
77850
78578
|
return {
|
|
77851
78579
|
id: provider,
|
|
77852
|
-
name: PROVIDER_NAME$4
|
|
78580
|
+
name: localizedProviderName(provider, PROVIDER_NAME$4)
|
|
77853
78581
|
};
|
|
77854
78582
|
}
|
|
77855
78583
|
providerRetryPolicy() {
|
|
@@ -77905,7 +78633,7 @@ var QoderAdapter = class extends LlmAdapter {
|
|
|
77905
78633
|
}));
|
|
77906
78634
|
}
|
|
77907
78635
|
async resolveModel(provider, model, signal) {
|
|
77908
|
-
if (signal?.aborted) throw new LlmError("
|
|
78636
|
+
if (signal?.aborted) throw new LlmError(t("qo.modelResolveAborted", { provider: PROVIDER_NAME$4 }), "ABORTED");
|
|
77909
78637
|
const settings = await this.settings();
|
|
77910
78638
|
const region = (await this.credentialFor().catch(() => null))?.credentials.region ?? "global";
|
|
77911
78639
|
const catalog = this.catalog(region);
|
|
@@ -78052,8 +78780,11 @@ var QoderAdapter = class extends LlmAdapter {
|
|
|
78052
78780
|
});
|
|
78053
78781
|
activity?.pulse();
|
|
78054
78782
|
} catch (error) {
|
|
78055
|
-
if (signal.aborted) throw new LlmError("
|
|
78056
|
-
throw new LlmError("
|
|
78783
|
+
if (signal.aborted) throw new LlmError(t("qo.requestAborted", { provider: PROVIDER_NAME$4 }), "ABORTED", { cause: error });
|
|
78784
|
+
throw new LlmError(t("qo.requestFailed", {
|
|
78785
|
+
provider: PROVIDER_NAME$4,
|
|
78786
|
+
detail: error instanceof Error ? error.message : String(error)
|
|
78787
|
+
}), "TRANSPORT", { cause: error });
|
|
78057
78788
|
}
|
|
78058
78789
|
if (!response.ok) {
|
|
78059
78790
|
const detail = await response.text().catch(() => "");
|
|
@@ -78061,7 +78792,7 @@ var QoderAdapter = class extends LlmAdapter {
|
|
|
78061
78792
|
if (await handlePreContentFailure(failure, response.headers)) continue;
|
|
78062
78793
|
throw failure;
|
|
78063
78794
|
}
|
|
78064
|
-
if (response.body === null) throw new LlmError("
|
|
78795
|
+
if (response.body === null) throw new LlmError(t("qo.emptyBody", { provider: PROVIDER_NAME$4 }), "PROVIDER_ERROR");
|
|
78065
78796
|
const reader = response.body.getReader();
|
|
78066
78797
|
const decoder = new TextDecoder();
|
|
78067
78798
|
const state = createQoderStreamState();
|
|
@@ -78159,7 +78890,7 @@ function createQoderDeviceParams(env = process.env) {
|
|
|
78159
78890
|
*/
|
|
78160
78891
|
function qoderDeviceAuthorizeUrl(params) {
|
|
78161
78892
|
const page = REGION_HOSTS$1.global.deviceAuthorizePage;
|
|
78162
|
-
if (page === null) throw new Error("
|
|
78893
|
+
if (page === null) throw new Error(t("qo.noBrowserOutsideGlobal", { provider: PROVIDER_NAME$4 }));
|
|
78163
78894
|
const url = new URL(page);
|
|
78164
78895
|
url.searchParams.set("challenge", params.challenge);
|
|
78165
78896
|
url.searchParams.set("challenge_method", "S256");
|
|
@@ -78201,18 +78932,22 @@ async function pollQoderDeviceToken(params, options = {}) {
|
|
|
78201
78932
|
const detail = qoderErrorDetail(await response.text().catch(() => ""), 160);
|
|
78202
78933
|
return {
|
|
78203
78934
|
state: "failed",
|
|
78204
|
-
reason: "
|
|
78935
|
+
reason: t("qo.devicePollFailed", {
|
|
78936
|
+
provider: PROVIDER_NAME$4,
|
|
78937
|
+
status: response.status,
|
|
78938
|
+
detail: detail === "" ? "" : ":" + detail
|
|
78939
|
+
})
|
|
78205
78940
|
};
|
|
78206
78941
|
}
|
|
78207
78942
|
const payload = await response.json().catch(() => void 0);
|
|
78208
78943
|
if (!isRecord$20(payload)) return {
|
|
78209
78944
|
state: "failed",
|
|
78210
|
-
reason: "
|
|
78945
|
+
reason: t("qo.devicePollNotJson", { provider: PROVIDER_NAME$4 })
|
|
78211
78946
|
};
|
|
78212
78947
|
const token = asText(payload.token);
|
|
78213
78948
|
if (token === void 0) return {
|
|
78214
78949
|
state: "failed",
|
|
78215
|
-
reason: "
|
|
78950
|
+
reason: t("qo.devicePollNoToken", { provider: PROVIDER_NAME$4 })
|
|
78216
78951
|
};
|
|
78217
78952
|
return {
|
|
78218
78953
|
state: "ready",
|
|
@@ -78279,7 +79014,7 @@ async function qoderCredentialsFromDevicePoll(ready, machineId, options = {}) {
|
|
|
78279
79014
|
*/
|
|
78280
79015
|
async function qoderCredentialsFromPat(personalToken, region, options = {}) {
|
|
78281
79016
|
const pat = personalToken.trim();
|
|
78282
|
-
if (pat === "") throw new Error("
|
|
79017
|
+
if (pat === "") throw new Error(t("qo.patEmpty", { provider: PROVIDER_NAME$4 }));
|
|
78283
79018
|
if (!pat.startsWith("pt-")) throw new Error("Qoder(订阅) 的 PAT 格式不对:它必须以 `pt-` 开头,粘贴时不要带引号或多余空白。令牌在 https://qoder.com/account/integrations(中国站是 https://qoder.com.cn/account/integrations)生成。");
|
|
78284
79019
|
const candidates = [region, ...QODER_REGIONS.filter((other) => other !== region)];
|
|
78285
79020
|
let resolved = region;
|
|
@@ -78363,7 +79098,7 @@ async function refreshQoderCredential(credentials, fetchFn = fetch) {
|
|
|
78363
79098
|
} : {}
|
|
78364
79099
|
};
|
|
78365
79100
|
if (credentials.refreshToken === null || credentials.refreshToken === "") {
|
|
78366
|
-
const error =
|
|
79101
|
+
const error = new Error(t("qo.noRefreshToken", { provider: PROVIDER_NAME$4 }));
|
|
78367
79102
|
error.status = 401;
|
|
78368
79103
|
throw error;
|
|
78369
79104
|
}
|
|
@@ -78404,7 +79139,7 @@ function sleep(ms, signal) {
|
|
|
78404
79139
|
clearTimeout(timer);
|
|
78405
79140
|
cleanup();
|
|
78406
79141
|
const reason = signal.reason;
|
|
78407
|
-
reject(reason instanceof Error ? reason :
|
|
79142
|
+
reject(reason instanceof Error ? reason : new Error(t("qo.cancelled")));
|
|
78408
79143
|
}
|
|
78409
79144
|
if (signal.aborted) {
|
|
78410
79145
|
onAbort();
|
|
@@ -78429,7 +79164,10 @@ async function beginQoderLogin(region, options = {}) {
|
|
|
78429
79164
|
region,
|
|
78430
79165
|
startedAt,
|
|
78431
79166
|
completedAt: Date.now(),
|
|
78432
|
-
error: "
|
|
79167
|
+
error: t("qo.cnNoBrowserLogin", {
|
|
79168
|
+
provider: PROVIDER_NAME$4,
|
|
79169
|
+
patPage: REGION_HOSTS$1.cn.patPage
|
|
79170
|
+
}),
|
|
78433
79171
|
retryable: false
|
|
78434
79172
|
};
|
|
78435
79173
|
return getQoderLoginStatus();
|
|
@@ -78447,13 +79185,13 @@ async function beginQoderLogin(region, options = {}) {
|
|
|
78447
79185
|
startedAt,
|
|
78448
79186
|
expiresAt: deadline,
|
|
78449
79187
|
pollIntervalSec: DEVICE_POLL_INTERVAL_MS / 1e3,
|
|
78450
|
-
progress: "
|
|
79188
|
+
progress: t("qo.waitingBrowserPoll", { seconds: DEVICE_POLL_INTERVAL_MS / 1e3 })
|
|
78451
79189
|
};
|
|
78452
79190
|
(async () => {
|
|
78453
79191
|
try {
|
|
78454
79192
|
for (;;) {
|
|
78455
79193
|
active.signal.throwIfAborted();
|
|
78456
|
-
if (Date.now() >= deadline) throw new Error("
|
|
79194
|
+
if (Date.now() >= deadline) throw new Error(t("qo.loginTimeout", { provider: PROVIDER_NAME$4 }));
|
|
78457
79195
|
const result = await pollQoderDeviceToken({
|
|
78458
79196
|
nonce: params.nonce,
|
|
78459
79197
|
verifier: params.verifier
|
|
@@ -78476,7 +79214,7 @@ async function beginQoderLogin(region, options = {}) {
|
|
|
78476
79214
|
completedAt: Date.now(),
|
|
78477
79215
|
expiresAt: deadline,
|
|
78478
79216
|
pollIntervalSec: DEVICE_POLL_INTERVAL_MS / 1e3,
|
|
78479
|
-
progress: "
|
|
79217
|
+
progress: t("qo.authorized"),
|
|
78480
79218
|
...credentials.uid === null ? {} : { uid: credentials.uid }
|
|
78481
79219
|
};
|
|
78482
79220
|
return;
|
|
@@ -78579,7 +79317,7 @@ function projectAccount(input) {
|
|
|
78579
79317
|
* 抛错等于让一行坏数据带走整个池。
|
|
78580
79318
|
*/
|
|
78581
79319
|
function parseQoderPoolData(value) {
|
|
78582
|
-
if (!isRecord$19(value)) throw new Error("
|
|
79320
|
+
if (!isRecord$19(value)) throw new Error(t("qo.poolPayloadInvalid", { provider: PROVIDER_NAME$4 }));
|
|
78583
79321
|
const accounts = [];
|
|
78584
79322
|
for (const item of Array.isArray(value.accounts) ? value.accounts : []) {
|
|
78585
79323
|
if (!isRecord$19(item) || typeof item.id !== "string") continue;
|
|
@@ -78724,7 +79462,7 @@ var QoderAccountPool = class extends AccountPoolCore {
|
|
|
78724
79462
|
const target = data.accounts.find((account) => account.id === data.activeAccountId) ?? data.accounts.find((account) => account.isPrimary) ?? data.accounts[0];
|
|
78725
79463
|
if (target === void 0) {
|
|
78726
79464
|
await this.getFreshCredential(void 0, fetchFn);
|
|
78727
|
-
throw new Error("
|
|
79465
|
+
throw new Error(t("qo.poolEmpty", { provider: PROVIDER_NAME$4 }));
|
|
78728
79466
|
}
|
|
78729
79467
|
return {
|
|
78730
79468
|
accountId: target.id,
|
|
@@ -79352,7 +80090,7 @@ function registerQoderRoutes(ctx, settings, options = {}) {
|
|
|
79352
80090
|
if (!isSameOriginMutation(request)) return sendCrossOrigin(response);
|
|
79353
80091
|
if (accountPool === void 0) return sendJson$2(response, 400, {
|
|
79354
80092
|
ok: false,
|
|
79355
|
-
error: "
|
|
80093
|
+
error: t("qo.poolNotInstalled")
|
|
79356
80094
|
});
|
|
79357
80095
|
const body = await readRequestJson$2(request);
|
|
79358
80096
|
const action = typeof body.action === "string" ? body.action : "";
|
|
@@ -79360,7 +80098,7 @@ function registerQoderRoutes(ctx, settings, options = {}) {
|
|
|
79360
80098
|
const strategy = body.strategy;
|
|
79361
80099
|
if (strategy !== "sequential" && strategy !== "round-robin" && strategy !== "sticky") return sendJson$2(response, 400, {
|
|
79362
80100
|
ok: false,
|
|
79363
|
-
error: "
|
|
80101
|
+
error: t("qo.unknownStrategy")
|
|
79364
80102
|
});
|
|
79365
80103
|
await accountPool.setStrategy(strategy);
|
|
79366
80104
|
return sendJson$2(response, 200, {
|
|
@@ -79389,7 +80127,7 @@ function registerQoderRoutes(ctx, settings, options = {}) {
|
|
|
79389
80127
|
break;
|
|
79390
80128
|
default: return sendJson$2(response, 400, {
|
|
79391
80129
|
ok: false,
|
|
79392
|
-
error: "
|
|
80130
|
+
error: t("qo.unknownAccountAction", { action })
|
|
79393
80131
|
});
|
|
79394
80132
|
}
|
|
79395
80133
|
return sendJson$2(response, 200, {
|
|
@@ -79432,7 +80170,7 @@ function registerQoderRoutes(ctx, settings, options = {}) {
|
|
|
79432
80170
|
const token = typeof body.token === "string" ? body.token : "";
|
|
79433
80171
|
if (token.trim() === "") return sendJson$2(response, 400, {
|
|
79434
80172
|
ok: false,
|
|
79435
|
-
error: "
|
|
80173
|
+
error: t("qo.pastePat")
|
|
79436
80174
|
});
|
|
79437
80175
|
const credentials = await qoderCredentialsFromPat(token, regionFromBody(body), {
|
|
79438
80176
|
fetchFn,
|
|
@@ -79578,7 +80316,7 @@ async function probeConnection$1(accountPool, fetchFn, env) {
|
|
|
79578
80316
|
account: null,
|
|
79579
80317
|
model: null,
|
|
79580
80318
|
checkedAt,
|
|
79581
|
-
error: "
|
|
80319
|
+
error: t("qo.notSignedIn", { provider: PROVIDER_NAME$4 })
|
|
79582
80320
|
};
|
|
79583
80321
|
const credentials = upstreamCredentialOf(target.credentials);
|
|
79584
80322
|
const started = Date.now();
|
|
@@ -79602,7 +80340,7 @@ async function probeConnection$1(accountPool, fetchFn, env) {
|
|
|
79602
80340
|
account: null,
|
|
79603
80341
|
model: null,
|
|
79604
80342
|
checkedAt,
|
|
79605
|
-
error: "
|
|
80343
|
+
error: t("qo.catalogHttp", { status: response.status }) + (detail === "" ? "" : ":" + detail.replace(/[\p{Cc}\p{Cf}]/gu, "").trim().slice(0, 160))
|
|
79606
80344
|
};
|
|
79607
80345
|
}
|
|
79608
80346
|
const entries = parseQoderModelListing(await response.json().catch(() => void 0), credentials.region);
|
|
@@ -82579,7 +83317,7 @@ var OpenDesignAdapter = class extends LlmAdapter {
|
|
|
82579
83317
|
providerInfo(provider) {
|
|
82580
83318
|
return {
|
|
82581
83319
|
id: provider,
|
|
82582
|
-
name: PROVIDER_NAME$2
|
|
83320
|
+
name: localizedProviderName(provider, PROVIDER_NAME$2)
|
|
82583
83321
|
};
|
|
82584
83322
|
}
|
|
82585
83323
|
providerRetryPolicy() {
|
|
@@ -99531,7 +100269,7 @@ var WorkBuddyAdapter = class extends LlmAdapter {
|
|
|
99531
100269
|
providerInfo(provider) {
|
|
99532
100270
|
return {
|
|
99533
100271
|
id: provider,
|
|
99534
|
-
name: PROVIDER_NAME$3
|
|
100272
|
+
name: localizedProviderName(provider, PROVIDER_NAME$3)
|
|
99535
100273
|
};
|
|
99536
100274
|
}
|
|
99537
100275
|
providerRetryPolicy() {
|
|
@@ -100171,7 +100909,7 @@ function parseWorkBuddyPoolState(value) {
|
|
|
100171
100909
|
if (typeof raw.pause === "object" && raw.pause !== null && !Array.isArray(raw.pause)) {
|
|
100172
100910
|
const record = raw.pause;
|
|
100173
100911
|
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 : "
|
|
100912
|
+
reason: typeof record.reason === "string" ? record.reason : t("wb.pool.pausedDefault"),
|
|
100175
100913
|
pausedSince: record.pausedSince,
|
|
100176
100914
|
pausedUntil: record.pausedUntil,
|
|
100177
100915
|
triggeredBy: Array.isArray(record.triggeredBy) ? record.triggeredBy.filter((id) => typeof id === "string") : []
|
|
@@ -100303,7 +101041,7 @@ function backendFromDomain(domain) {
|
|
|
100303
101041
|
* which is the case that used to be reported as "the account shows 账号 1".
|
|
100304
101042
|
*/
|
|
100305
101043
|
function defaultAliasFor(credentials, position) {
|
|
100306
|
-
return credentials.nickname || credentials.uin || credentials.uid ||
|
|
101044
|
+
return credentials.nickname || credentials.uin || credentials.uid || t("wb.pool.accountLabel", { position });
|
|
100307
101045
|
}
|
|
100308
101046
|
/**
|
|
100309
101047
|
* A meter's consumed share, from whichever fraction this line measured.
|
|
@@ -100493,7 +101231,11 @@ var WorkBuddyAccountPool = class extends AccountPoolCore {
|
|
|
100493
101231
|
/** The error every selection raises while the pool is paused. */
|
|
100494
101232
|
pausedError(pause, now = Date.now()) {
|
|
100495
101233
|
const minutes = Math.max(1, Math.ceil((pause.pausedUntil - now) / 6e4));
|
|
100496
|
-
return new WorkBuddyPoolPausedError(
|
|
101234
|
+
return new WorkBuddyPoolPausedError(t("wb.pool.paused", {
|
|
101235
|
+
provider: PROVIDER_NAME$3,
|
|
101236
|
+
reason: pause.reason,
|
|
101237
|
+
minutes
|
|
101238
|
+
}), pause.pausedUntil);
|
|
100497
101239
|
}
|
|
100498
101240
|
/**
|
|
100499
101241
|
* Record an account-scoped refusal reported by the protocol worker.
|
|
@@ -100520,7 +101262,11 @@ var WorkBuddyAccountPool = class extends AccountPoolCore {
|
|
|
100520
101262
|
* log instead of silently barring a healthy account.
|
|
100521
101263
|
*/
|
|
100522
101264
|
async markAccountRestriction(accountId, restriction) {
|
|
100523
|
-
if (restriction.code !== 11140) throw new Error(
|
|
101265
|
+
if (restriction.code !== 11140) throw new Error(t("wb.pool.notAccountScoped", {
|
|
101266
|
+
provider: PROVIDER_NAME$3,
|
|
101267
|
+
expected: WORKBUDDY_RESTRICTED_ACCOUNT_CODE,
|
|
101268
|
+
code: restriction.code
|
|
101269
|
+
}));
|
|
100524
101270
|
const now = Date.now();
|
|
100525
101271
|
const record = {
|
|
100526
101272
|
code: restriction.code,
|
|
@@ -100537,7 +101283,11 @@ var WorkBuddyAccountPool = class extends AccountPoolCore {
|
|
|
100537
101283
|
if (others.length > 0) {
|
|
100538
101284
|
const windowMinutes = Math.round(WORKBUDDY_RESTRICTION_ESCALATION_WINDOW_MS / 6e4);
|
|
100539
101285
|
state.pause = {
|
|
100540
|
-
reason:
|
|
101286
|
+
reason: t("wb.pool.upstreamRefused", {
|
|
101287
|
+
code: restriction.code,
|
|
101288
|
+
minutes: windowMinutes,
|
|
101289
|
+
count: others.length + 1
|
|
101290
|
+
}),
|
|
100541
101291
|
pausedSince: now,
|
|
100542
101292
|
pausedUntil: now + WORKBUDDY_POOL_PAUSE_MS,
|
|
100543
101293
|
triggeredBy: Object.keys(state.restrictions)
|
|
@@ -100853,7 +101603,7 @@ var WorkBuddyAccountPool = class extends AccountPoolCore {
|
|
|
100853
101603
|
* the user their account was deleted. Hiding is the supported action there.
|
|
100854
101604
|
*/
|
|
100855
101605
|
deleteAccountFromPool(data, accountId) {
|
|
100856
|
-
if (data.accounts.find((account) => account.id === accountId)?.source === "desktop") throw new Error("
|
|
101606
|
+
if (data.accounts.find((account) => account.id === accountId)?.source === "desktop") throw new Error(t("wb.pool.desktopAccountUndeletable"));
|
|
100857
101607
|
super.deleteAccountFromPool(data, accountId);
|
|
100858
101608
|
}
|
|
100859
101609
|
};
|
|
@@ -100930,10 +101680,14 @@ async function requestLoginState(region, fetchFn = fetch, signal) {
|
|
|
100930
101680
|
} catch {
|
|
100931
101681
|
root = void 0;
|
|
100932
101682
|
}
|
|
100933
|
-
if (!response.ok || root?.code !== 0 || !isRecord$1(root.data)) throw new Error(
|
|
101683
|
+
if (!response.ok || root?.code !== 0 || !isRecord$1(root.data)) throw new Error(t("wb.oauth.loginInitFailed", {
|
|
101684
|
+
provider: PROVIDER_NAME$3,
|
|
101685
|
+
status: response.status,
|
|
101686
|
+
detail: stringOf(root ?? {}, "msg") ?? text.slice(0, 160)
|
|
101687
|
+
}));
|
|
100934
101688
|
const state = stringOf(root.data, "state");
|
|
100935
101689
|
const authUrl = stringOf(root.data, "authUrl");
|
|
100936
|
-
if (!state || !authUrl) throw new Error(
|
|
101690
|
+
if (!state || !authUrl) throw new Error(t("wb.oauth.loginMissingState", { provider: PROVIDER_NAME$3 }));
|
|
100937
101691
|
return {
|
|
100938
101692
|
state,
|
|
100939
101693
|
authUrl,
|
|
@@ -100943,15 +101697,18 @@ async function requestLoginState(region, fetchFn = fetch, signal) {
|
|
|
100943
101697
|
}
|
|
100944
101698
|
/** Parse the successful token-poll shape while accepting the two observed wrappers. */
|
|
100945
101699
|
function parseLoginCredential(payload, attempt) {
|
|
100946
|
-
if (!isRecord$1(payload)) throw new Error(
|
|
101700
|
+
if (!isRecord$1(payload)) throw new Error(t("wb.oauth.loginPollInvalid", { provider: PROVIDER_NAME$3 }));
|
|
100947
101701
|
const code = numberOf(payload, "code");
|
|
100948
101702
|
if (code === 11217) return null;
|
|
100949
|
-
if (code !== 0) throw new Error(
|
|
101703
|
+
if (code !== 0) throw new Error(t("wb.oauth.loginFailed", {
|
|
101704
|
+
provider: PROVIDER_NAME$3,
|
|
101705
|
+
detail: stringOf(payload, "msg") ?? `code ${String(code)}`
|
|
101706
|
+
}));
|
|
100950
101707
|
const data = isRecord$1(payload.data) ? payload.data : payload;
|
|
100951
101708
|
const auth = isRecord$1(data.auth) ? data.auth : data;
|
|
100952
101709
|
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
101710
|
const accessToken = stringOf(auth, "accessToken") ?? stringOf(auth, "access_token") ?? stringOf(data, "token");
|
|
100954
|
-
if (!accessToken) throw new Error(
|
|
101711
|
+
if (!accessToken) throw new Error(t("wb.oauth.loginMissingToken", { provider: PROVIDER_NAME$3 }));
|
|
100955
101712
|
const domain = stringOf(auth, "domain") ?? attempt.domain;
|
|
100956
101713
|
const expiresIn = numberOf(auth, "expiresIn") ?? numberOf(auth, "expires_in");
|
|
100957
101714
|
const expiresAt = numberOf(auth, "expiresAt") ?? numberOf(auth, "expires_at") ?? (expiresIn === void 0 ? Date.now() + 3600 * 1e3 : Date.now() + expiresIn * 1e3);
|
|
@@ -100978,12 +101735,16 @@ async function pollLogin(attempt, fetchFn = fetch, signal) {
|
|
|
100978
101735
|
signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(2e4)]) : AbortSignal.timeout(2e4)
|
|
100979
101736
|
});
|
|
100980
101737
|
const text = await response.text().catch(() => "");
|
|
100981
|
-
if (!response.ok) throw new Error(
|
|
101738
|
+
if (!response.ok) throw new Error(t("wb.oauth.loginPollFailed", {
|
|
101739
|
+
provider: PROVIDER_NAME$3,
|
|
101740
|
+
status: response.status,
|
|
101741
|
+
detail: text.slice(0, 160)
|
|
101742
|
+
}));
|
|
100982
101743
|
let payload;
|
|
100983
101744
|
try {
|
|
100984
101745
|
payload = JSON.parse(text);
|
|
100985
101746
|
} catch {
|
|
100986
|
-
throw new Error(
|
|
101747
|
+
throw new Error(t("wb.oauth.loginPollNotJson", { provider: PROVIDER_NAME$3 }));
|
|
100987
101748
|
}
|
|
100988
101749
|
return parseLoginCredential(payload, attempt);
|
|
100989
101750
|
}
|
|
@@ -101021,7 +101782,7 @@ async function beginWebLogin$4(store, region, fetchFn = fetch, options = {}) {
|
|
|
101021
101782
|
status: "pending",
|
|
101022
101783
|
region,
|
|
101023
101784
|
authUrl: attempt.authUrl,
|
|
101024
|
-
progress: "
|
|
101785
|
+
progress: t("wb.oauth.waitingBrowser"),
|
|
101025
101786
|
startedAt
|
|
101026
101787
|
};
|
|
101027
101788
|
(async () => {
|
|
@@ -101034,7 +101795,7 @@ async function beginWebLogin$4(store, region, fetchFn = fetch, options = {}) {
|
|
|
101034
101795
|
if (credentials === null) {
|
|
101035
101796
|
flow = {
|
|
101036
101797
|
...flow,
|
|
101037
|
-
progress:
|
|
101798
|
+
progress: t("wb.oauth.waitingBrowserElapsed", { seconds: Math.floor((Date.now() - startedAt) / 1e3) })
|
|
101038
101799
|
};
|
|
101039
101800
|
continue;
|
|
101040
101801
|
}
|
|
@@ -101047,7 +101808,7 @@ async function beginWebLogin$4(store, region, fetchFn = fetch, options = {}) {
|
|
|
101047
101808
|
accountId: workBuddyAccountId(resolved),
|
|
101048
101809
|
startedAt,
|
|
101049
101810
|
completedAt: Date.now(),
|
|
101050
|
-
progress: "
|
|
101811
|
+
progress: t("wb.oauth.authorized")
|
|
101051
101812
|
};
|
|
101052
101813
|
return;
|
|
101053
101814
|
}
|
|
@@ -101056,7 +101817,7 @@ async function beginWebLogin$4(store, region, fetchFn = fetch, options = {}) {
|
|
|
101056
101817
|
region,
|
|
101057
101818
|
startedAt,
|
|
101058
101819
|
completedAt: Date.now(),
|
|
101059
|
-
error: "
|
|
101820
|
+
error: t("wb.oauth.loginTimeout")
|
|
101060
101821
|
};
|
|
101061
101822
|
} catch (error) {
|
|
101062
101823
|
if (active.signal.aborted) return;
|
|
@@ -102166,7 +102927,8 @@ const Config = z$1.object({
|
|
|
102166
102927
|
progressUpdatesLanguage: z$1.union([
|
|
102167
102928
|
z$1.const("auto"),
|
|
102168
102929
|
z$1.const("zh"),
|
|
102169
|
-
z$1.const("en")
|
|
102930
|
+
z$1.const("en"),
|
|
102931
|
+
z$1.const("ru")
|
|
102170
102932
|
]).default("auto").volatile().description("进展更新的输出语言:auto 跟随对话语言,zh 中文,en 英文。"),
|
|
102171
102933
|
planModePipeline: z$1.boolean().default(true).volatile().description("启用计划模式管线:允许调度模式在澄清访谈收敛后用 enter_plan_mode 进入计划模式,放弃规划时用 leave_plan_mode 退出。"),
|
|
102172
102934
|
dispatchExecutionGuard: z$1.boolean().default(true).volatile().description("启用调度执行守卫:在执行期拦截子代理越权调用主控专用工具,并拦截等待子代理期间的纯 sleep 空等命令;不修改工具声明面,零损耗保护 Kimi 缓存。"),
|
|
@@ -102185,6 +102947,8 @@ const inject = [
|
|
|
102185
102947
|
"loader"
|
|
102186
102948
|
];
|
|
102187
102949
|
function apply(ctx, pluginConfig = {}) {
|
|
102950
|
+
installHostLocale(new HostLocaleRuntime());
|
|
102951
|
+
ctx.effect(() => () => installHostLocale(void 0), "dsh-chatgpt-subscription: host locale");
|
|
102188
102952
|
const fetchConfiguration = resolveFetchConfiguration(pluginConfig);
|
|
102189
102953
|
const poolStorageSettings = new PoolStorageSettings();
|
|
102190
102954
|
poolStorageSettings.hydrate().catch(() => void 0);
|