@mars-sea/dsh-commandcode-provider 0.11.16 → 0.11.17
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 +20 -0
- package/README.md +2 -20
- package/README.zh-CN.md +2 -20
- package/lib/client.js +340 -654
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +294 -471
- package/lib/index.js +741 -1664
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { Context } from "@deepseek-ai/cordis";
|
|
|
7
7
|
import { AttachmentStore } 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.66.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;
|
|
@@ -93,8 +93,6 @@ interface CommandCodeConnectionOptions {
|
|
|
93
93
|
* `CMD_ZDR=1`). Default false. Every chat request carries the header when
|
|
94
94
|
* enabled. The provider refuses a model without a ZDR-capable upstream with
|
|
95
95
|
* 422 `cmd_zdr_no_providers`; never retry that request without the header.
|
|
96
|
-
* The decision endpoint (`/provider/v1/systemone`) is deliberately never
|
|
97
|
-
* reached through this connection option — see `./systemone.ts`.
|
|
98
96
|
*/
|
|
99
97
|
zdr?: boolean;
|
|
100
98
|
}
|
|
@@ -110,12 +108,11 @@ type ResolveAttachments = () => AttachmentStore | undefined;
|
|
|
110
108
|
* `invalid-credential` are the three the pool records as marks; `unavailable`
|
|
111
109
|
* is an account-scoped rejection that must NOT become a mark — the account's
|
|
112
110
|
* key is valid and its windows may be open, the ACCOUNT just cannot serve THIS
|
|
113
|
-
* request
|
|
114
|
-
* without remembering anything.
|
|
111
|
+
* request — so the pool moves on without remembering anything.
|
|
115
112
|
*
|
|
116
113
|
* The window/throttle split decides what the pool may CLAIM, never whether it
|
|
117
|
-
* rotates
|
|
118
|
-
*
|
|
114
|
+
* rotates (issue #54); the evidence that separates them is in
|
|
115
|
+
* {@link classifyAccountRejection}.
|
|
119
116
|
*/
|
|
120
117
|
type AccountRotationReason = 'rate-limit' | 'throttled' | 'invalid-credential' | 'unavailable';
|
|
121
118
|
/** What the rotation hook knows about the request it is rotating within. */
|
|
@@ -149,11 +146,10 @@ interface CommandCodeAdapterDeps<C extends CommandCodeConnectionOptions = Comman
|
|
|
149
146
|
* with several accounts a rejection that does not mark the key (a plan or
|
|
150
147
|
* balance rejection is model-specific, not account-fatal) would otherwise
|
|
151
148
|
* re-offer the same account on every attempt and the pool could never reach
|
|
152
|
-
* the accounts behind it.
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
* instead of waiting for a billing probe to learn the same fact.
|
|
149
|
+
* the accounts behind it. `rotation.resetAtMs` carries the provider's own
|
|
150
|
+
* reset time when the rejection body published one, so the host can hold the
|
|
151
|
+
* key out until then instead of waiting for a billing probe to learn the
|
|
152
|
+
* same fact.
|
|
157
153
|
*/
|
|
158
154
|
rotateApiKey?: (rejectedKey: string, rejection: AccountRotationReason, connection: C, model?: string, rotation?: AccountRotationContext) => Promise<string | undefined>;
|
|
159
155
|
/**
|
|
@@ -298,13 +294,13 @@ declare class CommandCodeAdapter<C extends CommandCodeConnectionOptions = Comman
|
|
|
298
294
|
* unbounded loop): `RATE_LIMIT`/`SERVER`/`TIMEOUT`/`TRANSPORT`/
|
|
299
295
|
* `EMPTY_RESPONSE` retry up to 1000 times with waits doubling from 500 ms
|
|
300
296
|
* and capping at 15 minutes (±10% jitter), so an exhausted 5-hour window
|
|
301
|
-
* recovers in-session instead of failing after two tries. Permanent
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
297
|
+
* recovers in-session instead of failing after two tries. Permanent failures
|
|
298
|
+
* (an invalid key's `INVALID_CREDENTIAL`, `UNSUPPORTED_CONTENT`, plan
|
|
299
|
+
* rejections) are absent from the whitelist and surface immediately instead
|
|
300
|
+
* of looping. Waits the pool/adapter attach as `providerRetryAfterMs` are
|
|
301
|
+
* honored verbatim at or below the 15-minute cap and never attached above it
|
|
302
|
+
* (in normal mode a longer attached wait makes the executor abandon the
|
|
303
|
+
* retry outright — see RETRY_MAX_DELAY_MS).
|
|
308
304
|
*
|
|
309
305
|
* Captured once at route registration (dsh-llm snapshots this value), so a
|
|
310
306
|
* future config knob for it would apply on profile restart, not per request.
|
|
@@ -318,12 +314,8 @@ declare class CommandCodeAdapter<C extends CommandCodeConnectionOptions = Comman
|
|
|
318
314
|
* session reports far less context than it is actually carrying. The price is
|
|
319
315
|
* computed at the dimensions this route would send (the same request target
|
|
320
316
|
* `readImageRequest` encodes to), so the estimate tracks the wire rather than
|
|
321
|
-
* the stored original.
|
|
322
|
-
*
|
|
323
|
-
* Both payload generations are handled, because they disagree: ≤0.1.5 hands
|
|
324
|
-
* over bare `ImageAttachmentRef`s, ≥0.1.6 hands over `ImageBlock`s that also
|
|
325
|
-
* carry the surface's `offloaded` mark. Returning a price per occurrence, in
|
|
326
|
-
* order, is a hard requirement — the meter throws when the counts differ.
|
|
317
|
+
* the stored original. One price per occurrence, in order, is a hard
|
|
318
|
+
* requirement — the meter throws when the counts differ.
|
|
327
319
|
*/
|
|
328
320
|
imageRequestPricing(_provider: string, model: string): LlmImageRequestPricing | undefined;
|
|
329
321
|
/** Refresh the catalog (live fetch, cache fallback) and return it. */
|
|
@@ -336,10 +328,10 @@ declare class CommandCodeAdapter<C extends CommandCodeConnectionOptions = Comman
|
|
|
336
328
|
private accountHeaders;
|
|
337
329
|
/**
|
|
338
330
|
* Fetch one account endpoint and parse its JSON body. Returns the HTTP
|
|
339
|
-
* status alongside the parsed record so each caller applies its own
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
331
|
+
* status alongside the parsed record so each caller applies its own failure
|
|
332
|
+
* accounting: the billing probe fails open silently, the usage report books
|
|
333
|
+
* failures per endpoint. Non-2xx and invalid JSON bodies come back without a
|
|
334
|
+
* record; only a fetch failure propagates to the caller.
|
|
343
335
|
*
|
|
344
336
|
* `timeoutMs` is the caller's budget for this one request. The default is the
|
|
345
337
|
* CATALOG probe's short cap, which fits the picker's fail-open reads; the
|
|
@@ -354,9 +346,6 @@ declare class CommandCodeAdapter<C extends CommandCodeConnectionOptions = Comman
|
|
|
354
346
|
* per picker load). `undefined` means the filter cannot be evaluated at all
|
|
355
347
|
* — no key resolved — which {@link modelVisibleForAnyAccount} reads as
|
|
356
348
|
* "show everything".
|
|
357
|
-
*
|
|
358
|
-
* The serving account is only the first entry: with several accounts the
|
|
359
|
-
* model list must not depend on which of them rotation happens to be using.
|
|
360
349
|
*/
|
|
361
350
|
private loadPoolBillingAccess;
|
|
362
351
|
/**
|
|
@@ -401,10 +390,9 @@ declare class CommandCodeAdapter<C extends CommandCodeConnectionOptions = Comman
|
|
|
401
390
|
* but a hard refusal. `/alpha/generate` routes every one of them, so this
|
|
402
391
|
* costs nothing.
|
|
403
392
|
*
|
|
404
|
-
* That decision is deliberately NOT written to `protocolCache
|
|
405
|
-
* keyed by API key alone
|
|
406
|
-
*
|
|
407
|
-
* which the Provider API serves correctly — off it until the entry expired.
|
|
393
|
+
* That decision is deliberately NOT written to `protocolCache`, which is
|
|
394
|
+
* keyed by API key alone: remembering it would pin the whole ACCOUNT to the
|
|
395
|
+
* CLI transport and drag every other model off it until the entry expired.
|
|
408
396
|
*/
|
|
409
397
|
private resolveProtocol;
|
|
410
398
|
/**
|
|
@@ -418,18 +406,14 @@ declare class CommandCodeAdapter<C extends CommandCodeConnectionOptions = Comman
|
|
|
418
406
|
* the default resolves the currently active account.
|
|
419
407
|
*
|
|
420
408
|
* Two failure modes are NOT "the network is down", and the report must say
|
|
421
|
-
* so rather than let {@link classifyTotalFailure} blame the connection:
|
|
422
|
-
*
|
|
423
|
-
*
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
* (`connection.requestTimeoutMs`, default 60 s), not the catalog's 10 s
|
|
430
|
-
* probe budget: on a slow link a 10 s cap made every account query time
|
|
431
|
-
* out while chat kept working, which is exactly a "check your network"
|
|
432
|
-
* banner that never clears.
|
|
409
|
+
* so rather than let {@link classifyTotalFailure} blame the connection: a
|
|
410
|
+
* key that no HTTP header can carry (a stray newline from a paste, a
|
|
411
|
+
* full-width character) makes `fetch` throw a `TypeError` before any I/O,
|
|
412
|
+
* for every endpoint at once, so this path runs `assertUsableApiKey` too and
|
|
413
|
+
* answers `blocked: 'invalid-key'`; and the four endpoints get the SAME
|
|
414
|
+
* per-request budget as a chat call (`connection.requestTimeoutMs`, default
|
|
415
|
+
* 60 s), not the catalog's 10 s probe budget, because on a slow link a 10 s
|
|
416
|
+
* cap made every account query time out while chat kept working.
|
|
433
417
|
*/
|
|
434
418
|
getUsage(apiKey?: string): Promise<CommandCodeUsageReport>;
|
|
435
419
|
/**
|
|
@@ -443,17 +427,16 @@ declare class CommandCodeAdapter<C extends CommandCodeConnectionOptions = Comman
|
|
|
443
427
|
* the same time (the two are metered separately), and reading only the
|
|
444
428
|
* shorter one revived such an account as "usable" — the pool then handed it
|
|
445
429
|
* out, the provider rejected the request again, and the next all-marked pass
|
|
446
|
-
* revived it once more
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
*
|
|
430
|
+
* revived it once more (issue #51's follow-up: "切到一个不可用账号").
|
|
431
|
+
* `exceeded` is therefore true when ANY published window is exceeded, and
|
|
432
|
+
* `resetAt` is the LATEST reset among the exceeded ones — the binding
|
|
433
|
+
* constraint, because a clear five-hour window buys nothing while the weekly
|
|
434
|
+
* quota is spent.
|
|
451
435
|
*
|
|
452
436
|
* Returns `undefined` when the probe itself failed (transport, non-200, or a
|
|
453
437
|
* payload with no window limits at all) — a failed probe never changes pool
|
|
454
|
-
* state. The
|
|
455
|
-
*
|
|
456
|
-
* time, and the server remains the final gate on them.
|
|
438
|
+
* state. The credit balances are deliberately NOT part of this answer: they
|
|
439
|
+
* carry no reset time, and the server remains the final gate on them.
|
|
457
440
|
*/
|
|
458
441
|
probeWindowLimits(apiKey: string): Promise<{
|
|
459
442
|
exceeded: boolean;
|
|
@@ -486,18 +469,17 @@ interface CommandCodeAccountSlot {
|
|
|
486
469
|
allowAuthFile: boolean;
|
|
487
470
|
}
|
|
488
471
|
/**
|
|
489
|
-
* Why a key stopped serving requests
|
|
472
|
+
* Why a key stopped serving requests, split by EVIDENCE — what the pool may
|
|
473
|
+
* claim about it — rather than by what it does.
|
|
490
474
|
*
|
|
491
475
|
* `rate-limit` is a USAGE-WINDOW rejection: the provider named one of its
|
|
492
476
|
* metered windows (`error.rateLimit.window`, or a message saying the plan's
|
|
493
477
|
* usage limit was reached — the only two shapes the official CLI's own
|
|
494
|
-
* `parseWindowLimitError`/`resolveWindowLabel` accept). `throttled` is the
|
|
495
|
-
*
|
|
496
|
-
* window, so the
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
* while the turn failed with "all 1 Command Code account(s) have exhausted
|
|
500
|
-
* their usage window".
|
|
478
|
+
* `parseWindowLimitError`/`resolveWindowLabel` accept). `throttled` is the plain
|
|
479
|
+
* 429: the key leaves rotation for now, but the provider said nothing about a
|
|
480
|
+
* window, so the pool must not describe one as exhausted. Collapsing the two is
|
|
481
|
+
* issue #54: a bare 429 was reported as a spent window while the account card
|
|
482
|
+
* showed both windows barely used.
|
|
501
483
|
*/
|
|
502
484
|
type AccountRejection = 'rate-limit' | 'throttled' | 'invalid-credential';
|
|
503
485
|
/** One key's rotation state. */
|
|
@@ -510,11 +492,11 @@ interface CommandCodeAccountState {
|
|
|
510
492
|
/** Marked by a 401: skipped until the stored credential changes. */
|
|
511
493
|
'disabled';
|
|
512
494
|
/**
|
|
513
|
-
* The evidence behind the mark — what the pool may CLAIM when it reports
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
*
|
|
495
|
+
* The evidence behind the mark — what the pool may CLAIM when it reports that
|
|
496
|
+
* no account can serve. `window`: the provider named a usage window, or a
|
|
497
|
+
* `/alpha/billing/credits` probe read one as exceeded. `throttle`: a 429 that
|
|
498
|
+
* said nothing about a window (a burst limiter, or a model-/spend-level limit
|
|
499
|
+
* the billing endpoint cannot show). `auth`: a 401.
|
|
518
500
|
*/
|
|
519
501
|
cause: 'window' | 'throttle' | 'auth';
|
|
520
502
|
/** Human-readable reason for the mark (e.g. `rate limited (429)`). */
|
|
@@ -547,43 +529,34 @@ interface CommandCodeAccountPoolDeps {
|
|
|
547
529
|
resolveRef(ref: CredentialRef): Promise<string | undefined>;
|
|
548
530
|
/** The official CLI auth-file key (`~/.commandcode/auth.json`); default slot only. */
|
|
549
531
|
authFileKey(): string | undefined;
|
|
550
|
-
/**
|
|
551
|
-
* Probe one key's usage windows — BOTH windows the endpoint publishes (the
|
|
552
|
-
* five-hour and the weekly one), not just the five-hour one; see
|
|
553
|
-
* {@link AccountWindowProbe}. Undefined when the probe itself failed.
|
|
554
|
-
*/
|
|
532
|
+
/** Probe one key's usage windows (BOTH windows the endpoint publishes); undefined when it failed. */
|
|
555
533
|
probeWindow(apiKey: string): Promise<AccountWindowProbe | undefined>;
|
|
556
534
|
/**
|
|
557
|
-
* The manually selected account
|
|
558
|
-
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
* the fallback lasts only as long as the window really is exceeded.
|
|
535
|
+
* The manually selected account slot id, re-read per resolution. It serves
|
|
536
|
+
* whenever it is usable; an unknown id or an exhausted preferred account falls
|
|
537
|
+
* back to the first usable slot — and an exhausted one is re-probed on the way
|
|
538
|
+
* (see {@link CommandCodeAccountPool.resolveKey}), so the fallback lasts only
|
|
539
|
+
* as long as the window really is exceeded.
|
|
563
540
|
*/
|
|
564
541
|
preferredId?(): string | undefined;
|
|
565
542
|
/**
|
|
566
543
|
* Model → account routing rules, re-read per resolution so settings changes
|
|
567
|
-
* apply live.
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
* before the preferred/rotation selection; an unusable routed account falls
|
|
571
|
-
* back to the normal selection (the router is a hint, never a hard gate).
|
|
544
|
+
* apply live. A matching, usable routed account serves before the
|
|
545
|
+
* preferred/rotation selection; an unusable one falls back to the normal
|
|
546
|
+
* selection — the router is a hint, never a hard gate.
|
|
572
547
|
*/
|
|
573
548
|
modelAccountRules?(): readonly CommandCodeModelAccountRule[];
|
|
574
549
|
/**
|
|
575
|
-
* Clock seam for the explicit-account probe throttle
|
|
576
|
-
* "
|
|
577
|
-
*
|
|
578
|
-
* waiting a real minute; production reads `Date.now()`.
|
|
550
|
+
* Clock seam for the explicit-account probe throttle, so the "the interval
|
|
551
|
+
* elapsed" half of {@link CommandCodeAccountPool.canProbeExplicit} is testable
|
|
552
|
+
* without waiting a real minute. Production reads `Date.now()`.
|
|
579
553
|
*/
|
|
580
554
|
now?(): number;
|
|
581
555
|
}
|
|
582
556
|
/**
|
|
583
557
|
* One "route these models to that account" rule. `models` lists catalog ids
|
|
584
|
-
* (`deepseek/deepseek-v4-pro`, …); `account` is a slot id (`default` or an
|
|
585
|
-
*
|
|
586
|
-
* list routes to that account. The first matching rule in list order wins.
|
|
558
|
+
* (`deepseek/deepseek-v4-pro`, …); `account` is a slot id (`default` or an extra
|
|
559
|
+
* account's credential reference). The first matching rule in list order wins.
|
|
587
560
|
*/
|
|
588
561
|
interface CommandCodeModelAccountRule {
|
|
589
562
|
/** Catalog model ids to match against the request's model. */
|
|
@@ -599,10 +572,10 @@ interface CommandCodeModelAccountRule {
|
|
|
599
572
|
*/
|
|
600
573
|
declare function accountUsable(state: CommandCodeAccountState | undefined): boolean;
|
|
601
574
|
/**
|
|
602
|
-
* Pick the account that should serve now: the manually preferred slot when it
|
|
603
|
-
*
|
|
604
|
-
*
|
|
605
|
-
*
|
|
575
|
+
* Pick the account that should serve now: the manually preferred slot when it is
|
|
576
|
+
* usable, otherwise the first usable account in rotation order; undefined when
|
|
577
|
+
* no account is usable. Shared by the pool (request path) and the plugin entry
|
|
578
|
+
* (the usage view's active badge) so both always agree.
|
|
606
579
|
*/
|
|
607
580
|
declare function selectActiveAccount(accounts: readonly ResolvedAccount[], preferredId: string | undefined): ResolvedAccount | undefined;
|
|
608
581
|
/**
|
|
@@ -643,27 +616,26 @@ declare class CommandCodeAccountPool {
|
|
|
643
616
|
*/
|
|
644
617
|
describeAccounts(): Promise<ResolvedAccount[]>;
|
|
645
618
|
/**
|
|
646
|
-
* Hand out the key for a request: the model-routed account when the
|
|
647
|
-
*
|
|
648
|
-
*
|
|
649
|
-
*
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
* `
|
|
619
|
+
* Hand out the key for a request: the model-routed account when the request's
|
|
620
|
+
* model matches a rule (and that account is usable), else the manually
|
|
621
|
+
* preferred account when usable, else the first usable account in rotation
|
|
622
|
+
* order. Returns `undefined` when no account resolves any key at all, or when
|
|
623
|
+
* an account this request already used is still UNMARKED — that rejection is
|
|
624
|
+
* the honest answer, so the caller's own rejection surfaces as itself. Throws
|
|
625
|
+
* `RATE_LIMIT` (naming the earliest window reset) or `INVALID_CREDENTIAL`
|
|
626
|
+
* when accounts exist but every one of them is marked.
|
|
653
627
|
*
|
|
654
628
|
* `options.model` is the request's model id; routing rules re-read per
|
|
655
|
-
* resolution, so a settings change applies live.
|
|
656
|
-
*
|
|
657
|
-
*
|
|
658
|
-
*
|
|
659
|
-
*
|
|
660
|
-
*
|
|
661
|
-
* account's plan) would otherwise be offered again on every attempt, and the
|
|
662
|
-
* accounts behind it would never be reached.
|
|
629
|
+
* resolution, so a settings change applies live. `options.tried` lists the
|
|
630
|
+
* keys this request has already used — the just-rejected one included — and
|
|
631
|
+
* they are removed from the resolution entirely, which is what lets one
|
|
632
|
+
* request walk a four-account pool: a rejection that does not mark the key
|
|
633
|
+
* (no credits, a model outside the account's plan) would otherwise be offered
|
|
634
|
+
* again on every attempt and the accounts behind it never reached.
|
|
663
635
|
*
|
|
664
|
-
* An explicit selection (the pin or a model rule) that a rate-limit mark
|
|
665
|
-
*
|
|
666
|
-
*
|
|
636
|
+
* An explicit selection (the pin or a model rule) that a rate-limit mark would
|
|
637
|
+
* demote is probed before the fallback serves, so "falls back while exhausted"
|
|
638
|
+
* never becomes "stays demoted until the process restarts" (issue #51).
|
|
667
639
|
*/
|
|
668
640
|
resolveKey(options?: {
|
|
669
641
|
tried?: readonly string[];
|
|
@@ -673,53 +645,46 @@ declare class CommandCodeAccountPool {
|
|
|
673
645
|
slot: CommandCodeAccountSlot;
|
|
674
646
|
} | undefined>;
|
|
675
647
|
/**
|
|
676
|
-
* Record a rejection against one key. `
|
|
677
|
-
*
|
|
678
|
-
*
|
|
679
|
-
*
|
|
680
|
-
*
|
|
681
|
-
*
|
|
682
|
-
*
|
|
683
|
-
* (`invalid-credential`) disables the key until the stored credential
|
|
648
|
+
* Record a rejection against one key. A `throttled` rejection (the plain 429
|
|
649
|
+
* that named no window) marks the key with the `throttle` cause, leaving
|
|
650
|
+
* rotation exactly like a window mark but keeping the pool's own diagnosis at
|
|
651
|
+
* "rate limited" rather than inventing an exhausted window. `rate-limit`
|
|
652
|
+
* marks a `cooldown` until `resetAtMs` when the body named the provider's own
|
|
653
|
+
* reset, otherwise an `unknown` mark whose window is probed lazily.
|
|
654
|
+
* `invalid-credential` (401) disables the key until the stored credential
|
|
684
655
|
* changes.
|
|
685
656
|
*
|
|
686
|
-
* `resetAtMs` is seconds-to-millis converted by the adapter from
|
|
687
|
-
*
|
|
688
|
-
*
|
|
689
|
-
* provider said. It only applies to a window mark; a plain throttle keeps the
|
|
690
|
-
* window unknown on purpose, so a probe can still find out.
|
|
657
|
+
* `resetAtMs` is seconds-to-millis converted by the adapter from
|
|
658
|
+
* `error.rateLimit.reset`; it applies to a window mark only. A plain throttle
|
|
659
|
+
* keeps its window unknown on purpose, so a probe can still find out.
|
|
691
660
|
*/
|
|
692
661
|
markRejected(apiKey: string, rejection: AccountRejection, resetAtMs?: number): void;
|
|
693
662
|
/**
|
|
694
663
|
* One account's key: literal → credential seam → auth file (default slot).
|
|
695
664
|
*
|
|
696
665
|
* Every source is normalized here, at the single point where a slot's key
|
|
697
|
-
* enters the pool. The adapter sends the key through
|
|
698
|
-
* `assertUsableApiKey()`, which trims it
|
|
699
|
-
*
|
|
700
|
-
*
|
|
701
|
-
*
|
|
702
|
-
*
|
|
703
|
-
* no mark, and the usage endpoints would 401 while chat kept working.
|
|
704
|
-
* Normalizing once makes resolution, probing, marking, and the request path
|
|
705
|
-
* agree on one string.
|
|
666
|
+
* enters the pool. The adapter sends the key through
|
|
667
|
+
* `assertUsableApiKey()`, which trims it, and reports that trimmed form back
|
|
668
|
+
* to {@link markRejected}: returning the raw value would file every 429/401
|
|
669
|
+
* mark under a key no later lookup can find — rotation would re-offer the same
|
|
670
|
+
* account, the account card would show no mark, and the usage endpoints would
|
|
671
|
+
* 401 while chat kept working.
|
|
706
672
|
*/
|
|
707
673
|
private resolveSlotKey;
|
|
708
674
|
/**
|
|
709
|
-
* The account the user explicitly asked for: the slot a model rule routes
|
|
710
|
-
*
|
|
711
|
-
*
|
|
712
|
-
*
|
|
713
|
-
* {@link
|
|
714
|
-
* usable, which is exactly what {@link resolveKey} re-probes.
|
|
675
|
+
* The account the user explicitly asked for: the slot a model rule routes the
|
|
676
|
+
* request to when that id exists among the resolved slots, else the manually
|
|
677
|
+
* pinned slot. Consulted only on the fallback path, so — unlike
|
|
678
|
+
* {@link selectAccountForModel} — it does NOT require the account to be usable,
|
|
679
|
+
* which is exactly what {@link resolveKey} re-probes.
|
|
715
680
|
*/
|
|
716
681
|
private explicitAccount;
|
|
717
682
|
/**
|
|
718
683
|
* Whether an explicitly selected account's mark is due for a window probe.
|
|
719
684
|
* Only an `unknown` mark (a 429 whose reset was never learned) is worth
|
|
720
|
-
* re-probing: a `cooldown`
|
|
721
|
-
*
|
|
722
|
-
*
|
|
685
|
+
* re-probing: a `cooldown` carries its reset and expires by itself, and a
|
|
686
|
+
* `disabled` (401) key stays out until the stored credential changes. The
|
|
687
|
+
* interval bounds a probe endpoint that keeps failing.
|
|
723
688
|
*/
|
|
724
689
|
private canProbeExplicit;
|
|
725
690
|
/** The clock the probe throttle reads; injected so a test can travel in time. */
|
|
@@ -727,8 +692,8 @@ declare class CommandCodeAccountPool {
|
|
|
727
692
|
/**
|
|
728
693
|
* Probe one explicitly selected account's window and apply the answer. A
|
|
729
694
|
* window that is no longer exceeded drops the mark, so the user's own
|
|
730
|
-
* selection serves again on this very request
|
|
731
|
-
*
|
|
695
|
+
* selection serves again on this very request; an exceeded one is stamped as
|
|
696
|
+
* a cooldown carrying the provider's reset time, after which
|
|
732
697
|
* {@link accountUsable} lets the account back in with no further probe. A
|
|
733
698
|
* probe that fails changes nothing: the mark stays `unknown` and the next
|
|
734
699
|
* attempt waits out the interval.
|
|
@@ -738,34 +703,18 @@ declare class CommandCodeAccountPool {
|
|
|
738
703
|
private pick;
|
|
739
704
|
}
|
|
740
705
|
//#endregion
|
|
741
|
-
//#region src/command-guard.d.ts
|
|
742
|
-
/**
|
|
743
|
-
* The auto-approve strictness a user picks (`Config.commandGuardLevel`). Each
|
|
744
|
-
* level is the probability every verdict must reach before the guard grants
|
|
745
|
-
* `allowed-once`; a higher level approves less, on stronger evidence. Three
|
|
746
|
-
* presets replace a free-form probability because the useful range is narrow
|
|
747
|
-
* and a hand-typed 0.6 silently turns the guard into a rubber stamp.
|
|
748
|
-
*/
|
|
749
|
-
type CommandGuardLevel = 'high' | 'medium' | 'low';
|
|
750
|
-
//#endregion
|
|
751
706
|
//#region src/capabilities.d.ts
|
|
752
707
|
/**
|
|
753
708
|
* Static capability snapshot for the Command Code provider: model →
|
|
754
709
|
* reasoning-effort levels, vision/thinking flags, model → minimum plan tier,
|
|
755
710
|
* subscription-plan labels, deals, and hourly (peak/off-peak) pricing.
|
|
756
711
|
*
|
|
757
|
-
* Everything
|
|
758
|
-
*
|
|
759
|
-
* dsh-commandcode-upstream skill
|
|
760
|
-
*
|
|
761
|
-
*
|
|
762
|
-
*
|
|
763
|
-
* these tables + read helpers.
|
|
764
|
-
*
|
|
765
|
-
* Snapshot read helpers (planLabel, dealLabel, formatContext,
|
|
766
|
-
* capabilityDescription, peakPricing*, compareByPlan, modelVisibleInPlan,
|
|
767
|
-
* subscriptionPlanInfo, isFreeModel) live here too — they exist only to read
|
|
768
|
-
* the tables, so a sync never has to touch src/adapter.ts.
|
|
712
|
+
* Everything here is synced from official sources — the command-code CLI
|
|
713
|
+
* bundle's model table (`dist/cli.mjs`, re-verified at command-code@1.66.0) and
|
|
714
|
+
* the official plan/pricing/model docs; see the dsh-commandcode-upstream skill
|
|
715
|
+
* for the extraction procedures. Keeping the snapshot in its own module
|
|
716
|
+
* confines those frequent sync diffs here: src/adapter.ts holds only the stable
|
|
717
|
+
* wire/runtime logic. The read helpers live here too, for the same reason.
|
|
769
718
|
*
|
|
770
719
|
* Ported from pi-commandcode-provider (MIT); originally part of src/adapter.ts
|
|
771
720
|
* and split out so upstream syncs stay reviewable.
|
|
@@ -789,20 +738,22 @@ declare const KNOWN_EFFORTS: Readonly<Record<string, readonly string[]>>;
|
|
|
789
738
|
declare const KNOWN_IMAGE_MODELS: ReadonlySet<string>;
|
|
790
739
|
/**
|
|
791
740
|
* Models WITHOUT a zero-data-retention upstream, per the official CLI's own
|
|
792
|
-
* registry (`command-code@1.
|
|
793
|
-
*
|
|
794
|
-
*
|
|
795
|
-
*
|
|
796
|
-
*
|
|
797
|
-
*
|
|
798
|
-
*
|
|
799
|
-
*
|
|
800
|
-
*
|
|
741
|
+
* registry (`command-code@1.66.0` `dist/cli.mjs`): `modelSupportsZdr(id)` is
|
|
742
|
+
* exactly `!nonZdrSet.has(canonicalize(id))`, and `knownModelSupportsZdr`
|
|
743
|
+
* carries the same membership in the sibling route table — the UNION of both
|
|
744
|
+
* is this set. Reading only the sibling route table would drop `meituan/
|
|
745
|
+
* LongCat-2.0` and `stealth/pixel-canary`, which each appear in
|
|
746
|
+
* `modelSupportsZdr` alone. The official docs (commandcode.ai/docs/resources/
|
|
747
|
+
* zdr) put it in prose — "99% of our models have ZDR-capable upstreams … only
|
|
748
|
+
* a small handful of models are affected" — so the CLI's exclusion list is
|
|
749
|
+
* the only per-model evidence there is; a ZDR request naming one of these
|
|
750
|
+
* fails with HTTP 422 `cmd_zdr_no_providers` instead of routing through a
|
|
751
|
+
* provider that retains.
|
|
801
752
|
*
|
|
802
753
|
* Why a NEGATIVE set, and why "not listed" answers TRUE: 99% of the catalog is
|
|
803
754
|
* covered, so the maintained difference is the exception list. This helper is
|
|
804
755
|
* informational; the adapter sends the ZDR header for EVERY request when the
|
|
805
|
-
* switch is on
|
|
756
|
+
* switch is on — the provider remains the routing authority and refuses an
|
|
806
757
|
* unsupported model rather than silently dropping the privacy guarantee.
|
|
807
758
|
*
|
|
808
759
|
* `minimax/minimax-m3-free` is the one entry the public catalog
|
|
@@ -813,16 +764,9 @@ declare const KNOWN_IMAGE_MODELS: ReadonlySet<string>;
|
|
|
813
764
|
* Keep in sync via the dsh-commandcode-upstream skill: the CLI's registry data
|
|
814
765
|
* (its `zdr:{only:[…]}` provider routes and the per-provider `zdr`/`noTraining`
|
|
815
766
|
* flags) is upstream-internal routing, not a per-model contract, so this table
|
|
816
|
-
* is the snapshot of the exclusion set and nothing more.
|
|
817
|
-
*
|
|
818
|
-
*
|
|
819
|
-
* how rare a change here is expected to be. The 1.64.0 → 1.65.0 diff (2026-09-24)
|
|
820
|
-
* is the counterexample that proves the check still runs: exactly one member
|
|
821
|
-
* joins (`stealth/space-bunny-alpha`), and it is in both anchors. `meituan/
|
|
822
|
-
* LongCat-2.0` is the one member the two anchors disagree about (it is in
|
|
823
|
-
* `modelSupportsZdr`'s set in both releases and in neither `knownModelSupportsZdr`
|
|
824
|
-
* set), so the union is
|
|
825
|
-
* what this table follows; reading only the sibling route table would drop it.
|
|
767
|
+
* is the snapshot of the exclusion set and nothing more. It is a rare change:
|
|
768
|
+
* 20 members held across 1.62.0 → 1.64.0, and 1.65.0 and 1.66.0 each added
|
|
769
|
+
* exactly one (the two stealth-preview models below).
|
|
826
770
|
*/
|
|
827
771
|
declare const KNOWN_NON_ZDR_MODELS: ReadonlySet<string>;
|
|
828
772
|
/**
|
|
@@ -832,65 +776,30 @@ declare const KNOWN_NON_ZDR_MODELS: ReadonlySet<string>;
|
|
|
832
776
|
*/
|
|
833
777
|
declare function supportsZeroDataRetention(modelId: string): boolean;
|
|
834
778
|
/**
|
|
835
|
-
* Models the official CLI's model table
|
|
836
|
-
*
|
|
837
|
-
*
|
|
838
|
-
*
|
|
839
|
-
*
|
|
840
|
-
*
|
|
841
|
-
* description — it exists for programmatic consumers.
|
|
779
|
+
* Models the official CLI's model table marks `reasoning:!0` but defines no
|
|
780
|
+
* selectable `reasoning_effort` levels — they think automatically, with
|
|
781
|
+
* Command Code driving the depth. `KNOWN_EFFORTS` (which mirrors the CLI's
|
|
782
|
+
* effort map exactly) stays the sole source for selectable effort levels, and
|
|
783
|
+
* this snapshot is not surfaced in the picker's compact description — it exists
|
|
784
|
+
* for programmatic consumers.
|
|
842
785
|
*
|
|
843
|
-
* Source: the
|
|
844
|
-
*
|
|
845
|
-
*
|
|
846
|
-
*
|
|
847
|
-
*
|
|
848
|
-
* joined this set in command-code@1.37.0 — reasoning:!0, no efforts, 1M
|
|
849
|
-
* context, routed through OpenRouter — then gained selectable
|
|
850
|
-
* `['low', 'medium', 'high']` efforts in command-code@1.38.0 and moved to
|
|
851
|
-
* `KNOWN_EFFORTS`. `moonshotai/Kimi-K3` followed the same path in
|
|
852
|
-
* command-code@1.39.3 — it gained `['low', 'high', 'max']` efforts and moved
|
|
853
|
-
* to `KNOWN_EFFORTS`. command-code@1.42.0 added LongCat 2.0 (then
|
|
854
|
-
* `meituan/LongCat-2.0:free`, now the paid `meituan/LongCat-2.0`; reasoning:!0,
|
|
855
|
-
* no efforts). command-code@1.45.0 gave the Muse Spark family
|
|
856
|
-
* (1.1, 1.2, 1.2-contributor, 1.3, 1.3-contributor) selectable
|
|
857
|
-
* `['low', 'medium', 'high', 'xhigh']` efforts — they moved to `KNOWN_EFFORTS`.
|
|
858
|
-
* command-code@1.51.3 gave `MiniMaxAI/MiniMax-M3` selectable
|
|
859
|
-
* `['low', 'medium', 'high']` efforts — it moved to `KNOWN_EFFORTS` too.
|
|
860
|
-
* command-code@1.52.0 added `inclusionai/ling-3.0-flash-sante:free`
|
|
861
|
-
* (reasoning:!0, no efforts).)
|
|
862
|
-
* command-code@1.53.0 added `deepseek/deepseek-v4.1-flash` with selectable
|
|
863
|
-
* ['low', 'high', 'max'] efforts, so it lives in `KNOWN_EFFORTS`, not here.)
|
|
864
|
-
* Keep in sync via the dsh-commandcode-upstream skill.
|
|
786
|
+
* Source: the bundled model table (dist/cli.mjs), cross-checked with
|
|
787
|
+
* https://commandcode.ai/docs/reference/cli/models. Keep in sync via the
|
|
788
|
+
* dsh-commandcode-upstream skill; a model that GAINS selectable efforts leaves
|
|
789
|
+
* this set for `KNOWN_EFFORTS` (Tencent Hy4 Preview, Kimi K3, the Muse Spark
|
|
790
|
+
* family and MiniMax M3 all took that path).
|
|
865
791
|
*/
|
|
866
792
|
declare const KNOWN_THINKING_MODELS: ReadonlySet<string>;
|
|
867
793
|
/**
|
|
868
794
|
* The minimum subscription plan a model is included in, per the official plan
|
|
869
|
-
* pages (`/docs/plans/go`, `/docs/plans/goat`, `/docs/plans/pro`,
|
|
870
|
-
* and `/docs/resources/pricing-limits`). Each plan's model
|
|
871
|
-
* the one below it: Go ⊂ GOAT ⊂ Pro ⊂ Provider/Max.
|
|
872
|
-
* plan list (Claude Opus/Fable, Fugu Ultra) are
|
|
873
|
-
*
|
|
874
|
-
*
|
|
875
|
-
*
|
|
876
|
-
*
|
|
877
|
-
* command-code@1.41.0 added `Qwen/Qwen3.8-Max-0902` (Go) and 1.42.0 added
|
|
878
|
-
* LongCat 2.0 (Go — a free promo until 2026-09-19, when the backend renamed
|
|
879
|
-
* `meituan/LongCat-2.0:free` to the paid `meituan/LongCat-2.0`); 1.43.0 added
|
|
880
|
-
* `google/gemini-3.8-flash` (GOAT) and 1.44.0 added `meta/muse-spark-1.3`
|
|
881
|
-
* (GOAT) plus its Contributor sibling (Go); command-code@1.52.0 added the
|
|
882
|
-
* free `inclusionai/ling-3.0-flash-sante:free` (Go); command-code@1.53.0
|
|
883
|
-
* added `deepseek/deepseek-v4.1-flash` (Go); command-code@1.56.0 added
|
|
884
|
-
* `Qwen/Qwen3.8-Omni-Flash` (Go); command-code@1.57.0 added
|
|
885
|
-
* `z-ai/glm-5.3-flashx` (Go); command-code@1.59.0 added `xai/grok-4.7` (GOAT)
|
|
886
|
-
* and 1.60.0 added `stepfun/Step-5-Preview` (Go); command-code@1.62.0 added the
|
|
887
|
-
* MiMo V2.6 family — `xiaomi/mimo-v2.6-flash` + `xiaomi/mimo-v2.6-pro` (Go) and
|
|
888
|
-
* `xiaomi/mimo-v2.6-pro-ultraspeed` (GOAT) — so the 1.58.0 -> 1.62.0 window's
|
|
889
|
-
* only tier changes are additions and the superset chain still holds. The
|
|
890
|
-
* 1.62.0 -> 1.65.0 window continues the pattern: 1.64.0 added
|
|
891
|
-
* `claude-opus-5-5` (Provider/Max), `gpt-6-sol` (Pro) and `gpt-6-luna` (Go),
|
|
892
|
-
* and 1.65.0 added `stealth/space-bunny-alpha` (Go, every tier) — additions
|
|
893
|
-
* only, no tier moves.
|
|
795
|
+
* pages (`/docs/plans/go`, `/docs/plans/goat`, `/docs/plans/pro`,
|
|
796
|
+
* `/docs/plans/max` and `/docs/resources/pricing-limits`). Each plan's model
|
|
797
|
+
* list is a superset of the one below it: Go ⊂ GOAT ⊂ Pro ⊂ Provider/Max.
|
|
798
|
+
* Models absent from every plan list (Claude Opus/Fable, Fugu Ultra) are
|
|
799
|
+
* Provider-tier. Re-verified at command-code@1.66.0 (2026-09-27): 82 catalog
|
|
800
|
+
* ids at 52/60/74/82 cumulative, a strict superset chain — every release since
|
|
801
|
+
* 1.49.0 has been additive with no tier move, and per-entry tags below name the
|
|
802
|
+
* release that added each row.
|
|
894
803
|
*
|
|
895
804
|
* The Provider API exposes no plan metadata, so this snapshot is the source of
|
|
896
805
|
* truth for the picker's plan annotation — it answers "which plan do I need to
|
|
@@ -922,11 +831,11 @@ declare function compareByPlan(a: {
|
|
|
922
831
|
}): number;
|
|
923
832
|
/**
|
|
924
833
|
* Subscription plan table, synced from the official CLI bundle's plan maps
|
|
925
|
-
* (located by the `"individual-go"` key in
|
|
926
|
-
*
|
|
927
|
-
*
|
|
928
|
-
*
|
|
929
|
-
*
|
|
834
|
+
* (located by the `"individual-go"` key in `dist/cli.mjs`, re-verified unchanged
|
|
835
|
+
* through command-code@1.66.0): subscription `planId` prefix → display name and
|
|
836
|
+
* the plan's monthly credit total. This is the account's own subscription
|
|
837
|
+
* (from `/alpha/billing/subscriptions`) — distinct from {@link KNOWN_PLANS},
|
|
838
|
+
* which maps catalog models to their minimum tier.
|
|
930
839
|
*
|
|
931
840
|
* `tierWeight` is plugin-added (not from the CLI maps): the plan's rank on
|
|
932
841
|
* the {@link PLAN_ORDER} scale, used by the picker's plan filter
|
|
@@ -982,8 +891,13 @@ declare function modelVisibleInPlan(modelId: string, access: CommandCodeBillingA
|
|
|
982
891
|
* render time against `Date.now()`), the deal label is hidden until the
|
|
983
892
|
* snapshot is refreshed from the official page. `undefined` means
|
|
984
893
|
* "no expiry" (permanent).
|
|
985
|
-
* - `free` marks models whose requests cost no credits
|
|
986
|
-
*
|
|
894
|
+
* - `free` marks models whose requests cost no credits, shown as a `FREE`
|
|
895
|
+
* badge; it degrades to a plain discount once the deal lapses.
|
|
896
|
+
*
|
|
897
|
+
* A deal whose promo ENDS is removed here rather than left to lapse on
|
|
898
|
+
* `expiresAt`: the pricing page drops the entry, so a lapsed row would badge a
|
|
899
|
+
* model the catalog now serves at full price (Grok 4.7 reverts to $2.00 in /
|
|
900
|
+
* $6.00 out after its 2026-09-27 window).
|
|
987
901
|
*
|
|
988
902
|
* Keep in sync with the official pricing page when deals change (see the
|
|
989
903
|
* dsh-commandcode-upstream skill).
|
|
@@ -1003,24 +917,11 @@ declare const KNOWN_DEALS: Readonly<Record<string, KnownDeal>>;
|
|
|
1003
917
|
* charges by the hour: peak hours are 01:00–04:00 and 06:00–10:00 UTC (7h per
|
|
1004
918
|
* weekday, full price) **Monday to Friday only**; the other 17 hours of a
|
|
1005
919
|
* weekday and every hour of Saturday/Sunday (UTC) are off-peak at half price.
|
|
1006
|
-
*
|
|
1007
|
-
*
|
|
1008
|
-
*
|
|
1009
|
-
*
|
|
1010
|
-
*
|
|
1011
|
-
* The picker shows the
|
|
1012
|
-
* *current* state as a compact
|
|
1013
|
-
* label (`Peak`/`Half`) matching the English noun style of the other markers
|
|
1014
|
-
* (`Image`, `FREE`), so a developer can tell at a glance whether calling the
|
|
1015
|
-
* model right now is cheap or expensive.
|
|
1016
|
-
*
|
|
1017
|
-
* Authoritative extraction: the pricing page embeds a model JSON array whose
|
|
1018
|
-
* hourly-priced entries carry a `timeOfDay` block
|
|
1019
|
-
* (`{ windows: "01–04 & 06–10 UTC, Mon–Fri", peakHoursPerDay: 7,
|
|
1020
|
-
* offPeakHoursPerDay: 17, peak: {...}, offPeak: {...} }`). Exactly four models
|
|
1021
|
-
* carry it: V4 Pro, V4 Flash, V4 Flash Vision (exp), and V4.1 Flash (added in
|
|
1022
|
-
* command-code@1.53.0 at $0.15/$0.60 off-peak, $0.30/$1.20 peak — the same
|
|
1023
|
-
* schedule as the other three).
|
|
920
|
+
* Exactly four models carry the page's `timeOfDay` block (the four rows below).
|
|
921
|
+
* The picker shows the *current* state as a compact label (`Peak`/`Half`)
|
|
922
|
+
* matching the English noun style of the other markers (`Image`, `FREE`), so a
|
|
923
|
+
* developer can tell at a glance whether calling the model right now is cheap
|
|
924
|
+
* or expensive.
|
|
1024
925
|
*
|
|
1025
926
|
* Extraction caution: the rendered HTML rows are a trap. Each annotation div
|
|
1026
927
|
* sits inside its OWN row's container, immediately before the NEXT row starts,
|
|
@@ -1028,18 +929,19 @@ declare const KNOWN_DEALS: Readonly<Record<string, KnownDeal>>;
|
|
|
1028
929
|
* to the model printed after it — that is how `deepseek/deepseek-v4-flash-fast`
|
|
1029
930
|
* was wrongly added here (its row is flat-priced at $0.28/$0.56/$0.07 and has
|
|
1030
931
|
* no `timeOfDay` block). Trust the embedded JSON's `timeOfDay` membership and
|
|
1031
|
-
* the 2× price relation, never the flat-text neighbor.
|
|
932
|
+
* the 2× price relation, never the flat-text neighbor. A rate that is
|
|
933
|
+
* internally consistent can still be the wrong row (the V4 Flash Vision (exp)
|
|
934
|
+
* variant is priced from the page's own `timeOfDay` block, not from 2× its own
|
|
935
|
+
* off-peak figures), which is why the vendored price table
|
|
936
|
+
* (`./model-prices.ts`) is synced from the page and not hand-kept.
|
|
1032
937
|
*
|
|
1033
938
|
* Keep in sync with the official pricing page when the model set, the peak
|
|
1034
939
|
* windows, or the weekday rule change (see the dsh-commandcode-upstream skill).
|
|
1035
940
|
*/
|
|
1036
941
|
declare const KNOWN_PEAK_PRICING: ReadonlySet<string>;
|
|
1037
942
|
/**
|
|
1038
|
-
*
|
|
1039
|
-
*
|
|
1040
|
-
* official rule charges Saturday and Sunday completely off-peak for all 24
|
|
1041
|
-
* hours, so a weekend timestamp is off-peak even inside `PEAK_HOUR_RANGES`.
|
|
1042
|
-
* `undefined` for models outside the snapshot.
|
|
943
|
+
* As {@link isPeakPricingHour}, plus the {@link KNOWN_PEAK_PRICING} membership
|
|
944
|
+
* test; `undefined` for models outside the snapshot.
|
|
1043
945
|
*/
|
|
1044
946
|
declare function peakPricingState(modelId: string, now?: number): 'peak' | 'off-peak' | undefined;
|
|
1045
947
|
/**
|
|
@@ -1193,19 +1095,16 @@ interface CommandCodePriceTable {
|
|
|
1193
1095
|
//#endregion
|
|
1194
1096
|
//#region src/command-locales.d.ts
|
|
1195
1097
|
/**
|
|
1196
|
-
*
|
|
1197
|
-
*
|
|
1198
|
-
*
|
|
1199
|
-
*
|
|
1200
|
-
*
|
|
1201
|
-
* `pickCommandLocale()`. The image-gate wrapper also lives on the client
|
|
1202
|
-
* but is reached from a non-React path that has no `t` in scope, so the
|
|
1203
|
-
* same dictionaries serve both surfaces.
|
|
1098
|
+
* zh/en copy for the Host-side `/commandcode` usage command, as plain
|
|
1099
|
+
* constants: the command runs on the Host and has no access to the client's
|
|
1100
|
+
* `ctx.locale`, so the active locale is resolved by `pickCommandLocale()` and
|
|
1101
|
+
* the dictionaries are read by direct lookup. Distinct from
|
|
1102
|
+
* `./client/locales.ts` (the settings-page `settings.commandcode` namespace).
|
|
1204
1103
|
*
|
|
1205
|
-
* zh is the source of truth for the key set; en must carry the
|
|
1206
|
-
* keys
|
|
1104
|
+
* zh is the source of truth for the key set; `en` must carry exactly the same
|
|
1105
|
+
* keys, which the `Record` type makes a compile error.
|
|
1207
1106
|
*/
|
|
1208
|
-
/** Active locale id
|
|
1107
|
+
/** Active locale id for the `/commandcode` command. */
|
|
1209
1108
|
type LocaleId = 'zh' | 'en';
|
|
1210
1109
|
//#endregion
|
|
1211
1110
|
//#region src/commands.d.ts
|
|
@@ -1220,11 +1119,9 @@ interface CommandCodeCommandDeps<C extends CommandCodeConnectionOptions = Comman
|
|
|
1220
1119
|
*/
|
|
1221
1120
|
reports?: () => Promise<CommandCodeAccountsReport>;
|
|
1222
1121
|
/**
|
|
1223
|
-
* Resolve the active locale for one command run
|
|
1224
|
-
*
|
|
1225
|
-
*
|
|
1226
|
-
* with the default locale (`'zh'`) — historically the only language the
|
|
1227
|
-
* command ever shipped in.
|
|
1122
|
+
* Resolve the active locale for one command run; the plugin entry wires it
|
|
1123
|
+
* from `Config.lang` and the shell's `LC_ALL`/`LANG`. Absent (notably in
|
|
1124
|
+
* tests), the command renders with the default locale `'zh'`.
|
|
1228
1125
|
*/
|
|
1229
1126
|
getLocale?: () => LocaleId;
|
|
1230
1127
|
}
|
|
@@ -1286,9 +1183,9 @@ declare const loginStatusSchema: TypertSchema<CommandCodeLoginStatus>;
|
|
|
1286
1183
|
/**
|
|
1287
1184
|
* The browser-login face the usage service exposes (`commandcode/login*`).
|
|
1288
1185
|
* Backed by the Host-half {@link !CommandCodeLoginFlow} when the plugin entry
|
|
1289
|
-
* wired one; absent, `status`/`cancel` degrade to the idle status
|
|
1290
|
-
*
|
|
1291
|
-
*
|
|
1186
|
+
* wired one; absent, `status`/`cancel` degrade to the idle status and `begin`
|
|
1187
|
+
* rejects with a plain message, so the page's manual paste path stays the
|
|
1188
|
+
* fallback instead of hanging.
|
|
1292
1189
|
*/
|
|
1293
1190
|
interface LoginFlowFacade {
|
|
1294
1191
|
/** Start (or rejoin) an attempt; rejects when it cannot start at all. */
|
|
@@ -1309,10 +1206,9 @@ interface CommandCodeUsageDeps<C extends CommandCodeConnectionOptions = CommandC
|
|
|
1309
1206
|
*/
|
|
1310
1207
|
reports?: () => Promise<CommandCodeAccountsReport>;
|
|
1311
1208
|
/**
|
|
1312
|
-
* Model-catalog source for the settings page's model editors
|
|
1313
|
-
*
|
|
1314
|
-
*
|
|
1315
|
-
* editors degrade to the empty state.
|
|
1209
|
+
* Model-catalog source for the settings page's model editors. Absent, the
|
|
1210
|
+
* `models` endpoint answers an empty list — the page's editors degrade to
|
|
1211
|
+
* the empty state.
|
|
1316
1212
|
*/
|
|
1317
1213
|
listModels?: () => Promise<CommandCodeCatalog>;
|
|
1318
1214
|
/**
|
|
@@ -1322,11 +1218,7 @@ interface CommandCodeUsageDeps<C extends CommandCodeConnectionOptions = CommandC
|
|
|
1322
1218
|
* only to stub it in a test.
|
|
1323
1219
|
*/
|
|
1324
1220
|
prices?: () => CommandCodePriceTable;
|
|
1325
|
-
/**
|
|
1326
|
-
* The browser-login flow (wired by the plugin entry). Absent means the
|
|
1327
|
-
* login endpoints answer `idle` / reject with a plain message — the page's
|
|
1328
|
-
* manual paste path stays the fallback.
|
|
1329
|
-
*/
|
|
1221
|
+
/** The browser-login flow (wired by the plugin entry); see {@link LoginFlowFacade}. */
|
|
1330
1222
|
login?: LoginFlowFacade;
|
|
1331
1223
|
}
|
|
1332
1224
|
/**
|
|
@@ -1340,34 +1232,30 @@ declare class CommandCodeUsageService<C extends CommandCodeConnectionOptions = C
|
|
|
1340
1232
|
private readonly deps;
|
|
1341
1233
|
constructor(ctx: Context, deps: CommandCodeUsageDeps<C>);
|
|
1342
1234
|
/**
|
|
1343
|
-
* Account, usage, and credit state for the settings page's account card
|
|
1344
|
-
*
|
|
1345
|
-
*
|
|
1346
|
-
*
|
|
1347
|
-
* `MISSING_CREDENTIAL` when no key resolves, which the Gateway folds into
|
|
1348
|
-
* the failure branch the page renders as a hint.
|
|
1235
|
+
* Account, usage, and credit state for the settings page's account card.
|
|
1236
|
+
* Degrades per endpoint like the `/commandcode` command (failures land in
|
|
1237
|
+
* `report.failures`); throws `MISSING_CREDENTIAL` when no key resolves, which
|
|
1238
|
+
* the Gateway folds into the failure branch the page renders as a hint.
|
|
1349
1239
|
*/
|
|
1350
1240
|
report(): Promise<CommandCodeAccountsReport>;
|
|
1351
1241
|
/**
|
|
1352
|
-
* The full model catalog for the settings page's model editors
|
|
1353
|
-
*
|
|
1354
|
-
*
|
|
1355
|
-
*
|
|
1356
|
-
* the live list instead of typed by hand.
|
|
1242
|
+
* The full model catalog for the settings page's model editors. The browser
|
|
1243
|
+
* never calls the Command Code API directly — the Host serves the catalog
|
|
1244
|
+
* (already fetched/cached by the adapter) so models can be picked from the
|
|
1245
|
+
* live list instead of typed by hand.
|
|
1357
1246
|
*/
|
|
1358
1247
|
models(): Promise<CommandCodeCatalog>;
|
|
1359
1248
|
/**
|
|
1360
1249
|
* The model price table the composer prices an in-progress session with.
|
|
1361
|
-
* Static vendored data
|
|
1362
|
-
*
|
|
1363
|
-
*
|
|
1250
|
+
* Static vendored data, served Host-side so the browser bundle never carries
|
|
1251
|
+
* a copy that could drift from the snapshot, and so a price update reaches an
|
|
1252
|
+
* open page without a rebuild.
|
|
1364
1253
|
*/
|
|
1365
1254
|
prices(): Promise<CommandCodePriceTable>;
|
|
1366
1255
|
/**
|
|
1367
1256
|
* Start (or rejoin) a browser-login attempt and return its fresh status —
|
|
1368
1257
|
* `waiting` carrying the Studio URL. Rejects when the flow cannot start
|
|
1369
|
-
* (no free loopback port, disposed plugin)
|
|
1370
|
-
* into the failure branch the page renders.
|
|
1258
|
+
* (no free loopback port, disposed plugin).
|
|
1371
1259
|
*/
|
|
1372
1260
|
loginBegin(targetRef?: string): Promise<CommandCodeLoginStatus>;
|
|
1373
1261
|
/** Poll a login attempt's status. */
|
|
@@ -1469,16 +1357,15 @@ declare class CommandCodeLoginFlow {
|
|
|
1469
1357
|
* asynchronously (`complete()`), and that window is open to a cancel or a
|
|
1470
1358
|
* fresh `begin()`; the generation lets a late completion recognize that it
|
|
1471
1359
|
* no longer owns the status face and stop instead of storing a credential
|
|
1472
|
-
* the user cancelled
|
|
1360
|
+
* the user cancelled.
|
|
1473
1361
|
*/
|
|
1474
1362
|
private attemptSeq;
|
|
1475
1363
|
/**
|
|
1476
|
-
* The start currently binding a port, if any. Every `begin()`
|
|
1477
|
-
*
|
|
1478
|
-
*
|
|
1479
|
-
*
|
|
1480
|
-
*
|
|
1481
|
-
* the port window so browser login dies until the Host restarts.
|
|
1364
|
+
* The start currently binding a port, if any. Every `begin()` arriving before
|
|
1365
|
+
* it settles joins it: two independent starts would each bind a loopback
|
|
1366
|
+
* server, and only the LAST one is reachable by `teardown()` — the orphan
|
|
1367
|
+
* keeps answering `/callback` for the process's lifetime, and ten of them
|
|
1368
|
+
* exhaust the port window so browser login dies until the Host restarts.
|
|
1482
1369
|
*/
|
|
1483
1370
|
private starting;
|
|
1484
1371
|
/** A live attempt's destination; different rows may not rejoin it. */
|
|
@@ -1551,32 +1438,25 @@ declare class CommandCodeLoginFlow {
|
|
|
1551
1438
|
declare const COMMANDCODE_SEARCH_PROVIDER_ID = "commandcode";
|
|
1552
1439
|
/**
|
|
1553
1440
|
* The factory-declared search provider id dsh ships by default (from
|
|
1554
|
-
* `dsh-base`'s cordis patch `web.config.searchProvider`).
|
|
1555
|
-
*
|
|
1556
|
-
*
|
|
1557
|
-
* {@link applyCommandCodeSearchSelection}) — it never forces this default,
|
|
1558
|
-
* because forcing it is what used to silence sibling search plugins such as
|
|
1559
|
-
* modsearch even with Command Code search turned off (issue #26).
|
|
1441
|
+
* `dsh-base`'s cordis patch `web.config.searchProvider`). A documented
|
|
1442
|
+
* reference only: disabling this plugin's `webSearch` toggle restores the
|
|
1443
|
+
* PREVIOUSLY selected backend, never this default (issue #26).
|
|
1560
1444
|
*/
|
|
1561
1445
|
declare const DEFAULT_WEB_SEARCH_PROVIDER_ID = "deepseek-official";
|
|
1562
1446
|
/**
|
|
1563
1447
|
* Tracked web-search selection state for one mounted `WebRuntime`.
|
|
1564
1448
|
*
|
|
1565
|
-
* `owner` marks whether this plugin currently owns the selection
|
|
1566
|
-
*
|
|
1567
|
-
*
|
|
1568
|
-
*
|
|
1569
|
-
* configured, leave auto-select" and must round-trip untouched: writing the
|
|
1570
|
-
* factory default instead would still override a sibling plugin's own
|
|
1571
|
-
* constructor-time pin.
|
|
1449
|
+
* `owner` marks whether this plugin currently owns the selection. `displaced`
|
|
1450
|
+
* is the backend it took over — restored on disable or unload — and
|
|
1451
|
+
* `undefined` means "nothing was configured, leave auto-select" and must
|
|
1452
|
+
* round-trip untouched.
|
|
1572
1453
|
*
|
|
1573
1454
|
* `preexisting` is the one fact `displaced` cannot carry: an `undefined`
|
|
1574
1455
|
* `displaced` means EITHER "the field was unset when we took over" (give
|
|
1575
|
-
* `undefined` back
|
|
1576
|
-
*
|
|
1577
|
-
*
|
|
1578
|
-
*
|
|
1579
|
-
* search — the moment this plugin was disabled or unloaded.
|
|
1456
|
+
* `undefined` back) OR "the field already read `commandcode`" (touch
|
|
1457
|
+
* nothing). Collapsing the two is what turned a user's own
|
|
1458
|
+
* `searchProvider: commandcode` pin into an auto-select, and then into
|
|
1459
|
+
* `WEB_PROVIDER_AMBIGUOUS` on every search.
|
|
1580
1460
|
*/
|
|
1581
1461
|
interface CommandCodeSearchSelection {
|
|
1582
1462
|
owner: boolean;
|
|
@@ -1591,24 +1471,15 @@ declare function commandCodeSearchSelection(): CommandCodeSearchSelection;
|
|
|
1591
1471
|
* providers (issue #26).
|
|
1592
1472
|
*
|
|
1593
1473
|
* - Enabling writes `commandcode` and remembers whatever it displaced. When
|
|
1594
|
-
* the plugin already owns the selection
|
|
1595
|
-
*
|
|
1596
|
-
*
|
|
1597
|
-
* - Disabling hands the selection back to the remembered backend
|
|
1598
|
-
*
|
|
1599
|
-
*
|
|
1600
|
-
*
|
|
1601
|
-
* auto-select
|
|
1602
|
-
*
|
|
1603
|
-
* surviving runtime the plugin did not set, or a manual
|
|
1604
|
-
* `searchProvider: commandcode` pin), `displaced` stays undefined and
|
|
1605
|
-
* `preexisting` is set, so the later disable is a no-op rather than a guess
|
|
1606
|
-
* at the factory default. A "no-op" means the field is left ALONE: writing
|
|
1607
|
-
* that `undefined` back would destroy the user's own pin, and dsh-web reads
|
|
1608
|
-
* a cleared `searchProviderId` as auto-select — where a second usable
|
|
1609
|
-
* provider (the shipped `deepseek-official` is usable whenever a DeepSeek
|
|
1610
|
-
* key resolves) makes EVERY later search throw
|
|
1611
|
-
* `WEB_PROVIDER_AMBIGUOUS`.
|
|
1474
|
+
* the plugin already owns the selection, the original `displaced` is kept —
|
|
1475
|
+
* the field currently holds our own id, which must never be mistaken for the
|
|
1476
|
+
* user's backend.
|
|
1477
|
+
* - Disabling hands the selection back to the remembered backend only when
|
|
1478
|
+
* this plugin actually took it over. A fresh boot straight into
|
|
1479
|
+
* `webSearch: false`, or a `preexisting` field, leaves it ALONE: writing the
|
|
1480
|
+
* empty memory back would clear the user's own `searchProvider: commandcode`
|
|
1481
|
+
* pin and hand the selection to dsh-web's auto-select, where a second usable
|
|
1482
|
+
* provider makes every later search throw `WEB_PROVIDER_AMBIGUOUS`.
|
|
1612
1483
|
*
|
|
1613
1484
|
* Never throws: like the low-level rewrite, a hardened runtime shape degrades
|
|
1614
1485
|
* to registered-but-unselected.
|
|
@@ -1624,11 +1495,11 @@ interface CommandCodeSearchProviderDeps {
|
|
|
1624
1495
|
fetchImpl?: typeof fetch;
|
|
1625
1496
|
}
|
|
1626
1497
|
/**
|
|
1627
|
-
* A `ctx.web` search provider backed by the Command Code Provider API
|
|
1628
|
-
* the plugin's credential chain and `apiBase
|
|
1629
|
-
*
|
|
1630
|
-
*
|
|
1631
|
-
*
|
|
1498
|
+
* A `ctx.web` search provider backed by the Command Code Provider API, reusing
|
|
1499
|
+
* the plugin's credential chain and `apiBase` so the model-facing `web_search`
|
|
1500
|
+
* tool needs no separate configuration. Selection between multiple search
|
|
1501
|
+
* providers is the web seam's job (pin `searchProvider: commandcode` if
|
|
1502
|
+
* ambiguous).
|
|
1632
1503
|
*/
|
|
1633
1504
|
declare class CommandCodeSearchProvider implements WebSearchProvider {
|
|
1634
1505
|
private readonly deps;
|
|
@@ -1650,11 +1521,9 @@ interface TuiLocalizedText {
|
|
|
1650
1521
|
type TuiSettingsFieldKind = 'text' | 'number' | 'boolean' | 'select';
|
|
1651
1522
|
/** One choice of an options-bearing field. */
|
|
1652
1523
|
interface TuiSettingsFieldOption {
|
|
1653
|
-
/** Stored value. */
|
|
1654
1524
|
readonly value: string;
|
|
1655
1525
|
/** Display label (English; also the fallback). */
|
|
1656
1526
|
readonly label: string;
|
|
1657
|
-
/** Provider-owned translations for the label. */
|
|
1658
1527
|
readonly descriptions?: TuiLocalizedText;
|
|
1659
1528
|
}
|
|
1660
1529
|
/** The write one field's draft stages when the section is saved. */
|
|
@@ -1670,11 +1539,9 @@ interface TuiSettingsField {
|
|
|
1670
1539
|
readonly path: readonly string[];
|
|
1671
1540
|
/** Short field label (English; also the fallback). */
|
|
1672
1541
|
readonly label: string;
|
|
1673
|
-
/** Provider-owned translations for the label. */
|
|
1674
1542
|
readonly descriptions?: TuiLocalizedText;
|
|
1675
1543
|
/** Optional one-line help rendered under the field. */
|
|
1676
1544
|
readonly hint?: string;
|
|
1677
|
-
/** Provider-owned translations for the hint. */
|
|
1678
1545
|
readonly hintDescriptions?: TuiLocalizedText;
|
|
1679
1546
|
/** Optional group id; grouped fields render on that group's subpage. */
|
|
1680
1547
|
readonly group?: string;
|
|
@@ -1706,7 +1573,6 @@ interface TuiSettingsGroup {
|
|
|
1706
1573
|
readonly id: string;
|
|
1707
1574
|
/** Group title (English; also the fallback). */
|
|
1708
1575
|
readonly title: string;
|
|
1709
|
-
/** Provider-owned translations for the title. */
|
|
1710
1576
|
readonly descriptions?: TuiLocalizedText;
|
|
1711
1577
|
}
|
|
1712
1578
|
/** One plugin's section inside the dsh-TUI settings screen. */
|
|
@@ -1715,7 +1581,6 @@ interface TuiSettingsSection {
|
|
|
1715
1581
|
readonly ns: string;
|
|
1716
1582
|
/** Section title (English; also the fallback). */
|
|
1717
1583
|
readonly title: string;
|
|
1718
|
-
/** Provider-owned translations for the title. */
|
|
1719
1584
|
readonly descriptions?: TuiLocalizedText;
|
|
1720
1585
|
/** Optional navigation groups, in display order. */
|
|
1721
1586
|
readonly groups?: readonly TuiSettingsGroup[];
|
|
@@ -1783,25 +1648,22 @@ interface CommandCodeTuiSettingsDeps {
|
|
|
1783
1648
|
* Build the section descriptor. Pure, so tests can pin the exact fields
|
|
1784
1649
|
* without a dsh-TUI host.
|
|
1785
1650
|
*
|
|
1786
|
-
*
|
|
1787
|
-
* `
|
|
1788
|
-
*
|
|
1789
|
-
*
|
|
1790
|
-
*
|
|
1791
|
-
* unset
|
|
1792
|
-
*
|
|
1793
|
-
* the screen's "(empty)".
|
|
1651
|
+
* The two option-bearing fields (`activeAccount`, `lang`) are `text` +
|
|
1652
|
+
* `options` rather than `select`, because a `select` cannot express "unset" —
|
|
1653
|
+
* cycling only ever lands on a declared option, so it would strand the user on
|
|
1654
|
+
* a pinned value with no way back to automatic. The `auto` sentinel plus a
|
|
1655
|
+
* `parse` that clears the path keeps unset reachable. `filterModelsByPlan`
|
|
1656
|
+
* formats its EFFECTIVE default (unset means true at the adapter) so a fresh
|
|
1657
|
+
* install reads true instead of the screen's "(empty)".
|
|
1794
1658
|
*/
|
|
1795
1659
|
declare function buildCommandCodeTuiSection(deps: CommandCodeTuiSettingsDeps): TuiSettingsSection;
|
|
1796
1660
|
/**
|
|
1797
1661
|
* Register the Command Code section on a dsh-TUI host.
|
|
1798
1662
|
*
|
|
1799
|
-
* @param ctx - the context of an activated `tuiSettingsSections` injection.
|
|
1800
|
-
* @param deps - plugin-owned facts the section reads.
|
|
1801
1663
|
* @returns a refresh function that re-registers the section when a fact it
|
|
1802
|
-
* renders changed
|
|
1803
|
-
*
|
|
1804
|
-
* inert after the fiber is torn down.
|
|
1664
|
+
* renders changed — the plugin entry calls it from its
|
|
1665
|
+
* `loader/volatile-update` listener — or `undefined` when the seam is
|
|
1666
|
+
* unusable. The returned function is inert after the fiber is torn down.
|
|
1805
1667
|
*/
|
|
1806
1668
|
declare function applyCommandCodeTuiSettings(ctx: Context, deps: CommandCodeTuiSettingsDeps): (() => void) | undefined;
|
|
1807
1669
|
//#endregion
|
|
@@ -1836,14 +1698,11 @@ interface Config {
|
|
|
1836
1698
|
streamIdleTimeoutMs?: number;
|
|
1837
1699
|
/**
|
|
1838
1700
|
* Transport failures one request absorbs before the failure is surfaced;
|
|
1839
|
-
* defaults to 5. The route's retry policy is near-unbounded on purpose
|
|
1840
|
-
* attempts, waits doubling to 15 minutes) because that shape is for
|
|
1841
|
-
* failures a provider asks to have retried
|
|
1842
|
-
*
|
|
1843
|
-
*
|
|
1844
|
-
* after the failures before them, so ~15.5 s of grace), and after that the
|
|
1845
|
-
* wait is pure stall, so the retries are capped here. Raise it on a genuinely
|
|
1846
|
-
* flaky link; 0 surfaces every transport failure immediately.
|
|
1701
|
+
* defaults to 5. The route's retry policy is near-unbounded on purpose
|
|
1702
|
+
* (1000 attempts, waits doubling to 15 minutes) because that shape is for
|
|
1703
|
+
* the failures a provider asks to have retried; a transport failure is not
|
|
1704
|
+
* one of those, and after ~15.5 s of grace the wait is pure stall, so it is
|
|
1705
|
+
* capped here (issue #39). 0 surfaces every transport failure immediately.
|
|
1847
1706
|
*/
|
|
1848
1707
|
transportMaxRetries?: number;
|
|
1849
1708
|
/**
|
|
@@ -1855,8 +1714,7 @@ interface Config {
|
|
|
1855
1714
|
filterModelsByPlan?: boolean;
|
|
1856
1715
|
/**
|
|
1857
1716
|
* Visible-model allowlist: catalog model ids shown in pickers. Empty or
|
|
1858
|
-
* unset means "show everything"
|
|
1859
|
-
* filter card; applies after the subscription-tier filter.
|
|
1717
|
+
* unset means "show everything"; applied after the subscription-tier filter.
|
|
1860
1718
|
*/
|
|
1861
1719
|
visibleModels?: string[];
|
|
1862
1720
|
/**
|
|
@@ -1864,117 +1722,82 @@ interface Config {
|
|
|
1864
1722
|
* list, keyed by catalog id (`true` = listed, `false` = hidden). An id here
|
|
1865
1723
|
* decides that model on its own; an id absent here follows `visibleModels`.
|
|
1866
1724
|
* dsh-TUI keys a staged edit by the field's path, so the checkboxes need one
|
|
1867
|
-
* path per model — a map
|
|
1868
|
-
* is a member of the array".
|
|
1725
|
+
* path per model — a map.
|
|
1869
1726
|
*/
|
|
1870
1727
|
modelVisibility?: Record<string, boolean>;
|
|
1871
1728
|
/**
|
|
1872
1729
|
* Extra accounts for multi-account rotation. The top-level
|
|
1873
1730
|
* `apiKey`/`apiKeyEnv` (plus the CLI auth file) always form the first
|
|
1874
|
-
* (`default`) account; each entry here adds one more
|
|
1875
|
-
*
|
|
1876
|
-
*
|
|
1877
|
-
* request fails with a `RATE_LIMIT` error naming the earliest window
|
|
1878
|
-
* reset. Entries without `apiKey` or `apiKeyEnv` are ignored.
|
|
1731
|
+
* (`default`) account; each entry here adds one more, and an entry with
|
|
1732
|
+
* neither `apiKey` nor `apiKeyEnv` is ignored. A pre-stream 429/401 marks
|
|
1733
|
+
* the key and the next account's key is retried transparently.
|
|
1879
1734
|
*/
|
|
1880
1735
|
accounts?: CommandCodeAccountConfig[];
|
|
1881
1736
|
/**
|
|
1882
1737
|
* Manually selected active account: a slot id — `default`, or an extra
|
|
1883
|
-
* account's credential reference (e.g. `COMMANDCODE_API_KEY_2`).
|
|
1884
|
-
*
|
|
1885
|
-
*
|
|
1886
|
-
* rotation still applies). Unset means "first usable account".
|
|
1738
|
+
* account's credential reference (e.g. `COMMANDCODE_API_KEY_2`). It serves
|
|
1739
|
+
* whenever usable; an unknown id or an exhausted one falls back to rotation
|
|
1740
|
+
* order. Unset means "first usable account".
|
|
1887
1741
|
*/
|
|
1888
1742
|
activeAccount?: string;
|
|
1889
1743
|
/**
|
|
1890
|
-
* Model → account routing rules
|
|
1891
|
-
* account slot id
|
|
1892
|
-
*
|
|
1893
|
-
*
|
|
1894
|
-
* the passive rotation order. A routed account that is exhausted or invalid
|
|
1895
|
-
* falls back to the normal selection, so the router is a hint, never a hard
|
|
1896
|
-
* gate. The first matching rule wins.
|
|
1744
|
+
* Model → account routing rules, each listing catalog model ids for an
|
|
1745
|
+
* account slot id. A matching rule's account serves before {@link
|
|
1746
|
+
* activeAccount} and the passive rotation order; an unusable routed account
|
|
1747
|
+
* falls back, so the router is a hint, never a hard gate. First match wins.
|
|
1897
1748
|
*/
|
|
1898
1749
|
modelAccountRules?: CommandCodeModelAccountRule[];
|
|
1899
1750
|
/**
|
|
1900
1751
|
* Whether to use Command Code as the backend for dsh's model-facing
|
|
1901
|
-
* `web_search` tool.
|
|
1902
|
-
*
|
|
1903
|
-
*
|
|
1904
|
-
*
|
|
1905
|
-
*
|
|
1906
|
-
*
|
|
1907
|
-
*
|
|
1908
|
-
* rides dsh's internal `searchProviderId`, which is read per search call,
|
|
1909
|
-
* so a setting change lands on the next search without a restart.
|
|
1910
|
-
* Defaults to true.
|
|
1752
|
+
* `web_search` tool. Enabled registers a `commandcode` search provider on
|
|
1753
|
+
* `ctx.web` AND selects it over the shipped `deepseek-official` (or a
|
|
1754
|
+
* sibling plugin's pin), reusing the SAME key and apiBase as chat. Disabling
|
|
1755
|
+
* hands the selection back to whichever backend was there before, so a
|
|
1756
|
+
* sibling search plugin (e.g. modsearch) keeps working (issue #26). The
|
|
1757
|
+
* write rides dsh's internal `searchProviderId`, read per search call, so a
|
|
1758
|
+
* setting change lands on the next search without a restart. Defaults true.
|
|
1911
1759
|
*/
|
|
1912
1760
|
webSearch?: boolean;
|
|
1913
1761
|
/**
|
|
1914
1762
|
* Whether the Web sidebar shows the plans & quota card
|
|
1915
|
-
* (`sidebar.footer.action`). Defaults to false
|
|
1916
|
-
*
|
|
1917
|
-
*
|
|
1918
|
-
*
|
|
1919
|
-
* the toggle is on. Read by the browser client; the adapter ignores it.
|
|
1763
|
+
* (`sidebar.footer.action`). Defaults to false, so an unset document mounts
|
|
1764
|
+
* no sidebar quota surface and no background usage poll for it; the
|
|
1765
|
+
* dashboard cell behind it stays registered. Read by the browser client; the
|
|
1766
|
+
* adapter ignores it.
|
|
1920
1767
|
*/
|
|
1921
1768
|
showSidebarQuota?: boolean;
|
|
1922
|
-
/**
|
|
1923
|
-
* Whether the Command Code decision model (`typesafe/jev`) may auto-approve
|
|
1924
|
-
* shell commands that dsh was about to ask about. Defaults to FALSE: the
|
|
1925
|
-
* guard turns a model's opinion into a one-shot approval grant, so it is
|
|
1926
|
-
* opt-in, and the command text (plus the agent's own description of it) is
|
|
1927
|
-
* sent to Command Code to judge. Only commands a policy already wanted a
|
|
1928
|
-
* human to look at are ever judged, and only a confident "safe" verdict
|
|
1929
|
-
* (`commandGuardLevel`) skips the prompt — every other outcome, including
|
|
1930
|
-
* any failure of the decision call itself, delegates to the normal approval
|
|
1931
|
-
* flow. See `./command-guard.ts`.
|
|
1932
|
-
*/
|
|
1933
|
-
commandGuard?: boolean;
|
|
1934
|
-
/**
|
|
1935
|
-
* How confident every verdict must be before the guard skips the approval
|
|
1936
|
-
* prompt: `high` (0.95), `medium` (0.9, the default) or `low` (0.8). A lower
|
|
1937
|
-
* level approves more, on less evidence. The decision budget is fixed
|
|
1938
|
-
* (`COMMAND_GUARD_TIMEOUT_MS`), so this is the guard's only tuning knob.
|
|
1939
|
-
*/
|
|
1940
|
-
commandGuardLevel?: CommandGuardLevel;
|
|
1941
1769
|
/**
|
|
1942
1770
|
* Whether requests enforce zero data retention: the provider then routes
|
|
1943
1771
|
* them only through upstreams that keep no prompts/completions and never
|
|
1944
1772
|
* train on them (its own opt-in, `CMD_ZDR=1` in the CLI / `x-cmd-zdr: 1` on
|
|
1945
1773
|
* the Provider API). Defaults to FALSE: `zdr` changes WHERE a request is
|
|
1946
|
-
* served. Every chat request carries the header when enabled
|
|
1947
|
-
* no ZDR-capable upstream fails with 422 `cmd_zdr_no_providers`
|
|
1948
|
-
*
|
|
1949
|
-
*
|
|
1950
|
-
*
|
|
1951
|
-
* Command Code's Studio). The decision endpoint behind the command guard is
|
|
1952
|
-
* never ZDR-enforced — see `./systemone.ts`.
|
|
1774
|
+
* served. Every chat request carries the header when enabled, and a model
|
|
1775
|
+
* with no ZDR-capable upstream fails with 422 `cmd_zdr_no_providers` rather
|
|
1776
|
+
* than losing the guarantee. ZDR capacity is priced pass-through and usually
|
|
1777
|
+
* costs more; the price readout keeps quoting the ordinary catalog rates
|
|
1778
|
+
* (the real per-request price shows in Command Code's Studio).
|
|
1953
1779
|
*/
|
|
1954
1780
|
zdr?: boolean;
|
|
1955
1781
|
/**
|
|
1956
1782
|
* Language override for the `/commandcode` Host-side command's user-facing
|
|
1957
|
-
* copy. Host commands cannot read the client's `ctx.locale`, so this is
|
|
1958
|
-
*
|
|
1959
|
-
*
|
|
1960
|
-
*
|
|
1961
|
-
*
|
|
1962
|
-
*
|
|
1963
|
-
*
|
|
1964
|
-
* `pickCommandLocale`.
|
|
1783
|
+
* copy. Host commands cannot read the client's `ctx.locale`, so this is the
|
|
1784
|
+
* explicit knob: `'zh'` or `'en'`, defaulting to `'zh'`. The web settings
|
|
1785
|
+
* page is unaffected — it follows the browser's language preference on its
|
|
1786
|
+
* own. The declared type is `string` (the schemastery `pattern` cannot
|
|
1787
|
+
* narrow literal types); `pickCommandLocale` treats an unknown value as
|
|
1788
|
+
* "unset" and then reads `LC_ALL`/`LANG`, which is only reachable when
|
|
1789
|
+
* `lang` is absent from a programmatically built config.
|
|
1965
1790
|
*/
|
|
1966
1791
|
lang?: string;
|
|
1967
1792
|
}
|
|
1968
1793
|
/**
|
|
1969
1794
|
* The Config schema: every field volatile except the composition-only `apiKey`
|
|
1970
|
-
* secret.
|
|
1971
|
-
*
|
|
1972
|
-
*
|
|
1973
|
-
*
|
|
1974
|
-
*
|
|
1975
|
-
*
|
|
1976
|
-
* without remounting this fiber (the `loader/volatile-update` listener at the
|
|
1977
|
-
* bottom of `apply` covers the facts that are not re-derived per read).
|
|
1795
|
+
* secret. 0.1.7's settings forms are projected from the schema's
|
|
1796
|
+
* `meta.volatile` nodes, so an unmarked field would be invisible to AND
|
|
1797
|
+
* unwritable from the settings page. The loader also hands `apply()` a live
|
|
1798
|
+
* reference per marked field, so writes commit in place without remounting
|
|
1799
|
+
* this fiber — the `loader/volatile-update` listener at the bottom of `apply`
|
|
1800
|
+
* re-derives the two facts that are not re-read per request.
|
|
1978
1801
|
*/
|
|
1979
1802
|
declare const Config: z<Config>;
|
|
1980
1803
|
/** One resolution's complete request facts: connection plus credential reference. */
|
|
@@ -1985,7 +1808,7 @@ interface ResolvedCommandCodeOptions extends CommandCodeConnectionOptions {
|
|
|
1985
1808
|
* The one explicit resolve step from raw config to validated connection
|
|
1986
1809
|
* facts. Programmatic construction may bypass Schemastery normalization, so
|
|
1987
1810
|
* every default is re-judged here — for the composition entry at load and for
|
|
1988
|
-
*
|
|
1811
|
+
* every settings-backed read.
|
|
1989
1812
|
*/
|
|
1990
1813
|
declare function resolveAdapterOptions(config: Config): ResolvedCommandCodeOptions;
|
|
1991
1814
|
declare function apply(ctx: Context, config: Config): void;
|