@mars-sea/dsh-commandcode-provider 0.11.6 → 0.11.8
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 +15 -0
- package/lib/client.js +1 -1
- package/lib/index.d.ts +50 -15
- package/lib/index.js +198 -51
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.11.8] - 2026-09-22
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- **Synced with the official command-code@1.62.0 CLI** (2026-09-22 check of the 2026-09-21 npm `latest`; five releases since the last sync — 1.58.1, then the 1.59.0/1.60.0/1.61.0/1.62.0 train whose changelog entries are "Add Grok 4.7", "Add Step 5 Preview", "Grok 4.7 40% off" and "Add MiMo V2.6 Flash / Add MiMo V2.6 Pro and Pro UltraSpeed"). `COMMAND_CODE_CLI_VERSION` is now `1.62.0`. This train is purely additive: the CLI registry grows 78 → 83 with exactly five additions and no removal or edit, so five models gain their picker annotations and prices. `xai/grok-4.7` (500K context, text+image, `low`/`medium`/`high`/`xhigh` efforts, GOAT and above) launches on a 40% off deal running 2026-09-21 → 2026-09-27 that reverts to $2.00 in / $6.00 out when it lapses; its snapshotted rates are the discounted $1.20 in / $3.60 out / $0.30 cache read, doubling to $2.40 / $7.20 / $0.60 past 200K, and the deal carries the page's own expiry stamp so the badge hides itself after that instant. `stepfun/Step-5-Preview` is StepFun's 600B sparse-MoE agentic coding model (1M context, text+image, `low`/`medium`/`high` efforts, Go, $1.00 / $2.70 / $0.05). The MiMo V2.6 family is text+image with a 1,048,576-token context and no reasoning flag in any source: `xiaomi/mimo-v2.6-flash` ($0.14 / $0.28 / $0.0028) and `xiaomi/mimo-v2.6-pro` ($0.435 / $0.87 / $0.0036) on Go, plus `xiaomi/mimo-v2.6-pro-ultraspeed` on GOAT and above ($4.35 / $8.70 / $0.036). In snapshot terms: the effort map gains exactly two keys (46 → 48), the Vision set the five (52 → 57), the plan map three Go and two GOAT entries without moving a tier (46/52/65/72 → 49/57/70/77), the deals five → six, and the vendored price table exactly the five matching rows (71 → 76) with no rate change to any existing row (`node scripts/sync-model-prices.mjs --check` now reports all 76 rows up to date). Everything else is re-verified unchanged against both bundles and the public sources: the subscription plan maps, the peak/off-peak membership and schedule (01:00–04:00 and 06:00–10:00 UTC, Monday–Friday only), the automatic-reasoning set, and the public catalog — which serves 76 models (71 + the five) with its route mix moving 55 → 60 × chat/completions + responses exactly by those additions, the same 8 Claude ids still messages-only and 8 models still chat/completions-only, which agrees with the adapter's `claude-*` routing rule. Static inspection of the two bundles finds no transport drift: the `/alpha/*` endpoint set, the `/alpha/generate` converters (`toWireMessages`/`toWireTools`/`toWireToolOutput`), the stream event vocabulary, the `x-command-code-version` header, the browser-login call site and the web-search field names differ only by minified variable renames, and the documented Provider API endpoint set is unchanged. Two CLI-local changelog items reach nothing this adapter owns: 1.58.1's "Auto-compact past images and keep their result" (the CLI's own compaction behavior, not a wire change) and 1.59.0's YOLO/accept-edits keybinding rework. The two upstream leftovers stay deliberately un-snapshotted, exactly as the previous check recorded them: `gpt-6-astra` is still a CLI/pricing/docs-only model the public catalog does not serve, and the pricing page still embeds an already-expired (`2026-06-22`) `qwen-3.7-max-2x-usage` deal record its own Deals section does not list.
|
|
14
|
+
|
|
15
|
+
## [0.11.7] - 2026-09-20
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- **A plain 429 is no longer reported as an exhausted usage window** ([#54](https://github.com/Mars-Sea/dsh-commandcode-provider/issues/54)). The report was a contradiction: the turn failed with `llm-commandcode: all 1 Command Code account(s) have exhausted their usage window` while the account card at that moment showed the five-hour window at 2% ($0.22 / $14.00) and the weekly one at 10% ($3.43 / $35.00), and the reporter noted it only reproduced at the default reasoning effort and always recovered by itself a little later. The message was the tell: it carried no "the earliest window resets at …" clause, and that clause appears only when a mark is a `cooldown` with a known reset — so the pool was reporting an exhausted window from a mark that had no reset at all, i.e. from nothing but a 429. The chain: `classifyAccountRejection()` treated ANY 429 (or a bare `RATE_LIMITED` code) as a usage-window rejection, `markRejected()` filed it as `unknown`, the follow-up `/alpha/billing/credits` probe either failed (the same account was still being refused) or read no reset, and `allAccountsUnusable()` then asserted "exhausted their usage window" regardless of the evidence — exactly the sentence the reporter was shown. Classification now follows the official CLI's own bar (command-code@1.56.0 `parseWindowLimitError` → `resolveWindowLabel`): a rejection is a WINDOW limit only when the body names one — `error.rateLimit.window` of `fiveHour`/`weekly`/`daily`, or the "usage limit for your plan" wording — and `readWindowLimitEvidence()` reads that window and its `reset` (seconds, with the `resets at <ISO>` wording as the fallback) in one place. Everything else stays a new `throttled` reason: it rotates and marks the key exactly like a window limit does (so rotation across a multi-account pool is unchanged, and a burst or model-level limiter still moves the request off that key), but the mark carries a `cause` — `window`, `throttle` or `auth` — and only a `window` cause may be described as an exhausted window. A throttle mark is deliberately left `unknown` with no reset, so the next all-marked pass still probes the real windows and upgrades the cause to `window` when a probe reads one as exceeded; a throttle mark that a probe cannot confirm now answers `all N Command Code account(s) are rate limited (429) — the provider did not report an exhausted usage window; retrying` instead, with no invented reset and no invented wait. The same honesty was applied to a window mark whose provider published no reset (`— the provider published no reset time for it` / `,服务商未公布重置时间`), where the old message silently said nothing, and the adapter's end-of-turn `RATE_LIMIT` for a non-429 status carrying a bare `RATE_LIMITED` now says the same thing. `tests/accounts.test.ts` pins the throttle diagnosis (and that it never claims a window), the probe upgrade from throttle to window, the reset-stamped window cooldown, and the no-reset wording; `tests/adapter.test.ts` pins the classification of a bare 429 as `throttled`, the three window-carrying shapes as `rate-limit` (including the plan-usage-limit wording and a window without a reset), and the end-of-turn message.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **Synced with the official command-code@1.58.0 CLI** (2026-09-20 check of the 2026-09-19 npm `latest`, whose changelog entry is "Retire the free LongCat 2.0 tier and sell LongCat 2.0 as a paid model"). `COMMAND_CODE_CLI_VERSION` is now `1.58.0`. The CLI registry grows 77 → 78 with exactly one addition — the paid `meituan/LongCat-2.0` — while its retired `meituan/LongCat-2.0:free` sibling gains `hidden` and the display name "LongCat 2.0 (Free)": that is the CLI catching up with the backend rename the 1.57.0 sync had already snapshotted, so no capability-snapshot entry moves, the model was already served under the paid id at $0.30 in / $1.20 out / $0.006 cache read on Go, and no runtime behavior changes. Everything else is re-verified unchanged against both the bundle and the public sources: the per-model effort map, the subscription plan maps (8 plans including their monthly credits), every plan tier (map still 46/52/65/72), the five model deals, the peak/off-peak membership and schedule (01:00–04:00 and 06:00–10:00 UTC, Monday–Friday only), the vendored price table (`node scripts/sync-model-prices.mjs --check` reports all 71 rows up to date), and the public catalog (71 models, its `supported_endpoints` mix still 55 × chat/completions + responses, the same 8 Claude ids × messages-only, 8 × chat/completions, which agrees with the adapter's `claude-*` routing rule). Static inspection of both bundles finds no transport drift: the `/alpha/*` endpoint set, the `/alpha/generate` converters (`toWireMessages`/`toWireTools`/`toWireToolOutput`), the stream event vocabulary, the `x-command-code-version` header, the browser-login call site and the web-search field names are byte-identical to 1.57.0, and the documented Provider API endpoint set is unchanged. Two upstream leftovers stay deliberately un-snapshotted, exactly as the previous check recorded them: `gpt-6-astra` is still a CLI/pricing/docs-only model the public catalog does not serve, and the pricing page still embeds an already-expired (`2026-06-22`) `qwen-3.7-max-2x-usage` deal record that its own Deals section does not list. The Provider API docs now also document the optional `x-cmd-zdr: 1` zero-data-retention header (the CLI parity of `CMD_ZDR=1`); this plugin does not send it, because ZDR opt-in would be a new feature rather than a data sync.
|
|
23
|
+
|
|
9
24
|
## [0.11.6] - 2026-09-19
|
|
10
25
|
|
|
11
26
|
### Fixed
|
package/lib/client.js
CHANGED
|
@@ -2157,7 +2157,7 @@ window.__ModuleLoader__.load({
|
|
|
2157
2157
|
}
|
|
2158
2158
|
//#endregion
|
|
2159
2159
|
//#region package.json
|
|
2160
|
-
var version = "0.11.
|
|
2160
|
+
var version = "0.11.8";
|
|
2161
2161
|
var repository = {
|
|
2162
2162
|
"type": "git",
|
|
2163
2163
|
"url": "git+https://github.com/Mars-Sea/dsh-commandcode-provider.git"
|
package/lib/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { Context } from "@deepseek-ai/cordis";
|
|
|
7
7
|
import { AttachmentStore, ImageAttachmentRef } from "@deepseek-ai/dsh-attachment";
|
|
8
8
|
import { CommandDefinition } from "@deepseek-ai/dsh-commands";
|
|
9
9
|
//#region src/adapter.d.ts
|
|
10
|
-
declare const COMMAND_CODE_CLI_VERSION = "1.
|
|
10
|
+
declare const COMMAND_CODE_CLI_VERSION = "1.62.0";
|
|
11
11
|
declare const DEFAULT_API_BASE = "https://api.commandcode.ai";
|
|
12
12
|
declare const DEFAULT_GENERATE_MAX_TOKENS = 64000;
|
|
13
13
|
declare const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
|
|
@@ -101,14 +101,19 @@ interface CommandCodeConnectionOptions {
|
|
|
101
101
|
*/
|
|
102
102
|
type ResolveAttachments = () => AttachmentStore | undefined;
|
|
103
103
|
/**
|
|
104
|
-
* Why a pre-stream rejection rotates to another account. `rate-limit`
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* is
|
|
104
|
+
* Why a pre-stream rejection rotates to another account. `rate-limit` (a usage
|
|
105
|
+
* window the provider NAMED), `throttled` (a 429 that named no window) and
|
|
106
|
+
* `invalid-credential` are the three the pool records as marks; `unavailable`
|
|
107
|
+
* is an account-scoped rejection that must NOT become a mark — the account's
|
|
108
|
+
* key is valid and its windows may be open, the ACCOUNT just cannot serve THIS
|
|
108
109
|
* request (no credits, a model outside its plan) — so the pool moves on
|
|
109
110
|
* without remembering anything.
|
|
111
|
+
*
|
|
112
|
+
* The window/throttle split decides what the pool may CLAIM, never whether it
|
|
113
|
+
* rotates: both leave rotation and mark the key, but only a named window lets
|
|
114
|
+
* the pool report an exhausted usage window (issue #54).
|
|
110
115
|
*/
|
|
111
|
-
type AccountRotationReason = 'rate-limit' | 'invalid-credential' | 'unavailable';
|
|
116
|
+
type AccountRotationReason = 'rate-limit' | 'throttled' | 'invalid-credential' | 'unavailable';
|
|
112
117
|
/** What the rotation hook knows about the request it is rotating within. */
|
|
113
118
|
interface AccountRotationContext {
|
|
114
119
|
/** Every API key this request has already used, just-rejected key included. */
|
|
@@ -461,8 +466,21 @@ interface CommandCodeAccountSlot {
|
|
|
461
466
|
/** Whether the official CLI auth file may back this slot (default slot only). */
|
|
462
467
|
allowAuthFile: boolean;
|
|
463
468
|
}
|
|
464
|
-
/**
|
|
465
|
-
|
|
469
|
+
/**
|
|
470
|
+
* Why a key stopped serving requests.
|
|
471
|
+
*
|
|
472
|
+
* `rate-limit` is a USAGE-WINDOW rejection: the provider named one of its
|
|
473
|
+
* metered windows (`error.rateLimit.window`, or a message saying the plan's
|
|
474
|
+
* usage limit was reached — the only two shapes the official CLI's own
|
|
475
|
+
* `parseWindowLimitError`/`resolveWindowLabel` accept). `throttled` is the
|
|
476
|
+
* plain 429: the provider refused the request without saying anything about a
|
|
477
|
+
* window, so the key leaves rotation for now but the pool must not describe it
|
|
478
|
+
* as an exhausted window. Collapsing the two is issue #54: the reporter's
|
|
479
|
+
* account panel showed the five-hour window at 2% and the weekly one at 10%
|
|
480
|
+
* while the turn failed with "all 1 Command Code account(s) have exhausted
|
|
481
|
+
* their usage window".
|
|
482
|
+
*/
|
|
483
|
+
type AccountRejection = 'rate-limit' | 'throttled' | 'invalid-credential';
|
|
466
484
|
/** One key's rotation state. */
|
|
467
485
|
interface CommandCodeAccountState {
|
|
468
486
|
kind:
|
|
@@ -472,6 +490,14 @@ interface CommandCodeAccountState {
|
|
|
472
490
|
'cooldown' |
|
|
473
491
|
/** Marked by a 401: skipped until the stored credential changes. */
|
|
474
492
|
'disabled';
|
|
493
|
+
/**
|
|
494
|
+
* The evidence behind the mark — what the pool may CLAIM when it reports
|
|
495
|
+
* that no account can serve. `window`: the provider named a usage window, or
|
|
496
|
+
* a `/alpha/billing/credits` probe read one as exceeded. `throttle`: a 429
|
|
497
|
+
* that said nothing about a window (a burst limiter, or a model- or
|
|
498
|
+
* spend-level limit the billing endpoint cannot show). `auth`: a 401.
|
|
499
|
+
*/
|
|
500
|
+
cause: 'window' | 'throttle' | 'auth';
|
|
475
501
|
/** Human-readable reason for the mark (e.g. `rate limited (429)`). */
|
|
476
502
|
reason: string;
|
|
477
503
|
/** Cooldown end in millis; 0 for the other kinds. */
|
|
@@ -628,16 +654,21 @@ declare class CommandCodeAccountPool {
|
|
|
628
654
|
slot: CommandCodeAccountSlot;
|
|
629
655
|
} | undefined>;
|
|
630
656
|
/**
|
|
631
|
-
* Record a rejection against one key. `rate-limit` marks the key
|
|
632
|
-
*
|
|
633
|
-
*
|
|
634
|
-
*
|
|
635
|
-
*
|
|
657
|
+
* Record a rejection against one key. `rate-limit` marks the key's usage
|
|
658
|
+
* WINDOW exhausted — as a `cooldown` until `resetAtMs` when the rejection
|
|
659
|
+
* body named the provider's own reset time, otherwise as an `unknown` mark
|
|
660
|
+
* whose window is probed lazily. `throttled` (the plain 429 that named no
|
|
661
|
+
* window) marks the key with the `throttle` cause instead: it leaves rotation
|
|
662
|
+
* exactly like a window mark does, but the pool's own diagnosis keeps saying
|
|
663
|
+
* "rate limited" rather than inventing an exhausted window. A 401
|
|
664
|
+
* (`invalid-credential`) disables the key until the stored credential
|
|
665
|
+
* changes.
|
|
636
666
|
*
|
|
637
667
|
* `resetAtMs` is seconds-to-millis converted by the adapter from the
|
|
638
668
|
* provider's `error.rateLimit.reset`: knowing the real reset immediately is
|
|
639
669
|
* what keeps an exhausted account out of rotation for exactly as long as the
|
|
640
|
-
* provider said
|
|
670
|
+
* provider said. It only applies to a window mark; a plain throttle keeps the
|
|
671
|
+
* window unknown on purpose, so a probe can still find out.
|
|
641
672
|
*/
|
|
642
673
|
markRejected(apiKey: string, rejection: AccountRejection, resetAtMs?: number): void;
|
|
643
674
|
/**
|
|
@@ -778,7 +809,11 @@ declare const KNOWN_THINKING_MODELS: ReadonlySet<string>;
|
|
|
778
809
|
* free `inclusionai/ling-3.0-flash-sante:free` (Go); command-code@1.53.0
|
|
779
810
|
* added `deepseek/deepseek-v4.1-flash` (Go); command-code@1.56.0 added
|
|
780
811
|
* `Qwen/Qwen3.8-Omni-Flash` (Go); command-code@1.57.0 added
|
|
781
|
-
* `z-ai/glm-5.3-flashx` (Go).
|
|
812
|
+
* `z-ai/glm-5.3-flashx` (Go); command-code@1.59.0 added `xai/grok-4.7` (GOAT)
|
|
813
|
+
* and 1.60.0 added `stepfun/Step-5-Preview` (Go); command-code@1.62.0 added the
|
|
814
|
+
* MiMo V2.6 family — `xiaomi/mimo-v2.6-flash` + `xiaomi/mimo-v2.6-pro` (Go) and
|
|
815
|
+
* `xiaomi/mimo-v2.6-pro-ultraspeed` (GOAT) — so the 1.58.0 -> 1.62.0 window's
|
|
816
|
+
* only tier changes are additions and the superset chain still holds.
|
|
782
817
|
*
|
|
783
818
|
* The Provider API exposes no plan metadata, so this snapshot is the source of
|
|
784
819
|
* truth for the picker's plan annotation — it answers "which plan do I need to
|
package/lib/index.js
CHANGED
|
@@ -203,6 +203,11 @@ const KNOWN_EFFORTS = {
|
|
|
203
203
|
"high"
|
|
204
204
|
],
|
|
205
205
|
"sakana/fugu-ultra": ["high", "xhigh"],
|
|
206
|
+
"stepfun/Step-5-Preview": [
|
|
207
|
+
"low",
|
|
208
|
+
"medium",
|
|
209
|
+
"high"
|
|
210
|
+
],
|
|
206
211
|
"tencent/hy4-preview": [
|
|
207
212
|
"low",
|
|
208
213
|
"medium",
|
|
@@ -219,6 +224,12 @@ const KNOWN_EFFORTS = {
|
|
|
219
224
|
"high",
|
|
220
225
|
"xhigh"
|
|
221
226
|
],
|
|
227
|
+
"xai/grok-4.7": [
|
|
228
|
+
"low",
|
|
229
|
+
"medium",
|
|
230
|
+
"high",
|
|
231
|
+
"xhigh"
|
|
232
|
+
],
|
|
222
233
|
"z-ai/glm-5.3-flash": [
|
|
223
234
|
"low",
|
|
224
235
|
"high",
|
|
@@ -340,11 +351,16 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
|
|
|
340
351
|
"moonshotai/Kimi-K3",
|
|
341
352
|
"sakana/fugu-ultra",
|
|
342
353
|
"stepfun/Step-3.7-Flash",
|
|
354
|
+
"stepfun/Step-5-Preview",
|
|
343
355
|
"thinkingmachines/inkling",
|
|
344
356
|
"thinkingmachines/inkling-small",
|
|
345
357
|
"xai/grok-4.5",
|
|
346
358
|
"xai/grok-4.6",
|
|
359
|
+
"xai/grok-4.7",
|
|
347
360
|
"xiaomi/mimo-v2.5",
|
|
361
|
+
"xiaomi/mimo-v2.6-flash",
|
|
362
|
+
"xiaomi/mimo-v2.6-pro",
|
|
363
|
+
"xiaomi/mimo-v2.6-pro-ultraspeed",
|
|
348
364
|
"z-ai/glm-5.3-flash",
|
|
349
365
|
"z-ai/glm-5.3-flashx"
|
|
350
366
|
]);
|
|
@@ -458,7 +474,11 @@ function requiresMessagesEndpoint(modelId) {
|
|
|
458
474
|
* free `inclusionai/ling-3.0-flash-sante:free` (Go); command-code@1.53.0
|
|
459
475
|
* added `deepseek/deepseek-v4.1-flash` (Go); command-code@1.56.0 added
|
|
460
476
|
* `Qwen/Qwen3.8-Omni-Flash` (Go); command-code@1.57.0 added
|
|
461
|
-
* `z-ai/glm-5.3-flashx` (Go).
|
|
477
|
+
* `z-ai/glm-5.3-flashx` (Go); command-code@1.59.0 added `xai/grok-4.7` (GOAT)
|
|
478
|
+
* and 1.60.0 added `stepfun/Step-5-Preview` (Go); command-code@1.62.0 added the
|
|
479
|
+
* MiMo V2.6 family — `xiaomi/mimo-v2.6-flash` + `xiaomi/mimo-v2.6-pro` (Go) and
|
|
480
|
+
* `xiaomi/mimo-v2.6-pro-ultraspeed` (GOAT) — so the 1.58.0 -> 1.62.0 window's
|
|
481
|
+
* only tier changes are additions and the superset chain still holds.
|
|
462
482
|
*
|
|
463
483
|
* The Provider API exposes no plan metadata, so this snapshot is the source of
|
|
464
484
|
* truth for the picker's plan annotation — it answers "which plan do I need to
|
|
@@ -501,6 +521,7 @@ const KNOWN_PLANS = {
|
|
|
501
521
|
"poolside/laguna-s-2.1-free": "go",
|
|
502
522
|
"stepfun/Step-3.5-Flash": "go",
|
|
503
523
|
"stepfun/Step-3.7-Flash": "go",
|
|
524
|
+
"stepfun/Step-5-Preview": "go",
|
|
504
525
|
"tencent/hy3-paid": "go",
|
|
505
526
|
"tencent/hy4-preview": "go",
|
|
506
527
|
"thinkingmachines/inkling": "go",
|
|
@@ -508,6 +529,8 @@ const KNOWN_PLANS = {
|
|
|
508
529
|
"xai/grok-4.5": "go",
|
|
509
530
|
"xiaomi/mimo-v2.5": "go",
|
|
510
531
|
"xiaomi/mimo-v2.5-pro": "go",
|
|
532
|
+
"xiaomi/mimo-v2.6-flash": "go",
|
|
533
|
+
"xiaomi/mimo-v2.6-pro": "go",
|
|
511
534
|
"z-ai/glm-5.3-flash": "go",
|
|
512
535
|
"z-ai/glm-5.3-flashx": "go",
|
|
513
536
|
"zai-org/GLM-5": "go",
|
|
@@ -521,6 +544,8 @@ const KNOWN_PLANS = {
|
|
|
521
544
|
"meta/muse-spark-1.2": "goat",
|
|
522
545
|
"meta/muse-spark-1.3": "goat",
|
|
523
546
|
"xai/grok-4.6": "goat",
|
|
547
|
+
"xai/grok-4.7": "goat",
|
|
548
|
+
"xiaomi/mimo-v2.6-pro-ultraspeed": "goat",
|
|
524
549
|
"claude-haiku-4-5-20251001": "pro",
|
|
525
550
|
"claude-sonnet-4-6": "pro",
|
|
526
551
|
"claude-sonnet-5": "pro",
|
|
@@ -691,6 +716,10 @@ const KNOWN_DEALS = {
|
|
|
691
716
|
"MiniMaxAI/MiniMax-M3": { label: "50% off" },
|
|
692
717
|
"xiaomi/mimo-v2.5-pro": { label: "99% off" },
|
|
693
718
|
"xiaomi/mimo-v2.5": { label: "98% off" },
|
|
719
|
+
"xai/grok-4.7": {
|
|
720
|
+
label: "40% off",
|
|
721
|
+
expiresAt: "2026-09-27T23:59:59.999Z"
|
|
722
|
+
},
|
|
694
723
|
"poolside/laguna-s-2.1-free": {
|
|
695
724
|
label: "FREE",
|
|
696
725
|
free: true
|
|
@@ -1273,6 +1302,26 @@ const MODEL_PRICE_ROWS = [
|
|
|
1273
1302
|
1
|
|
1274
1303
|
] }]
|
|
1275
1304
|
},
|
|
1305
|
+
{
|
|
1306
|
+
id: "grok-4.7",
|
|
1307
|
+
rates: [
|
|
1308
|
+
1.2,
|
|
1309
|
+
3.6,
|
|
1310
|
+
.3
|
|
1311
|
+
],
|
|
1312
|
+
contextTiers: [{
|
|
1313
|
+
"maxContext": 2e5,
|
|
1314
|
+
"rates": [
|
|
1315
|
+
1.2,
|
|
1316
|
+
3.6,
|
|
1317
|
+
.3
|
|
1318
|
+
]
|
|
1319
|
+
}, { "rates": [
|
|
1320
|
+
2.4,
|
|
1321
|
+
7.2,
|
|
1322
|
+
.6
|
|
1323
|
+
] }]
|
|
1324
|
+
},
|
|
1276
1325
|
{
|
|
1277
1326
|
id: "inkling",
|
|
1278
1327
|
rates: [
|
|
@@ -1353,6 +1402,30 @@ const MODEL_PRICE_ROWS = [
|
|
|
1353
1402
|
.0036
|
|
1354
1403
|
]
|
|
1355
1404
|
},
|
|
1405
|
+
{
|
|
1406
|
+
id: "mimo-v2.6-flash",
|
|
1407
|
+
rates: [
|
|
1408
|
+
.14,
|
|
1409
|
+
.28,
|
|
1410
|
+
.0028
|
|
1411
|
+
]
|
|
1412
|
+
},
|
|
1413
|
+
{
|
|
1414
|
+
id: "mimo-v2.6-pro",
|
|
1415
|
+
rates: [
|
|
1416
|
+
.435,
|
|
1417
|
+
.87,
|
|
1418
|
+
.0036
|
|
1419
|
+
]
|
|
1420
|
+
},
|
|
1421
|
+
{
|
|
1422
|
+
id: "mimo-v2.6-pro-ultraspeed",
|
|
1423
|
+
rates: [
|
|
1424
|
+
4.35,
|
|
1425
|
+
8.7,
|
|
1426
|
+
.036
|
|
1427
|
+
]
|
|
1428
|
+
},
|
|
1356
1429
|
{
|
|
1357
1430
|
id: "minimax-m2.5",
|
|
1358
1431
|
rates: [
|
|
@@ -1578,6 +1651,14 @@ const MODEL_PRICE_ROWS = [
|
|
|
1578
1651
|
.04
|
|
1579
1652
|
]
|
|
1580
1653
|
},
|
|
1654
|
+
{
|
|
1655
|
+
id: "step-5-preview",
|
|
1656
|
+
rates: [
|
|
1657
|
+
1,
|
|
1658
|
+
2.7,
|
|
1659
|
+
.05
|
|
1660
|
+
]
|
|
1661
|
+
},
|
|
1581
1662
|
{
|
|
1582
1663
|
id: "tencent/hy3-paid",
|
|
1583
1664
|
rates: [
|
|
@@ -1924,10 +2005,11 @@ function installCostProjection(ctx) {
|
|
|
1924
2005
|
* usable, the routed account — resolving each slot's key lazily (literal
|
|
1925
2006
|
* config key → credential seam → launch environment → the official CLI
|
|
1926
2007
|
* auth file for the default slot only).
|
|
1927
|
-
* - {@link CommandCodeAccountPool.markRejected} records a 429
|
|
1928
|
-
*
|
|
1929
|
-
*
|
|
1930
|
-
*
|
|
2008
|
+
* - {@link CommandCodeAccountPool.markRejected} records a 429 or 401 against
|
|
2009
|
+
* the exact API key, so several slots sharing one key share one state. A
|
|
2010
|
+
* 429 that NAMED a usage window marks the window exhausted; a 429 that
|
|
2011
|
+
* named none is recorded as a plain throttle, which rotates the same way
|
|
2012
|
+
* but is never reported as an exhausted window (issue #54).
|
|
1931
2013
|
* - When every account is marked, the pool probes each key's
|
|
1932
2014
|
* `/alpha/billing/credits` window limits (through the injected
|
|
1933
2015
|
* {@link CommandCodeAccountPoolDeps.probeWindow}): an account whose window
|
|
@@ -2125,9 +2207,16 @@ var CommandCodeAccountPool = class {
|
|
|
2125
2207
|
}
|
|
2126
2208
|
if (probe.resetAt > 0) this.states.set(account.key, {
|
|
2127
2209
|
kind: "cooldown",
|
|
2128
|
-
|
|
2210
|
+
cause: "window",
|
|
2211
|
+
reason: account.state?.reason ?? "usage window exhausted (429)",
|
|
2129
2212
|
until: probe.resetAt
|
|
2130
2213
|
});
|
|
2214
|
+
else if (account.state?.kind !== "cooldown") this.states.set(account.key, {
|
|
2215
|
+
kind: "unknown",
|
|
2216
|
+
cause: "window",
|
|
2217
|
+
reason: account.state?.reason ?? "usage window exhausted (429)",
|
|
2218
|
+
until: 0
|
|
2219
|
+
});
|
|
2131
2220
|
}));
|
|
2132
2221
|
const latestAccounts = await this.resolvedAccounts();
|
|
2133
2222
|
const revived = selectActiveAccount(tried === void 0 || tried.length === 0 ? latestAccounts : latestAccounts.filter((account) => !tried.includes(account.key)), preferred);
|
|
@@ -2136,31 +2225,45 @@ var CommandCodeAccountPool = class {
|
|
|
2136
2225
|
throw allAccountsUnusable(latestAccounts.length > 0 ? latestAccounts : accounts);
|
|
2137
2226
|
}
|
|
2138
2227
|
/**
|
|
2139
|
-
* Record a rejection against one key. `rate-limit` marks the key
|
|
2140
|
-
*
|
|
2141
|
-
*
|
|
2142
|
-
*
|
|
2143
|
-
*
|
|
2228
|
+
* Record a rejection against one key. `rate-limit` marks the key's usage
|
|
2229
|
+
* WINDOW exhausted — as a `cooldown` until `resetAtMs` when the rejection
|
|
2230
|
+
* body named the provider's own reset time, otherwise as an `unknown` mark
|
|
2231
|
+
* whose window is probed lazily. `throttled` (the plain 429 that named no
|
|
2232
|
+
* window) marks the key with the `throttle` cause instead: it leaves rotation
|
|
2233
|
+
* exactly like a window mark does, but the pool's own diagnosis keeps saying
|
|
2234
|
+
* "rate limited" rather than inventing an exhausted window. A 401
|
|
2235
|
+
* (`invalid-credential`) disables the key until the stored credential
|
|
2236
|
+
* changes.
|
|
2144
2237
|
*
|
|
2145
2238
|
* `resetAtMs` is seconds-to-millis converted by the adapter from the
|
|
2146
2239
|
* provider's `error.rateLimit.reset`: knowing the real reset immediately is
|
|
2147
2240
|
* what keeps an exhausted account out of rotation for exactly as long as the
|
|
2148
|
-
* provider said
|
|
2241
|
+
* provider said. It only applies to a window mark; a plain throttle keeps the
|
|
2242
|
+
* window unknown on purpose, so a probe can still find out.
|
|
2149
2243
|
*/
|
|
2150
2244
|
markRejected(apiKey, rejection, resetAtMs) {
|
|
2151
2245
|
if (rejection === "invalid-credential") this.states.set(apiKey, {
|
|
2152
2246
|
kind: "disabled",
|
|
2247
|
+
cause: "auth",
|
|
2153
2248
|
reason: "invalid API key (401)",
|
|
2154
2249
|
until: 0
|
|
2155
2250
|
});
|
|
2251
|
+
else if (rejection === "throttled") this.states.set(apiKey, {
|
|
2252
|
+
kind: "unknown",
|
|
2253
|
+
cause: "throttle",
|
|
2254
|
+
reason: "rate limited (429)",
|
|
2255
|
+
until: 0
|
|
2256
|
+
});
|
|
2156
2257
|
else if (resetAtMs !== void 0 && resetAtMs > Date.now()) this.states.set(apiKey, {
|
|
2157
2258
|
kind: "cooldown",
|
|
2158
|
-
|
|
2259
|
+
cause: "window",
|
|
2260
|
+
reason: "usage window exhausted (429)",
|
|
2159
2261
|
until: resetAtMs
|
|
2160
2262
|
});
|
|
2161
2263
|
else this.states.set(apiKey, {
|
|
2162
2264
|
kind: "unknown",
|
|
2163
|
-
|
|
2265
|
+
cause: "window",
|
|
2266
|
+
reason: "usage window exhausted (429)",
|
|
2164
2267
|
until: 0
|
|
2165
2268
|
});
|
|
2166
2269
|
}
|
|
@@ -2255,9 +2358,16 @@ var CommandCodeAccountPool = class {
|
|
|
2255
2358
|
}
|
|
2256
2359
|
if (probe.resetAt > 0) this.states.set(account.key, {
|
|
2257
2360
|
kind: "cooldown",
|
|
2258
|
-
|
|
2361
|
+
cause: "window",
|
|
2362
|
+
reason: account.state?.reason ?? "usage window exhausted (429)",
|
|
2259
2363
|
until: probe.resetAt
|
|
2260
2364
|
});
|
|
2365
|
+
else if (account.state?.kind !== "cooldown") this.states.set(account.key, {
|
|
2366
|
+
kind: "unknown",
|
|
2367
|
+
cause: "window",
|
|
2368
|
+
reason: account.state?.reason ?? "usage window exhausted (429)",
|
|
2369
|
+
until: 0
|
|
2370
|
+
});
|
|
2261
2371
|
}
|
|
2262
2372
|
/** Hand out the chosen account's key. */
|
|
2263
2373
|
pick(account) {
|
|
@@ -2268,26 +2378,39 @@ var CommandCodeAccountPool = class {
|
|
|
2268
2378
|
}
|
|
2269
2379
|
};
|
|
2270
2380
|
/**
|
|
2271
|
-
* The error for "accounts exist but none of them can serve"
|
|
2272
|
-
*
|
|
2273
|
-
*
|
|
2381
|
+
* The error for "accounts exist but none of them can serve". Three shapes, each
|
|
2382
|
+
* claiming only what the pool actually knows:
|
|
2383
|
+
*
|
|
2384
|
+
* - every account rejected with 401 → `INVALID_CREDENTIAL`;
|
|
2385
|
+
* - at least one account marked by a NAMED usage window (or by a probe that
|
|
2386
|
+
* read a window as exceeded) → the window diagnosis, naming the earliest
|
|
2387
|
+
* known reset when the provider published one;
|
|
2388
|
+
* - every mark a plain throttle (a 429 that said nothing about a window, and
|
|
2389
|
+
* no probe could confirm one) → a throttle diagnosis that says so. Claiming
|
|
2390
|
+
* "all accounts have exhausted their usage window" here is issue #54: the
|
|
2391
|
+
* report's account panel showed the five-hour window at 2% and the weekly
|
|
2392
|
+
* one at 10% while the turn failed with exactly that sentence.
|
|
2393
|
+
*
|
|
2394
|
+
* Shared by the all-marked tail of {@link CommandCodeAccountPool.resolveKey}
|
|
2274
2395
|
* and by its already-tried diagnosis, so the two can never drift apart.
|
|
2275
2396
|
*
|
|
2276
2397
|
* The attached `providerRetryAfterMs` is the exact wait until the earliest
|
|
2277
|
-
* known reset, so dsh-llm-retry sleeps through the window instead of
|
|
2278
|
-
* at its backoff cadence. It is capped at {@link RETRY_MAX_DELAY_MS}:
|
|
2279
|
-
* executor honors a provider wait verbatim only at or below the policy's
|
|
2398
|
+
* known window reset, so dsh-llm-retry sleeps through the window instead of
|
|
2399
|
+
* polling at its backoff cadence. It is capped at {@link RETRY_MAX_DELAY_MS}:
|
|
2400
|
+
* the executor honors a provider wait verbatim only at or below the policy's
|
|
2280
2401
|
* `maxDelayMs` — a LONGER attached wait makes it abandon the retry entirely
|
|
2281
2402
|
* (normal mode), which would turn "poll until the window opens" into "fail
|
|
2282
2403
|
* now". Longer resets simply ride the capped local backoff and the probe
|
|
2283
|
-
* revival.
|
|
2404
|
+
* revival. A throttle diagnosis attaches none: its marks carry no reset.
|
|
2284
2405
|
*/
|
|
2285
2406
|
function allAccountsUnusable(accounts) {
|
|
2286
2407
|
if (accounts.filter((account) => account.state?.kind === "disabled").length === accounts.length) return new LlmError(`llm-commandcode: every configured Command Code account (${accounts.length}) was rejected with 401 — check the stored API keys (Models page / settings) or the auth file;已配置的 ${accounts.length} 个 Command Code 账户密钥均被拒绝(401)——请在设置页检查存储的 API 密钥,或重新运行 command-code login`, "INVALID_CREDENTIAL");
|
|
2287
|
-
const
|
|
2408
|
+
const windowMarked = accounts.map((account) => account.state).filter((state) => state !== void 0).filter((state) => state.cause === "window");
|
|
2409
|
+
if (windowMarked.length === 0) return new LlmError(`llm-commandcode: all ${accounts.length} Command Code account(s) are rate limited (429) — the provider did not report an exhausted usage window; retrying;全部 ${accounts.length} 个 Command Code 账户被限流(429)——服务商未报告用量窗口用尽,正在重试`, "RATE_LIMIT");
|
|
2410
|
+
const resets = windowMarked.filter((state) => state.kind === "cooldown" && state.until > 0).map((state) => state.until);
|
|
2288
2411
|
const earliest = resets.length > 0 ? Math.min(...resets) : 0;
|
|
2289
2412
|
const wait = earliest > 0 ? Math.max(1e3, earliest - Date.now()) : 0;
|
|
2290
|
-
return new LlmError(`llm-commandcode: all ${accounts.length} Command Code account(s) have exhausted their usage window` + (earliest > 0 ? `; the earliest window resets at ${clockLabel(earliest)}` : "") + ` — requests will succeed again after the reset (or add another account);已用尽全部 ${accounts.length} 个 Command Code 账户的用量窗口` + (earliest > 0 ? `,最早的重置时间为 ${clockLabel(earliest)}` : "") + "——窗口重置后请求会自动恢复(也可以添加更多账户)", "RATE_LIMIT", wait > 0 && wait <= 9e5 ? { providerRetryAfterMs: wait } : void 0);
|
|
2413
|
+
return new LlmError(`llm-commandcode: all ${accounts.length} Command Code account(s) have exhausted their usage window` + (earliest > 0 ? `; the earliest window resets at ${clockLabel(earliest)}` : " — the provider published no reset time for it") + ` — requests will succeed again after the reset (or add another account);已用尽全部 ${accounts.length} 个 Command Code 账户的用量窗口` + (earliest > 0 ? `,最早的重置时间为 ${clockLabel(earliest)}` : ",服务商未公布重置时间") + "——窗口重置后请求会自动恢复(也可以添加更多账户)", "RATE_LIMIT", wait > 0 && wait <= 9e5 ? { providerRetryAfterMs: wait } : void 0);
|
|
2291
2414
|
}
|
|
2292
2415
|
/**
|
|
2293
2416
|
* Normalize one resolved credential to the form every consumer sees. Trim
|
|
@@ -2538,7 +2661,7 @@ function scaleBy(size, factor) {
|
|
|
2538
2661
|
* and API key or subscription, and Command Code's terms apply.
|
|
2539
2662
|
*
|
|
2540
2663
|
* Wire protocol (reverse-engineered by the pi plugin, command-code@1.28.4;
|
|
2541
|
-
* re-verified against command-code@1.
|
|
2664
|
+
* re-verified against command-code@1.62.0 — endpoints, request shape, and
|
|
2542
2665
|
* stream events unchanged):
|
|
2543
2666
|
* POST {apiBase}/alpha/generate
|
|
2544
2667
|
* body: { config, memory, taste, skills, params: { model, messages, tools,
|
|
@@ -2551,7 +2674,7 @@ function scaleBy(size, factor) {
|
|
|
2551
2674
|
* per-request options thunk and an API-key resolver from the plugin entry
|
|
2552
2675
|
* (src/index.ts), so a settings change reaches the very next request.
|
|
2553
2676
|
*/
|
|
2554
|
-
const COMMAND_CODE_CLI_VERSION = "1.
|
|
2677
|
+
const COMMAND_CODE_CLI_VERSION = "1.62.0";
|
|
2555
2678
|
const DEFAULT_API_BASE = "https://api.commandcode.ai";
|
|
2556
2679
|
const DEFAULT_GENERATE_MAX_TOKENS = 64e3;
|
|
2557
2680
|
const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
|
|
@@ -4272,11 +4395,12 @@ var CommandCodeAdapter = class extends LlmAdapter {
|
|
|
4272
4395
|
continue;
|
|
4273
4396
|
}
|
|
4274
4397
|
}
|
|
4275
|
-
if (rejection
|
|
4398
|
+
if (rejection !== void 0 && (rejection.reason === "rate-limit" || rejection.reason === "throttled") && (rejection.resetAtMs !== void 0 || attempt.status !== 429)) {
|
|
4276
4399
|
const reset = rejection.resetAtMs;
|
|
4277
4400
|
const wait = reset === void 0 ? 0 : Math.min(Math.max(1e3, reset - Date.now()), RETRY_MAX_DELAY_MS);
|
|
4278
4401
|
const when = reset === void 0 ? void 0 : new Date(reset).toISOString();
|
|
4279
|
-
|
|
4402
|
+
const window = rejection.reason === "rate-limit";
|
|
4403
|
+
throw new LlmError((window ? "llm-commandcode: the Command Code account is rate limited" : "llm-commandcode: the Command Code account is rate limited (429) — the provider did not report an exhausted usage window") + (when === void 0 ? "" : ` — the provider reports it resets at ${when}`) + (window ? ";当前 Command Code 账户已被限流" : ";当前 Command Code 账户被限流(429),服务商未报告用量窗口用尽") + (when === void 0 ? "" : `,服务商给出的重置时间为 ${when}`), "RATE_LIMIT", wait > 0 ? { providerRetryAfterMs: wait } : void 0);
|
|
4280
4404
|
}
|
|
4281
4405
|
throw generateHttpError(attempt.status, attempt.errText, attempt.retryAfterMs);
|
|
4282
4406
|
}
|
|
@@ -4687,10 +4811,19 @@ function mapFinishReason(reason) {
|
|
|
4687
4811
|
* the host should do with them, which is the caller's decision, not this
|
|
4688
4812
|
* function's:
|
|
4689
4813
|
*
|
|
4690
|
-
* - `rate-limit`: a usage
|
|
4814
|
+
* - `rate-limit`: a usage WINDOW is spent. The code `RATE_LIMITED` is the
|
|
4691
4815
|
* authoritative signal — the CLI accepts the code OR a 429 status — and the
|
|
4692
4816
|
* body's `error.rateLimit` names the window and its `reset` (in seconds),
|
|
4693
4817
|
* so the host can hold the account out until the provider's own reset time.
|
|
4818
|
+
* - `throttled`: the provider refused the request (429 or a bare
|
|
4819
|
+
* `RATE_LIMITED` code) without naming a usage window. It is account-scoped
|
|
4820
|
+
* like the above, so it rotates and marks the key the same way, but it is
|
|
4821
|
+
* NOT evidence that a metered window is spent: the CLI's own
|
|
4822
|
+
* `parseWindowLimitError` returns a window limit only when
|
|
4823
|
+
* `resolveWindowLabel` can name one, and a burst/model/spend limiter the
|
|
4824
|
+
* billing endpoint cannot see is exactly this shape (issue #54's report: a
|
|
4825
|
+
* 429 whose probe read five-hour 2% and weekly 10% while the error claimed
|
|
4826
|
+
* both were exhausted).
|
|
4694
4827
|
* - `invalid-credential`: 401; the key itself is bad.
|
|
4695
4828
|
* - `unavailable`: the key is fine but this account cannot serve: no credits
|
|
4696
4829
|
* (`400 Insufficient credits`, the codes `INSUFFICIENT_CREDITS`,
|
|
@@ -4702,10 +4835,11 @@ function mapFinishReason(reason) {
|
|
|
4702
4835
|
*/
|
|
4703
4836
|
function classifyAccountRejection(status, errText) {
|
|
4704
4837
|
if (status === 429 || readProviderErrorCode(errText)?.toUpperCase() === "RATE_LIMITED") {
|
|
4705
|
-
const
|
|
4706
|
-
|
|
4838
|
+
const evidence = readWindowLimitEvidence(errText);
|
|
4839
|
+
if (evidence.window === void 0) return { reason: "throttled" };
|
|
4840
|
+
return evidence.resetAtMs === void 0 ? { reason: "rate-limit" } : {
|
|
4707
4841
|
reason: "rate-limit",
|
|
4708
|
-
resetAtMs
|
|
4842
|
+
resetAtMs: evidence.resetAtMs
|
|
4709
4843
|
};
|
|
4710
4844
|
}
|
|
4711
4845
|
if (status === 401) return { reason: "invalid-credential" };
|
|
@@ -4726,31 +4860,44 @@ function readProviderErrorCode(errText) {
|
|
|
4726
4860
|
}
|
|
4727
4861
|
}
|
|
4728
4862
|
/**
|
|
4729
|
-
* The
|
|
4730
|
-
*
|
|
4731
|
-
*
|
|
4732
|
-
*
|
|
4733
|
-
*
|
|
4734
|
-
|
|
4735
|
-
|
|
4863
|
+
* The usage-window evidence carried by a rejected request, mirroring the CLI's
|
|
4864
|
+
* `parseWindowLimitError` → `resolveWindowLabel`/`extractResetAtMs` pair.
|
|
4865
|
+
*
|
|
4866
|
+
* `window` is present only when the body actually names one: a
|
|
4867
|
+
* `error.rateLimit.window` of `fiveHour`/`weekly`/`daily`, or the
|
|
4868
|
+
* "usage limit for your plan" wording (read as `weekly` when it says so, else
|
|
4869
|
+
* `fiveHour`). That is the CLI's own bar for calling a rejection a WINDOW
|
|
4870
|
+
* limit, and it is what keeps a bare 429 — a burst limiter, a model-level
|
|
4871
|
+
* limit, a spend cap `windowLimits` cannot show — from being reported as an
|
|
4872
|
+
* exhausted window (issue #54).
|
|
4873
|
+
*
|
|
4874
|
+
* `resetAtMs` is the reset the body publishes: `error.rateLimit.reset` is
|
|
4875
|
+
* SECONDS (`1e3 * reset`, like the CLI), and a `resets at <ISO>` stamp in the
|
|
4876
|
+
* message is honored as the fallback. Either can be present without the other;
|
|
4877
|
+
* the window label is what decides the classification.
|
|
4878
|
+
*/
|
|
4879
|
+
function readWindowLimitEvidence(errText) {
|
|
4880
|
+
let named;
|
|
4881
|
+
let message = "";
|
|
4882
|
+
let seconds;
|
|
4736
4883
|
try {
|
|
4737
4884
|
const parsed = JSON.parse(errText);
|
|
4738
4885
|
if (isRecord(parsed)) {
|
|
4739
4886
|
const error = isRecord(parsed.error) ? parsed.error : parsed;
|
|
4740
|
-
const
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
if (stamp !== void 0) {
|
|
4745
|
-
const at = Date.parse(stamp);
|
|
4746
|
-
if (!Number.isNaN(at)) return at;
|
|
4747
|
-
}
|
|
4887
|
+
const rateLimit = isRecord(error.rateLimit) ? error.rateLimit : void 0;
|
|
4888
|
+
named = stringValue(rateLimit?.window);
|
|
4889
|
+
message = stringValue(error.message) ?? stringValue(parsed.message) ?? "";
|
|
4890
|
+
seconds = numberValue(rateLimit?.reset);
|
|
4748
4891
|
}
|
|
4749
4892
|
} catch {}
|
|
4750
|
-
const
|
|
4751
|
-
|
|
4752
|
-
const
|
|
4753
|
-
|
|
4893
|
+
const window = named === "fiveHour" || named === "weekly" || named === "daily" ? named : /usage limit for your plan/i.test(message) || /usage limit for your plan/i.test(errText) ? /weekly/i.test(message) ? "weekly" : "fiveHour" : void 0;
|
|
4894
|
+
const stamp = /resets at (\d{4}-\d{2}-\d{2}T[\d:.]+Z)/i.exec(message)?.[1] ?? /resets at (\d{4}-\d{2}-\d{2}T[\d:.]+Z)/i.exec(errText)?.[1];
|
|
4895
|
+
const stamped = stamp === void 0 ? void 0 : Date.parse(stamp);
|
|
4896
|
+
const resetAtMs = seconds !== void 0 && seconds > 0 ? Math.round(seconds * 1e3) : stamped !== void 0 && !Number.isNaN(stamped) ? stamped : void 0;
|
|
4897
|
+
return {
|
|
4898
|
+
...window === void 0 ? {} : { window },
|
|
4899
|
+
...resetAtMs === void 0 ? {} : { resetAtMs }
|
|
4900
|
+
};
|
|
4754
4901
|
}
|
|
4755
4902
|
function isUpgradeRequiredError(status, errText) {
|
|
4756
4903
|
if (status !== 403) return false;
|