@mars-sea/dsh-commandcode-provider 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.ts CHANGED
@@ -24,7 +24,7 @@ declare const KNOWN_EFFORTS: Readonly<Record<string, readonly string[]>>;
24
24
  */
25
25
  declare const KNOWN_IMAGE_MODELS: ReadonlySet<string>;
26
26
  /**
27
- * Models the official CLI's model table (`ZA` in command-code@1.27.1) marks
27
+ * Models the official CLI's model table (`ZA` in command-code@1.28.1) marks
28
28
  * `reasoning:!0` but defines no selectable `reasoning_effort` levels — they
29
29
  * think automatically, with Command Code driving the depth. This is the
30
30
  * authoritative "thinks, effort not adjustable" set: `KNOWN_EFFORTS` (which
@@ -32,7 +32,7 @@ declare const KNOWN_IMAGE_MODELS: ReadonlySet<string>;
32
32
  * effort levels, and this snapshot is not surfaced in the picker's compact
33
33
  * description — it exists for programmatic consumers.
34
34
  *
35
- * Source: the command-code@1.27.1 bundled model table (dist/cli.mjs, the `ZA`
35
+ * Source: the command-code@1.28.1 bundled model table (dist/cli.mjs, the `ZA`
36
36
  * object), cross-checked with https://commandcode.ai/docs/reference/cli/models.
37
37
  * Keep in sync via the dsh-commandcode-upstream skill.
38
38
  */
@@ -73,7 +73,7 @@ declare function compareByPlan(a: {
73
73
  }): number;
74
74
  /**
75
75
  * Subscription plan table, synced from the official CLI bundle's plan maps
76
- * (`Nn`/`$n` in command-code@1.27.1 `dist/cli.mjs`): subscription `planId`
76
+ * (`Nn`/`$n` in command-code@1.28.1 `dist/cli.mjs`): subscription `planId`
77
77
  * prefix → display name and the plan's monthly credit total. This is the
78
78
  * account's own subscription (from `/alpha/billing/subscriptions`) — distinct
79
79
  * from {@link KNOWN_PLANS}, which maps catalog models to their minimum tier.
@@ -172,7 +172,7 @@ declare function peakPricingState(modelId: string, now?: number): 'peak' | 'off-
172
172
  * for models without time-of-day pricing.
173
173
  */
174
174
  declare function peakPricingLabel(modelId: string, now?: number): string | undefined;
175
- declare const COMMAND_CODE_CLI_VERSION = "1.27.1";
175
+ declare const COMMAND_CODE_CLI_VERSION = "1.28.1";
176
176
  declare const DEFAULT_API_BASE = "https://api.commandcode.ai";
177
177
  declare const DEFAULT_GENERATE_MAX_TOKENS = 64000;
178
178
  declare const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
@@ -248,6 +248,15 @@ interface CommandCodeAdapterDeps<C extends CommandCodeConnectionOptions = Comman
248
248
  options: () => C;
249
249
  /** Resolve a usable API key for the given connection facts, or throw `MISSING_CREDENTIAL`. */
250
250
  resolveApiKey: (connection: C) => Promise<string>;
251
+ /**
252
+ * Multi-account rotation hook: the request sent with `rejectedKey` was
253
+ * refused with 429 (`rate-limit`) or 401 (`invalid-credential`) before
254
+ * any response body streamed. The host marks that key and returns the next
255
+ * account's key to retry with, or `undefined` to surface the failure.
256
+ * Only pre-stream rejections rotate — a mid-stream failure never replays a
257
+ * partially consumed generation against another account.
258
+ */
259
+ rotateApiKey?: (rejectedKey: string, rejection: 'rate-limit' | 'invalid-credential', connection: C) => Promise<string | undefined>;
251
260
  /** HTTP transport override (tests); defaults to the global `fetch`. */
252
261
  fetchImpl?: typeof fetch;
253
262
  /** Resolve the optional durable attachment service for image input (tests); defaults to none. */
@@ -318,8 +327,8 @@ declare class CommandCodeAdapter<C extends CommandCodeConnectionOptions = Comman
318
327
  private catalog;
319
328
  private readonly fetchImpl;
320
329
  private readonly resolveAttachments;
321
- private billingAccess;
322
- private billingAccessInflight;
330
+ private readonly billingAccess;
331
+ private readonly billingAccessInflight;
323
332
  constructor(deps: CommandCodeAdapterDeps<C>);
324
333
  /**
325
334
  * Command Code is a metered subscription API: 429 (rate limit) and 5xx
@@ -359,16 +368,204 @@ declare class CommandCodeAdapter<C extends CommandCodeConnectionOptions = Comman
359
368
  * Each endpoint degrades independently: a failed one lands in `failures`
360
369
  * while the rest still report, so a transient outage never blanks the whole
361
370
  * view. Requires a usable API key (throws `MISSING_CREDENTIAL` otherwise).
371
+ * Pass `apiKey` to report on a specific account of a multi-account pool;
372
+ * the default resolves the currently active account.
362
373
  */
363
- getUsage(): Promise<CommandCodeUsageReport>;
374
+ getUsage(apiKey?: string): Promise<CommandCodeUsageReport>;
375
+ /**
376
+ * Probe one account's five-hour window from `/alpha/billing/credits`. The
377
+ * multi-account pool calls this when every account is marked exhausted: an
378
+ * account whose window no longer reports `exceeded` is revived, and the
379
+ * `resetAt` values feed the "earliest reset" error message. Returns
380
+ * `undefined` when the probe itself failed (transport, non-200, or a
381
+ * payload without window limits) — a failed probe never changes pool state.
382
+ */
383
+ probeFiveHourWindow(apiKey: string): Promise<{
384
+ exceeded: boolean;
385
+ resetAt: number;
386
+ } | undefined>;
364
387
  stream(options: GenerateOptions): AsyncIterable<StreamChunk>;
365
388
  }
366
389
  //#endregion
390
+ //#region src/accounts.d.ts
391
+ /** One extra account's raw configuration (composition config or settings). */
392
+ interface CommandCodeAccountConfig {
393
+ /** Display label shown in the usage dashboard and settings page. */
394
+ label?: string;
395
+ /** Credential reference (environment-variable style name) holding this account's API key. */
396
+ apiKeyEnv?: string;
397
+ /** Literal API key (composition config only; never stored in settings). */
398
+ apiKey?: string;
399
+ }
400
+ /** One account slot after config normalization. */
401
+ interface CommandCodeAccountSlot {
402
+ /** Stable id: `default` for the implicit first account, `account-N` for extras. */
403
+ id: string;
404
+ /** Display label (user-provided or generated). */
405
+ label: string;
406
+ /** Credential reference resolved through the seam; undefined for literal-only slots. */
407
+ ref?: CredentialRef | undefined;
408
+ /** Literal key from composition config. */
409
+ literal?: string | undefined;
410
+ /** Whether the official CLI auth file may back this slot (default slot only). */
411
+ allowAuthFile: boolean;
412
+ }
413
+ /** Why a key stopped serving requests. */
414
+ type AccountRejection = 'rate-limit' | 'invalid-credential';
415
+ /** One key's rotation state. */
416
+ interface CommandCodeAccountState {
417
+ kind:
418
+ /** Marked by a 429; the window's reset time is unknown until probed. */
419
+ 'unknown' |
420
+ /** Probed (or marked with a known reset): unusable until `until` (millis). */
421
+ 'cooldown' |
422
+ /** Marked by a 401: skipped until the stored credential changes. */
423
+ 'disabled';
424
+ /** Human-readable reason for the mark (e.g. `rate limited (429)`). */
425
+ reason: string;
426
+ /** Cooldown end in millis; 0 for the other kinds. */
427
+ until: number;
428
+ }
429
+ /** A slot paired with its resolved key (both pool-internal and UI-facing). */
430
+ interface ResolvedAccount {
431
+ slot: CommandCodeAccountSlot;
432
+ key: string;
433
+ /** The key's current rotation state; undefined means usable. */
434
+ state: CommandCodeAccountState | undefined;
435
+ }
436
+ /** Five-hour window facts probed from `/alpha/billing/credits`. */
437
+ interface FiveHourWindowProbe {
438
+ exceeded: boolean;
439
+ resetAt: number;
440
+ }
441
+ /** Everything the pool needs from the host; all seams are injected. */
442
+ interface CommandCodeAccountPoolDeps {
443
+ /** The current account slots, re-read per resolution so settings changes apply live. */
444
+ slots(): readonly CommandCodeAccountSlot[];
445
+ /** Resolve one credential reference through the credentials service or the launch environment. */
446
+ resolveRef(ref: CredentialRef): Promise<string | undefined>;
447
+ /** The official CLI auth-file key (`~/.commandcode/auth.json`); default slot only. */
448
+ authFileKey(): string | undefined;
449
+ /** Probe one key's five-hour window; undefined when the probe itself failed. */
450
+ probeWindow(apiKey: string): Promise<FiveHourWindowProbe | undefined>;
451
+ /**
452
+ * The manually selected account (a slot id, e.g. `default` or an extra's
453
+ * credential reference), re-read per resolution. The preferred account
454
+ * serves whenever it is usable; an unknown id or an exhausted preferred
455
+ * account falls back to the first usable slot.
456
+ */
457
+ preferredId?(): string | undefined;
458
+ }
459
+ /**
460
+ * Whether an account with this rotation state can serve a request right now.
461
+ * `undefined` (never rejected) is usable; a cooldown becomes usable again
462
+ * once its reset time passes; `unknown` (429, reset unprobed) and
463
+ * `disabled` (401) are not.
464
+ */
465
+ declare function accountUsable(state: CommandCodeAccountState | undefined): boolean;
466
+ /**
467
+ * Pick the account that should serve now: the manually preferred slot when it
468
+ * is usable, otherwise the first usable account in rotation order; undefined
469
+ * when no account is usable. Shared by the pool (request path) and the plugin
470
+ * entry (the usage view's active badge) so both always agree.
471
+ */
472
+ declare function selectActiveAccount(accounts: readonly ResolvedAccount[], preferredId: string | undefined): ResolvedAccount | undefined;
473
+ /**
474
+ * The account pool. Rotation state is keyed by API key (never logged), so two
475
+ * slots resolving to the same credential share one mark, and a key changed in
476
+ * the credentials service starts with a clean slate.
477
+ */
478
+ declare class CommandCodeAccountPool {
479
+ private readonly deps;
480
+ /** Rotation state by API key. */
481
+ private readonly states;
482
+ constructor(deps: CommandCodeAccountPoolDeps);
483
+ /**
484
+ * Resolve every slot's key, deduplicated by key (first slot wins). Slots
485
+ * without any resolvable key are omitted — they still appear in the
486
+ * settings page as unconfigured, they just cannot serve requests.
487
+ */
488
+ resolvedAccounts(): Promise<ResolvedAccount[]>;
489
+ /**
490
+ * Every slot paired with its resolved key and rotation state — NOT
491
+ * deduplicated: two slots sharing one credential both appear (the usage
492
+ * view reports them individually), while slots without any resolvable key
493
+ * are omitted. The serving path uses {@link resolvedAccounts} instead.
494
+ */
495
+ describeAccounts(): Promise<ResolvedAccount[]>;
496
+ /**
497
+ * Hand out the first usable account's key (the manually preferred account
498
+ * when usable, else rotation order). Returns `undefined` when no account
499
+ * resolves any key at all (the caller then reports the missing credential).
500
+ * Throws `RATE_LIMIT` — naming the earliest window reset — or
501
+ * `INVALID_CREDENTIAL` when accounts exist but none can serve.
502
+ *
503
+ * `options.exclude` skips one key during the probe-revival pass: the
504
+ * rotation hook excludes the just-rejected key so a probe that clears its
505
+ * window cannot re-offer the same key within the same request (the adapter
506
+ * refuses already-tried keys; the next request picks the revived key up).
507
+ */
508
+ resolveKey(options?: {
509
+ exclude?: string;
510
+ }): Promise<{
511
+ key: string;
512
+ slot: CommandCodeAccountSlot;
513
+ } | undefined>;
514
+ /**
515
+ * Record a rejection against one key. `rate-limit` (429) marks the key
516
+ * exhausted with an unknown reset (probed lazily at the next resolution
517
+ * once every account is marked); `invalid-credential` (401) disables the
518
+ * key until the stored credential changes.
519
+ */
520
+ markRejected(apiKey: string, rejection: AccountRejection): void;
521
+ /** One account's key: literal → credential seam → auth file (default slot). */
522
+ private resolveSlotKey;
523
+ /** Hand out the chosen account's key. */
524
+ private pick;
525
+ }
526
+ //#endregion
527
+ //#region src/usage-wire.d.ts
528
+ /** One account's usage entry in the multi-account report. */
529
+ interface CommandCodeAccountUsage {
530
+ /** Stable slot id (`default`, `account-2`, …). */
531
+ id: string;
532
+ /** Display label (user-provided or generated). */
533
+ label: string;
534
+ /** Whether an API key resolved for this account. */
535
+ configured: boolean;
536
+ /** Whether this account currently serves requests (first usable slot). */
537
+ active: boolean;
538
+ /** Rotation mark: `''` (usable), `'rate-limit'`, or `'invalid-credential'`. */
539
+ mark: string;
540
+ /** Known cooldown end in millis; 0 when unknown or not cooling down. */
541
+ cooldownUntil: number;
542
+ /** The per-account report; `failures`-only when the fetch itself failed. */
543
+ report: CommandCodeUsageReport;
544
+ }
545
+ /** The settings page's account card data: one entry per configured account. */
546
+ interface CommandCodeAccountsReport {
547
+ accounts: CommandCodeAccountUsage[];
548
+ }
549
+ /** Canonical `<namespace>/<method>` endpoint of the usage report Remote. */
550
+ declare const USAGE_REPORT_ENDPOINT = "commandcode/report";
551
+ /**
552
+ * The strict result codec both halves attach to the descriptor. Hand-rolled:
553
+ * the client bundle may not require a schema library, and `TypertSchema` is
554
+ * deliberately minimal so one `parse` function satisfies it.
555
+ */
556
+ declare const usageReportSchema: TypertSchema<CommandCodeAccountsReport>;
557
+ //#endregion
367
558
  //#region src/commands.d.ts
368
559
  /** Everything the command needs beyond the adapter itself. */
369
560
  interface CommandCodeCommandDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {
370
561
  /** The registered adapter (for getUsage / listModels). */
371
562
  adapter: CommandCodeAdapter<C>;
563
+ /**
564
+ * Multi-account report source (wired by the plugin entry). Absent in
565
+ * programmatic setups, the command falls back to a single
566
+ * `adapter.getUsage()` report.
567
+ */
568
+ reports?: () => Promise<CommandCodeAccountsReport>;
372
569
  }
373
570
  /** The one registered `/commandcode` command. */
374
571
  declare function commandDefinition<C extends CommandCodeConnectionOptions>(deps: CommandCodeCommandDeps<C>): CommandDefinition;
@@ -380,6 +577,12 @@ declare function applyCommands<C extends CommandCodeConnectionOptions>(ctx: Cont
380
577
  interface CommandCodeUsageDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {
381
578
  /** The registered adapter (for getUsage). */
382
579
  adapter: CommandCodeAdapter<C>;
580
+ /**
581
+ * Multi-account report source (wired by the plugin entry). Absent in
582
+ * programmatic setups, the service falls back to a single default-account
583
+ * entry around `adapter.getUsage()`.
584
+ */
585
+ reports?: () => Promise<CommandCodeAccountsReport>;
383
586
  }
384
587
  /**
385
588
  * The Remote receiver: a Cordis service the Gateway resolves by key
@@ -392,12 +595,14 @@ declare class CommandCodeUsageService<C extends CommandCodeConnectionOptions = C
392
595
  private readonly deps;
393
596
  constructor(ctx: Context, deps: CommandCodeUsageDeps<C>);
394
597
  /**
395
- * Account, usage, and credit state for the settings page's account card.
396
- * Degrades per endpoint like the `/commandcode` command (failures land in
397
- * `report.failures`); throws `MISSING_CREDENTIAL` when no key resolves, which
398
- * the Gateway folds into the failure branch the page renders as a hint.
598
+ * Account, usage, and credit state for the settings page's account card
599
+ * one entry per pool account when the plugin entry wired `reports`, a
600
+ * single default-account entry otherwise. Degrades per endpoint like the
601
+ * `/commandcode` command (failures land in `report.failures`); throws
602
+ * `MISSING_CREDENTIAL` when no key resolves, which the Gateway folds into
603
+ * the failure branch the page renders as a hint.
399
604
  */
400
- report(): Promise<CommandCodeUsageReport>;
605
+ report(): Promise<CommandCodeAccountsReport>;
401
606
  }
402
607
  /**
403
608
  * Provide the usage service and register its Remote descriptor. The registry
@@ -406,16 +611,6 @@ declare class CommandCodeUsageService<C extends CommandCodeConnectionOptions = C
406
611
  */
407
612
  declare function applyUsageRemote<C extends CommandCodeConnectionOptions>(ctx: Context, deps: CommandCodeUsageDeps<C>): void;
408
613
  //#endregion
409
- //#region src/usage-wire.d.ts
410
- /** Canonical `<namespace>/<method>` endpoint of the usage report Remote. */
411
- declare const USAGE_REPORT_ENDPOINT = "commandcode/report";
412
- /**
413
- * The strict result codec both halves attach to the descriptor. Hand-rolled:
414
- * the client bundle may not require a schema library, and `TypertSchema` is
415
- * deliberately minimal so one `parse` function satisfies it.
416
- */
417
- declare const usageReportSchema: TypertSchema<CommandCodeUsageReport>;
418
- //#endregion
419
614
  //#region src/index.d.ts
420
615
  declare const name = "llm-commandcode";
421
616
  declare const inject: string[];
@@ -452,6 +647,24 @@ interface Config {
452
647
  * full catalog visible). Set false to always list every model.
453
648
  */
454
649
  filterModelsByPlan?: boolean;
650
+ /**
651
+ * Extra accounts for multi-account rotation. The top-level
652
+ * `apiKey`/`apiKeyEnv` (plus the CLI auth file) always form the first
653
+ * (`default`) account; each entry here adds one more. When a request is
654
+ * rejected pre-stream with 429 (usage window exhausted) or 401, the next
655
+ * account's key retried transparently; when every account is exhausted the
656
+ * request fails with a `RATE_LIMIT` error naming the earliest window
657
+ * reset. Entries without `apiKey` or `apiKeyEnv` are ignored.
658
+ */
659
+ accounts?: CommandCodeAccountConfig[];
660
+ /**
661
+ * Manually selected active account: a slot id — `default`, or an extra
662
+ * account's credential reference (e.g. `COMMANDCODE_API_KEY_2`). The
663
+ * selected account serves whenever it is usable; an unknown id or an
664
+ * exhausted selected account falls back to the first usable slot (automatic
665
+ * rotation still applies). Unset means "first usable account".
666
+ */
667
+ activeAccount?: string;
455
668
  }
456
669
  declare const Config: z<Config>;
457
670
  /** One resolution's complete request facts: connection plus credential reference. */
@@ -467,5 +680,5 @@ interface ResolvedCommandCodeOptions extends CommandCodeConnectionOptions {
467
680
  declare function resolveAdapterOptions(config: Config): ResolvedCommandCodeOptions;
468
681
  declare function apply(ctx: Context, config: Config): void;
469
682
  //#endregion
470
- export { BILLING_ACCESS_TTL_MS, COMMAND_CODE_CLI_VERSION, CommandCodeAdapter, type CommandCodeAdapterDeps, type CommandCodeBillingAccess, type CommandCodeCommandDeps, type CommandCodeConnectionOptions, type CommandCodeUsageDeps, type CommandCodeUsageReport, CommandCodeUsageService, Config, DEFAULT_API_BASE, DEFAULT_GENERATE_MAX_TOKENS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MODELS_CACHE_PATH, DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, KNOWN_DEALS, KNOWN_EFFORTS, KNOWN_IMAGE_MODELS, KNOWN_PEAK_PRICING, KNOWN_PLANS, KNOWN_SUBSCRIPTION_PLANS, KNOWN_THINKING_MODELS, PLAN_LABELS, PLAN_ORDER, PROVIDER, type ResolveAttachments, ResolvedCommandCodeOptions, USAGE_REPORT_ENDPOINT, apply, applyCommands, applyUsageRemote, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, modelVisibleInPlan, name, peakPricingLabel, peakPricingState, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey, subscriptionPlanInfo, usageReportSchema };
683
+ export { BILLING_ACCESS_TTL_MS, COMMAND_CODE_CLI_VERSION, type CommandCodeAccountConfig, CommandCodeAccountPool, type CommandCodeAccountSlot, type CommandCodeAccountState, type CommandCodeAccountUsage, type CommandCodeAccountsReport, CommandCodeAdapter, type CommandCodeAdapterDeps, type CommandCodeBillingAccess, type CommandCodeCommandDeps, type CommandCodeConnectionOptions, type CommandCodeUsageDeps, type CommandCodeUsageReport, CommandCodeUsageService, Config, DEFAULT_API_BASE, DEFAULT_GENERATE_MAX_TOKENS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MODELS_CACHE_PATH, DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, KNOWN_DEALS, KNOWN_EFFORTS, KNOWN_IMAGE_MODELS, KNOWN_PEAK_PRICING, KNOWN_PLANS, KNOWN_SUBSCRIPTION_PLANS, KNOWN_THINKING_MODELS, PLAN_LABELS, PLAN_ORDER, PROVIDER, type ResolveAttachments, ResolvedCommandCodeOptions, USAGE_REPORT_ENDPOINT, accountUsable, apply, applyCommands, applyUsageRemote, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, modelVisibleInPlan, name, peakPricingLabel, peakPricingState, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey, selectActiveAccount, subscriptionPlanInfo, usageReportSchema };
471
684
  //# sourceMappingURL=index.d.ts.map