@mars-sea/dsh-commandcode-provider 0.10.0-alpha.5 → 0.10.0-alpha.7

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.js CHANGED
@@ -235,27 +235,27 @@ var CommandCodeAccountPool = class {
235
235
  }
236
236
  };
237
237
  //#endregion
238
- //#region src/adapter.ts
238
+ //#region src/capabilities.ts
239
239
  /**
240
- * DeepSeek Harness LLM adapter for the Command Code Provider API.
240
+ * Static capability snapshot for the Command Code provider: model →
241
+ * reasoning-effort levels, vision/thinking flags, model → minimum plan tier,
242
+ * subscription-plan labels, deals, and hourly (peak/off-peak) pricing.
241
243
  *
242
- * Ported from pi-commandcode-provider@0.5.1 (MIT). This is an unofficial,
243
- * community-maintained integration; you need your own Command Code account
244
- * and API key or subscription, and Command Code's terms apply.
244
+ * Everything in this module is synced from official sources (the command-code
245
+ * CLI bundle's model table and the official plan/pricing/model docs — see the
246
+ * dsh-commandcode-upstream skill for the exact extraction procedures), and
247
+ * changes whenever an upstream CLI release reshuffles models/plans/prices.
248
+ * Keeping the snapshot in its own module confines those frequent sync diffs
249
+ * here: src/adapter.ts holds only the stable wire/runtime logic and imports
250
+ * these tables + read helpers.
245
251
  *
246
- * Wire protocol (reverse-engineered by the pi plugin, command-code@1.28.4;
247
- * re-verified against command-code@1.40.1 — endpoints, request shape, and
248
- * stream events unchanged):
249
- * POST {apiBase}/alpha/generate
250
- * body: { config, memory, taste, skills, params: { model, messages, tools,
251
- * system, max_tokens, temperature, stream, reasoning_effort? }, threadId }
252
- * SSE-ish JSONL events: text-delta | reasoning-start/delta/end | tool-call
253
- * | tool-result | finish | error
254
- * Model catalog: GET {apiBase}/provider/v1/models -> { object: 'list', data: [...] }
252
+ * Snapshot read helpers (planLabel, dealLabel, formatContext,
253
+ * capabilityDescription, peakPricing*, compareByPlan, modelVisibleInPlan,
254
+ * subscriptionPlanInfo, isFreeModel) live here too — they exist only to read
255
+ * the tables, so a sync never has to touch src/adapter.ts.
255
256
  *
256
- * The adapter is deliberately free of cordis/schemastery: it receives a
257
- * per-request options thunk and an API-key resolver from the plugin entry
258
- * (src/index.ts), so a settings change reaches the very next request.
257
+ * Ported from pi-commandcode-provider (MIT); originally part of src/adapter.ts
258
+ * and split out so upstream syncs stay reviewable.
259
259
  */
260
260
  const KNOWN_EFFORTS = {
261
261
  "Qwen/Qwen3.8-Max": [
@@ -263,6 +263,11 @@ const KNOWN_EFFORTS = {
263
263
  "medium",
264
264
  "xhigh"
265
265
  ],
266
+ "Qwen/Qwen3.8-Max-0902": [
267
+ "low",
268
+ "medium",
269
+ "xhigh"
270
+ ],
266
271
  "Qwen/Qwen3.8-27B": [
267
272
  "low",
268
273
  "medium",
@@ -273,6 +278,13 @@ const KNOWN_EFFORTS = {
273
278
  "medium",
274
279
  "xhigh"
275
280
  ],
281
+ "claude-fable-5-1": [
282
+ "low",
283
+ "medium",
284
+ "high",
285
+ "xhigh",
286
+ "max"
287
+ ],
276
288
  "claude-fable-5": [
277
289
  "low",
278
290
  "medium",
@@ -397,6 +409,11 @@ const KNOWN_EFFORTS = {
397
409
  "high",
398
410
  "max"
399
411
  ],
412
+ "google/gemini-3.8-flash": [
413
+ "low",
414
+ "medium",
415
+ "high"
416
+ ],
400
417
  "sakana/fugu-ultra": ["high", "xhigh"],
401
418
  "tencent/hy4-preview": [
402
419
  "low",
@@ -424,6 +441,36 @@ const KNOWN_EFFORTS = {
424
441
  "low",
425
442
  "high",
426
443
  "max"
444
+ ],
445
+ "meta/muse-spark-1.1": [
446
+ "low",
447
+ "medium",
448
+ "high",
449
+ "xhigh"
450
+ ],
451
+ "meta/muse-spark-1.2": [
452
+ "low",
453
+ "medium",
454
+ "high",
455
+ "xhigh"
456
+ ],
457
+ "meta/muse-spark-1.2-contributor": [
458
+ "low",
459
+ "medium",
460
+ "high",
461
+ "xhigh"
462
+ ],
463
+ "meta/muse-spark-1.3": [
464
+ "low",
465
+ "medium",
466
+ "high",
467
+ "xhigh"
468
+ ],
469
+ "meta/muse-spark-1.3-contributor": [
470
+ "low",
471
+ "medium",
472
+ "high",
473
+ "xhigh"
427
474
  ]
428
475
  };
429
476
  /**
@@ -449,6 +496,8 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
449
496
  "Qwen/Qwen3.8-27B",
450
497
  "Qwen/Qwen3.8-Flash",
451
498
  "Qwen/Qwen3.8-Max",
499
+ "Qwen/Qwen3.8-Max-0902",
500
+ "claude-fable-5-1",
452
501
  "claude-fable-5",
453
502
  "claude-haiku-4-5-20251001",
454
503
  "claude-opus-4-7",
@@ -462,6 +511,7 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
462
511
  "google/gemini-3.5-flash-lite",
463
512
  "google/gemini-3.6-flash",
464
513
  "google/gemini-3.7-flash",
514
+ "google/gemini-3.8-flash",
465
515
  "gpt-5.3-codex",
466
516
  "gpt-5.4",
467
517
  "gpt-5.4-mini",
@@ -472,6 +522,8 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
472
522
  "meta/muse-spark-1.1",
473
523
  "meta/muse-spark-1.2",
474
524
  "meta/muse-spark-1.2-contributor",
525
+ "meta/muse-spark-1.3",
526
+ "meta/muse-spark-1.3-contributor",
475
527
  "minimax/minimax-m3-free",
476
528
  "moonshotai/Kimi-K2.5",
477
529
  "moonshotai/Kimi-K2.6",
@@ -487,7 +539,7 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
487
539
  "z-ai/glm-5.3-flash"
488
540
  ]);
489
541
  /**
490
- * Models the official CLI's model table (command-code@1.40.1) marks
542
+ * Models the official CLI's model table (command-code@1.46.0) marks
491
543
  * `reasoning:!0` but defines no selectable `reasoning_effort` levels — they
492
544
  * think automatically, with Command Code driving the depth. This is the
493
545
  * authoritative "thinks, effort not adjustable" set: `KNOWN_EFFORTS` (which
@@ -495,7 +547,7 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
495
547
  * effort levels, and this snapshot is not surfaced in the picker's compact
496
548
  * description — it exists for programmatic consumers.
497
549
  *
498
- * Source: the command-code@1.40.1 bundled model table (dist/cli.mjs),
550
+ * Source: the command-code@1.46.0 bundled model table (dist/cli.mjs),
499
551
  * cross-checked with https://commandcode.ai/docs/reference/cli/models.
500
552
  * (`stealth/ox-alpha` left this set in command-code@1.32.1, which gave it
501
553
  * selectable `['low', 'high', 'max']` efforts; the preview then ended in
@@ -505,7 +557,10 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
505
557
  * `['low', 'medium', 'high']` efforts in command-code@1.38.0 and moved to
506
558
  * `KNOWN_EFFORTS`. `moonshotai/Kimi-K3` followed the same path in
507
559
  * command-code@1.39.3 — it gained `['low', 'high', 'max']` efforts and moved
508
- * to `KNOWN_EFFORTS`.)
560
+ * to `KNOWN_EFFORTS`. command-code@1.42.0 added `meituan/LongCat-2.0:free`
561
+ * (reasoning:!0, no efforts). command-code@1.45.0 gave the Muse Spark family
562
+ * (1.1, 1.2, 1.2-contributor, 1.3, 1.3-contributor) selectable
563
+ * `['low', 'medium', 'high', 'xhigh']` efforts — they moved to `KNOWN_EFFORTS`.)
509
564
  * Keep in sync via the dsh-commandcode-upstream skill.
510
565
  */
511
566
  const KNOWN_THINKING_MODELS = /* @__PURE__ */ new Set([
@@ -525,9 +580,7 @@ const KNOWN_THINKING_MODELS = /* @__PURE__ */ new Set([
525
580
  "thinkingmachines/inkling",
526
581
  "thinkingmachines/inkling-small",
527
582
  "poolside/laguna-s-2.1-free",
528
- "meta/muse-spark-1.1",
529
- "meta/muse-spark-1.2",
530
- "meta/muse-spark-1.2-contributor"
583
+ "meituan/LongCat-2.0:free"
531
584
  ]);
532
585
  /**
533
586
  * The minimum subscription plan a model is included in, per the official plan
@@ -535,6 +588,14 @@ const KNOWN_THINKING_MODELS = /* @__PURE__ */ new Set([
535
588
  * and `/docs/resources/pricing-limits`). Each plan's model list is a superset of
536
589
  * the one below it: Go ⊂ GOAT ⊂ Pro ⊂ Provider/Max. Models absent from every
537
590
  * plan list (Claude Opus/Fable, Fugu Ultra) are Provider-tier.
591
+ * `claude-fable-5-1` (Claude Fable 5.1, added in command-code@1.40.0) is
592
+ * Provider/Max-tier exactly like `claude-fable-5` — its availability matrix on
593
+ * the official plan/pricing pages grants individual-provider/max/ultra and
594
+ * teams-pro only, and the CLI's plan-access map blocks it on Go/GOAT/Pro.
595
+ * command-code@1.41.0 added `Qwen/Qwen3.8-Max-0902` (Go) and 1.42.0 added
596
+ * `meituan/LongCat-2.0:free` (Go, free promo); command-code@1.43.0 added
597
+ * `google/gemini-3.8-flash` (GOAT) and 1.44.0 added `meta/muse-spark-1.3`
598
+ * (GOAT) plus its Contributor sibling (Go).
538
599
  *
539
600
  * The Provider API exposes no plan metadata, so this snapshot is the source of
540
601
  * truth for the picker's plan annotation — it answers "which plan do I need to
@@ -556,13 +617,16 @@ const KNOWN_PLANS = {
556
617
  "Qwen/Qwen3.8-27B": "go",
557
618
  "Qwen/Qwen3.8-Flash": "go",
558
619
  "Qwen/Qwen3.8-Max": "go",
620
+ "Qwen/Qwen3.8-Max-0902": "go",
559
621
  "deepseek/deepseek-v4-flash-fast": "go",
560
622
  "deepseek/deepseek-v4-flash": "go",
561
623
  "deepseek/deepseek-v4-flash-vision-exp": "go",
562
624
  "deepseek/deepseek-v4-pro": "go",
563
625
  "gpt-5.6-luna": "go",
564
626
  "inclusionai/ling-3.0-flash-free": "go",
627
+ "meituan/LongCat-2.0:free": "go",
565
628
  "meta/muse-spark-1.2-contributor": "go",
629
+ "meta/muse-spark-1.3-contributor": "go",
566
630
  "minimax/minimax-m2.7-free": "go",
567
631
  "minimax/minimax-m3-free": "go",
568
632
  "moonshotai/Kimi-K2.5": "go",
@@ -589,8 +653,10 @@ const KNOWN_PLANS = {
589
653
  "zai-org/GLM-5.2-Fast": "go",
590
654
  "zai-org/GLM-5.3": "go",
591
655
  "google/gemini-3.7-flash": "goat",
656
+ "google/gemini-3.8-flash": "goat",
592
657
  "gpt-5.6-sol": "goat",
593
658
  "meta/muse-spark-1.2": "goat",
659
+ "meta/muse-spark-1.3": "goat",
594
660
  "xai/grok-4.6": "goat",
595
661
  "claude-haiku-4-5-20251001": "pro",
596
662
  "claude-sonnet-4-6": "pro",
@@ -605,6 +671,7 @@ const KNOWN_PLANS = {
605
671
  "gpt-5.5": "pro",
606
672
  "gpt-5.6-terra": "pro",
607
673
  "meta/muse-spark-1.1": "pro",
674
+ "claude-fable-5-1": "provider",
608
675
  "claude-fable-5": "provider",
609
676
  "claude-opus-4-7": "provider",
610
677
  "claude-opus-4-8": "provider",
@@ -745,6 +812,10 @@ const KNOWN_DEALS = {
745
812
  "poolside/laguna-s-2.1-free": {
746
813
  label: "FREE",
747
814
  free: true
815
+ },
816
+ "meituan/LongCat-2.0:free": {
817
+ label: "FREE",
818
+ free: true
748
819
  }
749
820
  };
750
821
  /**
@@ -798,30 +869,6 @@ function peakPricingLabel(modelId, now = Date.now()) {
798
869
  if (state === void 0) return void 0;
799
870
  return state === "peak" ? "Peak" : "Half";
800
871
  }
801
- const COMMAND_CODE_CLI_VERSION = "1.40.1";
802
- const DEFAULT_API_BASE = "https://api.commandcode.ai";
803
- const DEFAULT_GENERATE_MAX_TOKENS = 64e3;
804
- const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
805
- const MODELS_TIMEOUT_MS = 1e4;
806
- /** How long the picker's plan-filter billing facts stay cached before refetching. */
807
- const BILLING_ACCESS_TTL_MS = 3e5;
808
- /**
809
- * Subscription statuses the CLI treats as live (`Mr` in command-code's
810
- * cli.mjs): the plan gate applies only under one of these.
811
- */
812
- const ACTIVE_SUBSCRIPTION_STATUSES = /* @__PURE__ */ new Set([
813
- "active",
814
- "trialing",
815
- "past_due"
816
- ]);
817
- /** Head-of-request timeout: how long to wait for the first response byte. */
818
- const DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
819
- /** Stream idle timeout: a generation that stalls this long is a dead connection. */
820
- const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 3e5;
821
- const MODEL_CACHE_VERSION = 1;
822
- function isRecord(value) {
823
- return typeof value === "object" && value !== null && !Array.isArray(value);
824
- }
825
872
  /**
826
873
  * Official display label for a model's minimum plan, or undefined for models
827
874
  * outside the snapshot (e.g. future catalog additions).
@@ -877,6 +924,53 @@ function capabilityDescription(modelId, contextWindow, now = Date.now()) {
877
924
  if (ctx !== void 0) parts.push(ctx);
878
925
  return parts.join(" · ");
879
926
  }
927
+ //#endregion
928
+ //#region src/adapter.ts
929
+ /**
930
+ * DeepSeek Harness LLM adapter for the Command Code Provider API.
931
+ *
932
+ * Ported from pi-commandcode-provider@0.5.1 (MIT). This is an unofficial,
933
+ * community-maintained integration; you need your own Command Code account
934
+ * and API key or subscription, and Command Code's terms apply.
935
+ *
936
+ * Wire protocol (reverse-engineered by the pi plugin, command-code@1.28.4;
937
+ * re-verified against command-code@1.44.0 — endpoints, request shape, and
938
+ * stream events unchanged):
939
+ * POST {apiBase}/alpha/generate
940
+ * body: { config, memory, taste, skills, params: { model, messages, tools,
941
+ * system, max_tokens, temperature, stream, reasoning_effort? }, threadId }
942
+ * SSE-ish JSONL events: text-delta | reasoning-start/delta/end | tool-call
943
+ * | tool-result | finish | error
944
+ * Model catalog: GET {apiBase}/provider/v1/models -> { object: 'list', data: [...] }
945
+ *
946
+ * The adapter is deliberately free of cordis/schemastery: it receives a
947
+ * per-request options thunk and an API-key resolver from the plugin entry
948
+ * (src/index.ts), so a settings change reaches the very next request.
949
+ */
950
+ const COMMAND_CODE_CLI_VERSION = "1.46.0";
951
+ const DEFAULT_API_BASE = "https://api.commandcode.ai";
952
+ const DEFAULT_GENERATE_MAX_TOKENS = 64e3;
953
+ const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
954
+ const MODELS_TIMEOUT_MS = 1e4;
955
+ /** How long the picker's plan-filter billing facts stay cached before refetching. */
956
+ const BILLING_ACCESS_TTL_MS = 3e5;
957
+ /**
958
+ * Subscription statuses the CLI treats as live (`Mr` in command-code's
959
+ * cli.mjs): the plan gate applies only under one of these.
960
+ */
961
+ const ACTIVE_SUBSCRIPTION_STATUSES = /* @__PURE__ */ new Set([
962
+ "active",
963
+ "trialing",
964
+ "past_due"
965
+ ]);
966
+ /** Head-of-request timeout: how long to wait for the first response byte. */
967
+ const DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
968
+ /** Stream idle timeout: a generation that stalls this long is a dead connection. */
969
+ const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 3e5;
970
+ const MODEL_CACHE_VERSION = 1;
971
+ function isRecord(value) {
972
+ return typeof value === "object" && value !== null && !Array.isArray(value);
973
+ }
880
974
  function stringValue(value) {
881
975
  return typeof value === "string" ? value : void 0;
882
976
  }
@@ -2026,38 +2120,75 @@ function applyCommands(ctx, deps) {
2026
2120
  ctx.commands.register(commandDefinition(deps));
2027
2121
  }
2028
2122
  //#endregion
2123
+ //#region src/wire-shared.ts
2124
+ /** The npm package identity every contribution and descriptor claims. */
2125
+ const REMOTE_PACKAGE = "@mars-sea/dsh-commandcode-provider";
2126
+ /** The Cordis service key the Gateway resolves every Command Code Remote from. */
2127
+ const REMOTE_SERVICE = "commandcodeUsage";
2128
+ /** The wire namespace all Command Code endpoints share. */
2129
+ const REMOTE_NAMESPACE = "commandcode";
2130
+ /**
2131
+ * Build the validator helpers one endpoint uses Sequence. `prefix` names the
2132
+ * endpoint in the rejection message (e.g. `commandcode/report result:`), so
2133
+ * each wire file keeps its own diagnostic phrasing while sharing the helper
2134
+ * bodies.
2135
+ *
2136
+ * The helpers return the reject call directly in the failure branch: since
2137
+ * `reject` is typed `never`, the ternary's union collapses to the success type
2138
+ * without relying on TypeScript's control-flow analysis of a never-returning
2139
+ * call (which only recognizes function declarations, not the destructured
2140
+ * arrow `reject` callers receive from this factory).
2141
+ */
2142
+ function makeBoundaryValidator(prefix) {
2143
+ const reject = (field) => {
2144
+ throw new TypeError(`${prefix} invalid ${field}`);
2145
+ };
2146
+ const record = (value, field) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : reject(field);
2147
+ const stringField = (source, key, field) => typeof source[key] === "string" ? source[key] : reject(field);
2148
+ const numberField = (source, key, field) => typeof source[key] === "number" && Number.isFinite(source[key]) ? source[key] : reject(field);
2149
+ const booleanField = (source, key, field) => typeof source[key] === "boolean" ? source[key] : reject(field);
2150
+ return {
2151
+ reject,
2152
+ record,
2153
+ stringField,
2154
+ numberField,
2155
+ booleanField
2156
+ };
2157
+ }
2158
+ /**
2159
+ * Build one strict invocation descriptor. Every Command Code Remote shares the
2160
+ * `commandcode` namespace, the `commandcodeUsage` service, and a strict
2161
+ * `mode: 'strict'` result — only the endpoint, method, result type symbol, and
2162
+ * schema differ — so the boilerplate lives here once and each endpoint supplies
2163
+ * only its own facts.
2164
+ */
2165
+ function makeRemoteDescriptor(endpoint, method, typeSymbol, schema) {
2166
+ return {
2167
+ id: `${REMOTE_PACKAGE}#${endpoint}`,
2168
+ service: REMOTE_SERVICE,
2169
+ namespace: REMOTE_NAMESPACE,
2170
+ method,
2171
+ invocation: { kind: "direct" },
2172
+ parameters: [],
2173
+ result: {
2174
+ mode: "strict",
2175
+ typeSymbol,
2176
+ schema
2177
+ }
2178
+ };
2179
+ }
2180
+ //#endregion
2029
2181
  //#region src/usage-wire.ts
2030
2182
  /** The npm package identity both contribution registrations claim. */
2031
- const USAGE_REMOTE_PACKAGE = "@mars-sea/dsh-commandcode-provider";
2183
+ const USAGE_REMOTE_PACKAGE = REMOTE_PACKAGE;
2032
2184
  /** Canonical `<namespace>/<method>` endpoint of the usage report Remote. */
2033
2185
  const USAGE_REPORT_ENDPOINT = "commandcode/report";
2034
- /** Reject one boundary value with a field-naming error. */
2035
- function reject$1(field) {
2036
- throw new TypeError(`commandcode/report result: invalid ${field}`);
2037
- }
2038
- /** Read one required finite number field (`field` is the dotted error label). */
2039
- function numberField(source, key, field) {
2040
- const value = source[key];
2041
- if (typeof value !== "number" || !Number.isFinite(value)) reject$1(field);
2042
- return value;
2043
- }
2044
- /** Read one required string field (`field` is the dotted error label). */
2045
- function stringField(source, key, field) {
2046
- const value = source[key];
2047
- if (typeof value !== "string") reject$1(field);
2048
- return value;
2049
- }
2050
- /** Read one required boolean field (`field` is the dotted error label). */
2051
- function booleanField(source, key, field) {
2052
- const value = source[key];
2053
- if (typeof value !== "boolean") reject$1(field);
2054
- return value;
2055
- }
2056
- /** Narrow an unknown value to a plain record, or reject. */
2057
- function record(value, field) {
2058
- if (typeof value !== "object" || value === null || Array.isArray(value)) reject$1(field);
2059
- return value;
2060
- }
2186
+ /**
2187
+ * The shared read/validate helpers, prefixed with the report endpoint so
2188
+ * rejection messages name the offending boundary (the catalog endpoint below
2189
+ * shares this prefix, matching the historical behavior).
2190
+ */
2191
+ const { reject: reject$1, record, stringField, numberField, booleanField } = makeBoundaryValidator("commandcode/report result:");
2061
2192
  /** Validate one window-limit block (`fiveHour` / `weekly`). */
2062
2193
  function windowLimit(value, field) {
2063
2194
  const source = record(value, field);
@@ -2080,8 +2211,8 @@ function parseUsageReport(value) {
2080
2211
  const report = { failures };
2081
2212
  if (source.blocked !== void 0) {
2082
2213
  const blocked = source.blocked;
2083
- if (blocked !== "invalid-key" && blocked !== "service-unavailable" && blocked !== "network") reject$1("blocked");
2084
- report.blocked = blocked;
2214
+ if (blocked === "invalid-key" || blocked === "service-unavailable" || blocked === "network") report.blocked = blocked;
2215
+ else reject$1("blocked");
2085
2216
  }
2086
2217
  if (source.account !== void 0) {
2087
2218
  const account = record(source.account, "account");
@@ -2145,8 +2276,8 @@ function parseAccountUsage(value) {
2145
2276
  /** Parse the wire result into a {@link CommandCodeAccountsReport}. */
2146
2277
  function parseAccountsReport(value) {
2147
2278
  const accounts = record(value, "result").accounts;
2148
- if (!Array.isArray(accounts)) reject$1("accounts");
2149
- return { accounts: accounts.map(parseAccountUsage) };
2279
+ if (Array.isArray(accounts)) return { accounts: accounts.map(parseAccountUsage) };
2280
+ return reject$1("accounts");
2150
2281
  }
2151
2282
  /**
2152
2283
  * The strict result codec both halves attach to the descriptor. Hand-rolled:
@@ -2164,19 +2295,7 @@ const USAGE_HOST_CONTRIBUTION = {
2164
2295
  events: [],
2165
2296
  objects: []
2166
2297
  },
2167
- invocations: [{
2168
- id: `${USAGE_REMOTE_PACKAGE}#${USAGE_REPORT_ENDPOINT}`,
2169
- service: "commandcodeUsage",
2170
- namespace: "commandcode",
2171
- method: "report",
2172
- invocation: { kind: "direct" },
2173
- parameters: [],
2174
- result: {
2175
- mode: "strict",
2176
- typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeAccountsReport`,
2177
- schema: usageReportSchema
2178
- }
2179
- }]
2298
+ invocations: [makeRemoteDescriptor(USAGE_REPORT_ENDPOINT, "report", `${USAGE_REMOTE_PACKAGE}#CommandCodeAccountsReport`, usageReportSchema)]
2180
2299
  };
2181
2300
  /** Canonical `<namespace>/<method>` endpoint of the model-catalog Remote. */
2182
2301
  const MODELS_ENDPOINT = "commandcode/models";
@@ -2191,26 +2310,14 @@ function parseCatalogModel(value) {
2191
2310
  /** Parse the wire result into a {@link CommandCodeCatalog}. */
2192
2311
  function parseCatalog(value) {
2193
2312
  const models = record(value, "result").models;
2194
- if (!Array.isArray(models)) reject$1("models");
2195
- return { models: models.map(parseCatalogModel) };
2313
+ if (Array.isArray(models)) return { models: models.map(parseCatalogModel) };
2314
+ return reject$1("models");
2196
2315
  }
2197
2316
  /**
2198
2317
  * The model-catalog invocation descriptor, sharing the same `commandcodeUsage`
2199
2318
  * service and `commandcode` namespace as the usage report.
2200
2319
  */
2201
- const MODELS_DESCRIPTOR = {
2202
- id: `${USAGE_REMOTE_PACKAGE}#${MODELS_ENDPOINT}`,
2203
- service: "commandcodeUsage",
2204
- namespace: "commandcode",
2205
- method: "models",
2206
- invocation: { kind: "direct" },
2207
- parameters: [],
2208
- result: {
2209
- mode: "strict",
2210
- typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeCatalog`,
2211
- schema: { parse: parseCatalog }
2212
- }
2213
- };
2320
+ const MODELS_DESCRIPTOR = makeRemoteDescriptor(MODELS_ENDPOINT, "models", `${USAGE_REMOTE_PACKAGE}#CommandCodeCatalog`, { parse: parseCatalog });
2214
2321
  //#endregion
2215
2322
  //#region src/login-wire.ts
2216
2323
  /** The canonical endpoint paths of the three login Remotes. */
@@ -2226,7 +2333,12 @@ const REASONS = [
2226
2333
  "cancelled",
2227
2334
  "error"
2228
2335
  ];
2229
- /** Reject one boundary value with a field-naming error. */
2336
+ /** The shared read/validate helpers, prefixed with the login endpoint so
2337
+ * rejection messages name the offending boundary. */
2338
+ /** Reject one boundary value with a field-naming error. A module-level
2339
+ * function declaration (not the factory's destructured arrow) so TypeScript's
2340
+ * control-flow analysis recognizes it as never-returning and narrows `state`
2341
+ * after the guard below. */
2230
2342
  function reject(field) {
2231
2343
  throw new TypeError(`commandcode/login result: invalid ${field}`);
2232
2344
  }
@@ -2267,19 +2379,7 @@ function parseLoginStatus(value) {
2267
2379
  const loginStatusSchema = { parse: parseLoginStatus };
2268
2380
  /** Build one login invocation descriptor (uniform result, no parameters). */
2269
2381
  function loginDescriptor(endpoint, method) {
2270
- return {
2271
- id: `${USAGE_REMOTE_PACKAGE}#${endpoint}`,
2272
- service: "commandcodeUsage",
2273
- namespace: "commandcode",
2274
- method,
2275
- invocation: { kind: "direct" },
2276
- parameters: [],
2277
- result: {
2278
- mode: "strict",
2279
- typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeLoginStatus`,
2280
- schema: loginStatusSchema
2281
- }
2282
- };
2382
+ return makeRemoteDescriptor(endpoint, method, `${REMOTE_PACKAGE}#CommandCodeLoginStatus`, loginStatusSchema);
2283
2383
  }
2284
2384
  /** The three login descriptors, shared verbatim by Host registration and Client mount. */
2285
2385
  const LOGIN_DESCRIPTORS = [