@mars-sea/dsh-commandcode-provider 0.2.4 → 0.3.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/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.3.0] - 2026-08-17
8
+
9
+ ### Added
10
+
11
+ - **The model picker now shows DeepSeek's time-of-day pricing state as a compact `Peak`/`Half` marker.** Since 2026-08-16 16:00 UTC, DeepSeek V4 Pro and V4 Flash cost full price during peak hours (01:00–04:00 and 06:00–10:00 UTC, 7h/day) and half price off-peak (the other 17h/day) — the official pricing page retired the old 75%-off deal in favor of this hourly pricing. `capabilityDescription()` now reads the current UTC hour and appends `Peak` (full price) or `Half` (off-peak, half price) for models in the new `KNOWN_PEAK_PRICING` snapshot, e.g. `Go · Half · 1M` at 17:00 UTC. The English noun markers match the picker's existing style (`Go`, `Image`, `FREE`), and since they appear only on time-of-day priced models they double as a "priced by the hour" signal. New `peakPricingState()`/`peakPricingLabel()` helpers are exported and covered by boundary-hour unit tests. The lapsed 75%-off entry was removed from `KNOWN_DEALS` (expired deals are dropped once the official page retires them).
12
+
13
+ ### Fixed
14
+
15
+ - **`projectSlugFromPath` no longer exhibits quadratic matching on adversarial paths (CodeQL `js/polynomial-redos`, alert #1).** The old trim step `/^-+|-+$/g` was ambiguous: on input like `a<200k dashes>b` the unanchored `-+$` alternation retried every start position, taking ~14.5s where a linear trim takes ~0ms. The trailing trim now uses the negative lookbehind `(?<!-)-+$` (the fix CodeQL documents), so only one start position is ever tried. The `x-project-slug` header is derived from the user-configurable working directory, so this was reachable from user input. A regression test pins the linear behavior.
16
+
7
17
  ## [0.2.4] - 2026-08-16
8
18
 
9
19
  ### Fixed
package/README.md CHANGED
@@ -19,7 +19,7 @@ Unofficial [DeepSeek Harness](https://deepseek-harness.github.io/deepseek-harnes
19
19
  - **Plugin bundle** installable into any dsh profile with `dsh plugin add`, plus a **`commandcode` provider route** with a live catalog (`GET {apiBase}/provider/v1/models`, cached at `~/.commandcode/models-cache.json`).
20
20
  - **Dedicated "Command Code" settings page** (Settings → **Command Code**) with an **API-key field** and connection knobs (API base, working directory, request/stream timeouts). The key is stored through the dsh credentials service; connection fields land in the `llm-commandcode` section and apply to the very next request, no restart.
21
21
  - **API key resolution order**: `config.apiKey` → credential ref `apiKeyEnv` (default `COMMANDCODE_API_KEY`) → launch environment → the official CLI auth file (`~/.commandcode/auth.json`, from `command-code login`).
22
- - **Model-picker annotations**: every model shows the **minimum plan** that includes it (`KNOWN_PLANS`), an **active deal** or `FREE` badge (`KNOWN_DEALS`, expiry-aware so lapsed discounts hide themselves), an **`Image`** marker for Vision models, and the **context window** (`1M` / `256K` / `262K`) — e.g. *"Go · 50% off · Image · 1M"*. The list is **sorted by plan tier** (Go → GOAT → Pro → Provider/Max), so the models your plan can use lead the picker.
22
+ - **Model-picker annotations**: every model shows the **minimum plan** that includes it (`KNOWN_PLANS`), an **active deal** or `FREE` badge (`KNOWN_DEALS`, expiry-aware so lapsed discounts hide themselves), the **current peak/off-peak state** (`Peak`/`Half`) for time-of-day-priced models, an **`Image`** marker for Vision models, and the **context window** (`1M` / `256K` / `262K`) — e.g. *"Go · 50% off · Image · 1M"*, *"Go · Half · 1M"*. The list is **sorted by plan tier** (Go → GOAT → Pro → Provider/Max), so the models your plan can use lead the picker.
23
23
  - **Reasoning-effort support** for models the official catalog marks as such (`KNOWN_EFFORTS`, matching `command-code@1.26.0`); reasoning models without effort levels still think automatically, exactly like the official CLI.
24
24
  - **Image input for Vision-capable models** (sent in the official wire format via the dsh attachment service); text-only models refuse images loudly (`UNSUPPORTED_CONTENT`) rather than dropping them.
25
25
 
package/README.zh-CN.md CHANGED
@@ -19,7 +19,7 @@
19
19
  - **插件包**:可通过 `dsh plugin add` 安装到任意 dsh 配置,并提供 **`commandcode` provider 路由**,带实时模型目录(`GET {apiBase}/provider/v1/models`,缓存于 `~/.commandcode/models-cache.json`)。
20
20
  - **专属"Command Code"设置页**(设置 → **Command Code**),带 **API key 输入框** 与连接参数(API 地址、工作目录、请求/流超时)。密钥通过 dsh 凭据服务存储;连接参数写入 `llm-commandcode` 设置段,对下一次请求即刻生效,无需重启。
21
21
  - **API key 解析顺序**:`config.apiKey` → 凭据引用 `apiKeyEnv`(默认 `COMMANDCODE_API_KEY`)→ 启动环境变量 → 官方 CLI 认证文件(`~/.commandcode/auth.json`,由 `command-code login` 写入)。
22
- - **模型选择器标注**:每个模型显示包含它的**最低套餐**(`KNOWN_PLANS`)、**活动折扣**或 `FREE` 徽章(`KNOWN_DEALS`,到期自动隐藏已失效折扣)、Vision 模型的 **`Image`** 标记,以及**上下文长度**(`1M` / `256K` / `262K`)——例如 *"Go · 50% off · Image · 1M"*。列表**按套餐排序**(Go → GOAT → Pro → Provider/Max),你当前套餐能用的模型总是排在最前。
22
+ - **模型选择器标注**:每个模型显示包含它的**最低套餐**(`KNOWN_PLANS`)、**活动折扣**或 `FREE` 徽章(`KNOWN_DEALS`,到期自动隐藏已失效折扣)、峰谷定价模型的**当前时段状态**(`Peak`/`Half`,按当前 UTC 小时动态判断)、Vision 模型的 **`Image`** 标记,以及**上下文长度**(`1M` / `256K` / `262K`)——例如 *"Go · 50% off · Image · 1M"*、*"Go · Half · 1M"*。列表**按套餐排序**(Go → GOAT → Pro → Provider/Max),你当前套餐能用的模型总是排在最前。
23
23
  - **推理强度(reasoning-effort)支持**:针对官方目录标为推理模型的模型(`KNOWN_EFFORTS`,与 `command-code@1.26.0` 一致);没有可选档位但仍支持思考的模型会自动思考,与官方 CLI 行为完全一致。
24
24
  - **支持视觉模型的图片输入**(通过 dsh 附件服务、以官方 wire 格式发送);纯文本模型会明确拒绝图片(`UNSUPPORTED_CONTENT`)而非静默丢弃。
25
25
 
package/lib/index.d.ts CHANGED
@@ -95,6 +95,32 @@ interface KnownDeal {
95
95
  free?: boolean;
96
96
  }
97
97
  declare const KNOWN_DEALS: Readonly<Record<string, KnownDeal>>;
98
+ /**
99
+ * Models with time-of-day (peak/off-peak) pricing, per the official pricing
100
+ * page (`/docs/resources/pricing-limits`). Since 2026-08-16 16:00 UTC, DeepSeek
101
+ * charges by the hour: peak hours are 01:00–04:00 and 06:00–10:00 UTC (7h/day,
102
+ * full price); the other 17 hours are off-peak at half price. The picker shows
103
+ * the *current* state as a compact label (`Peak`/`Half`) matching the English
104
+ * noun style of the other markers (`Image`, `FREE`), so a developer can tell at
105
+ * a glance whether calling the model right now is cheap or expensive.
106
+ *
107
+ * Keep in sync with the official pricing page when the model set or the peak
108
+ * windows change (see the dsh-commandcode-upstream skill).
109
+ */
110
+ declare const KNOWN_PEAK_PRICING: ReadonlySet<string>;
111
+ /**
112
+ * Whether `now` (defaults to `Date.now()`) falls in a peak-pricing hour for
113
+ * time-of-day-priced models. `undefined` for models outside the snapshot.
114
+ */
115
+ declare function peakPricingState(modelId: string, now?: number): 'peak' | 'off-peak' | undefined;
116
+ /**
117
+ * Compact label for the current peak/off-peak state: `Peak` (full price) or
118
+ * `Half` (off-peak, half price). These English nouns match the picker's other
119
+ * markers (`Go`, `Image`, `FREE`), and since they appear only on time-of-day
120
+ * priced models they double as a "priced by the hour" signal. Returns undefined
121
+ * for models without time-of-day pricing.
122
+ */
123
+ declare function peakPricingLabel(modelId: string, now?: number): string | undefined;
98
124
  declare const COMMAND_CODE_CLI_VERSION = "1.26.0";
99
125
  declare const DEFAULT_API_BASE = "https://api.commandcode.ai";
100
126
  declare const DEFAULT_GENERATE_MAX_TOKENS = 64000;
@@ -124,9 +150,10 @@ declare function dealLabel(modelId: string, now?: number): string | undefined;
124
150
  declare function formatContext(contextWindow: number | undefined): string | undefined;
125
151
  /**
126
152
  * Compact one-line summary for the model picker: plan tier, then any active
127
- * deal (discount or FREE), then `Image` for Vision-capable models, then the
128
- * context window. Text-only models simply omit the Image marker "Text only"
129
- * adds nothing the picker needs to show.
153
+ * deal (discount or FREE), then the current peak/off-peak state (`Peak`/`Half`)
154
+ * for time-of-day-priced models, then `Image` for Vision-capable models, then
155
+ * the context window. Text-only models simply omit the Image marker "Text
156
+ * only" adds nothing the picker needs to show.
130
157
  */
131
158
  declare function capabilityDescription(modelId: string, contextWindow?: number, now?: number): string;
132
159
  declare function projectSlugFromPath(pathName: string): string;
@@ -297,5 +324,5 @@ interface ResolvedCommandCodeOptions extends CommandCodeConnectionOptions {
297
324
  declare function resolveAdapterOptions(config: Config): ResolvedCommandCodeOptions;
298
325
  declare function apply(ctx: Context, config: Config): void;
299
326
  //#endregion
300
- export { COMMAND_CODE_CLI_VERSION, CommandCodeAdapter, type CommandCodeAdapterDeps, type CommandCodeCommandDeps, type CommandCodeConnectionOptions, type CommandCodeUsageReport, 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_PLANS, KNOWN_THINKING_MODELS, PLAN_LABELS, PLAN_ORDER, PROVIDER, type ResolveAttachments, ResolvedCommandCodeOptions, apply, applyCommands, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, name, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey };
327
+ export { COMMAND_CODE_CLI_VERSION, CommandCodeAdapter, type CommandCodeAdapterDeps, type CommandCodeCommandDeps, type CommandCodeConnectionOptions, type CommandCodeUsageReport, 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_THINKING_MODELS, PLAN_LABELS, PLAN_ORDER, PROVIDER, type ResolveAttachments, ResolvedCommandCodeOptions, apply, applyCommands, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, name, peakPricingLabel, peakPricingState, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey };
301
328
  //# sourceMappingURL=index.d.ts.map
package/lib/index.js CHANGED
@@ -360,10 +360,6 @@ function compareByPlan(a, b) {
360
360
  return a.id.localeCompare(b.id);
361
361
  }
362
362
  const KNOWN_DEALS = {
363
- "deepseek/deepseek-v4-pro": {
364
- label: "75% off",
365
- expiresAt: "2026-08-16T15:59:59.999Z"
366
- },
367
363
  "google/gemini-3.7-flash": {
368
364
  label: "50% off",
369
365
  expiresAt: "2026-12-31T23:59:59Z"
@@ -376,6 +372,42 @@ const KNOWN_DEALS = {
376
372
  free: true
377
373
  }
378
374
  };
375
+ /**
376
+ * Models with time-of-day (peak/off-peak) pricing, per the official pricing
377
+ * page (`/docs/resources/pricing-limits`). Since 2026-08-16 16:00 UTC, DeepSeek
378
+ * charges by the hour: peak hours are 01:00–04:00 and 06:00–10:00 UTC (7h/day,
379
+ * full price); the other 17 hours are off-peak at half price. The picker shows
380
+ * the *current* state as a compact label (`Peak`/`Half`) matching the English
381
+ * noun style of the other markers (`Image`, `FREE`), so a developer can tell at
382
+ * a glance whether calling the model right now is cheap or expensive.
383
+ *
384
+ * Keep in sync with the official pricing page when the model set or the peak
385
+ * windows change (see the dsh-commandcode-upstream skill).
386
+ */
387
+ const KNOWN_PEAK_PRICING = /* @__PURE__ */ new Set(["deepseek/deepseek-v4-pro", "deepseek/deepseek-v4-flash"]);
388
+ /** Peak hours (UTC, hour-of-day range end-exclusive): 01–03 and 06–09. */
389
+ const PEAK_HOUR_RANGES = [[1, 4], [6, 10]];
390
+ /**
391
+ * Whether `now` (defaults to `Date.now()`) falls in a peak-pricing hour for
392
+ * time-of-day-priced models. `undefined` for models outside the snapshot.
393
+ */
394
+ function peakPricingState(modelId, now = Date.now()) {
395
+ if (!KNOWN_PEAK_PRICING.has(modelId)) return void 0;
396
+ const hour = new Date(now).getUTCHours();
397
+ return PEAK_HOUR_RANGES.some(([start, end]) => hour >= start && hour < end) ? "peak" : "off-peak";
398
+ }
399
+ /**
400
+ * Compact label for the current peak/off-peak state: `Peak` (full price) or
401
+ * `Half` (off-peak, half price). These English nouns match the picker's other
402
+ * markers (`Go`, `Image`, `FREE`), and since they appear only on time-of-day
403
+ * priced models they double as a "priced by the hour" signal. Returns undefined
404
+ * for models without time-of-day pricing.
405
+ */
406
+ function peakPricingLabel(modelId, now = Date.now()) {
407
+ const state = peakPricingState(modelId, now);
408
+ if (state === void 0) return void 0;
409
+ return state === "peak" ? "Peak" : "Half";
410
+ }
379
411
  const COMMAND_CODE_CLI_VERSION = "1.26.0";
380
412
  const DEFAULT_API_BASE = "https://api.commandcode.ai";
381
413
  const DEFAULT_GENERATE_MAX_TOKENS = 64e3;
@@ -425,9 +457,10 @@ function formatContext(contextWindow) {
425
457
  }
426
458
  /**
427
459
  * Compact one-line summary for the model picker: plan tier, then any active
428
- * deal (discount or FREE), then `Image` for Vision-capable models, then the
429
- * context window. Text-only models simply omit the Image marker "Text only"
430
- * adds nothing the picker needs to show.
460
+ * deal (discount or FREE), then the current peak/off-peak state (`Peak`/`Half`)
461
+ * for time-of-day-priced models, then `Image` for Vision-capable models, then
462
+ * the context window. Text-only models simply omit the Image marker "Text
463
+ * only" adds nothing the picker needs to show.
431
464
  */
432
465
  function capabilityDescription(modelId, contextWindow, now = Date.now()) {
433
466
  const parts = [];
@@ -435,6 +468,8 @@ function capabilityDescription(modelId, contextWindow, now = Date.now()) {
435
468
  if (plan !== void 0) parts.push(plan);
436
469
  const deal = dealLabel(modelId, now);
437
470
  if (deal !== void 0) parts.push(deal);
471
+ const peak = peakPricingLabel(modelId, now);
472
+ if (peak !== void 0) parts.push(peak);
438
473
  if (KNOWN_IMAGE_MODELS.has(modelId)) parts.push("Image");
439
474
  const ctx = formatContext(contextWindow);
440
475
  if (ctx !== void 0) parts.push(ctx);
@@ -472,7 +507,7 @@ function recordOrEmpty(value) {
472
507
  return {};
473
508
  }
474
509
  function projectSlugFromPath(pathName) {
475
- return pathName.toLowerCase().replace(/^[a-z]:/i, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "project";
510
+ return pathName.toLowerCase().replace(/^[a-z]:/i, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|(?<!-)-+$/g, "") || "project";
476
511
  }
477
512
  function parseStreamEventLine(line) {
478
513
  let trimmed = line.trim();
@@ -1311,6 +1346,6 @@ function apply(ctx, config) {
1311
1346
  });
1312
1347
  }
1313
1348
  //#endregion
1314
- export { COMMAND_CODE_CLI_VERSION, CommandCodeAdapter, 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_PLANS, KNOWN_THINKING_MODELS, PLAN_LABELS, PLAN_ORDER, PROVIDER, apply, applyCommands, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, name, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey };
1349
+ export { COMMAND_CODE_CLI_VERSION, CommandCodeAdapter, 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_THINKING_MODELS, PLAN_LABELS, PLAN_ORDER, PROVIDER, apply, applyCommands, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, name, peakPricingLabel, peakPricingState, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey };
1315
1350
 
1316
1351
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/adapter.ts","../src/commands.ts","../src/index.ts"],"sourcesContent":["/**\n * DeepSeek Harness LLM adapter for the Command Code Provider API.\n *\n * Ported from pi-commandcode-provider@0.5.1 (MIT). This is an unofficial,\n * community-maintained integration; you need your own Command Code account\n * and API key or subscription, and Command Code's terms apply.\n *\n * Wire protocol (reverse-engineered by the pi plugin, command-code@1.26.0):\n * POST {apiBase}/alpha/generate\n * body: { config, memory, taste, skills, params: { model, messages, tools,\n * system, max_tokens, temperature, stream, reasoning_effort? }, threadId }\n * SSE-ish JSONL events: text-delta | reasoning-start/delta/end | tool-call\n * | tool-result | finish | error\n * Model catalog: GET {apiBase}/provider/v1/models -> { object: 'list', data: [...] }\n *\n * The adapter is deliberately free of cordis/schemastery: it receives a\n * per-request options thunk and an API-key resolver from the plugin entry\n * (src/index.ts), so a settings change reaches the very next request.\n */\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { randomUUID } from 'node:crypto'\n\nimport type { AttachmentStore, ImageAttachmentRef } from '@deepseek-ai/dsh-attachment'\n\nimport {\n attributionHeaders,\n CallId,\n LlmAdapter,\n LlmError,\n ReasoningEffortId,\n errorChain,\n resolveRetryPolicy,\n type ResolvedRetryPolicy,\n type ContentBlock,\n type FinishReason,\n type GenerateOptions,\n type LlmModelInfo,\n type LlmResolvedModelInfo,\n type Message,\n type StreamChunk,\n type TokenUsage,\n} from '@deepseek-ai/dsh-llm'\n\n// ---------------------------------------------------------------------------\n// Static capability snapshot (from the official command-code@1.26.0 bundled\n// model catalog, dist/cli.mjs). The Provider API does not expose reasoning\n// metadata; models omitted here let Command Code choose their reasoning\n// depth, matching the official CLI.\n// ---------------------------------------------------------------------------\n\nexport const KNOWN_EFFORTS: Readonly<Record<string, readonly string[]>> = {\n // Re-verified against the authoritative command-code@1.26.0 bundled model\n // table (dist/cli.mjs, the 'ZA' object): exactly these models carry\n // 'reasoningEfforts'. Models marked 'reasoning:!0' without 'reasoningEfforts'\n // (e.g. Kimi K3, MiniMax M3, Muse Spark 1.2, Tencent Hy3, GLM-5/5.1/5.2-Fast)\n // think automatically and are absent here - the CLI omits 'reasoning_effort'\n // for them, so the picker must not offer a selector. Do NOT add entries from\n // the OAuth provider tables (anthropic/openai) - only the Provider-API 'ZA'\n // table is authoritative for this plugin's route.\n 'Qwen/Qwen3.8-Max': ['low', 'medium', 'xhigh'],\n 'claude-fable-5': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-opus-4-7': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-opus-4-8': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-opus-5': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-sonnet-4-6': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-sonnet-5': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'deepseek/deepseek-v4-flash': ['high', 'max'],\n 'deepseek/deepseek-v4-pro': ['high', 'max'],\n 'google/gemini-3.1-flash-lite': ['low', 'medium', 'high'],\n 'google/gemini-3.5-flash': ['low', 'medium', 'high'],\n 'google/gemini-3.5-flash-lite': ['low', 'medium', 'high'],\n 'google/gemini-3.6-flash': ['low', 'medium', 'high'],\n 'google/gemini-3.7-flash': ['low', 'medium', 'high'],\n 'gpt-5.3-codex': ['low', 'medium', 'high', 'xhigh'],\n 'gpt-5.4': ['low', 'medium', 'high', 'xhigh'],\n 'gpt-5.4-mini': ['low', 'medium', 'high'],\n 'gpt-5.5': ['low', 'medium', 'high', 'xhigh'],\n 'gpt-5.6-luna': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'gpt-5.6-sol': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'gpt-5.6-terra': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'sakana/fugu-ultra': ['high', 'xhigh'],\n 'xai/grok-4.5': ['low', 'medium', 'high'],\n 'xai/grok-4.6': ['low', 'medium', 'high', 'xhigh'],\n 'zai-org/GLM-5.2': ['high', 'max'],\n 'zai-org/GLM-5.3': ['low', 'high', 'max'],\n}\n\n/**\n * Models whose Capabilities include Vision, per the official Command Code\n * model registry (`https://commandcode.ai/docs/reference/cli/models`, generated\n * from the same registry as `cmd --list-models` / the `/model` picker).\n *\n * The Provider API does not expose modality metadata, so this snapshot is the\n * source of truth for image-input gating. Command Code's own CLI falls back to\n * a client-side VISION side-call for text-only models; this adapter does not\n * reproduce that interactive feature, so images sent to a model outside this\n * list are refused loudly (`UNSUPPORTED_CONTENT`) instead of being dropped or\n * sent to a model that cannot read them.\n *\n * Keep in sync with the official registry when new models ship (see the\n * dsh-commandcode-upstream skill).\n */\nexport const KNOWN_IMAGE_MODELS: ReadonlySet<string> = new Set([\n 'MiniMaxAI/MiniMax-M3',\n 'Qwen/Qwen3.6-Plus',\n 'Qwen/Qwen3.7-Flash',\n 'Qwen/Qwen3.7-Plus',\n 'Qwen/Qwen3.8-Max',\n 'claude-fable-5',\n 'claude-haiku-4-5-20251001',\n 'claude-opus-4-7',\n 'claude-opus-4-8',\n 'claude-opus-5',\n 'claude-sonnet-4-6',\n 'claude-sonnet-5',\n 'google/gemini-3.1-flash-lite',\n 'google/gemini-3.5-flash',\n 'google/gemini-3.5-flash-lite',\n 'google/gemini-3.6-flash',\n 'google/gemini-3.7-flash',\n 'gpt-5.3-codex',\n 'gpt-5.4',\n 'gpt-5.4-mini',\n 'gpt-5.5',\n 'gpt-5.6-luna',\n 'gpt-5.6-sol',\n 'gpt-5.6-terra',\n 'meta/muse-spark-1.1',\n 'meta/muse-spark-1.2',\n 'meta/muse-spark-1.2-contributor',\n 'moonshotai/Kimi-K2.5',\n 'moonshotai/Kimi-K2.6',\n 'moonshotai/Kimi-K2.7-Code',\n 'moonshotai/Kimi-K2.7-Code-Highspeed',\n 'moonshotai/Kimi-K3',\n 'sakana/fugu-ultra',\n 'stepfun/Step-3.7-Flash',\n 'thinkingmachines/inkling',\n 'thinkingmachines/inkling-small',\n 'xai/grok-4.5',\n 'xiaomi/mimo-v2.5',\n])\n\n/**\n * Models the official CLI's model table (`ZA` in command-code@1.26.0) marks\n * `reasoning:!0` but defines no selectable `reasoning_effort` levels — they\n * think automatically, with Command Code driving the depth. This is the\n * authoritative \"thinks, effort not adjustable\" set: `KNOWN_EFFORTS` (which\n * mirrors the CLI's effort map exactly) stays the sole source for selectable\n * effort levels, and this snapshot is not surfaced in the picker's compact\n * description — it exists for programmatic consumers.\n *\n * Source: the command-code@1.26.0 bundled model table (dist/cli.mjs, the `ZA`\n * object), cross-checked with https://commandcode.ai/docs/reference/cli/models.\n * Keep in sync via the dsh-commandcode-upstream skill.\n */\nexport const KNOWN_THINKING_MODELS: ReadonlySet<string> = new Set([\n 'MiniMaxAI/MiniMax-M3',\n 'Qwen/Qwen3.6-Max-Preview',\n 'Qwen/Qwen3.6-Plus',\n 'Qwen/Qwen3.7-Flash',\n 'Qwen/Qwen3.7-Max',\n 'Qwen/Qwen3.7-Plus',\n 'moonshotai/Kimi-K3',\n 'moonshotai/Kimi-K2.7-Code',\n 'moonshotai/Kimi-K2.7-Code-Highspeed',\n 'stepfun/Step-3.5-Flash',\n 'stepfun/Step-3.7-Flash',\n 'tencent/hy3-paid',\n 'nvidia/nemotron-3-ultra-550b-a55b',\n 'thinkingmachines/inkling',\n 'thinkingmachines/inkling-small',\n 'poolside/laguna-s-2.1-free',\n 'meta/muse-spark-1.1',\n 'meta/muse-spark-1.2',\n 'meta/muse-spark-1.2-contributor',\n])\n\n/**\n * The minimum subscription plan a model is included in, per the official plan\n * pages (`/docs/plans/go`, `/docs/plans/goat`, `/docs/plans/pro`, `/docs/plans/max`\n * and `/docs/resources/pricing-limits`). Each plan's model list is a superset of\n * the one below it: Go ⊂ GOAT ⊂ Pro ⊂ Provider/Max. Models absent from every\n * plan list (Claude Opus/Fable, Fugu Ultra) are Provider-tier.\n *\n * The Provider API exposes no plan metadata, so this snapshot is the source of\n * truth for the picker's plan annotation — it answers \"which plan do I need to\n * actually use this model?\" at a glance. Plan labels use the official tier\n * names (`Go`, `GOAT`, `Pro`, `Provider`), with `Max` implying Provider.\n *\n * Keep in sync with the official plan pages when they change (see the\n * dsh-commandcode-upstream skill).\n */\nexport const KNOWN_PLANS: Readonly<Record<string, string>> = {\n // --- Go (33) ---\n 'MiniMaxAI/MiniMax-M2.5': 'go',\n 'MiniMaxAI/MiniMax-M2.7': 'go',\n 'MiniMaxAI/MiniMax-M3': 'go',\n 'Qwen/Qwen3.6-Max-Preview': 'go',\n 'Qwen/Qwen3.6-Plus': 'go',\n 'Qwen/Qwen3.7-Flash': 'go',\n 'Qwen/Qwen3.7-Max': 'go',\n 'Qwen/Qwen3.7-Plus': 'go',\n 'Qwen/Qwen3.8-Max': 'go',\n 'deepseek/deepseek-v4-flash': 'go',\n 'deepseek/deepseek-v4-pro': 'go',\n 'gpt-5.6-luna': 'go',\n 'meta/muse-spark-1.2-contributor': 'go',\n 'moonshotai/Kimi-K2.5': 'go',\n 'moonshotai/Kimi-K2.6': 'go',\n 'moonshotai/Kimi-K2.7-Code': 'go',\n 'moonshotai/Kimi-K2.7-Code-Highspeed': 'go',\n 'moonshotai/Kimi-K3': 'go',\n 'nvidia/nemotron-3-ultra-550b-a55b': 'go',\n 'poolside/laguna-s-2.1-free': 'go',\n 'stepfun/Step-3.5-Flash': 'go',\n 'stepfun/Step-3.7-Flash': 'go',\n 'tencent/hy3-paid': 'go',\n 'thinkingmachines/inkling': 'go',\n 'thinkingmachines/inkling-small': 'go',\n 'xai/grok-4.5': 'go',\n 'xiaomi/mimo-v2.5': 'go',\n 'xiaomi/mimo-v2.5-pro': 'go',\n 'zai-org/GLM-5': 'go',\n 'zai-org/GLM-5.1': 'go',\n 'zai-org/GLM-5.2': 'go',\n 'zai-org/GLM-5.2-Fast': 'go',\n 'zai-org/GLM-5.3': 'go',\n // --- GOAT (3 more) ---\n 'google/gemini-3.7-flash': 'goat',\n 'meta/muse-spark-1.2': 'goat',\n 'xai/grok-4.6': 'goat',\n // --- Pro (14 more) ---\n 'claude-haiku-4-5-20251001': 'pro',\n 'claude-sonnet-4-6': 'pro',\n 'claude-sonnet-5': 'pro',\n 'google/gemini-3.1-flash-lite': 'pro',\n 'google/gemini-3.5-flash': 'pro',\n 'google/gemini-3.5-flash-lite': 'pro',\n 'google/gemini-3.6-flash': 'pro',\n 'gpt-5.3-codex': 'pro',\n 'gpt-5.4': 'pro',\n 'gpt-5.4-mini': 'pro',\n 'gpt-5.5': 'pro',\n 'gpt-5.6-sol': 'pro',\n 'gpt-5.6-terra': 'pro',\n 'meta/muse-spark-1.1': 'pro',\n // --- Provider / Max (5) ---\n 'claude-fable-5': 'provider',\n 'claude-opus-4-7': 'provider',\n 'claude-opus-4-8': 'provider',\n 'claude-opus-5': 'provider',\n 'sakana/fugu-ultra': 'provider',\n}\n\n/** Official display labels for each plan tier. */\nexport const PLAN_LABELS: Readonly<Record<string, string>> = {\n go: 'Go',\n goat: 'GOAT',\n pro: 'Pro',\n provider: 'Provider',\n max: 'Max',\n}\n\n/**\n * Plan-tier sort weights, low to high. Models outside the snapshot (unknown\n * plans) sort after every known tier, keeping known models predictable.\n */\nexport const PLAN_ORDER: Readonly<Record<string, number>> = {\n go: 0,\n goat: 1,\n pro: 2,\n provider: 3,\n max: 4,\n}\n\n/**\n * Comparator for the model picker: sort by plan tier (lowest first), then by\n * model name, then by id as a tiebreak. Models with no known plan sort last.\n */\nexport function compareByPlan(\n a: { id: string; name: string },\n b: { id: string; name: string },\n): number {\n const pa = PLAN_ORDER[KNOWN_PLANS[a.id] ?? ''] ?? Number.MAX_SAFE_INTEGER\n const pb = PLAN_ORDER[KNOWN_PLANS[b.id] ?? ''] ?? Number.MAX_SAFE_INTEGER\n if (pa !== pb) return pa - pb\n const nameDiff = a.name.localeCompare(b.name)\n if (nameDiff !== 0) return nameDiff\n return a.id.localeCompare(b.id)\n}\n\n/**\n * Active pricing deals per the official pricing page\n * (`/docs/resources/pricing-limits#deals`). Each entry records the model's\n * promotional label and — critically — when it expires, so the picker never\n * shows a stale discount after the plugin's snapshot has gone out of date.\n *\n * - `expiresAt` is an ISO timestamp. When it is in the past (checked at\n * render time against `Date.now()`), the deal label is hidden until the\n * snapshot is refreshed from the official page. `undefined` means\n * \"no expiry\" (permanent).\n * - `free` marks models whose requests cost no credits (Laguna S 2.1), shown\n * as a `FREE` badge; it degrades to a plain discount once the deal lapses.\n *\n * Keep in sync with the official pricing page when deals change (see the\n * dsh-commandcode-upstream skill).\n */\nexport interface KnownDeal {\n /** Promotional label, e.g. \"50% off\" or \"2× usage\". */\n label: string\n /** Deal end date (ISO). `undefined` = permanent / no expiry. */\n expiresAt?: string\n /** Model is free (requests cost no credits). */\n free?: boolean\n}\n\nexport const KNOWN_DEALS: Readonly<Record<string, KnownDeal>> = {\n // Official pricing page (pricing-limits#deals): DeepSeek V4 Pro's 75%-off\n // deal is measured against the old $1.74 list rate and retires when DeepSeek\n // moves to peak/off-peak pricing on 2026-08-16 16:00 UTC - the 'expiresAt'\n // below is that exact official end timestamp, so an un-updated plugin stops\n // showing the discount the moment it lapses.\n 'deepseek/deepseek-v4-pro': { label: '75% off', expiresAt: '2026-08-16T15:59:59.999Z' },\n 'google/gemini-3.7-flash': { label: '50% off', expiresAt: '2026-12-31T23:59:59Z' },\n 'MiniMaxAI/MiniMax-M3': { label: '50% off' },\n 'xiaomi/mimo-v2.5-pro': { label: '99% off' },\n 'xiaomi/mimo-v2.5': { label: '98% off' },\n 'poolside/laguna-s-2.1-free': { label: 'FREE', free: true },\n}\n\nexport const COMMAND_CODE_CLI_VERSION = '1.26.0'\nexport const DEFAULT_API_BASE = 'https://api.commandcode.ai'\nexport const DEFAULT_GENERATE_MAX_TOKENS = 64_000\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 65_536\nexport const MODELS_TIMEOUT_MS = 10_000\n/** Head-of-request timeout: how long to wait for the first response byte. */\nexport const DEFAULT_REQUEST_TIMEOUT_MS = 60_000\n/** Stream idle timeout: a generation that stalls this long is a dead connection. */\nexport const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 300_000\nconst MODEL_CACHE_VERSION = 1\n\n// ---------------------------------------------------------------------------\n// Small helpers (ported from converters.ts / models.ts)\n// ---------------------------------------------------------------------------\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Official display label for a model's minimum plan, or undefined for models\n * outside the snapshot (e.g. future catalog additions).\n */\nexport function planLabel(modelId: string): string | undefined {\n const plan = KNOWN_PLANS[modelId]\n return plan === undefined ? undefined : PLAN_LABELS[plan]\n}\n\n/**\n * The active deal label for a model, or undefined when the model has no deal\n * or the deal has expired. Expiry is judged against `now` (defaults to\n * `Date.now()`), so a snapshot that has gone stale stops showing its discount\n * the moment the official end date passes — the user never believes a lapsed\n * deal is still live. Permanent deals (no `expiresAt`) never lapse.\n */\nexport function dealLabel(modelId: string, now: number = Date.now()): string | undefined {\n const deal = KNOWN_DEALS[modelId]\n if (deal === undefined) return undefined\n if (deal.expiresAt !== undefined && now >= Date.parse(deal.expiresAt)) return undefined\n return deal.label\n}\n\n/**\n * Compact human-readable context window, e.g. `1_000_000 -> \"1M\"`,\n * `256_000 -> \"256K\"`, `262_144 -> \"256K\"` (floor to the nearest K).\n * Returns undefined for unknown/absent sizes.\n */\nexport function formatContext(contextWindow: number | undefined): string | undefined {\n if (contextWindow === undefined || !Number.isFinite(contextWindow) || contextWindow <= 0) {\n return undefined\n }\n if (contextWindow >= 1_000_000) {\n const m = contextWindow / 1_000_000\n // Round to one decimal only when it adds information: 1_048_576 -> \"1M\",\n // 1_050_000 -> \"1.1M\".\n const rounded = Math.round(m * 10) / 10\n return `${Number.isInteger(rounded) ? rounded : rounded.toFixed(1)}M`\n }\n return `${Math.floor(contextWindow / 1_000)}K`\n}\n\n/**\n * Compact one-line summary for the model picker: plan tier, then any active\n * deal (discount or FREE), then `Image` for Vision-capable models, then the\n * context window. Text-only models simply omit the Image marker — \"Text only\"\n * adds nothing the picker needs to show.\n */\nexport function capabilityDescription(\n modelId: string,\n contextWindow?: number,\n now: number = Date.now(),\n): string {\n const parts: string[] = []\n const plan = planLabel(modelId)\n if (plan !== undefined) parts.push(plan)\n const deal = dealLabel(modelId, now)\n if (deal !== undefined) parts.push(deal)\n if (KNOWN_IMAGE_MODELS.has(modelId)) parts.push('Image')\n const ctx = formatContext(contextWindow)\n if (ctx !== undefined) parts.push(ctx)\n return parts.join(' · ')\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined\n}\n\nfunction numberValue(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined\n}\n\nfunction booleanValue(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined\n}\n\n/**\n * Terminal stream-error markers from the official CLI (`Xw` in command-code's\n * cli.mjs): these always mean \"retrying cannot succeed\", so the adapter must\n * not classify them as transient server errors.\n */\nconst TERMINAL_STREAM_ERROR_MARKERS = [\n 'premium_credits_exhausted',\n 'model_not_in_plan',\n 'insufficient credits',\n]\n\nfunction hasTerminalStreamMarker(message: string): boolean {\n const lower = message.toLowerCase()\n return TERMINAL_STREAM_ERROR_MARKERS.some((marker) => lower.includes(marker))\n}\n\nfunction recordOrEmpty(value: unknown): Record<string, unknown> {\n if (isRecord(value)) return value\n if (typeof value === 'string') {\n try {\n const parsed: unknown = JSON.parse(value)\n if (isRecord(parsed)) return parsed\n } catch {\n // Some providers stream incomplete JSON argument fragments.\n }\n }\n return {}\n}\n\nexport function projectSlugFromPath(pathName: string): string {\n const slug = pathName\n .toLowerCase()\n .replace(/^[a-z]:/i, '')\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n return slug || 'project'\n}\n\nfunction parseStreamEventLine(line: string): unknown | undefined {\n let trimmed = line.trim()\n if (!trimmed || trimmed.startsWith(':') || trimmed.startsWith('event:')) return undefined\n if (trimmed.startsWith('data:')) trimmed = trimmed.slice(5).trim()\n if (!trimmed || trimmed === '[DONE]') return undefined\n try {\n return JSON.parse(trimmed) as unknown\n } catch {\n return undefined\n }\n}\n\n// ---------------------------------------------------------------------------\n// Credential fallback from the official Command Code CLI auth file. Used as\n// the last fallback by the plugin entry, so a user who already logged in with\n// `command-code login` can reuse that credential. Only the official CLI's own\n// file is read — pi/OMP auth files are intentionally not scanned, so their\n// credentials and formats cannot surprise this adapter.\n// ---------------------------------------------------------------------------\n\n/** Extract the key from the CLI's nested credential records (`command-code`). */\nfunction apiKeyFromCredentialRecord(value: unknown): string | undefined {\n if (!isRecord(value)) return undefined\n const type = stringValue(value.type)\n if (type === 'api') return stringValue(value.key)\n if (type === 'oauth') return stringValue(value.access)\n return stringValue(value.key) ?? stringValue(value.access)\n}\n\n/** Read a usable Command Code credential from the official CLI auth file. */\nexport function resolveAuthFileApiKey(): string | undefined {\n const authPath = join(homedir(), '.commandcode', 'auth.json')\n try {\n if (!existsSync(authPath)) return undefined\n const parsed: unknown = JSON.parse(readFileSync(authPath, 'utf-8'))\n if (!isRecord(parsed)) return undefined\n const direct = stringValue(parsed.apiKey) ?? stringValue(parsed.commandcode)\n if (direct) return direct\n const nested =\n apiKeyFromCredentialRecord(parsed.commandcode) ??\n apiKeyFromCredentialRecord(parsed['command-code'])\n return nested\n } catch {\n // Ignore malformed or unreadable auth file.\n }\n return undefined\n}\n\n// ---------------------------------------------------------------------------\n// Model catalog discovery with on-disk cache fallback (ported from models.ts)\n// ---------------------------------------------------------------------------\n\ninterface CommandCodeModel {\n id: string\n name: string\n contextWindow: number\n maxTokens: number\n}\n\nfunction parseCatalogResponse(value: unknown): CommandCodeModel[] {\n if (!isRecord(value) || value.object !== 'list' || !Array.isArray(value.data)) {\n throw new LlmError('Unexpected Command Code models response shape', 'PROVIDER_PROTOCOL_ERROR')\n }\n const models: CommandCodeModel[] = []\n for (const entry of value.data) {\n if (!isRecord(entry)) continue\n const id = stringValue(entry.id)\n const name = stringValue(entry.name)\n const contextLength = numberValue(entry.context_length)\n if (!id || !name || !contextLength || contextLength <= 0) continue\n models.push({\n id,\n name,\n contextWindow: contextLength,\n maxTokens: Math.min(contextLength, DEFAULT_MAX_OUTPUT_TOKENS),\n })\n }\n if (models.length === 0) {\n throw new LlmError('Command Code returned an empty model catalog', 'PROVIDER_PROTOCOL_ERROR')\n }\n return models\n}\n\nasync function readModelsCache(cachePath: string): Promise<CommandCodeModel[]> {\n const parsed: unknown = JSON.parse(await readFile(cachePath, 'utf-8'))\n if (!isRecord(parsed) || parsed.version !== MODEL_CACHE_VERSION || !Array.isArray(parsed.models)) {\n throw new Error(`Invalid model cache at ${cachePath}`)\n }\n return parsed.models as CommandCodeModel[]\n}\n\nasync function writeModelsCache(cachePath: string, models: CommandCodeModel[]): Promise<void> {\n await mkdir(dirname(cachePath), { recursive: true })\n const tmp = `${cachePath}.${process.pid}.tmp`\n try {\n await writeFile(tmp, `${JSON.stringify({ version: MODEL_CACHE_VERSION, models }, null, 2)}\\n`, {\n encoding: 'utf-8',\n mode: 0o600,\n })\n await rename(tmp, cachePath)\n } finally {\n await rm(tmp, { force: true }).catch(() => undefined)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Message conversion: harness Message[] -> Command Code wire messages.\n// Reasoning blocks are intentionally NOT replayed (matches the pi plugin and\n// the official CLI: prior private reasoning must not leak into later turns).\n// Only tool calls with a paired tool result are replayed.\n// ---------------------------------------------------------------------------\n\nfunction pairedToolCallIds(messages: readonly Message[]): Set<string> {\n const callIds = new Set<string>()\n const resultIds = new Set<string>()\n for (const message of messages) {\n for (const block of message.content) {\n if (message.role === 'assistant' && block.type === 'tool-call') callIds.add(block.id)\n if (block.type === 'tool-result') resultIds.add(block.toolCallId)\n }\n }\n return new Set([...callIds].filter((id) => resultIds.has(id)))\n}\n\nfunction blockText(block: ContentBlock): string {\n return block.type === 'text' || block.type === 'reasoning' ? block.text : ''\n}\n\nfunction toolResultText(block: Extract<ContentBlock, { type: 'tool-result' }>): string {\n return block.content.map(blockText).filter(Boolean).join('\\n')\n}\n\nfunction hasImageContent(message: Message): boolean {\n const check = (blocks: readonly ContentBlock[]): boolean =>\n blocks.some(\n (b) => b.type === 'image' || (b.type === 'tool-result' && check(b.content)),\n )\n return check(message.content)\n}\n\n/**\n * Convert one image reference to the Command Code wire format, as the official\n * CLI does: `{ type: 'image', source: { type: 'base64', media_type, data } }`.\n * Bytes come from the durable attachment service; the media type is the one\n * verified at save time.\n */\nasync function imageToCommandCode(\n ref: ImageAttachmentRef,\n readImage: (ref: ImageAttachmentRef) => Promise<Uint8Array>,\n): Promise<{ type: 'image'; source: { type: 'base64'; media_type: string; data: string } }> {\n const data = await readImage(ref)\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: ref.mediaType,\n data: Buffer.from(data).toString('base64'),\n },\n }\n}\n\nasync function messagesToCC(\n messages: readonly Message[],\n readImage?: (ref: ImageAttachmentRef) => Promise<Uint8Array>,\n): Promise<unknown[]> {\n const out: unknown[] = []\n const paired = pairedToolCallIds(messages)\n\n for (const message of messages) {\n if (message.role === 'system') continue // folded into params.system by the caller\n\n if (message.role === 'user' && message.source.kind !== 'tool') {\n const parts: unknown[] = []\n for (const block of message.content) {\n if (block.type === 'text') parts.push({ type: 'text', text: block.text })\n if (block.type === 'image') {\n // The caller (stream) has already gated image input on model\n // capability and attachment-service availability, so reaching this\n // branch with no resolver is an internal contract violation.\n if (!readImage) {\n throw new LlmError(\n 'Image input requires the durable attachment service',\n 'UNSUPPORTED_CONTENT',\n )\n }\n parts.push(await imageToCommandCode(block.attachment, readImage))\n }\n }\n out.push({ role: 'user', content: parts })\n continue\n }\n\n if (message.role === 'assistant') {\n const parts: unknown[] = []\n for (const block of message.content) {\n if (block.type === 'text') {\n parts.push({ type: 'text', text: block.text })\n } else if (block.type === 'tool-call' && paired.has(block.id)) {\n parts.push({\n type: 'tool-call',\n toolCallId: block.id,\n toolName: block.name,\n input: recordOrEmpty(block.arguments),\n })\n }\n // reasoning blocks: skipped by design (see header comment)\n }\n if (parts.length > 0) out.push({ role: 'assistant', content: parts })\n continue\n }\n\n // tool-result message (user role, single tool-result block)\n if (message.role === 'user' && message.source.kind === 'tool') {\n const block = message.content[0]\n if (!block || block.type !== 'tool-result' || !paired.has(block.toolCallId)) continue\n out.push({\n role: 'tool',\n content: [\n {\n type: 'tool-result',\n toolCallId: block.toolCallId,\n toolName: '',\n output: block.isError\n ? { type: 'error-text', value: toolResultText(block) }\n : { type: 'text', value: toolResultText(block) },\n },\n ],\n })\n }\n }\n return out\n}\n\n// ---------------------------------------------------------------------------\n// Adapter\n// ---------------------------------------------------------------------------\n/** Connection facts resolved fresh per request by the plugin entry. */\nexport interface CommandCodeConnectionOptions {\n /** API base; the Provider API lives under it (`/alpha/generate`, `/provider/v1/models`). */\n apiBase: string\n /** Working directory reported to the API (project slug, config block). */\n workingDir: string\n /** Model catalog cache path. */\n modelsCachePath: string\n /**\n * Milliseconds to wait for generate response headers / first byte (default 60s).\n * Must not bound the subsequent body stream — long generations are gated by\n * {@link streamIdleTimeoutMs} and the caller AbortSignal instead.\n */\n requestTimeoutMs: number\n /** Milliseconds a stream may stall before it is treated as a dead connection (default 300s). */\n streamIdleTimeoutMs: number\n}\n\n/**\n * Resolve the durable attachment service, or undefined when the host does not\n * provide one. Called lazily only when a request actually carries images, so a\n * text-only request never depends on the attachment seam.\n */\nexport type ResolveAttachments = () => AttachmentStore | undefined\n\n/** Everything the adapter needs beyond the request itself. */\nexport interface CommandCodeAdapterDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {\n /** Resolve the current connection facts (fresh per request, settings-aware). */\n options: () => C\n /** Resolve a usable API key for the given connection facts, or throw `MISSING_CREDENTIAL`. */\n resolveApiKey: (connection: C) => Promise<string>\n /** HTTP transport override (tests); defaults to the global `fetch`. */\n fetchImpl?: typeof fetch\n /** Resolve the optional durable attachment service for image input (tests); defaults to none. */\n resolveAttachments?: ResolveAttachments\n}\n\n/** Account identity from `/alpha/whoami`. */\nexport interface CommandCodeAccount {\n id: string\n name: string\n userName: string\n}\n\n/** Usage summary from `/alpha/usage/summary`. */\nexport interface CommandCodeUsage {\n totalCount: number\n totalCost: number\n successRate: number\n completedCount: number\n failedCount: number\n totalTokensIn: number\n totalTokensOut: number\n totalCredits: number\n periodBasis: string\n}\n\n/** Credit/limit state from `/alpha/billing/credits`. */\nexport interface CommandCodeCredits {\n monthlyCredits: number\n purchasedCredits: number\n freeCredits: number\n /** Five-hour rolling window limits. */\n fiveHour: { used: number; cap: number; exceeded: boolean; resetAt: number }\n /** Weekly window limits. */\n weekly: { used: number; cap: number; exceeded: boolean; resetAt: number }\n}\n\n/** Everything the usage endpoints report, fetched together. */\nexport interface CommandCodeUsageReport {\n account?: CommandCodeAccount\n usage?: CommandCodeUsage\n credits?: CommandCodeCredits\n /** Endpoint failures degrade the report instead of failing it. */\n failures: string[]\n}\n\nexport class CommandCodeAdapter<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> extends LlmAdapter {\n private catalog: CommandCodeModel[] = []\n private readonly fetchImpl: typeof fetch\n private readonly resolveAttachments: ResolveAttachments | undefined\n\n constructor(private readonly deps: CommandCodeAdapterDeps<C>) {\n super()\n this.fetchImpl = deps.fetchImpl ?? fetch\n this.resolveAttachments = deps.resolveAttachments\n }\n\n /**\n * Command Code is a metered subscription API: 429 (rate limit) and 5xx\n * (transient server errors) are worth retrying at the agent-step boundary,\n * which is where dsh-llm-retry executes the policy returned here. The\n * default policy already retries `RATE_LIMIT` and `SERVER`; declaring it\n * explicitly documents the intent and gives the plugin entry a stable hook\n * to override (e.g. a stricter cap for a metered plan).\n */\n override providerRetryPolicy(_provider: string): ResolvedRetryPolicy {\n return resolveRetryPolicy(undefined, 'llm-commandcode: retryPolicy')\n }\n\n /** Refresh the catalog (live fetch, cache fallback) and return it. */\n private async loadCatalog(signal?: AbortSignal): Promise<CommandCodeModel[]> {\n const { apiBase, modelsCachePath } = this.deps.options()\n try {\n const response = await this.fetchImpl(`${apiBase}/provider/v1/models`, {\n headers: { accept: 'application/json', ...attributionHeaders() },\n signal: signal ?? AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) {\n throw new Error(`models endpoint returned ${response.status}`)\n }\n this.catalog = parseCatalogResponse(await response.json())\n await writeModelsCache(modelsCachePath, this.catalog).catch(() => undefined)\n } catch (error) {\n if (signal?.aborted) throw error\n // A catalog refresh failure is a degradation, not a request failure:\n // fall back to the last successful catalog on disk (or the in-memory\n // one from an earlier successful load). The adapter still serves any\n // model the user names; only the advisory selector loses entries.\n this.catalog = await readModelsCache(modelsCachePath).catch(() => this.catalog)\n }\n return this.catalog\n }\n\n override async listModels(provider: string): Promise<readonly LlmModelInfo[]> {\n const catalog = await this.loadCatalog()\n return catalog\n .map((model) => {\n const vision = KNOWN_IMAGE_MODELS.has(model.id)\n return {\n provider,\n id: model.id,\n name: `${model.name} (CC)`,\n // The picker renders `description` under the model name: plan tier,\n // active deal, Image marker for Vision models, and context window.\n description: capabilityDescription(model.id, model.contextWindow),\n inputModalities: vision ? (['text', 'image'] as const) : (['text'] as const),\n }\n })\n // The picker renders rows in the order returned: sort by plan tier\n // (Go first, … Provider last) so the models a Go-plan user can actually\n // use lead the list, then alphabetically within each tier.\n .sort(compareByPlan)\n }\n\n override async resolveModel(\n provider: string,\n model: string,\n signal?: AbortSignal,\n ): Promise<LlmResolvedModelInfo> {\n const entry =\n this.catalog.find((m) => m.id === model) ??\n (await this.loadCatalog(signal)).find((m) => m.id === model)\n\n const efforts = KNOWN_EFFORTS[model]\n const vision = KNOWN_IMAGE_MODELS.has(model)\n return {\n provider,\n id: model,\n name: entry ? `${entry.name} (CC)` : model,\n description: capabilityDescription(model, entry?.contextWindow),\n inputModalities: vision ? (['text', 'image'] as const) : (['text'] as const),\n ...(entry\n ? {\n context: { contextWindow: entry.contextWindow },\n defaultMaxTokens: Math.min(entry.maxTokens, DEFAULT_GENERATE_MAX_TOKENS),\n }\n : {}),\n // Omit `reasoning` entirely for models without known effort support:\n // the harness then treats the model as having no selectable efforts.\n ...(efforts\n ? {\n reasoning: {\n efforts: efforts.map((effort) => ({\n id: ReasoningEffortId(effort),\n name: effort,\n })),\n },\n }\n : {}),\n }\n }\n\n /**\n * Fetch account, usage, and credit state from the Command Code account\n * endpoints (`/alpha/whoami`, `/alpha/usage/summary`, `/alpha/billing/credits`).\n * Each endpoint degrades independently: a failed one lands in `failures`\n * while the rest still report, so a transient outage never blanks the whole\n * view. Requires a usable API key (throws `MISSING_CREDENTIAL` otherwise).\n */\n async getUsage(): Promise<CommandCodeUsageReport> {\n const connection = this.deps.options()\n const apiKey = await this.deps.resolveApiKey(connection)\n const base = connection.apiBase\n const headers = {\n Authorization: `Bearer ${apiKey}`,\n 'x-command-code-version': COMMAND_CODE_CLI_VERSION,\n 'x-cli-environment': 'production',\n ...attributionHeaders(),\n }\n const failures: string[] = []\n\n const getJson = async (path: string): Promise<Record<string, unknown> | undefined> => {\n try {\n const response = await this.fetchImpl(`${base}${path}`, { headers })\n if (!response.ok) {\n failures.push(`${path}: HTTP ${response.status}`)\n return undefined\n }\n const parsed: unknown = await response.json()\n return isRecord(parsed) ? parsed : undefined\n } catch (error: unknown) {\n failures.push(`${path}: ${error instanceof Error ? error.message : String(error)}`)\n return undefined\n }\n }\n\n const report: CommandCodeUsageReport = { failures }\n\n // whoami -> account identity.\n const whoami = await getJson('/alpha/whoami')\n const whoamiData = whoami && isRecord(whoami.user) ? whoami.user : undefined\n if (whoamiData) {\n report.account = {\n id: stringValue(whoamiData.id) ?? '',\n name: stringValue(whoamiData.name) ?? '',\n userName: stringValue(whoamiData.userName) ?? '',\n }\n }\n\n // usage/summary -> totals.\n const usage = await getJson('/alpha/usage/summary')\n if (usage) {\n report.usage = {\n totalCount: numberValue(usage.totalCount) ?? 0,\n totalCost: numberValue(usage.totalCost) ?? 0,\n successRate: numberValue(usage.successRate) ?? 0,\n completedCount: numberValue(usage.completedCount) ?? 0,\n failedCount: numberValue(usage.failedCount) ?? 0,\n totalTokensIn: numberValue(usage.totalTokensIn) ?? 0,\n totalTokensOut: numberValue(usage.totalTokensOut) ?? 0,\n totalCredits: numberValue(usage.totalCredits) ?? 0,\n periodBasis: stringValue(usage.periodBasis) ?? 'billing-period',\n }\n }\n\n // billing/credits -> credit + window limits.\n const credits = await getJson('/alpha/billing/credits')\n const creditsData = credits && isRecord(credits.credits) ? credits.credits : undefined\n const windowLimits = credits && isRecord(credits.windowLimits) ? credits.windowLimits : undefined\n const fiveHour = windowLimits && isRecord(windowLimits.fiveHour) ? windowLimits.fiveHour : undefined\n const weekly = windowLimits && isRecord(windowLimits.weekly) ? windowLimits.weekly : undefined\n if (creditsData || fiveHour || weekly) {\n report.credits = {\n monthlyCredits: numberValue(creditsData?.monthlyCredits) ?? 0,\n purchasedCredits: numberValue(creditsData?.purchasedCredits) ?? 0,\n freeCredits: numberValue(creditsData?.freeCredits) ?? 0,\n fiveHour: {\n used: numberValue(fiveHour?.used) ?? 0,\n cap: numberValue(fiveHour?.cap) ?? 0,\n exceeded: fiveHour?.exceeded === true,\n resetAt: numberValue(fiveHour?.resetAt) ?? 0,\n },\n weekly: {\n used: numberValue(weekly?.used) ?? 0,\n cap: numberValue(weekly?.cap) ?? 0,\n exceeded: weekly?.exceeded === true,\n resetAt: numberValue(weekly?.resetAt) ?? 0,\n },\n }\n }\n\n return report\n }\n\n async *stream(options: GenerateOptions): AsyncIterable<StreamChunk> {\n if (options.stop?.length) {\n // The Command Code wire format has no documented stop field; refuse\n // loudly instead of silently dropping a request field.\n throw new LlmError('Command Code adapter does not support stop sequences', 'UNSUPPORTED_OPTION')\n }\n const hasImages = options.messages.some(hasImageContent)\n // Per-call image byte resolver, set only when this request carries images.\n // Local, not an instance field: concurrent streams must never read each\n // other's resolver.\n let readImage: ((ref: ImageAttachmentRef) => Promise<Uint8Array>) | undefined\n if (hasImages) {\n // Model-capability gate: only models the official registry lists with\n // Vision accept images natively. Command Code's own CLI falls back to a\n // client-side VISION side-call for text-only models; this adapter does\n // not reproduce that interactive feature, so it refuses loudly instead\n // of sending bytes to a model that cannot read them.\n if (!KNOWN_IMAGE_MODELS.has(options.model)) {\n throw new LlmError(\n `Command Code model \"${options.model}\" does not support image input;`\n + ' switch to a Vision-capable model (see the model registry)',\n 'UNSUPPORTED_CONTENT',\n )\n }\n // Attachment seam: images arrive as durable references; resolving them\n // requires the host's attachment service.\n const attachments = this.resolveAttachments?.()\n if (attachments === undefined) {\n throw new LlmError(\n 'Command Code image input requires the durable attachment service',\n 'UNSUPPORTED_CONTENT',\n )\n }\n readImage = (ref) => attachments.readImage(ref).then((stored) => stored.data)\n }\n\n const connection = this.deps.options()\n const apiKey = await this.deps.resolveApiKey(connection)\n const entry = this.catalog.find((m) => m.id === options.model)\n const modelMax = entry?.maxTokens ?? DEFAULT_MAX_OUTPUT_TOKENS\n const maxTokens = Math.min(\n options.maxTokens ?? modelMax,\n modelMax,\n DEFAULT_GENERATE_MAX_TOKENS,\n )\n\n const effort = options.reasoningEffort as string | undefined\n const supported = KNOWN_EFFORTS[options.model]\n const reasoningEffort =\n effort && effort !== 'off' && supported?.includes(effort) ? effort : undefined\n\n const systemText = [\n options.system ?? '',\n ...options.messages\n .filter((m) => m.role === 'system')\n .map((m) => m.content.map(blockText).filter(Boolean).join('\\n')),\n ]\n .filter(Boolean)\n .join('\\n\\n')\n\n const body = {\n config: {\n workingDir: connection.workingDir,\n date: new Date().toISOString().split('T')[0],\n environment: `${process.platform}-${process.arch}, Node.js ${process.version}`,\n structure: [],\n isGitRepo: false,\n currentBranch: '',\n mainBranch: '',\n gitStatus: '',\n recentCommits: [],\n },\n memory: null,\n taste: null,\n skills: null,\n params: {\n model: options.model,\n messages: await messagesToCC(options.messages, readImage),\n tools: (options.tools ?? []).map((tool) => ({\n type: 'function',\n name: tool.name,\n description: tool.description,\n input_schema: tool.parameters,\n })),\n system: systemText,\n max_tokens: maxTokens,\n temperature: options.temperature ?? 0.3,\n stream: true,\n ...(reasoningEffort ? { reasoning_effort: reasoningEffort } : {}),\n },\n threadId: randomUUID(),\n }\n\n // requestTimeoutMs must only bound the wait for response headers.\n // Passing AbortSignal.timeout() straight into fetch() also aborts a healthy\n // body after that duration, which cuts long reasoning/generation mid-stream\n // and surfaces as \"failed while reading: aborted due to timeout\". After\n // headers arrive, only the caller signal and streamIdleTimeoutMs may abort.\n const connectAbort = new AbortController()\n let connectTimedOut = false\n const connectTimer = setTimeout(() => {\n connectTimedOut = true\n connectAbort.abort(\n new DOMException(\n `Command Code API request to ${connection.apiBase}/alpha/generate did not respond within ${connection.requestTimeoutMs}ms`,\n 'TimeoutError',\n ),\n )\n }, connection.requestTimeoutMs)\n const onCallerAbort = () => {\n connectAbort.abort(options.signal?.reason)\n }\n if (options.signal) {\n if (options.signal.aborted) {\n onCallerAbort()\n } else {\n options.signal.addEventListener('abort', onCallerAbort, { once: true })\n }\n }\n\n let response: Response\n try {\n response = await this.fetchImpl(`${connection.apiBase}/alpha/generate`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n 'x-command-code-version': COMMAND_CODE_CLI_VERSION,\n 'x-cli-environment': 'production',\n 'x-project-slug': projectSlugFromPath(connection.workingDir),\n 'x-taste-learning': 'true',\n 'x-co-flag': 'false',\n ...attributionHeaders(),\n },\n body: JSON.stringify(body),\n signal: connectAbort.signal,\n })\n clearTimeout(connectTimer)\n } catch (error: unknown) {\n clearTimeout(connectTimer)\n if (options.signal) {\n options.signal.removeEventListener('abort', onCallerAbort)\n }\n if (options.signal?.aborted) {\n throw error\n }\n if (connectTimedOut || (error instanceof DOMException && error.name === 'TimeoutError')) {\n throw new LlmError(\n `Command Code API request to ${connection.apiBase}/alpha/generate did not respond within ${connection.requestTimeoutMs}ms`\n + `: ${errorChain(error)}`,\n 'TIMEOUT',\n { cause: error },\n )\n }\n // fetch wraps every transport failure (DNS, refused connection, TLS,\n // proxy, reset) in a bare `TypeError: fetch failed` whose actionable\n // detail lives on `cause`. Include the full chain so the failure reason\n // shown in the web UI (which renders only the message, not `cause`)\n // names the real root cause instead of a generic wrapper.\n throw new LlmError(\n `Command Code API request to ${connection.apiBase}/alpha/generate failed: ${errorChain(error)}`,\n 'TRANSPORT',\n { cause: error },\n )\n }\n\n if (!response.ok) {\n if (options.signal) {\n options.signal.removeEventListener('abort', onCallerAbort)\n }\n const errText = await response.text().catch(() => '')\n // Command Code folds several business rejections into 403 (plan limits,\n // CLI version, model access). Prefer the machine-readable `error.code`\n // when present; the status alone cannot distinguish them.\n let providerCode: string | undefined\n try {\n const parsed: unknown = JSON.parse(errText)\n if (isRecord(parsed) && isRecord(parsed.error)) {\n providerCode = stringValue(parsed.error.code)\n }\n } catch {\n // Plain-text bodies: rely on the status mapping below.\n }\n const detail = providerCode ?? `HTTP ${response.status}`\n if (response.status === 401) {\n // An invalid or missing credential is a config problem, not a\n // transport failure: retrying it identically cannot succeed.\n throw new LlmError(\n `Command Code API error 401 (${detail}): the API key is missing or invalid — check the`\n + ' key stored for COMMANDCODE_API_KEY (Models page) or the auth file',\n 'INVALID_CREDENTIAL',\n { status: 401 },\n )\n }\n throw new LlmError(\n `Command Code API error ${response.status}${detail === `HTTP ${response.status}` ? '' : ` (${detail})`}: ${errText.slice(0, 500)}`,\n response.status === 429 ? 'RATE_LIMIT' : 'PROVIDER_HTTP_ERROR',\n { status: response.status },\n )\n }\n if (!response.body) {\n if (options.signal) {\n options.signal.removeEventListener('abort', onCallerAbort)\n }\n throw new LlmError('Command Code API returned no response body', 'PROVIDER_PROTOCOL_ERROR')\n }\n\n // --- SSE/JSONL event stream -> harness StreamChunk protocol ---\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n\n // Stream idle watchdog: a generation that stalls this long has a dead\n // connection (the API keeps the socket open between reasoning/text\n // bursts). The default (300s) is deliberately generous: frontier\n // reasoning models (xhigh/max effort) can legitimately stay silent for\n // minutes while thinking, and the official CLI sets no idle cap at all —\n // an aggressive cap turns long thinking into spurious TIMEOUTs and\n // retries. reader.cancel() unblocks a pending read(), which the loop then\n // turns into a TIMEOUT failure instead of hanging forever.\n let idleTimer: ReturnType<typeof setTimeout> | undefined\n let idleFired = false\n const armIdle = () => {\n if (idleTimer !== undefined) clearTimeout(idleTimer)\n idleTimer = setTimeout(() => {\n idleFired = true\n void reader.cancel().catch(() => undefined)\n }, connection.streamIdleTimeoutMs)\n }\n const clearIdle = () => {\n if (idleTimer !== undefined) {\n clearTimeout(idleTimer)\n idleTimer = undefined\n }\n }\n\n // Block assembly state: at most one text block and one reasoning block\n // are open at a time (same assumption as the pi plugin).\n let nextIndex = 0\n let textIndex = -1\n let textContent = ''\n let reasoningIndex = -1\n let reasoningContent = ''\n let sawContent = false\n\n const closeText = function* (): Generator<StreamChunk> {\n if (textIndex < 0) return\n yield {\n type: 'block-end',\n index: textIndex,\n block: { type: 'text', text: textContent },\n }\n textIndex = -1\n textContent = ''\n }\n const closeReasoning = function* (): Generator<StreamChunk> {\n if (reasoningIndex < 0) return\n yield {\n type: 'block-end',\n index: reasoningIndex,\n block: { type: 'reasoning', text: reasoningContent },\n }\n reasoningIndex = -1\n reasoningContent = ''\n }\n\n const handleEvent = (event: unknown): StreamChunk[] => {\n const chunks: StreamChunk[] = []\n if (!isRecord(event)) return chunks\n\n switch (event.type) {\n case 'text-delta': {\n chunks.push(...closeReasoning())\n if (textIndex < 0) {\n textIndex = nextIndex++\n chunks.push({ type: 'block-start', index: textIndex, blockType: 'text' })\n }\n const delta = stringValue(event.text) ?? ''\n textContent += delta\n sawContent = true\n chunks.push({ type: 'text-delta', index: textIndex, text: delta })\n break\n }\n case 'reasoning-delta': {\n chunks.push(...closeText())\n if (reasoningIndex < 0) {\n reasoningIndex = nextIndex++\n chunks.push({ type: 'block-start', index: reasoningIndex, blockType: 'reasoning' })\n }\n const delta = stringValue(event.text) ?? ''\n reasoningContent += delta\n chunks.push({ type: 'reasoning-delta', index: reasoningIndex, text: delta })\n break\n }\n case 'reasoning-start':\n chunks.push(...closeText())\n break\n case 'reasoning-end':\n chunks.push(...closeReasoning())\n break\n case 'tool-call': {\n chunks.push(...closeText(), ...closeReasoning())\n const id = stringValue(event.toolCallId) ?? randomUUID()\n const name = stringValue(event.toolName) ?? ''\n const args = JSON.stringify(recordOrEmpty(event.input ?? event.args ?? event.arguments))\n const index = nextIndex++\n sawContent = true\n chunks.push(\n { type: 'block-start', index, blockType: 'tool-call' },\n { type: 'tool-call-delta', index, id: CallId(id), name, argumentsDelta: args },\n {\n type: 'block-end',\n index,\n block: { type: 'tool-call', id: CallId(id), name, arguments: args },\n },\n )\n break\n }\n case 'finish': {\n chunks.push(...closeText(), ...closeReasoning())\n const usage = isRecord(event.totalUsage) ? event.totalUsage : undefined\n if (usage) {\n const details = isRecord(usage.inputTokenDetails) ? usage.inputTokenDetails : undefined\n const totalInput = numberValue(usage.inputTokens) ?? 0\n const cacheRead = numberValue(details?.cacheReadTokens) ?? 0\n const cacheWrite = numberValue(details?.cacheWriteTokens) ?? 0\n // Harness TokenUsage counts are disjoint: uncached input only.\n const tokenUsage: TokenUsage = {\n inputTokens:\n numberValue(details?.noCacheTokens) ?? Math.max(0, totalInput - cacheRead - cacheWrite),\n outputTokens: numberValue(usage.outputTokens) ?? 0,\n cacheReadTokens: cacheRead,\n cacheWriteTokens: cacheWrite,\n }\n chunks.push({ type: 'usage', usage: tokenUsage })\n }\n chunks.push({ type: 'finish', reason: mapFinishReason(event.finishReason) })\n break\n }\n case 'error': {\n // Mirror the official CLI's stream-error classification\n // (readStreamErrorEvent + isStreamErrorRetryable in command-code's\n // cli.mjs): a stream error that is explicitly non-retryable, carries\n // a terminal marker (quota/plan/credits), or reports a non-retryable\n // HTTP status is a hard failure; anything else is a transient\n // mid-stream drop that the harness's default retry policy should\n // retry (SERVER is in the default retryable set, PROVIDER_STREAM_ERROR\n // is not). Without this, a server-side blip that the official CLI\n // silently recovers from fails the whole turn.\n const err = isRecord(event.error) ? event.error : undefined\n const detail = isRecord(event.error)\n ? (stringValue(event.error.message) ?? JSON.stringify(event.error))\n : (stringValue(event.error) ?? stringValue(event.message) ?? 'Stream error')\n const statusCode = err ? numberValue(err.statusCode) : undefined\n const isRetryable = err ? booleanValue(err.isRetryable) : undefined\n const retryableStatus = statusCode !== undefined && (statusCode === 429 || statusCode >= 500)\n const terminal = hasTerminalStreamMarker(detail)\n const retryable = isRetryable === true\n || (statusCode !== undefined ? retryableStatus : (isRetryable !== false && !terminal))\n if (!retryable) {\n throw new LlmError(\n `Command Code stream error: ${detail}`,\n 'PROVIDER_STREAM_ERROR',\n statusCode !== undefined ? { status: statusCode } : undefined,\n )\n }\n throw new LlmError(\n `Command Code stream error: ${detail}`,\n 'SERVER',\n statusCode !== undefined ? { status: statusCode } : undefined,\n )\n }\n }\n return chunks\n }\n\n try {\n let finished = false\n for (;;) {\n let read: ReadableStreamReadResult<Uint8Array>\n armIdle()\n try {\n read = await reader.read()\n } catch (error: unknown) {\n // A mid-stream transport failure (connection reset, TLS teardown)\n // surfaces here. Caller cancellation propagates as-is.\n if (options.signal?.aborted) throw error\n throw new LlmError(\n `Command Code API stream from ${connection.apiBase} failed while reading: ${errorChain(error)}`,\n 'TRANSPORT',\n { cause: error },\n )\n } finally {\n clearIdle()\n }\n const { done, value } = read\n if (done) {\n // The idle watchdog cancels the reader to unblock a stalled read;\n // cancel() resolves a pending read() as done, so a done here after\n // the watchdog fired is a timeout, not a normal stream end.\n if (idleFired) {\n throw new LlmError(\n `Command Code API stream from ${connection.apiBase} was idle for ${connection.streamIdleTimeoutMs}ms`\n + ' (no events) and was treated as a dead connection',\n 'TIMEOUT',\n )\n }\n if (buffer.trim()) for (const chunk of handleEvent(parseStreamEventLine(buffer))) yield chunk\n break\n }\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n for (const line of lines) {\n const chunks = handleEvent(parseStreamEventLine(line))\n for (const chunk of chunks) {\n yield chunk\n if (chunk.type === 'finish') finished = true\n }\n }\n if (finished) break\n }\n if (!finished) {\n // Stream ended without a finish event: close open blocks and\n // terminate according to the adapter contract (usage, then finish).\n yield* closeText()\n yield* closeReasoning()\n if (!sawContent) {\n throw new LlmError('Command Code returned an empty response', 'EMPTY_RESPONSE')\n }\n yield { type: 'finish', reason: { kind: 'stop' } }\n }\n } finally {\n clearIdle()\n if (options.signal) {\n options.signal.removeEventListener('abort', onCallerAbort)\n }\n await reader.cancel().catch(() => undefined)\n reader.releaseLock()\n }\n }\n}\n\nfunction mapFinishReason(reason: unknown): FinishReason {\n if (reason === 'tool-calls') return { kind: 'tool-calls' }\n if (\n reason === 'length' ||\n reason === 'max_tokens' ||\n reason === 'max-tokens' ||\n reason === 'max_output_tokens'\n ) {\n return { kind: 'max-tokens' }\n }\n return { kind: 'stop' }\n}\n","/**\n * `/commandcode` slash command — account usage dashboard.\n *\n * /commandcode show account, usage, and credit state\n * /commandcode status same as bare `/commandcode`\n *\n * Backed by the Command Code account endpoints the official CLI uses\n * (`/alpha/whoami`, `/alpha/usage/summary`, `/alpha/billing/credits`),\n * exposed through `CommandCodeAdapter.getUsage()`.\n *\n * @module dsh-commandcode-provider/commands\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\n// Type-only import that loads the module augmentation (`ctx.commands`).\nimport type { CommandDefinition } from '@deepseek-ai/dsh-commands'\nimport { CommandCodeAdapter } from './adapter.ts'\nimport type { CommandCodeConnectionOptions, CommandCodeUsageReport } from './adapter.ts'\n\n/** Everything the command needs beyond the adapter itself. */\nexport interface CommandCodeCommandDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {\n /** The registered adapter (for getUsage / listModels). */\n adapter: CommandCodeAdapter<C>\n}\n\n/** Format a dollar amount. */\nfunction money(value: number): string {\n return `$${value.toFixed(4)}`\n}\n\n/** Format a dollar amount compactly (2 decimals). */\nfunction moneyShort(value: number): string {\n return `$${value.toFixed(2)}`\n}\n\n/** Format a token count with thousands separators. */\n/** Format a large token count compactly (1.9亿 style). */\nfunction tokensCompact(value: number): string {\n if (value >= 1e9) return `${(value / 1e9).toFixed(1)}B`\n if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`\n if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`\n return String(value)\n}\n\n/** Format a millis timestamp as a local date. */\nfunction resetLabel(ms: number): string {\n if (ms <= 0) return 'n/a'\n return new Date(ms).toLocaleString()\n}\n\n/**\n * A 10-cell horizontal bar: `██████████` for 100%, `███░░░░░░░` for ~33%.\n * Handles caps of 0 (no limit) and out-of-range values.\n */\nfunction bar(used: number, cap: number): string {\n if (cap <= 0) return '—'\n const ratio = Math.max(0, Math.min(1, used / cap))\n const filled = Math.round(ratio * 10)\n return '█'.repeat(filled) + '░'.repeat(10 - filled)\n}\n\n/** Render the usage report as a structured, aligned, bar-chart text view. */\nfunction renderReport(report: CommandCodeUsageReport): string {\n const lines: string[] = []\n const account = report.account ? ` (${report.account.userName || report.account.name})` : ''\n\n lines.push(`📊 Command Code 用量${account}`, '')\n\n if (report.usage) {\n const u = report.usage\n lines.push(\n '── 请求 ──────────────────────────────',\n ` 💬 请求 ${u.completedCount} 次 / 失败 ${u.failedCount} 成功率 ${u.successRate}%`,\n ` 💰 花费 ${money(u.totalCost)} (${moneyShort(u.totalCredits)} credits)`,\n ` 🔤 Token ${tokensCompact(u.totalTokensIn)} 入 / ${tokensCompact(u.totalTokensOut)} 出`,\n '',\n )\n }\n\n if (report.credits) {\n const c = report.credits\n const monthlyPct = c.monthlyCredits > 0\n ? `${((c.monthlyCredits / (c.monthlyCredits + c.purchasedCredits)) * 100).toFixed(0)}%`\n : '—'\n lines.push(\n '── 信用 ──────────────────────────────',\n ` 💳 月额度 ${moneyShort(c.monthlyCredits)} (已购 ${moneyShort(c.purchasedCredits)} / 赠送 ${moneyShort(c.freeCredits)})`,\n ` └ ${bar(c.monthlyCredits, c.monthlyCredits + c.purchasedCredits)} ${monthlyPct}`,\n '',\n '── 窗口用量 ──────────────────────────',\n ` ⏱ 5 小时 ${moneyShort(c.fiveHour.used)} / ${moneyShort(c.fiveHour.cap)}${c.fiveHour.exceeded ? ' ⚠️ 超限!' : ''}`,\n ` └ ${bar(c.fiveHour.used, c.fiveHour.cap)} 重置 ${resetLabel(c.fiveHour.resetAt)}`,\n ` 📅 每周 ${moneyShort(c.weekly.used)} / ${moneyShort(c.weekly.cap)}${c.weekly.exceeded ? ' ⚠️ 超限!' : ''}`,\n ` └ ${bar(c.weekly.used, c.weekly.cap)} 重置 ${resetLabel(c.weekly.resetAt)}`,\n '',\n )\n }\n\n if (report.failures.length > 0) {\n lines.push(`⚠️ 部分端点失败: ${report.failures.join('; ')}`, '')\n }\n if (!report.account && !report.usage && !report.credits) {\n lines.push('(no data — check your API key)', '')\n }\n\n return lines.join('\\n').trimEnd()\n}\n\n/** The one registered `/commandcode` command. */\nexport function commandDefinition<C extends CommandCodeConnectionOptions>(\n deps: CommandCodeCommandDeps<C>,\n): CommandDefinition {\n const { adapter } = deps\n return {\n name: 'commandcode',\n description: 'Command Code account usage dashboard',\n input: { hint: '[status]' },\n handler: async () => {\n try {\n const report = await adapter.getUsage()\n return { kind: 'success', text: renderReport(report) }\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n kind: 'error',\n text: `Could not fetch Command Code usage: ${message}`,\n }\n }\n },\n }\n}\n\n/** Register the command on `ctx.commands` (called from the plugin entry). */\nexport function applyCommands<C extends CommandCodeConnectionOptions>(\n ctx: Context,\n deps: CommandCodeCommandDeps<C>,\n): void {\n ctx.commands.register(commandDefinition(deps))\n}\n","/**\n * dsh-commandcode-provider — DeepSeek Harness LLM provider plugin for Command\n * Code (unofficial; ported from pi-commandcode-provider@0.5.1).\n *\n * Registers the `commandcode` provider route on `ctx.llm` and declares it in\n * the configurable-provider directory, so the web Models page shows a\n * \"Command Code\" card with an API-key field and the model picker lists the\n * live Command Code model catalog. Connection facts resolve per request over\n * the optional `llm-commandcode` user-settings section and the credential\n * seam, so a changed key, endpoint, or cache path reaches the next request\n * without a restart.\n *\n * ```yaml\n * - id: llm-commandcode\n * name: \"@mars-sea/dsh-commandcode-provider\"\n * config:\n * apiKeyEnv: COMMANDCODE_API_KEY\n * ```\n *\n * The `name` is the full package specifier as installed in the profile's\n * node_modules: the loader imports it as a module, and pnpm links packages by\n * their true (scoped) name — a bare `dsh-commandcode-provider` fails to\n * resolve (ERR_MODULE_NOT_FOUND) and crashes the app on boot. The value must\n * be quoted in YAML: an unquoted scalar starting with `@` fails to parse.\n *\n * @module dsh-commandcode-provider\n */\n\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport z from '@deepseek-ai/schemastery'\nimport { MAX_TIMER_DELAY_MS } from '@deepseek-ai/dsh-timeout'\nimport { assertUsableApiKey, LlmError } from '@deepseek-ai/dsh-llm'\nimport { credentialRef, type CredentialRef } from '@deepseek-ai/dsh-credentials'\nimport { launchEnvironmentOf } from '@deepseek-ai/dsh-launch-environment'\nimport { installSettingsSection, settingsNamespace } from '@deepseek-ai/dsh-settings'\nimport { CommandCodeAdapter, DEFAULT_API_BASE, resolveAuthFileApiKey } from './adapter.ts'\nimport { DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_STREAM_IDLE_TIMEOUT_MS } from './adapter.ts'\nimport type { CommandCodeConnectionOptions } from './adapter.ts'\nimport { applyCommands } from './commands.ts'\n\nexport {\n COMMAND_CODE_CLI_VERSION,\n DEFAULT_API_BASE,\n DEFAULT_GENERATE_MAX_TOKENS,\n DEFAULT_MAX_OUTPUT_TOKENS,\n DEFAULT_REQUEST_TIMEOUT_MS,\n DEFAULT_STREAM_IDLE_TIMEOUT_MS,\n CommandCodeAdapter,\n KNOWN_EFFORTS,\n KNOWN_IMAGE_MODELS,\n KNOWN_THINKING_MODELS,\n KNOWN_PLANS,\n KNOWN_DEALS,\n PLAN_LABELS,\n PLAN_ORDER,\n capabilityDescription,\n compareByPlan,\n dealLabel,\n formatContext,\n planLabel,\n projectSlugFromPath,\n resolveAuthFileApiKey,\n} from './adapter.ts'\nexport type { CommandCodeAdapterDeps, CommandCodeConnectionOptions, CommandCodeUsageReport, ResolveAttachments } from './adapter.ts'\nexport { applyCommands, commandDefinition } from './commands.ts'\nexport type { CommandCodeCommandDeps } from './commands.ts'\n\nexport const name = 'llm-commandcode'\nexport const inject = ['llm']\n\nconst NS = settingsNamespace('llm-commandcode')\nconst DEFAULT_API_KEY_ENV = 'COMMANDCODE_API_KEY'\n\n/** The single provider route this plugin owns. */\nexport const PROVIDER = 'commandcode'\n/** Default models cache path (mirrors the pi plugin's on-disk cache). */\nexport const DEFAULT_MODELS_CACHE_PATH = join(homedir(), '.commandcode', 'models-cache.json')\n\n/**\n * Plugin config, validated by the same-named schemastery schema and doubling\n * as the `llm-commandcode` settings-section shape. Every field is optional:\n * a missing API key resolves through {@link Config.apiKeyEnv} at each request\n * (the web Models page writes it), with the official Command Code CLI auth\n * file (`~/.commandcode/auth.json`) as the last fallback.\n */\nexport interface Config {\n /** Credential reference (environment-variable name) resolved per request; defaults to `COMMANDCODE_API_KEY`. */\n apiKeyEnv?: string\n /** Literal API key override (composition config only); takes precedence over `apiKeyEnv`. */\n apiKey?: string\n /** API base; defaults to the public Command Code Provider API. */\n apiBase?: string\n /** Working directory reported to the API; defaults to the process cwd. */\n workingDir?: string\n /** Model catalog cache path; defaults to `~/.commandcode/models-cache.json`. */\n modelsCachePath?: string\n /** Milliseconds to wait for the generate response's first byte; defaults to 60s. */\n requestTimeoutMs?: number\n /** Milliseconds a stream may stall before being treated as a dead connection; defaults to 300s. */\n streamIdleTimeoutMs?: number\n}\n\nexport const Config: z<Config> = z.object({\n apiKeyEnv: z.string().role('credential-ref').default(DEFAULT_API_KEY_ENV),\n apiKey: z.string(),\n apiBase: z.string(),\n workingDir: z.string(),\n modelsCachePath: z.string(),\n requestTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS),\n streamIdleTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS),\n})\n\n/** One resolution's complete request facts: connection plus credential reference. */\nexport interface ResolvedCommandCodeOptions extends CommandCodeConnectionOptions {\n apiKeyEnv: CredentialRef\n}\n\n/**\n * The one explicit resolve step from raw config to validated connection\n * facts. Programmatic construction may bypass Schemastery normalization, so\n * every default is re-judged here — for the composition entry at load and for\n * each settings snapshot at its first use.\n */\nexport function resolveAdapterOptions(config: Config): ResolvedCommandCodeOptions {\n return {\n apiKeyEnv: credentialRef(config.apiKeyEnv ?? DEFAULT_API_KEY_ENV),\n apiBase: config.apiBase ?? DEFAULT_API_BASE,\n workingDir: config.workingDir ?? process.cwd(),\n modelsCachePath: config.modelsCachePath ?? DEFAULT_MODELS_CACHE_PATH,\n requestTimeoutMs: config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n streamIdleTimeoutMs: config.streamIdleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS,\n }\n}\n\nexport function apply(ctx: Context, config: Config): void {\n let current: () => Config = () => config\n let lastRaw: Config | undefined\n let lastGood: ResolvedCommandCodeOptions | undefined\n const options = (): ResolvedCommandCodeOptions => {\n const raw = current()\n if (raw === lastRaw && lastGood !== undefined) return lastGood\n const next = resolveAdapterOptions(raw)\n lastRaw = raw\n lastGood = next\n return next\n }\n options()\n\n const resolveApiKey = async (connection: ResolvedCommandCodeOptions): Promise<string> => {\n // 1. A literal key in composition config wins outright.\n const literal = current().apiKey\n if (literal) return assertUsableApiKey(literal, 'llm-commandcode', 'config.apiKey')\n // 2. The credential seam (web Models page) or the trusted environment.\n const ref = connection.apiKeyEnv\n const credentials = ctx.get('credentials')\n if (credentials !== undefined) {\n const hit = await credentials.resolve(ref)\n if (hit !== undefined) return assertUsableApiKey(hit.value, 'llm-commandcode', ref)\n } else {\n const ambient = launchEnvironmentOf(ctx).get(ref)\n if (ambient !== undefined && ambient.value.length > 0) {\n return assertUsableApiKey(ambient.value, 'llm-commandcode', ref)\n }\n }\n // 3. Last resort: reuse the official Command Code CLI login (~/.commandcode/auth.json).\n const authFileKey = resolveAuthFileApiKey()\n if (authFileKey) return assertUsableApiKey(authFileKey, 'llm-commandcode', '~/.commandcode/auth.json')\n throw new LlmError(\n `llm-commandcode: no API key for provider route \"${PROVIDER}\"; store ${ref} through the`\n + ' credentials service (the web Models page writes it), export it in the launching'\n + ' environment, set config.apiKey, or run `command-code login` to write'\n + ' ~/.commandcode/auth.json',\n 'MISSING_CREDENTIAL',\n )\n }\n\n const adapter = new CommandCodeAdapter({\n options,\n resolveApiKey,\n // The durable attachment service carries image bytes referenced by\n // ImageBlock; resolved lazily only when a request actually has images.\n resolveAttachments: () => {\n const attachments = ctx.get('attachments')\n return attachments === undefined ? undefined : attachments\n },\n })\n // The Models page card: a configurable provider with a settings address.\n // settingsPath [] means the whole `llm-commandcode` section configures it.\n ctx.llm.registerConfigurableProviders([\n { provider: PROVIDER, displayName: 'Command Code', settingsNs: NS, settingsPath: [] },\n ])\n // The live route: this is what makes models requestable under `commandcode`.\n ctx.llm.registerAdapter([PROVIDER], adapter)\n\n // The /commandcode usage command rides the optional `commands` service: a\n // child fiber injects it, so it registers whenever the profile mounts\n // dsh-commands and the fiber simply never activates when it does not.\n ctx.inject(['commands'], (commandCtx) => {\n applyCommands(commandCtx, { adapter })\n })\n\n installSettingsSection(ctx, NS, Config, config, {\n setSource: (source) => {\n current = source\n },\n // Everything the adapter reads is resolved per request, so a settings\n // change needs no registration-level action.\n onChange: () => {},\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/adapter.ts","../src/commands.ts","../src/index.ts"],"sourcesContent":["/**\n * DeepSeek Harness LLM adapter for the Command Code Provider API.\n *\n * Ported from pi-commandcode-provider@0.5.1 (MIT). This is an unofficial,\n * community-maintained integration; you need your own Command Code account\n * and API key or subscription, and Command Code's terms apply.\n *\n * Wire protocol (reverse-engineered by the pi plugin, command-code@1.26.0):\n * POST {apiBase}/alpha/generate\n * body: { config, memory, taste, skills, params: { model, messages, tools,\n * system, max_tokens, temperature, stream, reasoning_effort? }, threadId }\n * SSE-ish JSONL events: text-delta | reasoning-start/delta/end | tool-call\n * | tool-result | finish | error\n * Model catalog: GET {apiBase}/provider/v1/models -> { object: 'list', data: [...] }\n *\n * The adapter is deliberately free of cordis/schemastery: it receives a\n * per-request options thunk and an API-key resolver from the plugin entry\n * (src/index.ts), so a settings change reaches the very next request.\n */\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { randomUUID } from 'node:crypto'\n\nimport type { AttachmentStore, ImageAttachmentRef } from '@deepseek-ai/dsh-attachment'\n\nimport {\n attributionHeaders,\n CallId,\n LlmAdapter,\n LlmError,\n ReasoningEffortId,\n errorChain,\n resolveRetryPolicy,\n type ResolvedRetryPolicy,\n type ContentBlock,\n type FinishReason,\n type GenerateOptions,\n type LlmModelInfo,\n type LlmResolvedModelInfo,\n type Message,\n type StreamChunk,\n type TokenUsage,\n} from '@deepseek-ai/dsh-llm'\n\n// ---------------------------------------------------------------------------\n// Static capability snapshot (from the official command-code@1.26.0 bundled\n// model catalog, dist/cli.mjs). The Provider API does not expose reasoning\n// metadata; models omitted here let Command Code choose their reasoning\n// depth, matching the official CLI.\n// ---------------------------------------------------------------------------\n\nexport const KNOWN_EFFORTS: Readonly<Record<string, readonly string[]>> = {\n // Re-verified against the authoritative command-code@1.26.0 bundled model\n // table (dist/cli.mjs, the 'ZA' object): exactly these models carry\n // 'reasoningEfforts'. Models marked 'reasoning:!0' without 'reasoningEfforts'\n // (e.g. Kimi K3, MiniMax M3, Muse Spark 1.2, Tencent Hy3, GLM-5/5.1/5.2-Fast)\n // think automatically and are absent here - the CLI omits 'reasoning_effort'\n // for them, so the picker must not offer a selector. Do NOT add entries from\n // the OAuth provider tables (anthropic/openai) - only the Provider-API 'ZA'\n // table is authoritative for this plugin's route.\n 'Qwen/Qwen3.8-Max': ['low', 'medium', 'xhigh'],\n 'claude-fable-5': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-opus-4-7': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-opus-4-8': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-opus-5': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-sonnet-4-6': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'claude-sonnet-5': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'deepseek/deepseek-v4-flash': ['high', 'max'],\n 'deepseek/deepseek-v4-pro': ['high', 'max'],\n 'google/gemini-3.1-flash-lite': ['low', 'medium', 'high'],\n 'google/gemini-3.5-flash': ['low', 'medium', 'high'],\n 'google/gemini-3.5-flash-lite': ['low', 'medium', 'high'],\n 'google/gemini-3.6-flash': ['low', 'medium', 'high'],\n 'google/gemini-3.7-flash': ['low', 'medium', 'high'],\n 'gpt-5.3-codex': ['low', 'medium', 'high', 'xhigh'],\n 'gpt-5.4': ['low', 'medium', 'high', 'xhigh'],\n 'gpt-5.4-mini': ['low', 'medium', 'high'],\n 'gpt-5.5': ['low', 'medium', 'high', 'xhigh'],\n 'gpt-5.6-luna': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'gpt-5.6-sol': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'gpt-5.6-terra': ['low', 'medium', 'high', 'xhigh', 'max'],\n 'sakana/fugu-ultra': ['high', 'xhigh'],\n 'xai/grok-4.5': ['low', 'medium', 'high'],\n 'xai/grok-4.6': ['low', 'medium', 'high', 'xhigh'],\n 'zai-org/GLM-5.2': ['high', 'max'],\n 'zai-org/GLM-5.3': ['low', 'high', 'max'],\n}\n\n/**\n * Models whose Capabilities include Vision, per the official Command Code\n * model registry (`https://commandcode.ai/docs/reference/cli/models`, generated\n * from the same registry as `cmd --list-models` / the `/model` picker).\n *\n * The Provider API does not expose modality metadata, so this snapshot is the\n * source of truth for image-input gating. Command Code's own CLI falls back to\n * a client-side VISION side-call for text-only models; this adapter does not\n * reproduce that interactive feature, so images sent to a model outside this\n * list are refused loudly (`UNSUPPORTED_CONTENT`) instead of being dropped or\n * sent to a model that cannot read them.\n *\n * Keep in sync with the official registry when new models ship (see the\n * dsh-commandcode-upstream skill).\n */\nexport const KNOWN_IMAGE_MODELS: ReadonlySet<string> = new Set([\n 'MiniMaxAI/MiniMax-M3',\n 'Qwen/Qwen3.6-Plus',\n 'Qwen/Qwen3.7-Flash',\n 'Qwen/Qwen3.7-Plus',\n 'Qwen/Qwen3.8-Max',\n 'claude-fable-5',\n 'claude-haiku-4-5-20251001',\n 'claude-opus-4-7',\n 'claude-opus-4-8',\n 'claude-opus-5',\n 'claude-sonnet-4-6',\n 'claude-sonnet-5',\n 'google/gemini-3.1-flash-lite',\n 'google/gemini-3.5-flash',\n 'google/gemini-3.5-flash-lite',\n 'google/gemini-3.6-flash',\n 'google/gemini-3.7-flash',\n 'gpt-5.3-codex',\n 'gpt-5.4',\n 'gpt-5.4-mini',\n 'gpt-5.5',\n 'gpt-5.6-luna',\n 'gpt-5.6-sol',\n 'gpt-5.6-terra',\n 'meta/muse-spark-1.1',\n 'meta/muse-spark-1.2',\n 'meta/muse-spark-1.2-contributor',\n 'moonshotai/Kimi-K2.5',\n 'moonshotai/Kimi-K2.6',\n 'moonshotai/Kimi-K2.7-Code',\n 'moonshotai/Kimi-K2.7-Code-Highspeed',\n 'moonshotai/Kimi-K3',\n 'sakana/fugu-ultra',\n 'stepfun/Step-3.7-Flash',\n 'thinkingmachines/inkling',\n 'thinkingmachines/inkling-small',\n 'xai/grok-4.5',\n 'xiaomi/mimo-v2.5',\n])\n\n/**\n * Models the official CLI's model table (`ZA` in command-code@1.26.0) marks\n * `reasoning:!0` but defines no selectable `reasoning_effort` levels — they\n * think automatically, with Command Code driving the depth. This is the\n * authoritative \"thinks, effort not adjustable\" set: `KNOWN_EFFORTS` (which\n * mirrors the CLI's effort map exactly) stays the sole source for selectable\n * effort levels, and this snapshot is not surfaced in the picker's compact\n * description — it exists for programmatic consumers.\n *\n * Source: the command-code@1.26.0 bundled model table (dist/cli.mjs, the `ZA`\n * object), cross-checked with https://commandcode.ai/docs/reference/cli/models.\n * Keep in sync via the dsh-commandcode-upstream skill.\n */\nexport const KNOWN_THINKING_MODELS: ReadonlySet<string> = new Set([\n 'MiniMaxAI/MiniMax-M3',\n 'Qwen/Qwen3.6-Max-Preview',\n 'Qwen/Qwen3.6-Plus',\n 'Qwen/Qwen3.7-Flash',\n 'Qwen/Qwen3.7-Max',\n 'Qwen/Qwen3.7-Plus',\n 'moonshotai/Kimi-K3',\n 'moonshotai/Kimi-K2.7-Code',\n 'moonshotai/Kimi-K2.7-Code-Highspeed',\n 'stepfun/Step-3.5-Flash',\n 'stepfun/Step-3.7-Flash',\n 'tencent/hy3-paid',\n 'nvidia/nemotron-3-ultra-550b-a55b',\n 'thinkingmachines/inkling',\n 'thinkingmachines/inkling-small',\n 'poolside/laguna-s-2.1-free',\n 'meta/muse-spark-1.1',\n 'meta/muse-spark-1.2',\n 'meta/muse-spark-1.2-contributor',\n])\n\n/**\n * The minimum subscription plan a model is included in, per the official plan\n * pages (`/docs/plans/go`, `/docs/plans/goat`, `/docs/plans/pro`, `/docs/plans/max`\n * and `/docs/resources/pricing-limits`). Each plan's model list is a superset of\n * the one below it: Go ⊂ GOAT ⊂ Pro ⊂ Provider/Max. Models absent from every\n * plan list (Claude Opus/Fable, Fugu Ultra) are Provider-tier.\n *\n * The Provider API exposes no plan metadata, so this snapshot is the source of\n * truth for the picker's plan annotation — it answers \"which plan do I need to\n * actually use this model?\" at a glance. Plan labels use the official tier\n * names (`Go`, `GOAT`, `Pro`, `Provider`), with `Max` implying Provider.\n *\n * Keep in sync with the official plan pages when they change (see the\n * dsh-commandcode-upstream skill).\n */\nexport const KNOWN_PLANS: Readonly<Record<string, string>> = {\n // --- Go (33) ---\n 'MiniMaxAI/MiniMax-M2.5': 'go',\n 'MiniMaxAI/MiniMax-M2.7': 'go',\n 'MiniMaxAI/MiniMax-M3': 'go',\n 'Qwen/Qwen3.6-Max-Preview': 'go',\n 'Qwen/Qwen3.6-Plus': 'go',\n 'Qwen/Qwen3.7-Flash': 'go',\n 'Qwen/Qwen3.7-Max': 'go',\n 'Qwen/Qwen3.7-Plus': 'go',\n 'Qwen/Qwen3.8-Max': 'go',\n 'deepseek/deepseek-v4-flash': 'go',\n 'deepseek/deepseek-v4-pro': 'go',\n 'gpt-5.6-luna': 'go',\n 'meta/muse-spark-1.2-contributor': 'go',\n 'moonshotai/Kimi-K2.5': 'go',\n 'moonshotai/Kimi-K2.6': 'go',\n 'moonshotai/Kimi-K2.7-Code': 'go',\n 'moonshotai/Kimi-K2.7-Code-Highspeed': 'go',\n 'moonshotai/Kimi-K3': 'go',\n 'nvidia/nemotron-3-ultra-550b-a55b': 'go',\n 'poolside/laguna-s-2.1-free': 'go',\n 'stepfun/Step-3.5-Flash': 'go',\n 'stepfun/Step-3.7-Flash': 'go',\n 'tencent/hy3-paid': 'go',\n 'thinkingmachines/inkling': 'go',\n 'thinkingmachines/inkling-small': 'go',\n 'xai/grok-4.5': 'go',\n 'xiaomi/mimo-v2.5': 'go',\n 'xiaomi/mimo-v2.5-pro': 'go',\n 'zai-org/GLM-5': 'go',\n 'zai-org/GLM-5.1': 'go',\n 'zai-org/GLM-5.2': 'go',\n 'zai-org/GLM-5.2-Fast': 'go',\n 'zai-org/GLM-5.3': 'go',\n // --- GOAT (3 more) ---\n 'google/gemini-3.7-flash': 'goat',\n 'meta/muse-spark-1.2': 'goat',\n 'xai/grok-4.6': 'goat',\n // --- Pro (14 more) ---\n 'claude-haiku-4-5-20251001': 'pro',\n 'claude-sonnet-4-6': 'pro',\n 'claude-sonnet-5': 'pro',\n 'google/gemini-3.1-flash-lite': 'pro',\n 'google/gemini-3.5-flash': 'pro',\n 'google/gemini-3.5-flash-lite': 'pro',\n 'google/gemini-3.6-flash': 'pro',\n 'gpt-5.3-codex': 'pro',\n 'gpt-5.4': 'pro',\n 'gpt-5.4-mini': 'pro',\n 'gpt-5.5': 'pro',\n 'gpt-5.6-sol': 'pro',\n 'gpt-5.6-terra': 'pro',\n 'meta/muse-spark-1.1': 'pro',\n // --- Provider / Max (5) ---\n 'claude-fable-5': 'provider',\n 'claude-opus-4-7': 'provider',\n 'claude-opus-4-8': 'provider',\n 'claude-opus-5': 'provider',\n 'sakana/fugu-ultra': 'provider',\n}\n\n/** Official display labels for each plan tier. */\nexport const PLAN_LABELS: Readonly<Record<string, string>> = {\n go: 'Go',\n goat: 'GOAT',\n pro: 'Pro',\n provider: 'Provider',\n max: 'Max',\n}\n\n/**\n * Plan-tier sort weights, low to high. Models outside the snapshot (unknown\n * plans) sort after every known tier, keeping known models predictable.\n */\nexport const PLAN_ORDER: Readonly<Record<string, number>> = {\n go: 0,\n goat: 1,\n pro: 2,\n provider: 3,\n max: 4,\n}\n\n/**\n * Comparator for the model picker: sort by plan tier (lowest first), then by\n * model name, then by id as a tiebreak. Models with no known plan sort last.\n */\nexport function compareByPlan(\n a: { id: string; name: string },\n b: { id: string; name: string },\n): number {\n const pa = PLAN_ORDER[KNOWN_PLANS[a.id] ?? ''] ?? Number.MAX_SAFE_INTEGER\n const pb = PLAN_ORDER[KNOWN_PLANS[b.id] ?? ''] ?? Number.MAX_SAFE_INTEGER\n if (pa !== pb) return pa - pb\n const nameDiff = a.name.localeCompare(b.name)\n if (nameDiff !== 0) return nameDiff\n return a.id.localeCompare(b.id)\n}\n\n/**\n * Active pricing deals per the official pricing page\n * (`/docs/resources/pricing-limits#deals`). Each entry records the model's\n * promotional label and — critically — when it expires, so the picker never\n * shows a stale discount after the plugin's snapshot has gone out of date.\n *\n * - `expiresAt` is an ISO timestamp. When it is in the past (checked at\n * render time against `Date.now()`), the deal label is hidden until the\n * snapshot is refreshed from the official page. `undefined` means\n * \"no expiry\" (permanent).\n * - `free` marks models whose requests cost no credits (Laguna S 2.1), shown\n * as a `FREE` badge; it degrades to a plain discount once the deal lapses.\n *\n * Keep in sync with the official pricing page when deals change (see the\n * dsh-commandcode-upstream skill).\n */\nexport interface KnownDeal {\n /** Promotional label, e.g. \"50% off\" or \"2× usage\". */\n label: string\n /** Deal end date (ISO). `undefined` = permanent / no expiry. */\n expiresAt?: string\n /** Model is free (requests cost no credits). */\n free?: boolean\n}\n\nexport const KNOWN_DEALS: Readonly<Record<string, KnownDeal>> = {\n // Note: DeepSeek V4 Pro's 75%-off deal was retired on 2026-08-16 16:00 UTC\n // when DeepSeek moved to peak/off-peak pricing (see KNOWN_PEAK_PRICING); it\n // was removed from this snapshot once it lapsed, per the skill's rule that\n // expired deals are dropped from the official page.\n 'google/gemini-3.7-flash': { label: '50% off', expiresAt: '2026-12-31T23:59:59Z' },\n 'MiniMaxAI/MiniMax-M3': { label: '50% off' },\n 'xiaomi/mimo-v2.5-pro': { label: '99% off' },\n 'xiaomi/mimo-v2.5': { label: '98% off' },\n 'poolside/laguna-s-2.1-free': { label: 'FREE', free: true },\n}\n\n/**\n * Models with time-of-day (peak/off-peak) pricing, per the official pricing\n * page (`/docs/resources/pricing-limits`). Since 2026-08-16 16:00 UTC, DeepSeek\n * charges by the hour: peak hours are 01:00–04:00 and 06:00–10:00 UTC (7h/day,\n * full price); the other 17 hours are off-peak at half price. The picker shows\n * the *current* state as a compact label (`Peak`/`Half`) matching the English\n * noun style of the other markers (`Image`, `FREE`), so a developer can tell at\n * a glance whether calling the model right now is cheap or expensive.\n *\n * Keep in sync with the official pricing page when the model set or the peak\n * windows change (see the dsh-commandcode-upstream skill).\n */\nexport const KNOWN_PEAK_PRICING: ReadonlySet<string> = new Set([\n 'deepseek/deepseek-v4-pro',\n 'deepseek/deepseek-v4-flash',\n])\n\n/** Peak hours (UTC, hour-of-day range end-exclusive): 01–03 and 06–09. */\nconst PEAK_HOUR_RANGES: ReadonlyArray<readonly [number, number]> = [\n [1, 4],\n [6, 10],\n]\n\n/**\n * Whether `now` (defaults to `Date.now()`) falls in a peak-pricing hour for\n * time-of-day-priced models. `undefined` for models outside the snapshot.\n */\nexport function peakPricingState(\n modelId: string,\n now: number = Date.now(),\n): 'peak' | 'off-peak' | undefined {\n if (!KNOWN_PEAK_PRICING.has(modelId)) return undefined\n const hour = new Date(now).getUTCHours()\n const inPeak = PEAK_HOUR_RANGES.some(([start, end]) => hour >= start && hour < end)\n return inPeak ? 'peak' : 'off-peak'\n}\n\n/**\n * Compact label for the current peak/off-peak state: `Peak` (full price) or\n * `Half` (off-peak, half price). These English nouns match the picker's other\n * markers (`Go`, `Image`, `FREE`), and since they appear only on time-of-day\n * priced models they double as a \"priced by the hour\" signal. Returns undefined\n * for models without time-of-day pricing.\n */\nexport function peakPricingLabel(\n modelId: string,\n now: number = Date.now(),\n): string | undefined {\n const state = peakPricingState(modelId, now)\n if (state === undefined) return undefined\n return state === 'peak' ? 'Peak' : 'Half'\n}\n\nexport const COMMAND_CODE_CLI_VERSION = '1.26.0'\nexport const DEFAULT_API_BASE = 'https://api.commandcode.ai'\nexport const DEFAULT_GENERATE_MAX_TOKENS = 64_000\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 65_536\nexport const MODELS_TIMEOUT_MS = 10_000\n/** Head-of-request timeout: how long to wait for the first response byte. */\nexport const DEFAULT_REQUEST_TIMEOUT_MS = 60_000\n/** Stream idle timeout: a generation that stalls this long is a dead connection. */\nexport const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 300_000\nconst MODEL_CACHE_VERSION = 1\n\n// ---------------------------------------------------------------------------\n// Small helpers (ported from converters.ts / models.ts)\n// ---------------------------------------------------------------------------\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Official display label for a model's minimum plan, or undefined for models\n * outside the snapshot (e.g. future catalog additions).\n */\nexport function planLabel(modelId: string): string | undefined {\n const plan = KNOWN_PLANS[modelId]\n return plan === undefined ? undefined : PLAN_LABELS[plan]\n}\n\n/**\n * The active deal label for a model, or undefined when the model has no deal\n * or the deal has expired. Expiry is judged against `now` (defaults to\n * `Date.now()`), so a snapshot that has gone stale stops showing its discount\n * the moment the official end date passes — the user never believes a lapsed\n * deal is still live. Permanent deals (no `expiresAt`) never lapse.\n */\nexport function dealLabel(modelId: string, now: number = Date.now()): string | undefined {\n const deal = KNOWN_DEALS[modelId]\n if (deal === undefined) return undefined\n if (deal.expiresAt !== undefined && now >= Date.parse(deal.expiresAt)) return undefined\n return deal.label\n}\n\n/**\n * Compact human-readable context window, e.g. `1_000_000 -> \"1M\"`,\n * `256_000 -> \"256K\"`, `262_144 -> \"256K\"` (floor to the nearest K).\n * Returns undefined for unknown/absent sizes.\n */\nexport function formatContext(contextWindow: number | undefined): string | undefined {\n if (contextWindow === undefined || !Number.isFinite(contextWindow) || contextWindow <= 0) {\n return undefined\n }\n if (contextWindow >= 1_000_000) {\n const m = contextWindow / 1_000_000\n // Round to one decimal only when it adds information: 1_048_576 -> \"1M\",\n // 1_050_000 -> \"1.1M\".\n const rounded = Math.round(m * 10) / 10\n return `${Number.isInteger(rounded) ? rounded : rounded.toFixed(1)}M`\n }\n return `${Math.floor(contextWindow / 1_000)}K`\n}\n\n/**\n * Compact one-line summary for the model picker: plan tier, then any active\n * deal (discount or FREE), then the current peak/off-peak state (`Peak`/`Half`)\n * for time-of-day-priced models, then `Image` for Vision-capable models, then\n * the context window. Text-only models simply omit the Image marker — \"Text\n * only\" adds nothing the picker needs to show.\n */\nexport function capabilityDescription(\n modelId: string,\n contextWindow?: number,\n now: number = Date.now(),\n): string {\n const parts: string[] = []\n const plan = planLabel(modelId)\n if (plan !== undefined) parts.push(plan)\n const deal = dealLabel(modelId, now)\n if (deal !== undefined) parts.push(deal)\n const peak = peakPricingLabel(modelId, now)\n if (peak !== undefined) parts.push(peak)\n if (KNOWN_IMAGE_MODELS.has(modelId)) parts.push('Image')\n const ctx = formatContext(contextWindow)\n if (ctx !== undefined) parts.push(ctx)\n return parts.join(' · ')\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined\n}\n\nfunction numberValue(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined\n}\n\nfunction booleanValue(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined\n}\n\n/**\n * Terminal stream-error markers from the official CLI (`Xw` in command-code's\n * cli.mjs): these always mean \"retrying cannot succeed\", so the adapter must\n * not classify them as transient server errors.\n */\nconst TERMINAL_STREAM_ERROR_MARKERS = [\n 'premium_credits_exhausted',\n 'model_not_in_plan',\n 'insufficient credits',\n]\n\nfunction hasTerminalStreamMarker(message: string): boolean {\n const lower = message.toLowerCase()\n return TERMINAL_STREAM_ERROR_MARKERS.some((marker) => lower.includes(marker))\n}\n\nfunction recordOrEmpty(value: unknown): Record<string, unknown> {\n if (isRecord(value)) return value\n if (typeof value === 'string') {\n try {\n const parsed: unknown = JSON.parse(value)\n if (isRecord(parsed)) return parsed\n } catch {\n // Some providers stream incomplete JSON argument fragments.\n }\n }\n return {}\n}\n\nexport function projectSlugFromPath(pathName: string): string {\n const slug = pathName\n .toLowerCase()\n .replace(/^[a-z]:/i, '')\n .replace(/[^a-z0-9]+/g, '-')\n // Trim leading/trailing separators. This must stay linear: the classic\n // `/^-+|-+$/` form is ambiguous — on `a<200k dashes>b` the unanchored\n // `-+$` retries every start position, giving O(n^2) matching (CodeQL\n // js/polynomial-redos). The negative lookbehind `(?<!-)` restricts `-+$`\n // to the first dash of the trailing run, so only one start position is\n // tried. Verified empirically: ~14.5s -> ~0ms on a 200k-dash input.\n .replace(/^-+|(?<!-)-+$/g, '')\n return slug || 'project'\n}\n\nfunction parseStreamEventLine(line: string): unknown | undefined {\n let trimmed = line.trim()\n if (!trimmed || trimmed.startsWith(':') || trimmed.startsWith('event:')) return undefined\n if (trimmed.startsWith('data:')) trimmed = trimmed.slice(5).trim()\n if (!trimmed || trimmed === '[DONE]') return undefined\n try {\n return JSON.parse(trimmed) as unknown\n } catch {\n return undefined\n }\n}\n\n// ---------------------------------------------------------------------------\n// Credential fallback from the official Command Code CLI auth file. Used as\n// the last fallback by the plugin entry, so a user who already logged in with\n// `command-code login` can reuse that credential. Only the official CLI's own\n// file is read — pi/OMP auth files are intentionally not scanned, so their\n// credentials and formats cannot surprise this adapter.\n// ---------------------------------------------------------------------------\n\n/** Extract the key from the CLI's nested credential records (`command-code`). */\nfunction apiKeyFromCredentialRecord(value: unknown): string | undefined {\n if (!isRecord(value)) return undefined\n const type = stringValue(value.type)\n if (type === 'api') return stringValue(value.key)\n if (type === 'oauth') return stringValue(value.access)\n return stringValue(value.key) ?? stringValue(value.access)\n}\n\n/** Read a usable Command Code credential from the official CLI auth file. */\nexport function resolveAuthFileApiKey(): string | undefined {\n const authPath = join(homedir(), '.commandcode', 'auth.json')\n try {\n if (!existsSync(authPath)) return undefined\n const parsed: unknown = JSON.parse(readFileSync(authPath, 'utf-8'))\n if (!isRecord(parsed)) return undefined\n const direct = stringValue(parsed.apiKey) ?? stringValue(parsed.commandcode)\n if (direct) return direct\n const nested =\n apiKeyFromCredentialRecord(parsed.commandcode) ??\n apiKeyFromCredentialRecord(parsed['command-code'])\n return nested\n } catch {\n // Ignore malformed or unreadable auth file.\n }\n return undefined\n}\n\n// ---------------------------------------------------------------------------\n// Model catalog discovery with on-disk cache fallback (ported from models.ts)\n// ---------------------------------------------------------------------------\n\ninterface CommandCodeModel {\n id: string\n name: string\n contextWindow: number\n maxTokens: number\n}\n\nfunction parseCatalogResponse(value: unknown): CommandCodeModel[] {\n if (!isRecord(value) || value.object !== 'list' || !Array.isArray(value.data)) {\n throw new LlmError('Unexpected Command Code models response shape', 'PROVIDER_PROTOCOL_ERROR')\n }\n const models: CommandCodeModel[] = []\n for (const entry of value.data) {\n if (!isRecord(entry)) continue\n const id = stringValue(entry.id)\n const name = stringValue(entry.name)\n const contextLength = numberValue(entry.context_length)\n if (!id || !name || !contextLength || contextLength <= 0) continue\n models.push({\n id,\n name,\n contextWindow: contextLength,\n maxTokens: Math.min(contextLength, DEFAULT_MAX_OUTPUT_TOKENS),\n })\n }\n if (models.length === 0) {\n throw new LlmError('Command Code returned an empty model catalog', 'PROVIDER_PROTOCOL_ERROR')\n }\n return models\n}\n\nasync function readModelsCache(cachePath: string): Promise<CommandCodeModel[]> {\n const parsed: unknown = JSON.parse(await readFile(cachePath, 'utf-8'))\n if (!isRecord(parsed) || parsed.version !== MODEL_CACHE_VERSION || !Array.isArray(parsed.models)) {\n throw new Error(`Invalid model cache at ${cachePath}`)\n }\n return parsed.models as CommandCodeModel[]\n}\n\nasync function writeModelsCache(cachePath: string, models: CommandCodeModel[]): Promise<void> {\n await mkdir(dirname(cachePath), { recursive: true })\n const tmp = `${cachePath}.${process.pid}.tmp`\n try {\n await writeFile(tmp, `${JSON.stringify({ version: MODEL_CACHE_VERSION, models }, null, 2)}\\n`, {\n encoding: 'utf-8',\n mode: 0o600,\n })\n await rename(tmp, cachePath)\n } finally {\n await rm(tmp, { force: true }).catch(() => undefined)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Message conversion: harness Message[] -> Command Code wire messages.\n// Reasoning blocks are intentionally NOT replayed (matches the pi plugin and\n// the official CLI: prior private reasoning must not leak into later turns).\n// Only tool calls with a paired tool result are replayed.\n// ---------------------------------------------------------------------------\n\nfunction pairedToolCallIds(messages: readonly Message[]): Set<string> {\n const callIds = new Set<string>()\n const resultIds = new Set<string>()\n for (const message of messages) {\n for (const block of message.content) {\n if (message.role === 'assistant' && block.type === 'tool-call') callIds.add(block.id)\n if (block.type === 'tool-result') resultIds.add(block.toolCallId)\n }\n }\n return new Set([...callIds].filter((id) => resultIds.has(id)))\n}\n\nfunction blockText(block: ContentBlock): string {\n return block.type === 'text' || block.type === 'reasoning' ? block.text : ''\n}\n\nfunction toolResultText(block: Extract<ContentBlock, { type: 'tool-result' }>): string {\n return block.content.map(blockText).filter(Boolean).join('\\n')\n}\n\nfunction hasImageContent(message: Message): boolean {\n const check = (blocks: readonly ContentBlock[]): boolean =>\n blocks.some(\n (b) => b.type === 'image' || (b.type === 'tool-result' && check(b.content)),\n )\n return check(message.content)\n}\n\n/**\n * Convert one image reference to the Command Code wire format, as the official\n * CLI does: `{ type: 'image', source: { type: 'base64', media_type, data } }`.\n * Bytes come from the durable attachment service; the media type is the one\n * verified at save time.\n */\nasync function imageToCommandCode(\n ref: ImageAttachmentRef,\n readImage: (ref: ImageAttachmentRef) => Promise<Uint8Array>,\n): Promise<{ type: 'image'; source: { type: 'base64'; media_type: string; data: string } }> {\n const data = await readImage(ref)\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: ref.mediaType,\n data: Buffer.from(data).toString('base64'),\n },\n }\n}\n\nasync function messagesToCC(\n messages: readonly Message[],\n readImage?: (ref: ImageAttachmentRef) => Promise<Uint8Array>,\n): Promise<unknown[]> {\n const out: unknown[] = []\n const paired = pairedToolCallIds(messages)\n\n for (const message of messages) {\n if (message.role === 'system') continue // folded into params.system by the caller\n\n if (message.role === 'user' && message.source.kind !== 'tool') {\n const parts: unknown[] = []\n for (const block of message.content) {\n if (block.type === 'text') parts.push({ type: 'text', text: block.text })\n if (block.type === 'image') {\n // The caller (stream) has already gated image input on model\n // capability and attachment-service availability, so reaching this\n // branch with no resolver is an internal contract violation.\n if (!readImage) {\n throw new LlmError(\n 'Image input requires the durable attachment service',\n 'UNSUPPORTED_CONTENT',\n )\n }\n parts.push(await imageToCommandCode(block.attachment, readImage))\n }\n }\n out.push({ role: 'user', content: parts })\n continue\n }\n\n if (message.role === 'assistant') {\n const parts: unknown[] = []\n for (const block of message.content) {\n if (block.type === 'text') {\n parts.push({ type: 'text', text: block.text })\n } else if (block.type === 'tool-call' && paired.has(block.id)) {\n parts.push({\n type: 'tool-call',\n toolCallId: block.id,\n toolName: block.name,\n input: recordOrEmpty(block.arguments),\n })\n }\n // reasoning blocks: skipped by design (see header comment)\n }\n if (parts.length > 0) out.push({ role: 'assistant', content: parts })\n continue\n }\n\n // tool-result message (user role, single tool-result block)\n if (message.role === 'user' && message.source.kind === 'tool') {\n const block = message.content[0]\n if (!block || block.type !== 'tool-result' || !paired.has(block.toolCallId)) continue\n out.push({\n role: 'tool',\n content: [\n {\n type: 'tool-result',\n toolCallId: block.toolCallId,\n toolName: '',\n output: block.isError\n ? { type: 'error-text', value: toolResultText(block) }\n : { type: 'text', value: toolResultText(block) },\n },\n ],\n })\n }\n }\n return out\n}\n\n// ---------------------------------------------------------------------------\n// Adapter\n// ---------------------------------------------------------------------------\n/** Connection facts resolved fresh per request by the plugin entry. */\nexport interface CommandCodeConnectionOptions {\n /** API base; the Provider API lives under it (`/alpha/generate`, `/provider/v1/models`). */\n apiBase: string\n /** Working directory reported to the API (project slug, config block). */\n workingDir: string\n /** Model catalog cache path. */\n modelsCachePath: string\n /**\n * Milliseconds to wait for generate response headers / first byte (default 60s).\n * Must not bound the subsequent body stream — long generations are gated by\n * {@link streamIdleTimeoutMs} and the caller AbortSignal instead.\n */\n requestTimeoutMs: number\n /** Milliseconds a stream may stall before it is treated as a dead connection (default 300s). */\n streamIdleTimeoutMs: number\n}\n\n/**\n * Resolve the durable attachment service, or undefined when the host does not\n * provide one. Called lazily only when a request actually carries images, so a\n * text-only request never depends on the attachment seam.\n */\nexport type ResolveAttachments = () => AttachmentStore | undefined\n\n/** Everything the adapter needs beyond the request itself. */\nexport interface CommandCodeAdapterDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {\n /** Resolve the current connection facts (fresh per request, settings-aware). */\n options: () => C\n /** Resolve a usable API key for the given connection facts, or throw `MISSING_CREDENTIAL`. */\n resolveApiKey: (connection: C) => Promise<string>\n /** HTTP transport override (tests); defaults to the global `fetch`. */\n fetchImpl?: typeof fetch\n /** Resolve the optional durable attachment service for image input (tests); defaults to none. */\n resolveAttachments?: ResolveAttachments\n}\n\n/** Account identity from `/alpha/whoami`. */\nexport interface CommandCodeAccount {\n id: string\n name: string\n userName: string\n}\n\n/** Usage summary from `/alpha/usage/summary`. */\nexport interface CommandCodeUsage {\n totalCount: number\n totalCost: number\n successRate: number\n completedCount: number\n failedCount: number\n totalTokensIn: number\n totalTokensOut: number\n totalCredits: number\n periodBasis: string\n}\n\n/** Credit/limit state from `/alpha/billing/credits`. */\nexport interface CommandCodeCredits {\n monthlyCredits: number\n purchasedCredits: number\n freeCredits: number\n /** Five-hour rolling window limits. */\n fiveHour: { used: number; cap: number; exceeded: boolean; resetAt: number }\n /** Weekly window limits. */\n weekly: { used: number; cap: number; exceeded: boolean; resetAt: number }\n}\n\n/** Everything the usage endpoints report, fetched together. */\nexport interface CommandCodeUsageReport {\n account?: CommandCodeAccount\n usage?: CommandCodeUsage\n credits?: CommandCodeCredits\n /** Endpoint failures degrade the report instead of failing it. */\n failures: string[]\n}\n\nexport class CommandCodeAdapter<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> extends LlmAdapter {\n private catalog: CommandCodeModel[] = []\n private readonly fetchImpl: typeof fetch\n private readonly resolveAttachments: ResolveAttachments | undefined\n\n constructor(private readonly deps: CommandCodeAdapterDeps<C>) {\n super()\n this.fetchImpl = deps.fetchImpl ?? fetch\n this.resolveAttachments = deps.resolveAttachments\n }\n\n /**\n * Command Code is a metered subscription API: 429 (rate limit) and 5xx\n * (transient server errors) are worth retrying at the agent-step boundary,\n * which is where dsh-llm-retry executes the policy returned here. The\n * default policy already retries `RATE_LIMIT` and `SERVER`; declaring it\n * explicitly documents the intent and gives the plugin entry a stable hook\n * to override (e.g. a stricter cap for a metered plan).\n */\n override providerRetryPolicy(_provider: string): ResolvedRetryPolicy {\n return resolveRetryPolicy(undefined, 'llm-commandcode: retryPolicy')\n }\n\n /** Refresh the catalog (live fetch, cache fallback) and return it. */\n private async loadCatalog(signal?: AbortSignal): Promise<CommandCodeModel[]> {\n const { apiBase, modelsCachePath } = this.deps.options()\n try {\n const response = await this.fetchImpl(`${apiBase}/provider/v1/models`, {\n headers: { accept: 'application/json', ...attributionHeaders() },\n signal: signal ?? AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) {\n throw new Error(`models endpoint returned ${response.status}`)\n }\n this.catalog = parseCatalogResponse(await response.json())\n await writeModelsCache(modelsCachePath, this.catalog).catch(() => undefined)\n } catch (error) {\n if (signal?.aborted) throw error\n // A catalog refresh failure is a degradation, not a request failure:\n // fall back to the last successful catalog on disk (or the in-memory\n // one from an earlier successful load). The adapter still serves any\n // model the user names; only the advisory selector loses entries.\n this.catalog = await readModelsCache(modelsCachePath).catch(() => this.catalog)\n }\n return this.catalog\n }\n\n override async listModels(provider: string): Promise<readonly LlmModelInfo[]> {\n const catalog = await this.loadCatalog()\n return catalog\n .map((model) => {\n const vision = KNOWN_IMAGE_MODELS.has(model.id)\n return {\n provider,\n id: model.id,\n name: `${model.name} (CC)`,\n // The picker renders `description` under the model name: plan tier,\n // active deal, Image marker for Vision models, and context window.\n description: capabilityDescription(model.id, model.contextWindow),\n inputModalities: vision ? (['text', 'image'] as const) : (['text'] as const),\n }\n })\n // The picker renders rows in the order returned: sort by plan tier\n // (Go first, … Provider last) so the models a Go-plan user can actually\n // use lead the list, then alphabetically within each tier.\n .sort(compareByPlan)\n }\n\n override async resolveModel(\n provider: string,\n model: string,\n signal?: AbortSignal,\n ): Promise<LlmResolvedModelInfo> {\n const entry =\n this.catalog.find((m) => m.id === model) ??\n (await this.loadCatalog(signal)).find((m) => m.id === model)\n\n const efforts = KNOWN_EFFORTS[model]\n const vision = KNOWN_IMAGE_MODELS.has(model)\n return {\n provider,\n id: model,\n name: entry ? `${entry.name} (CC)` : model,\n description: capabilityDescription(model, entry?.contextWindow),\n inputModalities: vision ? (['text', 'image'] as const) : (['text'] as const),\n ...(entry\n ? {\n context: { contextWindow: entry.contextWindow },\n defaultMaxTokens: Math.min(entry.maxTokens, DEFAULT_GENERATE_MAX_TOKENS),\n }\n : {}),\n // Omit `reasoning` entirely for models without known effort support:\n // the harness then treats the model as having no selectable efforts.\n ...(efforts\n ? {\n reasoning: {\n efforts: efforts.map((effort) => ({\n id: ReasoningEffortId(effort),\n name: effort,\n })),\n },\n }\n : {}),\n }\n }\n\n /**\n * Fetch account, usage, and credit state from the Command Code account\n * endpoints (`/alpha/whoami`, `/alpha/usage/summary`, `/alpha/billing/credits`).\n * Each endpoint degrades independently: a failed one lands in `failures`\n * while the rest still report, so a transient outage never blanks the whole\n * view. Requires a usable API key (throws `MISSING_CREDENTIAL` otherwise).\n */\n async getUsage(): Promise<CommandCodeUsageReport> {\n const connection = this.deps.options()\n const apiKey = await this.deps.resolveApiKey(connection)\n const base = connection.apiBase\n const headers = {\n Authorization: `Bearer ${apiKey}`,\n 'x-command-code-version': COMMAND_CODE_CLI_VERSION,\n 'x-cli-environment': 'production',\n ...attributionHeaders(),\n }\n const failures: string[] = []\n\n const getJson = async (path: string): Promise<Record<string, unknown> | undefined> => {\n try {\n const response = await this.fetchImpl(`${base}${path}`, { headers })\n if (!response.ok) {\n failures.push(`${path}: HTTP ${response.status}`)\n return undefined\n }\n const parsed: unknown = await response.json()\n return isRecord(parsed) ? parsed : undefined\n } catch (error: unknown) {\n failures.push(`${path}: ${error instanceof Error ? error.message : String(error)}`)\n return undefined\n }\n }\n\n const report: CommandCodeUsageReport = { failures }\n\n // whoami -> account identity.\n const whoami = await getJson('/alpha/whoami')\n const whoamiData = whoami && isRecord(whoami.user) ? whoami.user : undefined\n if (whoamiData) {\n report.account = {\n id: stringValue(whoamiData.id) ?? '',\n name: stringValue(whoamiData.name) ?? '',\n userName: stringValue(whoamiData.userName) ?? '',\n }\n }\n\n // usage/summary -> totals.\n const usage = await getJson('/alpha/usage/summary')\n if (usage) {\n report.usage = {\n totalCount: numberValue(usage.totalCount) ?? 0,\n totalCost: numberValue(usage.totalCost) ?? 0,\n successRate: numberValue(usage.successRate) ?? 0,\n completedCount: numberValue(usage.completedCount) ?? 0,\n failedCount: numberValue(usage.failedCount) ?? 0,\n totalTokensIn: numberValue(usage.totalTokensIn) ?? 0,\n totalTokensOut: numberValue(usage.totalTokensOut) ?? 0,\n totalCredits: numberValue(usage.totalCredits) ?? 0,\n periodBasis: stringValue(usage.periodBasis) ?? 'billing-period',\n }\n }\n\n // billing/credits -> credit + window limits.\n const credits = await getJson('/alpha/billing/credits')\n const creditsData = credits && isRecord(credits.credits) ? credits.credits : undefined\n const windowLimits = credits && isRecord(credits.windowLimits) ? credits.windowLimits : undefined\n const fiveHour = windowLimits && isRecord(windowLimits.fiveHour) ? windowLimits.fiveHour : undefined\n const weekly = windowLimits && isRecord(windowLimits.weekly) ? windowLimits.weekly : undefined\n if (creditsData || fiveHour || weekly) {\n report.credits = {\n monthlyCredits: numberValue(creditsData?.monthlyCredits) ?? 0,\n purchasedCredits: numberValue(creditsData?.purchasedCredits) ?? 0,\n freeCredits: numberValue(creditsData?.freeCredits) ?? 0,\n fiveHour: {\n used: numberValue(fiveHour?.used) ?? 0,\n cap: numberValue(fiveHour?.cap) ?? 0,\n exceeded: fiveHour?.exceeded === true,\n resetAt: numberValue(fiveHour?.resetAt) ?? 0,\n },\n weekly: {\n used: numberValue(weekly?.used) ?? 0,\n cap: numberValue(weekly?.cap) ?? 0,\n exceeded: weekly?.exceeded === true,\n resetAt: numberValue(weekly?.resetAt) ?? 0,\n },\n }\n }\n\n return report\n }\n\n async *stream(options: GenerateOptions): AsyncIterable<StreamChunk> {\n if (options.stop?.length) {\n // The Command Code wire format has no documented stop field; refuse\n // loudly instead of silently dropping a request field.\n throw new LlmError('Command Code adapter does not support stop sequences', 'UNSUPPORTED_OPTION')\n }\n const hasImages = options.messages.some(hasImageContent)\n // Per-call image byte resolver, set only when this request carries images.\n // Local, not an instance field: concurrent streams must never read each\n // other's resolver.\n let readImage: ((ref: ImageAttachmentRef) => Promise<Uint8Array>) | undefined\n if (hasImages) {\n // Model-capability gate: only models the official registry lists with\n // Vision accept images natively. Command Code's own CLI falls back to a\n // client-side VISION side-call for text-only models; this adapter does\n // not reproduce that interactive feature, so it refuses loudly instead\n // of sending bytes to a model that cannot read them.\n if (!KNOWN_IMAGE_MODELS.has(options.model)) {\n throw new LlmError(\n `Command Code model \"${options.model}\" does not support image input;`\n + ' switch to a Vision-capable model (see the model registry)',\n 'UNSUPPORTED_CONTENT',\n )\n }\n // Attachment seam: images arrive as durable references; resolving them\n // requires the host's attachment service.\n const attachments = this.resolveAttachments?.()\n if (attachments === undefined) {\n throw new LlmError(\n 'Command Code image input requires the durable attachment service',\n 'UNSUPPORTED_CONTENT',\n )\n }\n readImage = (ref) => attachments.readImage(ref).then((stored) => stored.data)\n }\n\n const connection = this.deps.options()\n const apiKey = await this.deps.resolveApiKey(connection)\n const entry = this.catalog.find((m) => m.id === options.model)\n const modelMax = entry?.maxTokens ?? DEFAULT_MAX_OUTPUT_TOKENS\n const maxTokens = Math.min(\n options.maxTokens ?? modelMax,\n modelMax,\n DEFAULT_GENERATE_MAX_TOKENS,\n )\n\n const effort = options.reasoningEffort as string | undefined\n const supported = KNOWN_EFFORTS[options.model]\n const reasoningEffort =\n effort && effort !== 'off' && supported?.includes(effort) ? effort : undefined\n\n const systemText = [\n options.system ?? '',\n ...options.messages\n .filter((m) => m.role === 'system')\n .map((m) => m.content.map(blockText).filter(Boolean).join('\\n')),\n ]\n .filter(Boolean)\n .join('\\n\\n')\n\n const body = {\n config: {\n workingDir: connection.workingDir,\n date: new Date().toISOString().split('T')[0],\n environment: `${process.platform}-${process.arch}, Node.js ${process.version}`,\n structure: [],\n isGitRepo: false,\n currentBranch: '',\n mainBranch: '',\n gitStatus: '',\n recentCommits: [],\n },\n memory: null,\n taste: null,\n skills: null,\n params: {\n model: options.model,\n messages: await messagesToCC(options.messages, readImage),\n tools: (options.tools ?? []).map((tool) => ({\n type: 'function',\n name: tool.name,\n description: tool.description,\n input_schema: tool.parameters,\n })),\n system: systemText,\n max_tokens: maxTokens,\n temperature: options.temperature ?? 0.3,\n stream: true,\n ...(reasoningEffort ? { reasoning_effort: reasoningEffort } : {}),\n },\n threadId: randomUUID(),\n }\n\n // requestTimeoutMs must only bound the wait for response headers.\n // Passing AbortSignal.timeout() straight into fetch() also aborts a healthy\n // body after that duration, which cuts long reasoning/generation mid-stream\n // and surfaces as \"failed while reading: aborted due to timeout\". After\n // headers arrive, only the caller signal and streamIdleTimeoutMs may abort.\n const connectAbort = new AbortController()\n let connectTimedOut = false\n const connectTimer = setTimeout(() => {\n connectTimedOut = true\n connectAbort.abort(\n new DOMException(\n `Command Code API request to ${connection.apiBase}/alpha/generate did not respond within ${connection.requestTimeoutMs}ms`,\n 'TimeoutError',\n ),\n )\n }, connection.requestTimeoutMs)\n const onCallerAbort = () => {\n connectAbort.abort(options.signal?.reason)\n }\n if (options.signal) {\n if (options.signal.aborted) {\n onCallerAbort()\n } else {\n options.signal.addEventListener('abort', onCallerAbort, { once: true })\n }\n }\n\n let response: Response\n try {\n response = await this.fetchImpl(`${connection.apiBase}/alpha/generate`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n 'x-command-code-version': COMMAND_CODE_CLI_VERSION,\n 'x-cli-environment': 'production',\n 'x-project-slug': projectSlugFromPath(connection.workingDir),\n 'x-taste-learning': 'true',\n 'x-co-flag': 'false',\n ...attributionHeaders(),\n },\n body: JSON.stringify(body),\n signal: connectAbort.signal,\n })\n clearTimeout(connectTimer)\n } catch (error: unknown) {\n clearTimeout(connectTimer)\n if (options.signal) {\n options.signal.removeEventListener('abort', onCallerAbort)\n }\n if (options.signal?.aborted) {\n throw error\n }\n if (connectTimedOut || (error instanceof DOMException && error.name === 'TimeoutError')) {\n throw new LlmError(\n `Command Code API request to ${connection.apiBase}/alpha/generate did not respond within ${connection.requestTimeoutMs}ms`\n + `: ${errorChain(error)}`,\n 'TIMEOUT',\n { cause: error },\n )\n }\n // fetch wraps every transport failure (DNS, refused connection, TLS,\n // proxy, reset) in a bare `TypeError: fetch failed` whose actionable\n // detail lives on `cause`. Include the full chain so the failure reason\n // shown in the web UI (which renders only the message, not `cause`)\n // names the real root cause instead of a generic wrapper.\n throw new LlmError(\n `Command Code API request to ${connection.apiBase}/alpha/generate failed: ${errorChain(error)}`,\n 'TRANSPORT',\n { cause: error },\n )\n }\n\n if (!response.ok) {\n if (options.signal) {\n options.signal.removeEventListener('abort', onCallerAbort)\n }\n const errText = await response.text().catch(() => '')\n // Command Code folds several business rejections into 403 (plan limits,\n // CLI version, model access). Prefer the machine-readable `error.code`\n // when present; the status alone cannot distinguish them.\n let providerCode: string | undefined\n try {\n const parsed: unknown = JSON.parse(errText)\n if (isRecord(parsed) && isRecord(parsed.error)) {\n providerCode = stringValue(parsed.error.code)\n }\n } catch {\n // Plain-text bodies: rely on the status mapping below.\n }\n const detail = providerCode ?? `HTTP ${response.status}`\n if (response.status === 401) {\n // An invalid or missing credential is a config problem, not a\n // transport failure: retrying it identically cannot succeed.\n throw new LlmError(\n `Command Code API error 401 (${detail}): the API key is missing or invalid — check the`\n + ' key stored for COMMANDCODE_API_KEY (Models page) or the auth file',\n 'INVALID_CREDENTIAL',\n { status: 401 },\n )\n }\n throw new LlmError(\n `Command Code API error ${response.status}${detail === `HTTP ${response.status}` ? '' : ` (${detail})`}: ${errText.slice(0, 500)}`,\n response.status === 429 ? 'RATE_LIMIT' : 'PROVIDER_HTTP_ERROR',\n { status: response.status },\n )\n }\n if (!response.body) {\n if (options.signal) {\n options.signal.removeEventListener('abort', onCallerAbort)\n }\n throw new LlmError('Command Code API returned no response body', 'PROVIDER_PROTOCOL_ERROR')\n }\n\n // --- SSE/JSONL event stream -> harness StreamChunk protocol ---\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n\n // Stream idle watchdog: a generation that stalls this long has a dead\n // connection (the API keeps the socket open between reasoning/text\n // bursts). The default (300s) is deliberately generous: frontier\n // reasoning models (xhigh/max effort) can legitimately stay silent for\n // minutes while thinking, and the official CLI sets no idle cap at all —\n // an aggressive cap turns long thinking into spurious TIMEOUTs and\n // retries. reader.cancel() unblocks a pending read(), which the loop then\n // turns into a TIMEOUT failure instead of hanging forever.\n let idleTimer: ReturnType<typeof setTimeout> | undefined\n let idleFired = false\n const armIdle = () => {\n if (idleTimer !== undefined) clearTimeout(idleTimer)\n idleTimer = setTimeout(() => {\n idleFired = true\n void reader.cancel().catch(() => undefined)\n }, connection.streamIdleTimeoutMs)\n }\n const clearIdle = () => {\n if (idleTimer !== undefined) {\n clearTimeout(idleTimer)\n idleTimer = undefined\n }\n }\n\n // Block assembly state: at most one text block and one reasoning block\n // are open at a time (same assumption as the pi plugin).\n let nextIndex = 0\n let textIndex = -1\n let textContent = ''\n let reasoningIndex = -1\n let reasoningContent = ''\n let sawContent = false\n\n const closeText = function* (): Generator<StreamChunk> {\n if (textIndex < 0) return\n yield {\n type: 'block-end',\n index: textIndex,\n block: { type: 'text', text: textContent },\n }\n textIndex = -1\n textContent = ''\n }\n const closeReasoning = function* (): Generator<StreamChunk> {\n if (reasoningIndex < 0) return\n yield {\n type: 'block-end',\n index: reasoningIndex,\n block: { type: 'reasoning', text: reasoningContent },\n }\n reasoningIndex = -1\n reasoningContent = ''\n }\n\n const handleEvent = (event: unknown): StreamChunk[] => {\n const chunks: StreamChunk[] = []\n if (!isRecord(event)) return chunks\n\n switch (event.type) {\n case 'text-delta': {\n chunks.push(...closeReasoning())\n if (textIndex < 0) {\n textIndex = nextIndex++\n chunks.push({ type: 'block-start', index: textIndex, blockType: 'text' })\n }\n const delta = stringValue(event.text) ?? ''\n textContent += delta\n sawContent = true\n chunks.push({ type: 'text-delta', index: textIndex, text: delta })\n break\n }\n case 'reasoning-delta': {\n chunks.push(...closeText())\n if (reasoningIndex < 0) {\n reasoningIndex = nextIndex++\n chunks.push({ type: 'block-start', index: reasoningIndex, blockType: 'reasoning' })\n }\n const delta = stringValue(event.text) ?? ''\n reasoningContent += delta\n chunks.push({ type: 'reasoning-delta', index: reasoningIndex, text: delta })\n break\n }\n case 'reasoning-start':\n chunks.push(...closeText())\n break\n case 'reasoning-end':\n chunks.push(...closeReasoning())\n break\n case 'tool-call': {\n chunks.push(...closeText(), ...closeReasoning())\n const id = stringValue(event.toolCallId) ?? randomUUID()\n const name = stringValue(event.toolName) ?? ''\n const args = JSON.stringify(recordOrEmpty(event.input ?? event.args ?? event.arguments))\n const index = nextIndex++\n sawContent = true\n chunks.push(\n { type: 'block-start', index, blockType: 'tool-call' },\n { type: 'tool-call-delta', index, id: CallId(id), name, argumentsDelta: args },\n {\n type: 'block-end',\n index,\n block: { type: 'tool-call', id: CallId(id), name, arguments: args },\n },\n )\n break\n }\n case 'finish': {\n chunks.push(...closeText(), ...closeReasoning())\n const usage = isRecord(event.totalUsage) ? event.totalUsage : undefined\n if (usage) {\n const details = isRecord(usage.inputTokenDetails) ? usage.inputTokenDetails : undefined\n const totalInput = numberValue(usage.inputTokens) ?? 0\n const cacheRead = numberValue(details?.cacheReadTokens) ?? 0\n const cacheWrite = numberValue(details?.cacheWriteTokens) ?? 0\n // Harness TokenUsage counts are disjoint: uncached input only.\n const tokenUsage: TokenUsage = {\n inputTokens:\n numberValue(details?.noCacheTokens) ?? Math.max(0, totalInput - cacheRead - cacheWrite),\n outputTokens: numberValue(usage.outputTokens) ?? 0,\n cacheReadTokens: cacheRead,\n cacheWriteTokens: cacheWrite,\n }\n chunks.push({ type: 'usage', usage: tokenUsage })\n }\n chunks.push({ type: 'finish', reason: mapFinishReason(event.finishReason) })\n break\n }\n case 'error': {\n // Mirror the official CLI's stream-error classification\n // (readStreamErrorEvent + isStreamErrorRetryable in command-code's\n // cli.mjs): a stream error that is explicitly non-retryable, carries\n // a terminal marker (quota/plan/credits), or reports a non-retryable\n // HTTP status is a hard failure; anything else is a transient\n // mid-stream drop that the harness's default retry policy should\n // retry (SERVER is in the default retryable set, PROVIDER_STREAM_ERROR\n // is not). Without this, a server-side blip that the official CLI\n // silently recovers from fails the whole turn.\n const err = isRecord(event.error) ? event.error : undefined\n const detail = isRecord(event.error)\n ? (stringValue(event.error.message) ?? JSON.stringify(event.error))\n : (stringValue(event.error) ?? stringValue(event.message) ?? 'Stream error')\n const statusCode = err ? numberValue(err.statusCode) : undefined\n const isRetryable = err ? booleanValue(err.isRetryable) : undefined\n const retryableStatus = statusCode !== undefined && (statusCode === 429 || statusCode >= 500)\n const terminal = hasTerminalStreamMarker(detail)\n const retryable = isRetryable === true\n || (statusCode !== undefined ? retryableStatus : (isRetryable !== false && !terminal))\n if (!retryable) {\n throw new LlmError(\n `Command Code stream error: ${detail}`,\n 'PROVIDER_STREAM_ERROR',\n statusCode !== undefined ? { status: statusCode } : undefined,\n )\n }\n throw new LlmError(\n `Command Code stream error: ${detail}`,\n 'SERVER',\n statusCode !== undefined ? { status: statusCode } : undefined,\n )\n }\n }\n return chunks\n }\n\n try {\n let finished = false\n for (;;) {\n let read: ReadableStreamReadResult<Uint8Array>\n armIdle()\n try {\n read = await reader.read()\n } catch (error: unknown) {\n // A mid-stream transport failure (connection reset, TLS teardown)\n // surfaces here. Caller cancellation propagates as-is.\n if (options.signal?.aborted) throw error\n throw new LlmError(\n `Command Code API stream from ${connection.apiBase} failed while reading: ${errorChain(error)}`,\n 'TRANSPORT',\n { cause: error },\n )\n } finally {\n clearIdle()\n }\n const { done, value } = read\n if (done) {\n // The idle watchdog cancels the reader to unblock a stalled read;\n // cancel() resolves a pending read() as done, so a done here after\n // the watchdog fired is a timeout, not a normal stream end.\n if (idleFired) {\n throw new LlmError(\n `Command Code API stream from ${connection.apiBase} was idle for ${connection.streamIdleTimeoutMs}ms`\n + ' (no events) and was treated as a dead connection',\n 'TIMEOUT',\n )\n }\n if (buffer.trim()) for (const chunk of handleEvent(parseStreamEventLine(buffer))) yield chunk\n break\n }\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n for (const line of lines) {\n const chunks = handleEvent(parseStreamEventLine(line))\n for (const chunk of chunks) {\n yield chunk\n if (chunk.type === 'finish') finished = true\n }\n }\n if (finished) break\n }\n if (!finished) {\n // Stream ended without a finish event: close open blocks and\n // terminate according to the adapter contract (usage, then finish).\n yield* closeText()\n yield* closeReasoning()\n if (!sawContent) {\n throw new LlmError('Command Code returned an empty response', 'EMPTY_RESPONSE')\n }\n yield { type: 'finish', reason: { kind: 'stop' } }\n }\n } finally {\n clearIdle()\n if (options.signal) {\n options.signal.removeEventListener('abort', onCallerAbort)\n }\n await reader.cancel().catch(() => undefined)\n reader.releaseLock()\n }\n }\n}\n\nfunction mapFinishReason(reason: unknown): FinishReason {\n if (reason === 'tool-calls') return { kind: 'tool-calls' }\n if (\n reason === 'length' ||\n reason === 'max_tokens' ||\n reason === 'max-tokens' ||\n reason === 'max_output_tokens'\n ) {\n return { kind: 'max-tokens' }\n }\n return { kind: 'stop' }\n}\n","/**\n * `/commandcode` slash command — account usage dashboard.\n *\n * /commandcode show account, usage, and credit state\n * /commandcode status same as bare `/commandcode`\n *\n * Backed by the Command Code account endpoints the official CLI uses\n * (`/alpha/whoami`, `/alpha/usage/summary`, `/alpha/billing/credits`),\n * exposed through `CommandCodeAdapter.getUsage()`.\n *\n * @module dsh-commandcode-provider/commands\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\n// Type-only import that loads the module augmentation (`ctx.commands`).\nimport type { CommandDefinition } from '@deepseek-ai/dsh-commands'\nimport { CommandCodeAdapter } from './adapter.ts'\nimport type { CommandCodeConnectionOptions, CommandCodeUsageReport } from './adapter.ts'\n\n/** Everything the command needs beyond the adapter itself. */\nexport interface CommandCodeCommandDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {\n /** The registered adapter (for getUsage / listModels). */\n adapter: CommandCodeAdapter<C>\n}\n\n/** Format a dollar amount. */\nfunction money(value: number): string {\n return `$${value.toFixed(4)}`\n}\n\n/** Format a dollar amount compactly (2 decimals). */\nfunction moneyShort(value: number): string {\n return `$${value.toFixed(2)}`\n}\n\n/** Format a token count with thousands separators. */\n/** Format a large token count compactly (1.9亿 style). */\nfunction tokensCompact(value: number): string {\n if (value >= 1e9) return `${(value / 1e9).toFixed(1)}B`\n if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`\n if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`\n return String(value)\n}\n\n/** Format a millis timestamp as a local date. */\nfunction resetLabel(ms: number): string {\n if (ms <= 0) return 'n/a'\n return new Date(ms).toLocaleString()\n}\n\n/**\n * A 10-cell horizontal bar: `██████████` for 100%, `███░░░░░░░` for ~33%.\n * Handles caps of 0 (no limit) and out-of-range values.\n */\nfunction bar(used: number, cap: number): string {\n if (cap <= 0) return '—'\n const ratio = Math.max(0, Math.min(1, used / cap))\n const filled = Math.round(ratio * 10)\n return '█'.repeat(filled) + '░'.repeat(10 - filled)\n}\n\n/** Render the usage report as a structured, aligned, bar-chart text view. */\nfunction renderReport(report: CommandCodeUsageReport): string {\n const lines: string[] = []\n const account = report.account ? ` (${report.account.userName || report.account.name})` : ''\n\n lines.push(`📊 Command Code 用量${account}`, '')\n\n if (report.usage) {\n const u = report.usage\n lines.push(\n '── 请求 ──────────────────────────────',\n ` 💬 请求 ${u.completedCount} 次 / 失败 ${u.failedCount} 成功率 ${u.successRate}%`,\n ` 💰 花费 ${money(u.totalCost)} (${moneyShort(u.totalCredits)} credits)`,\n ` 🔤 Token ${tokensCompact(u.totalTokensIn)} 入 / ${tokensCompact(u.totalTokensOut)} 出`,\n '',\n )\n }\n\n if (report.credits) {\n const c = report.credits\n const monthlyPct = c.monthlyCredits > 0\n ? `${((c.monthlyCredits / (c.monthlyCredits + c.purchasedCredits)) * 100).toFixed(0)}%`\n : '—'\n lines.push(\n '── 信用 ──────────────────────────────',\n ` 💳 月额度 ${moneyShort(c.monthlyCredits)} (已购 ${moneyShort(c.purchasedCredits)} / 赠送 ${moneyShort(c.freeCredits)})`,\n ` └ ${bar(c.monthlyCredits, c.monthlyCredits + c.purchasedCredits)} ${monthlyPct}`,\n '',\n '── 窗口用量 ──────────────────────────',\n ` ⏱ 5 小时 ${moneyShort(c.fiveHour.used)} / ${moneyShort(c.fiveHour.cap)}${c.fiveHour.exceeded ? ' ⚠️ 超限!' : ''}`,\n ` └ ${bar(c.fiveHour.used, c.fiveHour.cap)} 重置 ${resetLabel(c.fiveHour.resetAt)}`,\n ` 📅 每周 ${moneyShort(c.weekly.used)} / ${moneyShort(c.weekly.cap)}${c.weekly.exceeded ? ' ⚠️ 超限!' : ''}`,\n ` └ ${bar(c.weekly.used, c.weekly.cap)} 重置 ${resetLabel(c.weekly.resetAt)}`,\n '',\n )\n }\n\n if (report.failures.length > 0) {\n lines.push(`⚠️ 部分端点失败: ${report.failures.join('; ')}`, '')\n }\n if (!report.account && !report.usage && !report.credits) {\n lines.push('(no data — check your API key)', '')\n }\n\n return lines.join('\\n').trimEnd()\n}\n\n/** The one registered `/commandcode` command. */\nexport function commandDefinition<C extends CommandCodeConnectionOptions>(\n deps: CommandCodeCommandDeps<C>,\n): CommandDefinition {\n const { adapter } = deps\n return {\n name: 'commandcode',\n description: 'Command Code account usage dashboard',\n input: { hint: '[status]' },\n handler: async () => {\n try {\n const report = await adapter.getUsage()\n return { kind: 'success', text: renderReport(report) }\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n kind: 'error',\n text: `Could not fetch Command Code usage: ${message}`,\n }\n }\n },\n }\n}\n\n/** Register the command on `ctx.commands` (called from the plugin entry). */\nexport function applyCommands<C extends CommandCodeConnectionOptions>(\n ctx: Context,\n deps: CommandCodeCommandDeps<C>,\n): void {\n ctx.commands.register(commandDefinition(deps))\n}\n","/**\n * dsh-commandcode-provider — DeepSeek Harness LLM provider plugin for Command\n * Code (unofficial; ported from pi-commandcode-provider@0.5.1).\n *\n * Registers the `commandcode` provider route on `ctx.llm` and declares it in\n * the configurable-provider directory, so the web Models page shows a\n * \"Command Code\" card with an API-key field and the model picker lists the\n * live Command Code model catalog. Connection facts resolve per request over\n * the optional `llm-commandcode` user-settings section and the credential\n * seam, so a changed key, endpoint, or cache path reaches the next request\n * without a restart.\n *\n * ```yaml\n * - id: llm-commandcode\n * name: \"@mars-sea/dsh-commandcode-provider\"\n * config:\n * apiKeyEnv: COMMANDCODE_API_KEY\n * ```\n *\n * The `name` is the full package specifier as installed in the profile's\n * node_modules: the loader imports it as a module, and pnpm links packages by\n * their true (scoped) name — a bare `dsh-commandcode-provider` fails to\n * resolve (ERR_MODULE_NOT_FOUND) and crashes the app on boot. The value must\n * be quoted in YAML: an unquoted scalar starting with `@` fails to parse.\n *\n * @module dsh-commandcode-provider\n */\n\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport z from '@deepseek-ai/schemastery'\nimport { MAX_TIMER_DELAY_MS } from '@deepseek-ai/dsh-timeout'\nimport { assertUsableApiKey, LlmError } from '@deepseek-ai/dsh-llm'\nimport { credentialRef, type CredentialRef } from '@deepseek-ai/dsh-credentials'\nimport { launchEnvironmentOf } from '@deepseek-ai/dsh-launch-environment'\nimport { installSettingsSection, settingsNamespace } from '@deepseek-ai/dsh-settings'\nimport { CommandCodeAdapter, DEFAULT_API_BASE, resolveAuthFileApiKey } from './adapter.ts'\nimport { DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_STREAM_IDLE_TIMEOUT_MS } from './adapter.ts'\nimport type { CommandCodeConnectionOptions } from './adapter.ts'\nimport { applyCommands } from './commands.ts'\n\nexport {\n COMMAND_CODE_CLI_VERSION,\n DEFAULT_API_BASE,\n DEFAULT_GENERATE_MAX_TOKENS,\n DEFAULT_MAX_OUTPUT_TOKENS,\n DEFAULT_REQUEST_TIMEOUT_MS,\n DEFAULT_STREAM_IDLE_TIMEOUT_MS,\n CommandCodeAdapter,\n KNOWN_EFFORTS,\n KNOWN_IMAGE_MODELS,\n KNOWN_THINKING_MODELS,\n KNOWN_PLANS,\n KNOWN_DEALS,\n KNOWN_PEAK_PRICING,\n PLAN_LABELS,\n PLAN_ORDER,\n capabilityDescription,\n compareByPlan,\n dealLabel,\n formatContext,\n peakPricingLabel,\n peakPricingState,\n planLabel,\n projectSlugFromPath,\n resolveAuthFileApiKey,\n} from './adapter.ts'\nexport type { CommandCodeAdapterDeps, CommandCodeConnectionOptions, CommandCodeUsageReport, ResolveAttachments } from './adapter.ts'\nexport { applyCommands, commandDefinition } from './commands.ts'\nexport type { CommandCodeCommandDeps } from './commands.ts'\n\nexport const name = 'llm-commandcode'\nexport const inject = ['llm']\n\nconst NS = settingsNamespace('llm-commandcode')\nconst DEFAULT_API_KEY_ENV = 'COMMANDCODE_API_KEY'\n\n/** The single provider route this plugin owns. */\nexport const PROVIDER = 'commandcode'\n/** Default models cache path (mirrors the pi plugin's on-disk cache). */\nexport const DEFAULT_MODELS_CACHE_PATH = join(homedir(), '.commandcode', 'models-cache.json')\n\n/**\n * Plugin config, validated by the same-named schemastery schema and doubling\n * as the `llm-commandcode` settings-section shape. Every field is optional:\n * a missing API key resolves through {@link Config.apiKeyEnv} at each request\n * (the web Models page writes it), with the official Command Code CLI auth\n * file (`~/.commandcode/auth.json`) as the last fallback.\n */\nexport interface Config {\n /** Credential reference (environment-variable name) resolved per request; defaults to `COMMANDCODE_API_KEY`. */\n apiKeyEnv?: string\n /** Literal API key override (composition config only); takes precedence over `apiKeyEnv`. */\n apiKey?: string\n /** API base; defaults to the public Command Code Provider API. */\n apiBase?: string\n /** Working directory reported to the API; defaults to the process cwd. */\n workingDir?: string\n /** Model catalog cache path; defaults to `~/.commandcode/models-cache.json`. */\n modelsCachePath?: string\n /** Milliseconds to wait for the generate response's first byte; defaults to 60s. */\n requestTimeoutMs?: number\n /** Milliseconds a stream may stall before being treated as a dead connection; defaults to 300s. */\n streamIdleTimeoutMs?: number\n}\n\nexport const Config: z<Config> = z.object({\n apiKeyEnv: z.string().role('credential-ref').default(DEFAULT_API_KEY_ENV),\n apiKey: z.string(),\n apiBase: z.string(),\n workingDir: z.string(),\n modelsCachePath: z.string(),\n requestTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS),\n streamIdleTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS),\n})\n\n/** One resolution's complete request facts: connection plus credential reference. */\nexport interface ResolvedCommandCodeOptions extends CommandCodeConnectionOptions {\n apiKeyEnv: CredentialRef\n}\n\n/**\n * The one explicit resolve step from raw config to validated connection\n * facts. Programmatic construction may bypass Schemastery normalization, so\n * every default is re-judged here — for the composition entry at load and for\n * each settings snapshot at its first use.\n */\nexport function resolveAdapterOptions(config: Config): ResolvedCommandCodeOptions {\n return {\n apiKeyEnv: credentialRef(config.apiKeyEnv ?? DEFAULT_API_KEY_ENV),\n apiBase: config.apiBase ?? DEFAULT_API_BASE,\n workingDir: config.workingDir ?? process.cwd(),\n modelsCachePath: config.modelsCachePath ?? DEFAULT_MODELS_CACHE_PATH,\n requestTimeoutMs: config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n streamIdleTimeoutMs: config.streamIdleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS,\n }\n}\n\nexport function apply(ctx: Context, config: Config): void {\n let current: () => Config = () => config\n let lastRaw: Config | undefined\n let lastGood: ResolvedCommandCodeOptions | undefined\n const options = (): ResolvedCommandCodeOptions => {\n const raw = current()\n if (raw === lastRaw && lastGood !== undefined) return lastGood\n const next = resolveAdapterOptions(raw)\n lastRaw = raw\n lastGood = next\n return next\n }\n options()\n\n const resolveApiKey = async (connection: ResolvedCommandCodeOptions): Promise<string> => {\n // 1. A literal key in composition config wins outright.\n const literal = current().apiKey\n if (literal) return assertUsableApiKey(literal, 'llm-commandcode', 'config.apiKey')\n // 2. The credential seam (web Models page) or the trusted environment.\n const ref = connection.apiKeyEnv\n const credentials = ctx.get('credentials')\n if (credentials !== undefined) {\n const hit = await credentials.resolve(ref)\n if (hit !== undefined) return assertUsableApiKey(hit.value, 'llm-commandcode', ref)\n } else {\n const ambient = launchEnvironmentOf(ctx).get(ref)\n if (ambient !== undefined && ambient.value.length > 0) {\n return assertUsableApiKey(ambient.value, 'llm-commandcode', ref)\n }\n }\n // 3. Last resort: reuse the official Command Code CLI login (~/.commandcode/auth.json).\n const authFileKey = resolveAuthFileApiKey()\n if (authFileKey) return assertUsableApiKey(authFileKey, 'llm-commandcode', '~/.commandcode/auth.json')\n throw new LlmError(\n `llm-commandcode: no API key for provider route \"${PROVIDER}\"; store ${ref} through the`\n + ' credentials service (the web Models page writes it), export it in the launching'\n + ' environment, set config.apiKey, or run `command-code login` to write'\n + ' ~/.commandcode/auth.json',\n 'MISSING_CREDENTIAL',\n )\n }\n\n const adapter = new CommandCodeAdapter({\n options,\n resolveApiKey,\n // The durable attachment service carries image bytes referenced by\n // ImageBlock; resolved lazily only when a request actually has images.\n resolveAttachments: () => {\n const attachments = ctx.get('attachments')\n return attachments === undefined ? undefined : attachments\n },\n })\n // The Models page card: a configurable provider with a settings address.\n // settingsPath [] means the whole `llm-commandcode` section configures it.\n ctx.llm.registerConfigurableProviders([\n { provider: PROVIDER, displayName: 'Command Code', settingsNs: NS, settingsPath: [] },\n ])\n // The live route: this is what makes models requestable under `commandcode`.\n ctx.llm.registerAdapter([PROVIDER], adapter)\n\n // The /commandcode usage command rides the optional `commands` service: a\n // child fiber injects it, so it registers whenever the profile mounts\n // dsh-commands and the fiber simply never activates when it does not.\n ctx.inject(['commands'], (commandCtx) => {\n applyCommands(commandCtx, { adapter })\n })\n\n installSettingsSection(ctx, NS, Config, config, {\n setSource: (source) => {\n current = source\n },\n // Everything the adapter reads is resolved per request, so a settings\n // change needs no registration-level action.\n onChange: () => {},\n })\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mars-sea/dsh-commandcode-provider",
3
- "version": "0.2.4",
3
+ "version": "0.3.0",
4
4
  "description": "Unofficial DeepSeek Harness LLM provider plugin for Command Code, ported from pi-commandcode-provider (MIT). Registers the 'commandcode' provider route with a Models-page card and live model catalog.",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",