@mars-sea/dsh-commandcode-provider 0.9.1 → 0.10.0-alpha.2
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 +31 -1
- package/README.md +31 -5
- package/README.zh-CN.md +31 -5
- package/lib/client.js +715 -110
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +91 -12
- package/lib/index.js +136 -37
- package/lib/index.js.map +1 -1
- package/package.json +38 -39
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 (command-code@1.
|
|
27
|
+
* Models the official CLI's model table (command-code@1.38.2) 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,13 +32,15 @@ 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.
|
|
35
|
+
* Source: the command-code@1.38.2 bundled model table (dist/cli.mjs),
|
|
36
36
|
* cross-checked with https://commandcode.ai/docs/reference/cli/models.
|
|
37
37
|
* (`stealth/ox-alpha` left this set in command-code@1.32.1, which gave it
|
|
38
38
|
* selectable `['low', 'high', 'max']` efforts; the preview then ended in
|
|
39
39
|
* 1.34.0, removing the model from the catalog entirely. `tencent/hy4-preview`
|
|
40
40
|
* joined this set in command-code@1.37.0 — reasoning:!0, no efforts, 1M
|
|
41
|
-
* context, routed through OpenRouter
|
|
41
|
+
* context, routed through OpenRouter — then gained selectable
|
|
42
|
+
* `['low', 'medium', 'high']` efforts in command-code@1.38.0 and moved to
|
|
43
|
+
* `KNOWN_EFFORTS`.)
|
|
42
44
|
* Keep in sync via the dsh-commandcode-upstream skill.
|
|
43
45
|
*/
|
|
44
46
|
declare const KNOWN_THINKING_MODELS: ReadonlySet<string>;
|
|
@@ -189,7 +191,7 @@ declare function peakPricingState(modelId: string, now?: number): 'peak' | 'off-
|
|
|
189
191
|
* for models without time-of-day pricing.
|
|
190
192
|
*/
|
|
191
193
|
declare function peakPricingLabel(modelId: string, now?: number): string | undefined;
|
|
192
|
-
declare const COMMAND_CODE_CLI_VERSION = "1.
|
|
194
|
+
declare const COMMAND_CODE_CLI_VERSION = "1.38.2";
|
|
193
195
|
declare const DEFAULT_API_BASE = "https://api.commandcode.ai";
|
|
194
196
|
declare const DEFAULT_GENERATE_MAX_TOKENS = 64000;
|
|
195
197
|
declare const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
|
|
@@ -263,8 +265,12 @@ type ResolveAttachments = () => AttachmentStore | undefined;
|
|
|
263
265
|
interface CommandCodeAdapterDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {
|
|
264
266
|
/** Resolve the current connection facts (fresh per request, settings-aware). */
|
|
265
267
|
options: () => C;
|
|
266
|
-
/**
|
|
267
|
-
|
|
268
|
+
/**
|
|
269
|
+
* Resolve a usable API key for the given connection facts and the request's
|
|
270
|
+
* model id, or throw `MISSING_CREDENTIAL`. The model is optional: hosts
|
|
271
|
+
* without model-aware routing ignore it.
|
|
272
|
+
*/
|
|
273
|
+
resolveApiKey: (connection: C, model?: string) => Promise<string>;
|
|
268
274
|
/**
|
|
269
275
|
* Multi-account rotation hook: the request sent with `rejectedKey` was
|
|
270
276
|
* refused with 429 (`rate-limit`) or 401 (`invalid-credential`) before
|
|
@@ -273,7 +279,7 @@ interface CommandCodeAdapterDeps<C extends CommandCodeConnectionOptions = Comman
|
|
|
273
279
|
* Only pre-stream rejections rotate — a mid-stream failure never replays a
|
|
274
280
|
* partially consumed generation against another account.
|
|
275
281
|
*/
|
|
276
|
-
rotateApiKey?: (rejectedKey: string, rejection: 'rate-limit' | 'invalid-credential', connection: C) => Promise<string | undefined>;
|
|
282
|
+
rotateApiKey?: (rejectedKey: string, rejection: 'rate-limit' | 'invalid-credential', connection: C, model?: string) => Promise<string | undefined>;
|
|
277
283
|
/** HTTP transport override (tests); defaults to the global `fetch`. */
|
|
278
284
|
fetchImpl?: typeof fetch;
|
|
279
285
|
/** Resolve the optional durable attachment service for image input (tests); defaults to none. */
|
|
@@ -502,6 +508,27 @@ interface CommandCodeAccountPoolDeps {
|
|
|
502
508
|
* account falls back to the first usable slot.
|
|
503
509
|
*/
|
|
504
510
|
preferredId?(): string | undefined;
|
|
511
|
+
/**
|
|
512
|
+
* Model → account routing rules, re-read per resolution so settings changes
|
|
513
|
+
* apply live. Each rule lists catalog model ids (see
|
|
514
|
+
* {@link CommandCodeModelAccountRule}) to an account slot id. When the
|
|
515
|
+
* request's model matches a rule and that account is usable, it serves
|
|
516
|
+
* before the preferred/rotation selection; an unusable routed account falls
|
|
517
|
+
* back to the normal selection (the router is a hint, never a hard gate).
|
|
518
|
+
*/
|
|
519
|
+
modelAccountRules?(): readonly CommandCodeModelAccountRule[];
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* One "route these models to that account" rule. `models` lists catalog ids
|
|
523
|
+
* (`deepseek/deepseek-v4-pro`, …); `account` is a slot id (`default` or an
|
|
524
|
+
* extra account's credential reference). A request whose model id is in the
|
|
525
|
+
* list routes to that account. The first matching rule in list order wins.
|
|
526
|
+
*/
|
|
527
|
+
interface CommandCodeModelAccountRule {
|
|
528
|
+
/** Catalog model ids to match against the request's model. */
|
|
529
|
+
models: string[];
|
|
530
|
+
/** Account slot id to prefer for matching models. */
|
|
531
|
+
account: string;
|
|
505
532
|
}
|
|
506
533
|
/**
|
|
507
534
|
* Whether an account with this rotation state can serve a request right now.
|
|
@@ -517,6 +544,18 @@ declare function accountUsable(state: CommandCodeAccountState | undefined): bool
|
|
|
517
544
|
* entry (the usage view's active badge) so both always agree.
|
|
518
545
|
*/
|
|
519
546
|
declare function selectActiveAccount(accounts: readonly ResolvedAccount[], preferredId: string | undefined): ResolvedAccount | undefined;
|
|
547
|
+
/**
|
|
548
|
+
* The first routing rule whose model list contains the request's model id.
|
|
549
|
+
* Undefined when no rule matches.
|
|
550
|
+
*/
|
|
551
|
+
declare function matchModelRule(model: string, rules: readonly CommandCodeModelAccountRule[] | undefined): CommandCodeModelAccountRule | undefined;
|
|
552
|
+
/**
|
|
553
|
+
* The routed account for a request's model: the first usable account whose
|
|
554
|
+
* slot id matches the first matching rule's target. Undefined when no rule
|
|
555
|
+
* matches or the routed account is not usable (the caller then falls back to
|
|
556
|
+
* the normal preferred/rotation selection).
|
|
557
|
+
*/
|
|
558
|
+
declare function selectAccountForModel(accounts: readonly ResolvedAccount[], model: string, rules: readonly CommandCodeModelAccountRule[] | undefined): ResolvedAccount | undefined;
|
|
520
559
|
/**
|
|
521
560
|
* The account pool. Rotation state is keyed by API key (never logged), so two
|
|
522
561
|
* slots resolving to the same credential share one mark, and a key changed in
|
|
@@ -541,12 +580,17 @@ declare class CommandCodeAccountPool {
|
|
|
541
580
|
*/
|
|
542
581
|
describeAccounts(): Promise<ResolvedAccount[]>;
|
|
543
582
|
/**
|
|
544
|
-
* Hand out the
|
|
545
|
-
*
|
|
546
|
-
*
|
|
547
|
-
*
|
|
583
|
+
* Hand out the key for a request: the model-routed account when the
|
|
584
|
+
* request's model matches a rule (and that account is usable), else the
|
|
585
|
+
* manually preferred account when usable, else the first usable account in
|
|
586
|
+
* rotation order. Returns `undefined` when no account resolves any key at
|
|
587
|
+
* all (the caller then reports the missing credential). Throws
|
|
588
|
+
* `RATE_LIMIT` — naming the earliest window reset — or
|
|
548
589
|
* `INVALID_CREDENTIAL` when accounts exist but none can serve.
|
|
549
590
|
*
|
|
591
|
+
* `options.model` is the request's model id; routing rules re-read per
|
|
592
|
+
* resolution, so a settings change applies live.
|
|
593
|
+
*
|
|
550
594
|
* `options.exclude` skips one key during the probe-revival pass: the
|
|
551
595
|
* rotation hook excludes the just-rejected key so a probe that clears its
|
|
552
596
|
* window cannot re-offer the same key within the same request (the adapter
|
|
@@ -554,6 +598,7 @@ declare class CommandCodeAccountPool {
|
|
|
554
598
|
*/
|
|
555
599
|
resolveKey(options?: {
|
|
556
600
|
exclude?: string;
|
|
601
|
+
model?: string;
|
|
557
602
|
}): Promise<{
|
|
558
603
|
key: string;
|
|
559
604
|
slot: CommandCodeAccountSlot;
|
|
@@ -601,6 +646,17 @@ declare const USAGE_REPORT_ENDPOINT = "commandcode/report";
|
|
|
601
646
|
* deliberately minimal so one `parse` function satisfies it.
|
|
602
647
|
*/
|
|
603
648
|
declare const usageReportSchema: TypertSchema<CommandCodeAccountsReport>;
|
|
649
|
+
/** One catalog entry the settings page's routing-rule editor offers. */
|
|
650
|
+
interface CommandCodeCatalogModel {
|
|
651
|
+
/** Catalog model id (e.g. `deepseek/deepseek-v4-pro`). */
|
|
652
|
+
id: string;
|
|
653
|
+
/** Display name from the catalog. */
|
|
654
|
+
name: string;
|
|
655
|
+
}
|
|
656
|
+
/** The model-catalog Remote result: the full catalog, sorted for picking. */
|
|
657
|
+
interface CommandCodeCatalog {
|
|
658
|
+
models: CommandCodeCatalogModel[];
|
|
659
|
+
}
|
|
604
660
|
//#endregion
|
|
605
661
|
//#region src/command-locales.d.ts
|
|
606
662
|
/**
|
|
@@ -718,6 +774,12 @@ interface CommandCodeUsageDeps<C extends CommandCodeConnectionOptions = CommandC
|
|
|
718
774
|
* entry around `adapter.getUsage()`.
|
|
719
775
|
*/
|
|
720
776
|
reports?: () => Promise<CommandCodeAccountsReport>;
|
|
777
|
+
/**
|
|
778
|
+
* Model-catalog source for the routing-rule editor (wired by the plugin
|
|
779
|
+
* entry). Absent, the `models` endpoint answers an empty list — the page's
|
|
780
|
+
* rule editor degrades to the empty state.
|
|
781
|
+
*/
|
|
782
|
+
listModels?: () => Promise<CommandCodeCatalog>;
|
|
721
783
|
/**
|
|
722
784
|
* The browser-login flow (wired by the plugin entry). Absent means the
|
|
723
785
|
* login endpoints answer `idle` / reject with a plain message — the page's
|
|
@@ -744,6 +806,13 @@ declare class CommandCodeUsageService<C extends CommandCodeConnectionOptions = C
|
|
|
744
806
|
* the failure branch the page renders as a hint.
|
|
745
807
|
*/
|
|
746
808
|
report(): Promise<CommandCodeAccountsReport>;
|
|
809
|
+
/**
|
|
810
|
+
* The model catalog for the settings page's routing-rule editor. The
|
|
811
|
+
* browser never calls the Command Code API directly — the Host serves the
|
|
812
|
+
* catalog (already fetched/cached by the adapter) so rules can be picked
|
|
813
|
+
* from the live model list instead of typed by hand.
|
|
814
|
+
*/
|
|
815
|
+
models(): Promise<CommandCodeCatalog>;
|
|
747
816
|
/**
|
|
748
817
|
* Start (or rejoin) a browser-login attempt and return its fresh status —
|
|
749
818
|
* `waiting` carrying the Studio URL. Rejects when the flow cannot start
|
|
@@ -933,6 +1002,16 @@ interface Config {
|
|
|
933
1002
|
* rotation still applies). Unset means "first usable account".
|
|
934
1003
|
*/
|
|
935
1004
|
activeAccount?: string;
|
|
1005
|
+
/**
|
|
1006
|
+
* Model → account routing rules. Each rule lists catalog model ids to an
|
|
1007
|
+
* account slot id (`default`, or an extra account's credential reference).
|
|
1008
|
+
* When a request's model is in a rule's list and the routed account is
|
|
1009
|
+
* usable, that account serves — before the manual {@link activeAccount} and
|
|
1010
|
+
* the passive rotation order. A routed account that is exhausted or invalid
|
|
1011
|
+
* falls back to the normal selection, so the router is a hint, never a hard
|
|
1012
|
+
* gate. The first matching rule wins.
|
|
1013
|
+
*/
|
|
1014
|
+
modelAccountRules?: CommandCodeModelAccountRule[];
|
|
936
1015
|
/**
|
|
937
1016
|
* Language override for the `/commandcode` Host-side command's user-facing
|
|
938
1017
|
* copy. Host commands cannot read the client's `ctx.locale`, so this is
|
|
@@ -960,5 +1039,5 @@ interface ResolvedCommandCodeOptions extends CommandCodeConnectionOptions {
|
|
|
960
1039
|
declare function resolveAdapterOptions(config: Config): ResolvedCommandCodeOptions;
|
|
961
1040
|
declare function apply(ctx: Context, config: Config): void;
|
|
962
1041
|
//#endregion
|
|
963
|
-
export { type ApiKeyValidation, 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 CommandCodeLoginCredentials, type CommandCodeLoginFailureReason, CommandCodeLoginFlow, type CommandCodeLoginFlowDeps, type CommandCodeLoginStatus, 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, LOGIN_ALLOWED_ORIGINS, LOGIN_BEGIN_ENDPOINT, LOGIN_BODY_LIMIT_BYTES, LOGIN_CANCEL_ENDPOINT, LOGIN_MAX_PORT_ATTEMPTS, LOGIN_START_PORT, LOGIN_STATUS_ENDPOINT, LOGIN_TIMEOUT_MS, type LoginFlowFacade, PLAN_LABELS, PLAN_ORDER, PROVIDER, type ResolveAttachments, ResolvedCommandCodeOptions, USAGE_REPORT_ENDPOINT, accountUsable, apply, applyCommands, applyUsageRemote, buildCommandAuthUrl, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, loginStatusSchema, modelVisibleInPlan, name, parseLoginStatus, peakPricingLabel, peakPricingState, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey, selectActiveAccount, studioBaseForApiBase, subscriptionPlanInfo, usageReportSchema, validateCommandApiKey };
|
|
1042
|
+
export { type ApiKeyValidation, 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 CommandCodeLoginCredentials, type CommandCodeLoginFailureReason, CommandCodeLoginFlow, type CommandCodeLoginFlowDeps, type CommandCodeLoginStatus, type CommandCodeModelAccountRule, 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, LOGIN_ALLOWED_ORIGINS, LOGIN_BEGIN_ENDPOINT, LOGIN_BODY_LIMIT_BYTES, LOGIN_CANCEL_ENDPOINT, LOGIN_MAX_PORT_ATTEMPTS, LOGIN_START_PORT, LOGIN_STATUS_ENDPOINT, LOGIN_TIMEOUT_MS, type LoginFlowFacade, PLAN_LABELS, PLAN_ORDER, PROVIDER, type ResolveAttachments, ResolvedCommandCodeOptions, USAGE_REPORT_ENDPOINT, accountUsable, apply, applyCommands, applyUsageRemote, buildCommandAuthUrl, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, loginStatusSchema, matchModelRule, modelVisibleInPlan, name, parseLoginStatus, peakPricingLabel, peakPricingState, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey, selectAccountForModel, selectActiveAccount, studioBaseForApiBase, subscriptionPlanInfo, usageReportSchema, validateCommandApiKey };
|
|
964
1043
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.js
CHANGED
|
@@ -2,10 +2,9 @@ import { homedir } from "node:os";
|
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import z from "@deepseek-ai/schemastery";
|
|
4
4
|
import { MAX_TIMER_DELAY_MS } from "@deepseek-ai/dsh-timeout";
|
|
5
|
-
import {
|
|
5
|
+
import { LlmAdapter, LlmError, ReasoningEffortId, ToolCallId, assertUsableApiKey, attributionHeaders, errorChain, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
6
6
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
7
7
|
import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment";
|
|
8
|
-
import { installSettingsSection, settingsNamespace } from "@deepseek-ai/dsh-settings";
|
|
9
8
|
import { existsSync, readFileSync } from "node:fs";
|
|
10
9
|
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
11
10
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
@@ -22,9 +21,11 @@ import { createServer as createServer$1 } from "node:net";
|
|
|
22
21
|
* This module owns that rotation:
|
|
23
22
|
*
|
|
24
23
|
* - {@link CommandCodeAccountPool.resolveKey} hands out the first account
|
|
25
|
-
* whose key is not currently marked exhausted,
|
|
26
|
-
*
|
|
27
|
-
*
|
|
24
|
+
* whose key is not currently marked exhausted — or, when the request's
|
|
25
|
+
* model matches a {@link CommandCodeModelAccountRule} and that account is
|
|
26
|
+
* usable, the routed account — resolving each slot's key lazily (literal
|
|
27
|
+
* config key → credential seam → launch environment → the official CLI
|
|
28
|
+
* auth file for the default slot only).
|
|
28
29
|
* - {@link CommandCodeAccountPool.markRejected} records a 429 (rate limit,
|
|
29
30
|
* window unknown) or 401 (invalid key, disabled until the config changes)
|
|
30
31
|
* against the exact API key, so several slots sharing one key share one
|
|
@@ -80,6 +81,25 @@ function selectActiveAccount(accounts, preferredId) {
|
|
|
80
81
|
return usable[0];
|
|
81
82
|
}
|
|
82
83
|
/**
|
|
84
|
+
* The first routing rule whose model list contains the request's model id.
|
|
85
|
+
* Undefined when no rule matches.
|
|
86
|
+
*/
|
|
87
|
+
function matchModelRule(model, rules) {
|
|
88
|
+
if (model === "" || rules === void 0 || rules.length === 0) return void 0;
|
|
89
|
+
for (const rule of rules) if (rule.models.includes(model)) return rule;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The routed account for a request's model: the first usable account whose
|
|
93
|
+
* slot id matches the first matching rule's target. Undefined when no rule
|
|
94
|
+
* matches or the routed account is not usable (the caller then falls back to
|
|
95
|
+
* the normal preferred/rotation selection).
|
|
96
|
+
*/
|
|
97
|
+
function selectAccountForModel(accounts, model, rules) {
|
|
98
|
+
const rule = matchModelRule(model, rules);
|
|
99
|
+
if (rule === void 0) return void 0;
|
|
100
|
+
return accounts.find((account) => account.slot.id === rule.account && accountUsable(account.state));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
83
103
|
* The account pool. Rotation state is keyed by API key (never logged), so two
|
|
84
104
|
* slots resolving to the same credential share one mark, and a key changed in
|
|
85
105
|
* the credentials service starts with a clean slate.
|
|
@@ -131,12 +151,17 @@ var CommandCodeAccountPool = class {
|
|
|
131
151
|
return out;
|
|
132
152
|
}
|
|
133
153
|
/**
|
|
134
|
-
* Hand out the
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
154
|
+
* Hand out the key for a request: the model-routed account when the
|
|
155
|
+
* request's model matches a rule (and that account is usable), else the
|
|
156
|
+
* manually preferred account when usable, else the first usable account in
|
|
157
|
+
* rotation order. Returns `undefined` when no account resolves any key at
|
|
158
|
+
* all (the caller then reports the missing credential). Throws
|
|
159
|
+
* `RATE_LIMIT` — naming the earliest window reset — or
|
|
138
160
|
* `INVALID_CREDENTIAL` when accounts exist but none can serve.
|
|
139
161
|
*
|
|
162
|
+
* `options.model` is the request's model id; routing rules re-read per
|
|
163
|
+
* resolution, so a settings change applies live.
|
|
164
|
+
*
|
|
140
165
|
* `options.exclude` skips one key during the probe-revival pass: the
|
|
141
166
|
* rotation hook excludes the just-rejected key so a probe that clears its
|
|
142
167
|
* window cannot re-offer the same key within the same request (the adapter
|
|
@@ -145,6 +170,8 @@ var CommandCodeAccountPool = class {
|
|
|
145
170
|
async resolveKey(options) {
|
|
146
171
|
const accounts = await this.resolvedAccounts();
|
|
147
172
|
if (accounts.length === 0) return;
|
|
173
|
+
const routed = selectAccountForModel(accounts, options?.model ?? "", this.deps.modelAccountRules?.());
|
|
174
|
+
if (routed !== void 0) return this.pick(routed);
|
|
148
175
|
const chosen = selectActiveAccount(accounts, this.deps.preferredId?.());
|
|
149
176
|
if (chosen !== void 0) return this.pick(chosen);
|
|
150
177
|
await Promise.all(accounts.map(async (account) => {
|
|
@@ -216,7 +243,7 @@ var CommandCodeAccountPool = class {
|
|
|
216
243
|
* and API key or subscription, and Command Code's terms apply.
|
|
217
244
|
*
|
|
218
245
|
* Wire protocol (reverse-engineered by the pi plugin, command-code@1.28.4;
|
|
219
|
-
* re-verified against command-code@1.
|
|
246
|
+
* re-verified against command-code@1.38.2 — endpoints, request shape, and
|
|
220
247
|
* stream events unchanged):
|
|
221
248
|
* POST {apiBase}/alpha/generate
|
|
222
249
|
* body: { config, memory, taste, skills, params: { model, messages, tools,
|
|
@@ -360,6 +387,11 @@ const KNOWN_EFFORTS = {
|
|
|
360
387
|
"max"
|
|
361
388
|
],
|
|
362
389
|
"sakana/fugu-ultra": ["high", "xhigh"],
|
|
390
|
+
"tencent/hy4-preview": [
|
|
391
|
+
"low",
|
|
392
|
+
"medium",
|
|
393
|
+
"high"
|
|
394
|
+
],
|
|
363
395
|
"xai/grok-4.5": [
|
|
364
396
|
"low",
|
|
365
397
|
"medium",
|
|
@@ -444,7 +476,7 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
|
|
|
444
476
|
"z-ai/glm-5.3-flash"
|
|
445
477
|
]);
|
|
446
478
|
/**
|
|
447
|
-
* Models the official CLI's model table (command-code@1.
|
|
479
|
+
* Models the official CLI's model table (command-code@1.38.2) marks
|
|
448
480
|
* `reasoning:!0` but defines no selectable `reasoning_effort` levels — they
|
|
449
481
|
* think automatically, with Command Code driving the depth. This is the
|
|
450
482
|
* authoritative "thinks, effort not adjustable" set: `KNOWN_EFFORTS` (which
|
|
@@ -452,13 +484,15 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
|
|
|
452
484
|
* effort levels, and this snapshot is not surfaced in the picker's compact
|
|
453
485
|
* description — it exists for programmatic consumers.
|
|
454
486
|
*
|
|
455
|
-
* Source: the command-code@1.
|
|
487
|
+
* Source: the command-code@1.38.2 bundled model table (dist/cli.mjs),
|
|
456
488
|
* cross-checked with https://commandcode.ai/docs/reference/cli/models.
|
|
457
489
|
* (`stealth/ox-alpha` left this set in command-code@1.32.1, which gave it
|
|
458
490
|
* selectable `['low', 'high', 'max']` efforts; the preview then ended in
|
|
459
491
|
* 1.34.0, removing the model from the catalog entirely. `tencent/hy4-preview`
|
|
460
492
|
* joined this set in command-code@1.37.0 — reasoning:!0, no efforts, 1M
|
|
461
|
-
* context, routed through OpenRouter
|
|
493
|
+
* context, routed through OpenRouter — then gained selectable
|
|
494
|
+
* `['low', 'medium', 'high']` efforts in command-code@1.38.0 and moved to
|
|
495
|
+
* `KNOWN_EFFORTS`.)
|
|
462
496
|
* Keep in sync via the dsh-commandcode-upstream skill.
|
|
463
497
|
*/
|
|
464
498
|
const KNOWN_THINKING_MODELS = /* @__PURE__ */ new Set([
|
|
@@ -475,7 +509,6 @@ const KNOWN_THINKING_MODELS = /* @__PURE__ */ new Set([
|
|
|
475
509
|
"stepfun/Step-3.5-Flash",
|
|
476
510
|
"stepfun/Step-3.7-Flash",
|
|
477
511
|
"tencent/hy3-paid",
|
|
478
|
-
"tencent/hy4-preview",
|
|
479
512
|
"nvidia/nemotron-3-ultra-550b-a55b",
|
|
480
513
|
"thinkingmachines/inkling",
|
|
481
514
|
"thinkingmachines/inkling-small",
|
|
@@ -515,6 +548,7 @@ const KNOWN_PLANS = {
|
|
|
515
548
|
"deepseek/deepseek-v4-flash-vision-exp": "go",
|
|
516
549
|
"deepseek/deepseek-v4-pro": "go",
|
|
517
550
|
"gpt-5.6-luna": "go",
|
|
551
|
+
"inclusionai/ling-3.0-flash-free": "go",
|
|
518
552
|
"meta/muse-spark-1.2-contributor": "go",
|
|
519
553
|
"minimax/minimax-m2.7-free": "go",
|
|
520
554
|
"minimax/minimax-m3-free": "go",
|
|
@@ -527,6 +561,7 @@ const KNOWN_PLANS = {
|
|
|
527
561
|
"poolside/laguna-s-2.1-free": "go",
|
|
528
562
|
"stepfun/Step-3.5-Flash": "go",
|
|
529
563
|
"stepfun/Step-3.7-Flash": "go",
|
|
564
|
+
"tencent/Hy3": "go",
|
|
530
565
|
"tencent/hy3-paid": "go",
|
|
531
566
|
"tencent/hy4-preview": "go",
|
|
532
567
|
"thinkingmachines/inkling": "go",
|
|
@@ -691,10 +726,6 @@ function modelVisibleInPlan(modelId, access) {
|
|
|
691
726
|
return weight <= access.tierWeight;
|
|
692
727
|
}
|
|
693
728
|
const KNOWN_DEALS = {
|
|
694
|
-
"google/gemini-3.7-flash": {
|
|
695
|
-
label: "50% off",
|
|
696
|
-
expiresAt: "2026-12-31T23:59:59Z"
|
|
697
|
-
},
|
|
698
729
|
"MiniMaxAI/MiniMax-M3": { label: "50% off" },
|
|
699
730
|
"xiaomi/mimo-v2.5-pro": { label: "99% off" },
|
|
700
731
|
"xiaomi/mimo-v2.5": { label: "98% off" },
|
|
@@ -763,7 +794,7 @@ function peakPricingLabel(modelId, now = Date.now()) {
|
|
|
763
794
|
if (state === void 0) return void 0;
|
|
764
795
|
return state === "peak" ? "Peak" : "Half";
|
|
765
796
|
}
|
|
766
|
-
const COMMAND_CODE_CLI_VERSION = "1.
|
|
797
|
+
const COMMAND_CODE_CLI_VERSION = "1.38.2";
|
|
767
798
|
const DEFAULT_API_BASE = "https://api.commandcode.ai";
|
|
768
799
|
const DEFAULT_GENERATE_MAX_TOKENS = 64e3;
|
|
769
800
|
const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
|
|
@@ -1406,7 +1437,7 @@ var CommandCodeAdapter = class extends LlmAdapter {
|
|
|
1406
1437
|
readImage = (ref) => attachments.readImage(ref).then((stored) => stored.data);
|
|
1407
1438
|
}
|
|
1408
1439
|
const connection = this.deps.options();
|
|
1409
|
-
let apiKey = await this.deps.resolveApiKey(connection);
|
|
1440
|
+
let apiKey = await this.deps.resolveApiKey(connection, options.model);
|
|
1410
1441
|
const modelMax = this.catalog.find((m) => m.id === options.model)?.maxTokens ?? 65536;
|
|
1411
1442
|
const maxTokens = Math.min(options.maxTokens ?? modelMax, modelMax, DEFAULT_GENERATE_MAX_TOKENS);
|
|
1412
1443
|
const effort = options.reasoningEffort;
|
|
@@ -1516,7 +1547,7 @@ var CommandCodeAdapter = class extends LlmAdapter {
|
|
|
1516
1547
|
}
|
|
1517
1548
|
const rotate = this.deps.rotateApiKey;
|
|
1518
1549
|
if ((attempt.status === 429 || attempt.status === 401) && rotate !== void 0 && options.signal?.aborted !== true && tried.size < MAX_ACCOUNT_ROTATIONS) {
|
|
1519
|
-
const next = await rotate(apiKey, attempt.status === 429 ? "rate-limit" : "invalid-credential", connection);
|
|
1550
|
+
const next = await rotate(apiKey, attempt.status === 429 ? "rate-limit" : "invalid-credential", connection, options.model);
|
|
1520
1551
|
if (next !== void 0 && !tried.has(next)) {
|
|
1521
1552
|
apiKey = next;
|
|
1522
1553
|
continue;
|
|
@@ -1642,7 +1673,7 @@ var CommandCodeAdapter = class extends LlmAdapter {
|
|
|
1642
1673
|
}, {
|
|
1643
1674
|
type: "tool-call-delta",
|
|
1644
1675
|
index,
|
|
1645
|
-
id:
|
|
1676
|
+
id: ToolCallId(id),
|
|
1646
1677
|
name,
|
|
1647
1678
|
argumentsDelta: args
|
|
1648
1679
|
}, {
|
|
@@ -1650,7 +1681,7 @@ var CommandCodeAdapter = class extends LlmAdapter {
|
|
|
1650
1681
|
index,
|
|
1651
1682
|
block: {
|
|
1652
1683
|
type: "tool-call",
|
|
1653
|
-
id:
|
|
1684
|
+
id: ToolCallId(id),
|
|
1654
1685
|
name,
|
|
1655
1686
|
arguments: args
|
|
1656
1687
|
}
|
|
@@ -2124,6 +2155,11 @@ const USAGE_HOST_CONTRIBUTION = {
|
|
|
2124
2155
|
package: USAGE_REMOTE_PACKAGE,
|
|
2125
2156
|
face: "host",
|
|
2126
2157
|
schemas: [],
|
|
2158
|
+
model: {
|
|
2159
|
+
services: [],
|
|
2160
|
+
events: [],
|
|
2161
|
+
objects: []
|
|
2162
|
+
},
|
|
2127
2163
|
invocations: [{
|
|
2128
2164
|
id: `${USAGE_REMOTE_PACKAGE}#${USAGE_REPORT_ENDPOINT}`,
|
|
2129
2165
|
service: "commandcodeUsage",
|
|
@@ -2138,6 +2174,39 @@ const USAGE_HOST_CONTRIBUTION = {
|
|
|
2138
2174
|
}
|
|
2139
2175
|
}]
|
|
2140
2176
|
};
|
|
2177
|
+
/** Canonical `<namespace>/<method>` endpoint of the model-catalog Remote. */
|
|
2178
|
+
const MODELS_ENDPOINT = "commandcode/models";
|
|
2179
|
+
/** Parse one untrusted boundary value into a {@link CommandCodeCatalogModel}. */
|
|
2180
|
+
function parseCatalogModel(value) {
|
|
2181
|
+
const source = record(value, "model");
|
|
2182
|
+
return {
|
|
2183
|
+
id: stringField(source, "id", "model.id"),
|
|
2184
|
+
name: stringField(source, "name", "model.name")
|
|
2185
|
+
};
|
|
2186
|
+
}
|
|
2187
|
+
/** Parse the wire result into a {@link CommandCodeCatalog}. */
|
|
2188
|
+
function parseCatalog(value) {
|
|
2189
|
+
const models = record(value, "result").models;
|
|
2190
|
+
if (!Array.isArray(models)) reject$1("models");
|
|
2191
|
+
return { models: models.map(parseCatalogModel) };
|
|
2192
|
+
}
|
|
2193
|
+
/**
|
|
2194
|
+
* The model-catalog invocation descriptor, sharing the same `commandcodeUsage`
|
|
2195
|
+
* service and `commandcode` namespace as the usage report.
|
|
2196
|
+
*/
|
|
2197
|
+
const MODELS_DESCRIPTOR = {
|
|
2198
|
+
id: `${USAGE_REMOTE_PACKAGE}#${MODELS_ENDPOINT}`,
|
|
2199
|
+
service: "commandcodeUsage",
|
|
2200
|
+
namespace: "commandcode",
|
|
2201
|
+
method: "models",
|
|
2202
|
+
invocation: { kind: "direct" },
|
|
2203
|
+
parameters: [],
|
|
2204
|
+
result: {
|
|
2205
|
+
mode: "strict",
|
|
2206
|
+
typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeCatalog`,
|
|
2207
|
+
schema: { parse: parseCatalog }
|
|
2208
|
+
}
|
|
2209
|
+
};
|
|
2141
2210
|
//#endregion
|
|
2142
2211
|
//#region src/login-wire.ts
|
|
2143
2212
|
/** The canonical endpoint paths of the three login Remotes. */
|
|
@@ -2250,6 +2319,15 @@ var CommandCodeUsageService = class extends TypertRemoteService {
|
|
|
2250
2319
|
}] };
|
|
2251
2320
|
}
|
|
2252
2321
|
/**
|
|
2322
|
+
* The model catalog for the settings page's routing-rule editor. The
|
|
2323
|
+
* browser never calls the Command Code API directly — the Host serves the
|
|
2324
|
+
* catalog (already fetched/cached by the adapter) so rules can be picked
|
|
2325
|
+
* from the live model list instead of typed by hand.
|
|
2326
|
+
*/
|
|
2327
|
+
async models() {
|
|
2328
|
+
return this.deps.listModels?.() ?? { models: [] };
|
|
2329
|
+
}
|
|
2330
|
+
/**
|
|
2253
2331
|
* Start (or rejoin) a browser-login attempt and return its fresh status —
|
|
2254
2332
|
* `waiting` carrying the Studio URL. Rejects when the flow cannot start
|
|
2255
2333
|
* (no free loopback port, disposed plugin); the Gateway folds the throw
|
|
@@ -2283,7 +2361,11 @@ function applyUsageRemote(ctx, deps) {
|
|
|
2283
2361
|
new CommandCodeUsageService(remoteCtx, deps);
|
|
2284
2362
|
const unregister = remoteCtx.typert.register({
|
|
2285
2363
|
...USAGE_HOST_CONTRIBUTION,
|
|
2286
|
-
invocations: [
|
|
2364
|
+
invocations: [
|
|
2365
|
+
...USAGE_HOST_CONTRIBUTION.invocations,
|
|
2366
|
+
MODELS_DESCRIPTOR,
|
|
2367
|
+
...LOGIN_DESCRIPTORS
|
|
2368
|
+
]
|
|
2287
2369
|
});
|
|
2288
2370
|
remoteCtx.effect(() => () => void unregister(), "dsh-commandcode-provider: usage remote");
|
|
2289
2371
|
});
|
|
@@ -2700,7 +2782,7 @@ function corsOrigin(origin) {
|
|
|
2700
2782
|
*/
|
|
2701
2783
|
const name = "llm-commandcode";
|
|
2702
2784
|
const inject = ["llm"];
|
|
2703
|
-
const NS =
|
|
2785
|
+
const NS = "llm-commandcode";
|
|
2704
2786
|
const DEFAULT_API_KEY_ENV = "COMMANDCODE_API_KEY";
|
|
2705
2787
|
/** The single provider route this plugin owns. */
|
|
2706
2788
|
const PROVIDER = "commandcode";
|
|
@@ -2721,6 +2803,10 @@ const Config = z.object({
|
|
|
2721
2803
|
apiKey: z.string()
|
|
2722
2804
|
})),
|
|
2723
2805
|
activeAccount: z.string(),
|
|
2806
|
+
modelAccountRules: z.array(z.object({
|
|
2807
|
+
models: z.array(z.string()),
|
|
2808
|
+
account: z.string()
|
|
2809
|
+
})),
|
|
2724
2810
|
lang: z.string().pattern(/^(zh|en)$/).default("zh")
|
|
2725
2811
|
});
|
|
2726
2812
|
/**
|
|
@@ -2791,10 +2877,11 @@ function apply(ctx, config) {
|
|
|
2791
2877
|
resolveRef,
|
|
2792
2878
|
authFileKey: resolveAuthFileApiKey,
|
|
2793
2879
|
probeWindow: (apiKey) => adapter.probeFiveHourWindow(apiKey),
|
|
2794
|
-
preferredId
|
|
2880
|
+
preferredId,
|
|
2881
|
+
modelAccountRules: () => current().modelAccountRules ?? []
|
|
2795
2882
|
});
|
|
2796
|
-
const resolveApiKey = async (connection) => {
|
|
2797
|
-
const resolved = await pool.resolveKey();
|
|
2883
|
+
const resolveApiKey = async (connection, model) => {
|
|
2884
|
+
const resolved = await pool.resolveKey(model === void 0 ? {} : { model });
|
|
2798
2885
|
if (resolved !== void 0) return assertUsableApiKey(resolved.key, "llm-commandcode", resolved.slot.ref ?? `${resolved.slot.label} (config.apiKey)`);
|
|
2799
2886
|
const ref = connection.apiKeyEnv;
|
|
2800
2887
|
throw new LlmError(`llm-commandcode: no API key for provider route "${PROVIDER}"; store ${ref} through the credentials service (the web Models page writes it), export it in the launching environment, set config.apiKey, or run \`command-code login\` to write ~/.commandcode/auth.json`, "MISSING_CREDENTIAL");
|
|
@@ -2802,9 +2889,12 @@ function apply(ctx, config) {
|
|
|
2802
2889
|
const adapter = new CommandCodeAdapter({
|
|
2803
2890
|
options,
|
|
2804
2891
|
resolveApiKey,
|
|
2805
|
-
rotateApiKey: async (rejectedKey, rejection) => {
|
|
2892
|
+
rotateApiKey: async (rejectedKey, rejection, _connection, model) => {
|
|
2806
2893
|
pool.markRejected(rejectedKey, rejection);
|
|
2807
|
-
const resolved = await pool.resolveKey({ exclude: rejectedKey }
|
|
2894
|
+
const resolved = await pool.resolveKey(model === void 0 ? { exclude: rejectedKey } : {
|
|
2895
|
+
exclude: rejectedKey,
|
|
2896
|
+
model
|
|
2897
|
+
});
|
|
2808
2898
|
return resolved === void 0 ? void 0 : assertUsableApiKey(resolved.key, "llm-commandcode", resolved.slot.ref ?? `${resolved.slot.label} (config.apiKey)`);
|
|
2809
2899
|
},
|
|
2810
2900
|
resolveAttachments: () => {
|
|
@@ -2863,19 +2953,28 @@ function apply(ctx, config) {
|
|
|
2863
2953
|
}
|
|
2864
2954
|
});
|
|
2865
2955
|
ctx.effect(() => () => loginFlow.dispose(), "dsh-commandcode-provider: login flow");
|
|
2956
|
+
const catalogForRules = async () => {
|
|
2957
|
+
return { models: (await adapter.listModels(PROVIDER)).map((model) => ({
|
|
2958
|
+
id: model.id,
|
|
2959
|
+
name: model.name.replace(/\s*\(CC\)$/, "")
|
|
2960
|
+
})) };
|
|
2961
|
+
};
|
|
2866
2962
|
applyUsageRemote(ctx, {
|
|
2867
2963
|
adapter,
|
|
2868
2964
|
reports: usageReports,
|
|
2869
|
-
login: loginFlow
|
|
2965
|
+
login: loginFlow,
|
|
2966
|
+
listModels: catalogForRules
|
|
2870
2967
|
});
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2968
|
+
ctx.inject(["settings"], (settingsCtx) => {
|
|
2969
|
+
settingsCtx.settings.installSection(ctx, NS, Config, config, {
|
|
2970
|
+
setSource: (source) => {
|
|
2971
|
+
current = source;
|
|
2972
|
+
},
|
|
2973
|
+
onChange: () => {}
|
|
2974
|
+
});
|
|
2876
2975
|
});
|
|
2877
2976
|
}
|
|
2878
2977
|
//#endregion
|
|
2879
|
-
export { BILLING_ACCESS_TTL_MS, COMMAND_CODE_CLI_VERSION, CommandCodeAccountPool, CommandCodeAdapter, CommandCodeLoginFlow, 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, LOGIN_ALLOWED_ORIGINS, LOGIN_BEGIN_ENDPOINT, LOGIN_BODY_LIMIT_BYTES, LOGIN_CANCEL_ENDPOINT, LOGIN_MAX_PORT_ATTEMPTS, LOGIN_START_PORT, LOGIN_STATUS_ENDPOINT, LOGIN_TIMEOUT_MS, PLAN_LABELS, PLAN_ORDER, PROVIDER, USAGE_REPORT_ENDPOINT, accountUsable, apply, applyCommands, applyUsageRemote, buildCommandAuthUrl, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, loginStatusSchema, modelVisibleInPlan, name, parseLoginStatus, peakPricingLabel, peakPricingState, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey, selectActiveAccount, studioBaseForApiBase, subscriptionPlanInfo, usageReportSchema, validateCommandApiKey };
|
|
2978
|
+
export { BILLING_ACCESS_TTL_MS, COMMAND_CODE_CLI_VERSION, CommandCodeAccountPool, CommandCodeAdapter, CommandCodeLoginFlow, 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, LOGIN_ALLOWED_ORIGINS, LOGIN_BEGIN_ENDPOINT, LOGIN_BODY_LIMIT_BYTES, LOGIN_CANCEL_ENDPOINT, LOGIN_MAX_PORT_ATTEMPTS, LOGIN_START_PORT, LOGIN_STATUS_ENDPOINT, LOGIN_TIMEOUT_MS, PLAN_LABELS, PLAN_ORDER, PROVIDER, USAGE_REPORT_ENDPOINT, accountUsable, apply, applyCommands, applyUsageRemote, buildCommandAuthUrl, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, loginStatusSchema, matchModelRule, modelVisibleInPlan, name, parseLoginStatus, peakPricingLabel, peakPricingState, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey, selectAccountForModel, selectActiveAccount, studioBaseForApiBase, subscriptionPlanInfo, usageReportSchema, validateCommandApiKey };
|
|
2880
2979
|
|
|
2881
2980
|
//# sourceMappingURL=index.js.map
|