@mars-sea/dsh-commandcode-provider 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +7 -3
- package/README.zh-CN.md +7 -3
- package/assets/screenshots/settings-page.png +0 -0
- package/lib/index.d.ts +4 -4
- package/lib/index.js +25 -11
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ 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.4.2] - 2026-08-18
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **Tool results now round-trip the real tool name, fixing multi-turn tool calls on Google Gemini models ([#5](https://github.com/Mars-Sea/dsh-commandcode-provider/issues/5)).** `messagesToCC()` hard-coded `toolName: ''` on replayed `tool-result` messages; Anthropic/OpenAI-style backends tolerate that (they correlate by `tool_call_id`), but Gemini's `functionResponse` requires a non-empty function name, so every multi-turn tool call on Gemini-family models failed mid-stream with `[Google] Tool message must have either name or tool_call_id`. The adapter now collects each paired tool call's `toolCallId → toolName` in the same pass that computes pairing and writes the real name onto the result, falling back to `'unknown'` — mirroring the official CLI's `tool_use_id -> toolName` map (`?? "unknown"`). Thanks to @seva324 for the precise root-cause report and patch. The replay tests now assert the carried name (they previously only checked the tool message existed, which is how this slipped through), plus a new fallback case.
|
|
12
|
+
|
|
13
|
+
## [0.4.1] - 2026-08-18
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **Synced with the official command-code@1.27.1 CLI** (upstream moved from 1.26.0 → 1.27.0 → 1.27.1). `COMMAND_CODE_CLI_VERSION` is now `1.27.1`, sent as `x-command-code-version` on every request. The only user-visible upstream change is **GPT-5.6 Sol** (added in command-code@1.27.0, "50% off in GOAT and above"): it is a GOAT-tier model, so `KNOWN_PLANS` now maps `gpt-5.6-sol` to `goat` (was `pro`) — GOAT accounts will now see it in the picker instead of having it filtered out. Re-verified every other snapshot against the official sources with no changes: `KNOWN_EFFORTS` (identical to the 1.27.1 `ZA` table), `KNOWN_IMAGE_MODELS` (the docs registry's Vision set is unchanged and includes Sol), `KNOWN_THINKING_MODELS`, `KNOWN_SUBSCRIPTION_PLANS` (the `Nn`/`$n` plan maps are untouched), `KNOWN_DEALS` (the pricing page lists no Sol deal — its "50% off" is not a `KNOWN_DEALS` entry), and `KNOWN_PEAK_PRICING` (DeepSeek V4 Pro/Flash, 01–04 & 06–10 UTC). Wire protocol, endpoints, and auth flow are unchanged in the 1.27.x bundle.
|
|
18
|
+
|
|
7
19
|
## [0.4.0] - 2026-08-17
|
|
8
20
|
|
|
9
21
|
### Added
|
package/README.md
CHANGED
|
@@ -10,18 +10,18 @@
|
|
|
10
10
|
[](https://opensource.org/licenses/MIT)
|
|
11
11
|
[](https://www.npmjs.com/package/@mars-sea/dsh-commandcode-provider)
|
|
12
12
|
|
|
13
|
-
Unofficial [DeepSeek Harness](https://deepseek-harness.github.io/deepseek-harness/) LLM provider plugin for **Command Code**, ported from [pi-commandcode-provider](https://github.com/patlux/pi-commandcode-provider) (MIT). It registers a `commandcode` provider whose requests are translated to Command Code's Provider API (`POST /alpha/generate`, reverse-engineered by the pi plugin, `command-code@1.
|
|
13
|
+
Unofficial [DeepSeek Harness](https://deepseek-harness.github.io/deepseek-harness/) LLM provider plugin for **Command Code**, ported from [pi-commandcode-provider](https://github.com/patlux/pi-commandcode-provider) (MIT). It registers a `commandcode` provider whose requests are translated to Command Code's Provider API (`POST /alpha/generate`, reverse-engineered by the pi plugin, `command-code@1.27.1`).
|
|
14
14
|
|
|
15
15
|
> This is a community integration. You need your own Command Code account and API key or subscription, and Command Code's terms apply. This project is not affiliated with Command Code, Inc.
|
|
16
16
|
|
|
17
17
|
## What you get
|
|
18
18
|
|
|
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
|
-
- **Dedicated "Command Code" settings page** (Settings → **Command Code**) with an **API-key field
|
|
20
|
+
- **Dedicated "Command Code" settings page** (Settings → **Command Code**) with an **API-key field**, connection knobs (API base, working directory, request/stream timeouts), a **live "Account usage" card** (stats, credits, window-limit bars, subscription plan badge) and a **Hide out-of-plan models** toggle. 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
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
|
- **Plan-aware picker filtering**: the picker **hides models above your subscription tier** outright (resolved live from your account's billing state). It fails open — an unreachable billing endpoint, an unknown plan, or a positive on-demand credit balance (which the official CLI treats as unlocking every model) all keep the full catalog visible — and the server stays the final gate. Set **Hide out-of-plan models** off on the settings page (or `filterModelsByPlan: false` in the `llm-commandcode` settings section) to always list every model.
|
|
24
|
-
- **Reasoning-effort support** for models the official catalog marks as such (`KNOWN_EFFORTS`, matching `command-code@1.
|
|
24
|
+
- **Reasoning-effort support** for models the official catalog marks as such (`KNOWN_EFFORTS`, matching `command-code@1.27.1`); reasoning models without effort levels still think automatically, exactly like the official CLI.
|
|
25
25
|
- **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.
|
|
26
26
|
|
|
27
27
|
<img src="assets/screenshots/model-picker.png" alt="Model picker with plan, deal, image and context annotations" width="250">
|
|
@@ -143,6 +143,10 @@ Each endpoint degrades independently — a temporary failure of one leaves the r
|
|
|
143
143
|
|
|
144
144
|
**Settings → Command Code** is the primary surface: an **API-key** field (stored in `$DSH_HOME/.credentials.yaml` via the credentials service; write-only, reports whether a key is set), plus **API base URL**, **working directory**, and **request/stream timeout** fields, all written to the `llm-commandcode` section. The catalog is browsable without a key. The **working directory** is optional — leave it blank and the placeholder shows the process cwd it resolves to.
|
|
145
145
|
|
|
146
|
+
Once a key is configured, the page header shows a live **Account usage** card — the same account, spend, credit, and window-limit facts as `/commandcode`, plus your subscription plan badge and billing period end — fetched Host-side (the key never leaves it) and rendered natively:
|
|
147
|
+
|
|
148
|
+
<img src="assets/screenshots/settings-page.png" alt="Command Code settings page with the account usage card" width="640">
|
|
149
|
+
|
|
146
150
|
The same knobs live in `$DSH_HOME/settings.yaml` (per-request overrides, no restart):
|
|
147
151
|
|
|
148
152
|
```yaml
|
package/README.zh-CN.md
CHANGED
|
@@ -10,18 +10,18 @@
|
|
|
10
10
|
[](https://opensource.org/licenses/MIT)
|
|
11
11
|
[](https://www.npmjs.com/package/@mars-sea/dsh-commandcode-provider)
|
|
12
12
|
|
|
13
|
-
非官方 [DeepSeek Harness](https://deepseek-harness.github.io/deepseek-harness/) 的 LLM provider 插件,用于 **Command Code**,移植自 [pi-commandcode-provider](https://github.com/patlux/pi-commandcode-provider)(MIT 协议)。它注册了一个 `commandcode` provider,将请求转换为 Command Code 的 Provider API(`POST /alpha/generate`,由 pi 插件逆向工程,对应 `command-code@1.
|
|
13
|
+
非官方 [DeepSeek Harness](https://deepseek-harness.github.io/deepseek-harness/) 的 LLM provider 插件,用于 **Command Code**,移植自 [pi-commandcode-provider](https://github.com/patlux/pi-commandcode-provider)(MIT 协议)。它注册了一个 `commandcode` provider,将请求转换为 Command Code 的 Provider API(`POST /alpha/generate`,由 pi 插件逆向工程,对应 `command-code@1.27.1`)。
|
|
14
14
|
|
|
15
15
|
> 这是一个社区集成。你需要自己的 Command Code 账号、API key 或订阅,并遵守 Command Code 的服务条款。本项目与 Command Code, Inc. 无关。
|
|
16
16
|
|
|
17
17
|
## 功能一览
|
|
18
18
|
|
|
19
19
|
- **插件包**:可通过 `dsh plugin add` 安装到任意 dsh 配置,并提供 **`commandcode` provider 路由**,带实时模型目录(`GET {apiBase}/provider/v1/models`,缓存于 `~/.commandcode/models-cache.json`)。
|
|
20
|
-
- **专属"Command Code"设置页**(设置 → **Command Code**),带 **API key
|
|
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
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
|
- **按套餐过滤选择器**:选择器会**直接隐藏超出你订阅套餐的模型**(根据账户账单状态实时判断)。全程失败开放——账单接口不可用、套餐未知,或账户持有按需余额(官方 CLI 视为解锁全部模型)时都显示完整目录——服务端仍是最终闸门。在设置页关闭「隐藏套餐外模型」开关(或在 `llm-commandcode` 设置段中设 `filterModelsByPlan: false`)可始终列出全部模型。
|
|
24
|
-
- **推理强度(reasoning-effort)支持**:针对官方目录标为推理模型的模型(`KNOWN_EFFORTS`,与 `command-code@1.
|
|
24
|
+
- **推理强度(reasoning-effort)支持**:针对官方目录标为推理模型的模型(`KNOWN_EFFORTS`,与 `command-code@1.27.1` 一致);没有可选档位但仍支持思考的模型会自动思考,与官方 CLI 行为完全一致。
|
|
25
25
|
- **支持视觉模型的图片输入**(通过 dsh 附件服务、以官方 wire 格式发送);纯文本模型会明确拒绝图片(`UNSUPPORTED_CONTENT`)而非静默丢弃。
|
|
26
26
|
|
|
27
27
|
<img src="assets/screenshots/model-picker.png" alt="带套餐、折扣、图片与上下文标注的模型选择器" width="250">
|
|
@@ -143,6 +143,10 @@ dsh web
|
|
|
143
143
|
|
|
144
144
|
**设置 → Command Code** 是主要配置入口:**API key** 输入框(通过凭据服务存储在 `$DSH_HOME/.credentials.yaml`,只写不回显,并显示是否已配置),以及 **API 地址**、**工作目录**、**请求/流超时**字段,全部写入 `llm-commandcode` 设置段。没有 key 也可以浏览模型目录。**工作目录可选**——留空即可,占位符会显示它实际使用的进程 cwd。
|
|
145
145
|
|
|
146
|
+
配置好 key 后,页面顶部会显示实时**「账户用量」卡片**——与 `/commandcode` 相同的账户、花费、额度与窗口限制信息,外加订阅套餐徽章和账期截止——数据在宿主端获取(key 不会离开宿主),并以原生 UI 渲染:
|
|
147
|
+
|
|
148
|
+
<img src="assets/screenshots/settings-page.png" alt="Command Code 设置页面(含账户用量卡片)" width="640">
|
|
149
|
+
|
|
146
150
|
同一组选项也位于 `$DSH_HOME/settings.yaml`(按请求覆盖,无需重启):
|
|
147
151
|
|
|
148
152
|
```yaml
|
|
Binary file
|
package/lib/index.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ declare const KNOWN_EFFORTS: Readonly<Record<string, readonly string[]>>;
|
|
|
24
24
|
*/
|
|
25
25
|
declare const KNOWN_IMAGE_MODELS: ReadonlySet<string>;
|
|
26
26
|
/**
|
|
27
|
-
* Models the official CLI's model table (`ZA` in command-code@1.
|
|
27
|
+
* Models the official CLI's model table (`ZA` in command-code@1.27.1) marks
|
|
28
28
|
* `reasoning:!0` but defines no selectable `reasoning_effort` levels — they
|
|
29
29
|
* think automatically, with Command Code driving the depth. This is the
|
|
30
30
|
* authoritative "thinks, effort not adjustable" set: `KNOWN_EFFORTS` (which
|
|
@@ -32,7 +32,7 @@ declare const KNOWN_IMAGE_MODELS: ReadonlySet<string>;
|
|
|
32
32
|
* effort levels, and this snapshot is not surfaced in the picker's compact
|
|
33
33
|
* description — it exists for programmatic consumers.
|
|
34
34
|
*
|
|
35
|
-
* Source: the command-code@1.
|
|
35
|
+
* Source: the command-code@1.27.1 bundled model table (dist/cli.mjs, the `ZA`
|
|
36
36
|
* object), cross-checked with https://commandcode.ai/docs/reference/cli/models.
|
|
37
37
|
* Keep in sync via the dsh-commandcode-upstream skill.
|
|
38
38
|
*/
|
|
@@ -73,7 +73,7 @@ declare function compareByPlan(a: {
|
|
|
73
73
|
}): number;
|
|
74
74
|
/**
|
|
75
75
|
* Subscription plan table, synced from the official CLI bundle's plan maps
|
|
76
|
-
* (`Nn`/`$n` in command-code@1.
|
|
76
|
+
* (`Nn`/`$n` in command-code@1.27.1 `dist/cli.mjs`): subscription `planId`
|
|
77
77
|
* prefix → display name and the plan's monthly credit total. This is the
|
|
78
78
|
* account's own subscription (from `/alpha/billing/subscriptions`) — distinct
|
|
79
79
|
* from {@link KNOWN_PLANS}, which maps catalog models to their minimum tier.
|
|
@@ -172,7 +172,7 @@ declare function peakPricingState(modelId: string, now?: number): 'peak' | 'off-
|
|
|
172
172
|
* for models without time-of-day pricing.
|
|
173
173
|
*/
|
|
174
174
|
declare function peakPricingLabel(modelId: string, now?: number): string | undefined;
|
|
175
|
-
declare const COMMAND_CODE_CLI_VERSION = "1.
|
|
175
|
+
declare const COMMAND_CODE_CLI_VERSION = "1.27.1";
|
|
176
176
|
declare const DEFAULT_API_BASE = "https://api.commandcode.ai";
|
|
177
177
|
declare const DEFAULT_GENERATE_MAX_TOKENS = 64000;
|
|
178
178
|
declare const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
|
package/lib/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import { TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
|
18
18
|
* community-maintained integration; you need your own Command Code account
|
|
19
19
|
* and API key or subscription, and Command Code's terms apply.
|
|
20
20
|
*
|
|
21
|
-
* Wire protocol (reverse-engineered by the pi plugin, command-code@1.
|
|
21
|
+
* Wire protocol (reverse-engineered by the pi plugin, command-code@1.27.1):
|
|
22
22
|
* POST {apiBase}/alpha/generate
|
|
23
23
|
* body: { config, memory, taste, skills, params: { model, messages, tools,
|
|
24
24
|
* system, max_tokens, temperature, stream, reasoning_effort? }, threadId }
|
|
@@ -224,7 +224,7 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
|
|
|
224
224
|
"xiaomi/mimo-v2.5"
|
|
225
225
|
]);
|
|
226
226
|
/**
|
|
227
|
-
* Models the official CLI's model table (`ZA` in command-code@1.
|
|
227
|
+
* Models the official CLI's model table (`ZA` in command-code@1.27.1) marks
|
|
228
228
|
* `reasoning:!0` but defines no selectable `reasoning_effort` levels — they
|
|
229
229
|
* think automatically, with Command Code driving the depth. This is the
|
|
230
230
|
* authoritative "thinks, effort not adjustable" set: `KNOWN_EFFORTS` (which
|
|
@@ -232,7 +232,7 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
|
|
|
232
232
|
* effort levels, and this snapshot is not surfaced in the picker's compact
|
|
233
233
|
* description — it exists for programmatic consumers.
|
|
234
234
|
*
|
|
235
|
-
* Source: the command-code@1.
|
|
235
|
+
* Source: the command-code@1.27.1 bundled model table (dist/cli.mjs, the `ZA`
|
|
236
236
|
* object), cross-checked with https://commandcode.ai/docs/reference/cli/models.
|
|
237
237
|
* Keep in sync via the dsh-commandcode-upstream skill.
|
|
238
238
|
*/
|
|
@@ -307,6 +307,7 @@ const KNOWN_PLANS = {
|
|
|
307
307
|
"zai-org/GLM-5.2-Fast": "go",
|
|
308
308
|
"zai-org/GLM-5.3": "go",
|
|
309
309
|
"google/gemini-3.7-flash": "goat",
|
|
310
|
+
"gpt-5.6-sol": "goat",
|
|
310
311
|
"meta/muse-spark-1.2": "goat",
|
|
311
312
|
"xai/grok-4.6": "goat",
|
|
312
313
|
"claude-haiku-4-5-20251001": "pro",
|
|
@@ -320,7 +321,6 @@ const KNOWN_PLANS = {
|
|
|
320
321
|
"gpt-5.4": "pro",
|
|
321
322
|
"gpt-5.4-mini": "pro",
|
|
322
323
|
"gpt-5.5": "pro",
|
|
323
|
-
"gpt-5.6-sol": "pro",
|
|
324
324
|
"gpt-5.6-terra": "pro",
|
|
325
325
|
"meta/muse-spark-1.1": "pro",
|
|
326
326
|
"claude-fable-5": "provider",
|
|
@@ -362,7 +362,7 @@ function compareByPlan(a, b) {
|
|
|
362
362
|
}
|
|
363
363
|
/**
|
|
364
364
|
* Subscription plan table, synced from the official CLI bundle's plan maps
|
|
365
|
-
* (`Nn`/`$n` in command-code@1.
|
|
365
|
+
* (`Nn`/`$n` in command-code@1.27.1 `dist/cli.mjs`): subscription `planId`
|
|
366
366
|
* prefix → display name and the plan's monthly credit total. This is the
|
|
367
367
|
* account's own subscription (from `/alpha/billing/subscriptions`) — distinct
|
|
368
368
|
* from {@link KNOWN_PLANS}, which maps catalog models to their minimum tier.
|
|
@@ -492,7 +492,7 @@ function peakPricingLabel(modelId, now = Date.now()) {
|
|
|
492
492
|
if (state === void 0) return void 0;
|
|
493
493
|
return state === "peak" ? "Peak" : "Half";
|
|
494
494
|
}
|
|
495
|
-
const COMMAND_CODE_CLI_VERSION = "1.
|
|
495
|
+
const COMMAND_CODE_CLI_VERSION = "1.27.1";
|
|
496
496
|
const DEFAULT_API_BASE = "https://api.commandcode.ai";
|
|
497
497
|
const DEFAULT_GENERATE_MAX_TOKENS = 64e3;
|
|
498
498
|
const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
|
|
@@ -685,14 +685,28 @@ async function writeModelsCache(cachePath, models) {
|
|
|
685
685
|
await rm(tmp, { force: true }).catch(() => void 0);
|
|
686
686
|
}
|
|
687
687
|
}
|
|
688
|
-
|
|
688
|
+
/**
|
|
689
|
+
* Collect the tool calls that have a paired tool result, plus each call's
|
|
690
|
+
* name. The name map feeds the `toolName` of replayed tool results: some
|
|
691
|
+
* backends (e.g. Google Gemini `functionResponse`) reject a result whose
|
|
692
|
+
* function name is empty, so the real name must round-trip (the official
|
|
693
|
+
* CLI does the same via its `tool_use_id -> toolName` map).
|
|
694
|
+
*/
|
|
695
|
+
function pairedToolCalls(messages) {
|
|
689
696
|
const callIds = /* @__PURE__ */ new Set();
|
|
697
|
+
const names = /* @__PURE__ */ new Map();
|
|
690
698
|
const resultIds = /* @__PURE__ */ new Set();
|
|
691
699
|
for (const message of messages) for (const block of message.content) {
|
|
692
|
-
if (message.role === "assistant" && block.type === "tool-call")
|
|
700
|
+
if (message.role === "assistant" && block.type === "tool-call") {
|
|
701
|
+
callIds.add(block.id);
|
|
702
|
+
names.set(block.id, block.name);
|
|
703
|
+
}
|
|
693
704
|
if (block.type === "tool-result") resultIds.add(block.toolCallId);
|
|
694
705
|
}
|
|
695
|
-
return
|
|
706
|
+
return {
|
|
707
|
+
ids: new Set([...callIds].filter((id) => resultIds.has(id))),
|
|
708
|
+
names
|
|
709
|
+
};
|
|
696
710
|
}
|
|
697
711
|
function blockText(block) {
|
|
698
712
|
return block.type === "text" || block.type === "reasoning" ? block.text : "";
|
|
@@ -723,7 +737,7 @@ async function imageToCommandCode(ref, readImage) {
|
|
|
723
737
|
}
|
|
724
738
|
async function messagesToCC(messages, readImage) {
|
|
725
739
|
const out = [];
|
|
726
|
-
const paired =
|
|
740
|
+
const { ids: paired, names: toolNames } = pairedToolCalls(messages);
|
|
727
741
|
for (const message of messages) {
|
|
728
742
|
if (message.role === "system") continue;
|
|
729
743
|
if (message.role === "user" && message.source.kind !== "tool") {
|
|
@@ -770,7 +784,7 @@ async function messagesToCC(messages, readImage) {
|
|
|
770
784
|
content: [{
|
|
771
785
|
type: "tool-result",
|
|
772
786
|
toolCallId: block.toolCallId,
|
|
773
|
-
toolName: "",
|
|
787
|
+
toolName: toolNames.get(block.toolCallId) || "unknown",
|
|
774
788
|
output: block.isError ? {
|
|
775
789
|
type: "error-text",
|
|
776
790
|
value: toolResultText(block)
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/adapter.ts","../src/commands.ts","../src/usage-wire.ts","../src/usage-remote.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 * Subscription plan table, synced from the official CLI bundle's plan maps\n * (`Nn`/`$n` in command-code@1.26.0 `dist/cli.mjs`): subscription `planId`\n * prefix → display name and the plan's monthly credit total. This is the\n * account's own subscription (from `/alpha/billing/subscriptions`) — distinct\n * from {@link KNOWN_PLANS}, which maps catalog models to their minimum tier.\n *\n * `tierWeight` is plugin-added (not from the CLI maps): the plan's rank on\n * the {@link PLAN_ORDER} scale, used by the picker's plan filter\n * ({@link modelVisibleInPlan}) to hide models above the account's tier.\n */\nexport const KNOWN_SUBSCRIPTION_PLANS: Readonly<Record<string, { name: string; monthlyCredits: number; tierWeight: number }>> = {\n 'individual-go': { name: 'Go', monthlyCredits: 10, tierWeight: 0 },\n 'individual-goat': { name: 'GOAT', monthlyCredits: 70, tierWeight: 1 },\n 'individual-pro': { name: 'Pro', monthlyCredits: 30, tierWeight: 2 },\n 'individual-pro-v1': { name: 'Pro', monthlyCredits: 80, tierWeight: 2 },\n 'individual-provider': { name: 'Provider', monthlyCredits: 15, tierWeight: 3 },\n 'individual-max': { name: 'Max', monthlyCredits: 150, tierWeight: 4 },\n 'individual-ultra': { name: 'Ultra', monthlyCredits: 300, tierWeight: 4 },\n 'teams-pro': { name: 'Teams Pro', monthlyCredits: 40, tierWeight: 2 },\n}\n\n/** Plan-id prefixes, longest first — the CLI's prefix-match order. */\nconst SUBSCRIPTION_PLAN_PREFIXES = Object.keys(KNOWN_SUBSCRIPTION_PLANS).sort((a, b) => b.length - a.length)\n\n/**\n * Resolve a subscription `planId` (e.g. `individual-pro-v1`) to its display\n * name and monthly credit total, mirroring the CLI's `getPlanInfo`:\n * normalize (lowercase, `_` → `-`), then longest-prefix match so\n * `individual-pro-v1` wins over `individual-pro`. Unknown ids return\n * `undefined`.\n */\nexport function subscriptionPlanInfo(planId: string): { name: string; monthlyCredits: number; tierWeight: number } | undefined {\n const normalized = planId.toLowerCase().replace(/_/g, '-')\n const prefix = SUBSCRIPTION_PLAN_PREFIXES.find((candidate) => normalized.startsWith(candidate))\n return prefix === undefined ? undefined : KNOWN_SUBSCRIPTION_PLANS[prefix]\n}\n\n/**\n * The billing facts the picker's plan filter needs, fetched by mirroring the\n * CLI's `createBilling` flow (whoami → orgId, then `/alpha/billing/subscriptions`\n * for the plan id and `/alpha/billing/credits` for the on-demand balances).\n */\nexport interface CommandCodeBillingAccess {\n /** Account plan tier weight on the {@link PLAN_ORDER} scale; undefined when the plan is unknown. */\n tierWeight: number | undefined\n /**\n * Purchased + free on-demand credit balance. The official access model\n * (`evaluateModelAccess` in the CLI) allows every model when the account\n * holds any on-demand credits — the plan gate only applies at zero balance.\n */\n onDemandCredits: number\n}\n\n/**\n * Whether the picker lists `modelId` for an account with the given billing\n * access. Fails open at every uncertainty: no billing data, an unknown plan,\n * or a model outside {@link KNOWN_PLANS} all keep the model visible — the\n * server remains the final gate (`403 MODEL_NOT_IN_PLAN`).\n */\nexport function modelVisibleInPlan(modelId: string, access: CommandCodeBillingAccess | undefined): boolean {\n if (access === undefined) return true\n if (access.onDemandCredits > 0) return true\n if (access.tierWeight === undefined) return true\n const tier = KNOWN_PLANS[modelId]\n if (tier === undefined) return true\n const weight = PLAN_ORDER[tier]\n if (weight === undefined) return true\n return weight <= access.tierWeight\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/** How long the picker's plan-filter billing facts stay cached before refetching. */\nexport const BILLING_ACCESS_TTL_MS = 5 * 60_000\n\n/**\n * Subscription statuses the CLI treats as live (`Mr` in command-code's\n * cli.mjs): the plan gate applies only under one of these.\n */\nconst ACTIVE_SUBSCRIPTION_STATUSES: ReadonlySet<string> = new Set(['active', 'trialing', 'past_due'])\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/** Parse a billing-period timestamp (ISO string or millis) into millis; 0 when absent/invalid. */\nfunction periodEndValue(value: unknown): number {\n const asNumber = numberValue(value)\n if (asNumber !== undefined) return asNumber\n const asString = stringValue(value)\n if (asString === undefined) return 0\n const parsed = Date.parse(asString)\n return Number.isNaN(parsed) ? 0 : parsed\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 * Whether the picker hides models above the account's subscription tier\n * (default true). The filter fails open: unknown plan, billing-endpoint\n * failure, a positive on-demand credit balance, or an unmapped model all\n * keep the full catalog visible. Set false to always list every model.\n */\n filterModelsByPlan?: boolean\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/** Subscription plan state from `/alpha/billing/subscriptions`. */\nexport interface CommandCodePlan {\n /** Raw subscription plan id (e.g. `individual-pro`); empty when unreported. */\n planId: string\n /** Display name (e.g. `Pro`); falls back to the raw id for unknown plans. */\n name: string\n /** Raw subscription status (`active`, `trialing`, `past_due`, …); empty when unreported. */\n status: string\n /** The plan's monthly credit total per {@link KNOWN_SUBSCRIPTION_PLANS}; null for unknown plans. */\n monthlyCredits: number | null\n /** Billing period end in millis; 0 when the endpoint did not report one. */\n currentPeriodEnd: number\n}\n\n/** Everything the usage endpoints report, fetched together. */\nexport interface CommandCodeUsageReport {\n account?: CommandCodeAccount\n usage?: CommandCodeUsage\n credits?: CommandCodeCredits\n plan?: CommandCodePlan\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 private billingAccess: { value: CommandCodeBillingAccess | undefined; at: number } | undefined\n private billingAccessInflight: Promise<CommandCodeBillingAccess | undefined> | 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 // Plan filter: hide models above the account's subscription tier. Fails\n // open — a billing-fetch problem, an unknown plan, or a positive\n // on-demand balance all keep the full catalog visible, and the server\n // remains the final gate (403 MODEL_NOT_IN_PLAN). The catalog itself is\n // never filtered: resolveModel still serves every model.\n const access = this.deps.options().filterModelsByPlan === false\n ? undefined\n : await this.loadBillingAccess()\n return catalog\n .filter((model) => modelVisibleInPlan(model.id, access))\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 /** The headers every authenticated account endpoint shares. */\n private async accountHeaders(): Promise<Record<string, string>> {\n const connection = this.deps.options()\n const apiKey = await this.deps.resolveApiKey(connection)\n return {\n Authorization: `Bearer ${apiKey}`,\n 'x-command-code-version': COMMAND_CODE_CLI_VERSION,\n 'x-cli-environment': 'production',\n ...attributionHeaders(),\n }\n }\n\n /**\n * The billing facts behind the picker's plan filter, cached for\n * {@link BILLING_ACCESS_TTL_MS} and shared across concurrent callers.\n * `undefined` means \"unknown — show everything\" (fail-open).\n */\n private async loadBillingAccess(): Promise<CommandCodeBillingAccess | undefined> {\n const cached = this.billingAccess\n if (cached !== undefined && Date.now() - cached.at < BILLING_ACCESS_TTL_MS) return cached.value\n this.billingAccessInflight ??= this.fetchBillingAccess()\n .then((value) => {\n this.billingAccess = { value, at: Date.now() }\n return value\n })\n .finally(() => {\n this.billingAccessInflight = undefined\n })\n return this.billingAccessInflight\n }\n\n /**\n * The billing facts behind the picker's plan filter, mirroring the CLI's\n * `createBilling` flow: whoami yields the org id, then the subscriptions\n * and credits endpoints answer in parallel. The plan id is honored only\n * when the subscription reports an active-ish status (the CLI's rule); when\n * the subscriptions endpoint fails entirely, `credits.planId` is the\n * fallback (the CLI stamps plan identity from it too). Any failure resolves\n * to `undefined` (fail-open) rather than breaking the picker.\n */\n private async fetchBillingAccess(): Promise<CommandCodeBillingAccess | undefined> {\n try {\n const connection = this.deps.options()\n const headers = await this.accountHeaders()\n const base = connection.apiBase\n const getJson = async (path: string): Promise<Record<string, unknown> | undefined> => {\n const response = await this.fetchImpl(`${base}${path}`, {\n headers,\n // A hung billing connection must not stall the picker forever.\n signal: AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) return undefined\n const parsed: unknown = await response.json()\n return isRecord(parsed) ? parsed : undefined\n }\n const whoami = await getJson('/alpha/whoami')\n const orgData = whoami && isRecord(whoami.org) ? whoami.org : undefined\n const orgId = orgData === undefined ? undefined : stringValue(orgData.id)\n const [subscription, credits] = await Promise.all([\n getJson(orgId === undefined\n ? '/alpha/billing/subscriptions'\n : `/alpha/billing/subscriptions?orgId=${encodeURIComponent(orgId)}`),\n getJson('/alpha/billing/credits'),\n ])\n const subData = subscription && isRecord(subscription.data) ? subscription.data : undefined\n const creditsData = credits && isRecord(credits.credits) ? credits.credits : undefined\n if (subData === undefined && creditsData === undefined) return undefined\n let planId: string | undefined\n if (subData !== undefined) {\n const status = stringValue(subData.status)\n if (status !== undefined && ACTIVE_SUBSCRIPTION_STATUSES.has(status)) planId = stringValue(subData.planId)\n } else {\n planId = stringValue(creditsData?.planId)\n }\n return {\n tierWeight: planId === undefined ? undefined : subscriptionPlanInfo(planId)?.tierWeight,\n onDemandCredits: (numberValue(creditsData?.purchasedCredits) ?? 0) + (numberValue(creditsData?.freeCredits) ?? 0),\n }\n } catch {\n return undefined\n }\n }\n\n /**\n * Fetch account, usage, credit, and subscription state from the Command\n * Code account endpoints (`/alpha/whoami`, `/alpha/usage/summary`,\n * `/alpha/billing/credits`, `/alpha/billing/subscriptions`).\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 base = connection.apiBase\n const headers = await this.accountHeaders()\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}`, {\n headers,\n // A hung account endpoint degrades into `failures` instead of\n // stalling the usage card / command forever.\n signal: AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\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 (+ org id for the billing endpoints).\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 const orgData = whoami && isRecord(whoami.org) ? whoami.org : undefined\n const orgId = orgData === undefined ? undefined : stringValue(orgData.id)\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 // billing/subscriptions -> plan identity + billing period. The credits\n // response may also carry a planId; it is the fallback when the\n // subscriptions endpoint fails. Mirrors the CLI: orgId rides as a query\n // param when whoami reported one.\n const subscription = await getJson(orgId === undefined\n ? '/alpha/billing/subscriptions'\n : `/alpha/billing/subscriptions?orgId=${encodeURIComponent(orgId)}`)\n const subData = subscription && isRecord(subscription.data) ? subscription.data : undefined\n const planId = stringValue(subData?.planId) ?? stringValue(creditsData?.planId)\n if (subData !== undefined || planId !== undefined) {\n const info = planId === undefined ? undefined : subscriptionPlanInfo(planId)\n report.plan = {\n planId: planId ?? '',\n name: info?.name ?? planId ?? '',\n status: stringValue(subData?.status) ?? '',\n monthlyCredits: info?.monthlyCredits ?? null,\n currentPeriodEnd: periodEndValue(subData?.currentPeriodEnd),\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.plan && report.plan.name !== '') {\n const p = report.plan\n const status = p.status !== '' && p.status !== 'active' ? ` (${p.status})` : ''\n const period = p.currentPeriodEnd > 0 ? ` · 账期截止 ${new Date(p.currentPeriodEnd).toLocaleDateString()}` : ''\n lines.push(` 📦 套餐 ${p.name}${status}${period}`, '')\n }\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 * Wire contract for the Command Code account-usage Remote\n * (`commandcode/report`).\n *\n * The settings page renders the same account/usage/credit facts the\n * `/commandcode` command prints, but the browser never holds the API key —\n * the report must be produced Host-side and cross the Connection RPC carrier.\n * The harness exposes plugin-defined Host methods through the Typert Gateway:\n * the Host half registers a strict invocation descriptor against a Cordis\n * service (`src/usage-remote.ts`), and the browser half mounts the matching\n * Remote contribution on `ctx.remote` (`src/client/index.ts`).\n *\n * This module is the single source both halves share: the result validator\n * (a hand-rolled {@link TypertSchema}, so neither half needs a schema library)\n * and the exact descriptor object, so the endpoint can never drift apart.\n * It is deliberately dependency-free — the client bundle inlines it, and only\n * `import type` edges leave it (erased at build).\n *\n * @module dsh-commandcode-provider/usage-wire\n */\n\nimport type { CommandCodeUsageReport } from './adapter.ts'\nimport type { InvocationDescriptor, TypertRemoteContribution, TypertSchema } from '@deepseek-ai/dsh-typert-protocol'\n\n/** The npm package identity both contribution registrations claim. */\nexport const USAGE_REMOTE_PACKAGE = '@mars-sea/dsh-commandcode-provider'\n\n/** Canonical `<namespace>/<method>` endpoint of the usage report Remote. */\nexport const USAGE_REPORT_ENDPOINT = 'commandcode/report'\n\n/** Reject one boundary value with a field-naming error. */\nfunction reject(field: string): never {\n throw new TypeError(`commandcode/report result: invalid ${field}`)\n}\n\n/** Read one required finite number field (`field` is the dotted error label). */\nfunction numberField(source: Record<string, unknown>, key: string, field: string): number {\n const value = source[key]\n if (typeof value !== 'number' || !Number.isFinite(value)) reject(field)\n return value\n}\n\n/** Read one required string field (`field` is the dotted error label). */\nfunction stringField(source: Record<string, unknown>, key: string, field: string): string {\n const value = source[key]\n if (typeof value !== 'string') reject(field)\n return value\n}\n\n/** Read one required boolean field (`field` is the dotted error label). */\nfunction booleanField(source: Record<string, unknown>, key: string, field: string): boolean {\n const value = source[key]\n if (typeof value !== 'boolean') reject(field)\n return value\n}\n\n/** Narrow an unknown value to a plain record, or reject. */\nfunction record(value: unknown, field: string): Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) reject(field)\n return value as Record<string, unknown>\n}\n\n/** Validate one window-limit block (`fiveHour` / `weekly`). */\nfunction windowLimit(value: unknown, field: string): { used: number; cap: number; exceeded: boolean; resetAt: number } {\n const source = record(value, field)\n return {\n used: numberField(source, 'used', `${field}.used`),\n cap: numberField(source, 'cap', `${field}.cap`),\n exceeded: booleanField(source, 'exceeded', `${field}.exceeded`),\n resetAt: numberField(source, 'resetAt', `${field}.resetAt`),\n }\n}\n\n/**\n * Parse one untrusted boundary value into a {@link CommandCodeUsageReport}.\n * Optional sections stay optional; every present field is shape-checked so a\n * malformed frame fails the boundary instead of rendering garbage.\n */\nfunction parseUsageReport(value: unknown): CommandCodeUsageReport {\n const source = record(value, 'report')\n const failures = source.failures\n if (!Array.isArray(failures) || failures.some((entry) => typeof entry !== 'string')) reject('failures')\n const report: CommandCodeUsageReport = { failures: failures as string[] }\n\n if (source.account !== undefined) {\n const account = record(source.account, 'account')\n report.account = {\n id: stringField(account, 'id', 'account.id'),\n name: stringField(account, 'name', 'account.name'),\n userName: stringField(account, 'userName', 'account.userName'),\n }\n }\n\n if (source.usage !== undefined) {\n const usage = record(source.usage, 'usage')\n report.usage = {\n totalCount: numberField(usage, 'totalCount', 'usage.totalCount'),\n totalCost: numberField(usage, 'totalCost', 'usage.totalCost'),\n successRate: numberField(usage, 'successRate', 'usage.successRate'),\n completedCount: numberField(usage, 'completedCount', 'usage.completedCount'),\n failedCount: numberField(usage, 'failedCount', 'usage.failedCount'),\n totalTokensIn: numberField(usage, 'totalTokensIn', 'usage.totalTokensIn'),\n totalTokensOut: numberField(usage, 'totalTokensOut', 'usage.totalTokensOut'),\n totalCredits: numberField(usage, 'totalCredits', 'usage.totalCredits'),\n periodBasis: stringField(usage, 'periodBasis', 'usage.periodBasis'),\n }\n }\n\n if (source.credits !== undefined) {\n const credits = record(source.credits, 'credits')\n report.credits = {\n monthlyCredits: numberField(credits, 'monthlyCredits', 'credits.monthlyCredits'),\n purchasedCredits: numberField(credits, 'purchasedCredits', 'credits.purchasedCredits'),\n freeCredits: numberField(credits, 'freeCredits', 'credits.freeCredits'),\n fiveHour: windowLimit(credits.fiveHour, 'credits.fiveHour'),\n weekly: windowLimit(credits.weekly, 'credits.weekly'),\n }\n }\n\n if (source.plan !== undefined) {\n const plan = record(source.plan, 'plan')\n const monthly = plan.monthlyCredits\n if (monthly !== null && (typeof monthly !== 'number' || !Number.isFinite(monthly))) reject('plan.monthlyCredits')\n report.plan = {\n planId: stringField(plan, 'planId', 'plan.planId'),\n name: stringField(plan, 'name', 'plan.name'),\n status: stringField(plan, 'status', 'plan.status'),\n monthlyCredits: monthly as number | null,\n currentPeriodEnd: numberField(plan, 'currentPeriodEnd', 'plan.currentPeriodEnd'),\n }\n }\n\n return report\n}\n\n/**\n * The strict result codec both halves attach to the descriptor. Hand-rolled:\n * the client bundle may not require a schema library, and `TypertSchema` is\n * deliberately minimal so one `parse` function satisfies it.\n */\nexport const usageReportSchema: TypertSchema<CommandCodeUsageReport> = {\n parse: parseUsageReport,\n}\n\n/**\n * The one invocation descriptor, shared verbatim by the Host registration and\n * the Client mount. `service` names the Cordis key the Gateway resolves the\n * receiver from; `namespace`/`method` name the wire endpoint.\n */\nexport const USAGE_REPORT_DESCRIPTOR: InvocationDescriptor = {\n id: `${USAGE_REMOTE_PACKAGE}#${USAGE_REPORT_ENDPOINT}`,\n service: 'commandcodeUsage',\n namespace: 'commandcode',\n method: 'report',\n invocation: { kind: 'direct' },\n parameters: [],\n result: {\n mode: 'strict',\n typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeUsageReport`,\n schema: usageReportSchema,\n },\n}\n\n/** The Host-face contribution registered on `ctx.typert`. */\nexport const USAGE_HOST_CONTRIBUTION = {\n package: USAGE_REMOTE_PACKAGE,\n face: 'host' as const,\n schemas: [],\n invocations: [USAGE_REPORT_DESCRIPTOR],\n}\n\n/** The Client-face contribution mounted on `ctx.remote`. */\nexport const USAGE_REMOTE_CONTRIBUTION: TypertRemoteContribution = {\n package: USAGE_REMOTE_PACKAGE,\n descriptors: [USAGE_REPORT_DESCRIPTOR],\n}\n","/**\n * Host half of the account-usage Remote (`commandcode/report`).\n *\n * The settings page's account card needs the same report the `/commandcode`\n * command prints, but the browser never holds the API key — the fetch must\n * run Host-side. This module exposes `adapter.getUsage()` through the Typert\n * Gateway: a `TypertRemoteService` provides the receiver the Gateway resolves,\n * and the shared strict descriptor (`src/usage-wire.ts`) is registered on the\n * `typert` registry so the Gateway claims the `commandcode/report` endpoint.\n *\n * The whole wiring rides an optional `ctx.inject(['typert'], ...)` fiber: a\n * profile without the web stack (no Typert registry, no Gateway) simply never\n * activates it, exactly like the `/commandcode` command rides `commands`.\n *\n * @module dsh-commandcode-provider/usage-remote\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'\nimport type { CommandCodeAdapter, CommandCodeConnectionOptions, CommandCodeUsageReport } from './adapter.ts'\nimport { USAGE_HOST_CONTRIBUTION } from './usage-wire.ts'\n\n/** Everything the usage service needs beyond its Cordis context. */\nexport interface CommandCodeUsageDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {\n /** The registered adapter (for getUsage). */\n adapter: CommandCodeAdapter<C>\n}\n\n/**\n * The registry method surface this module uses. `Context['typert']` is typed\n * as the read-only `TypertRegistryContract`; contribution registration lives\n * on the concrete registry service, so the cast is spelled out once here.\n */\ninterface TypertContributionRegistry {\n register(contribution: typeof USAGE_HOST_CONTRIBUTION): () => void | Promise<void>\n}\n\n/**\n * The Remote receiver: a Cordis service the Gateway resolves by key\n * (`commandcodeUsage`) and binds to the wire namespace (`commandcode`). The\n * base class stamps the `typertRemote` binding the Gateway validates on every\n * dispatch; no decorators are needed because the descriptor is registered\n * explicitly (strict path) rather than discovered from source markers.\n */\nexport class CommandCodeUsageService<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions>\n extends TypertRemoteService {\n private readonly deps: CommandCodeUsageDeps<C>\n\n constructor(ctx: Context, deps: CommandCodeUsageDeps<C>) {\n super(ctx, 'commandcodeUsage', { namespace: 'commandcode' })\n this.deps = deps\n }\n\n /**\n * Account, usage, and credit state for the settings page's account card.\n * Degrades per endpoint like the `/commandcode` command (failures land in\n * `report.failures`); throws `MISSING_CREDENTIAL` when no key resolves, which\n * the Gateway folds into the failure branch the page renders as a hint.\n */\n async report(): Promise<CommandCodeUsageReport> {\n return this.deps.adapter.getUsage()\n }\n}\n\n/**\n * Provide the usage service and register its Remote descriptor. The registry\n * contribution is tied to this fiber's lifetime: the registry's own\n * `register()` effect would otherwise outlive the plugin.\n */\nexport function applyUsageRemote<C extends CommandCodeConnectionOptions>(\n ctx: Context,\n deps: CommandCodeUsageDeps<C>,\n): void {\n ctx.inject(['typert'], (remoteCtx) => {\n new CommandCodeUsageService(remoteCtx, deps)\n const registry = remoteCtx.typert as unknown as TypertContributionRegistry\n const unregister = registry.register(USAGE_HOST_CONTRIBUTION)\n // The registry's own effect would outlive this fiber; withdraw the\n // contribution when the plugin unloads.\n remoteCtx.effect(() => () => void unregister(), 'dsh-commandcode-provider: usage remote')\n })\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'\nimport { applyUsageRemote } from './usage-remote.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_SUBSCRIPTION_PLANS,\n KNOWN_DEALS,\n KNOWN_PEAK_PRICING,\n PLAN_LABELS,\n PLAN_ORDER,\n BILLING_ACCESS_TTL_MS,\n capabilityDescription,\n compareByPlan,\n dealLabel,\n formatContext,\n modelVisibleInPlan,\n peakPricingLabel,\n peakPricingState,\n planLabel,\n projectSlugFromPath,\n resolveAuthFileApiKey,\n subscriptionPlanInfo,\n} from './adapter.ts'\nexport type { CommandCodeAdapterDeps, CommandCodeBillingAccess, CommandCodeConnectionOptions, CommandCodeUsageReport, ResolveAttachments } from './adapter.ts'\nexport { applyCommands, commandDefinition } from './commands.ts'\nexport type { CommandCodeCommandDeps } from './commands.ts'\nexport { applyUsageRemote, CommandCodeUsageService } from './usage-remote.ts'\nexport type { CommandCodeUsageDeps } from './usage-remote.ts'\nexport { USAGE_REPORT_ENDPOINT, usageReportSchema } from './usage-wire.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 * Whether the model picker hides models above the account's subscription\n * tier; defaults to true. The filter fails open (unknown plan, billing\n * endpoint failure, or a positive on-demand credit balance all keep the\n * full catalog visible). Set false to always list every model.\n */\n filterModelsByPlan?: boolean\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 filterModelsByPlan: z.boolean(),\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 filterModelsByPlan: config.filterModelsByPlan ?? true,\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 // The settings page's account card: getUsage exposed to the browser through\n // the Typert Gateway (`commandcode/report`). Rides the optional `typert`\n // registry service, so profiles without the web stack never activate it.\n applyUsageRemote(ctx, { adapter })\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/usage-wire.ts","../src/usage-remote.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.27.1):\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.27.1 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.27.1 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.27.1) 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.27.1 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 (4 more) ---\n 'google/gemini-3.7-flash': 'goat',\n 'gpt-5.6-sol': 'goat',\n 'meta/muse-spark-1.2': 'goat',\n 'xai/grok-4.6': 'goat',\n // --- Pro (13 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-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 * Subscription plan table, synced from the official CLI bundle's plan maps\n * (`Nn`/`$n` in command-code@1.27.1 `dist/cli.mjs`): subscription `planId`\n * prefix → display name and the plan's monthly credit total. This is the\n * account's own subscription (from `/alpha/billing/subscriptions`) — distinct\n * from {@link KNOWN_PLANS}, which maps catalog models to their minimum tier.\n *\n * `tierWeight` is plugin-added (not from the CLI maps): the plan's rank on\n * the {@link PLAN_ORDER} scale, used by the picker's plan filter\n * ({@link modelVisibleInPlan}) to hide models above the account's tier.\n */\nexport const KNOWN_SUBSCRIPTION_PLANS: Readonly<Record<string, { name: string; monthlyCredits: number; tierWeight: number }>> = {\n 'individual-go': { name: 'Go', monthlyCredits: 10, tierWeight: 0 },\n 'individual-goat': { name: 'GOAT', monthlyCredits: 70, tierWeight: 1 },\n 'individual-pro': { name: 'Pro', monthlyCredits: 30, tierWeight: 2 },\n 'individual-pro-v1': { name: 'Pro', monthlyCredits: 80, tierWeight: 2 },\n 'individual-provider': { name: 'Provider', monthlyCredits: 15, tierWeight: 3 },\n 'individual-max': { name: 'Max', monthlyCredits: 150, tierWeight: 4 },\n 'individual-ultra': { name: 'Ultra', monthlyCredits: 300, tierWeight: 4 },\n 'teams-pro': { name: 'Teams Pro', monthlyCredits: 40, tierWeight: 2 },\n}\n\n/** Plan-id prefixes, longest first — the CLI's prefix-match order. */\nconst SUBSCRIPTION_PLAN_PREFIXES = Object.keys(KNOWN_SUBSCRIPTION_PLANS).sort((a, b) => b.length - a.length)\n\n/**\n * Resolve a subscription `planId` (e.g. `individual-pro-v1`) to its display\n * name and monthly credit total, mirroring the CLI's `getPlanInfo`:\n * normalize (lowercase, `_` → `-`), then longest-prefix match so\n * `individual-pro-v1` wins over `individual-pro`. Unknown ids return\n * `undefined`.\n */\nexport function subscriptionPlanInfo(planId: string): { name: string; monthlyCredits: number; tierWeight: number } | undefined {\n const normalized = planId.toLowerCase().replace(/_/g, '-')\n const prefix = SUBSCRIPTION_PLAN_PREFIXES.find((candidate) => normalized.startsWith(candidate))\n return prefix === undefined ? undefined : KNOWN_SUBSCRIPTION_PLANS[prefix]\n}\n\n/**\n * The billing facts the picker's plan filter needs, fetched by mirroring the\n * CLI's `createBilling` flow (whoami → orgId, then `/alpha/billing/subscriptions`\n * for the plan id and `/alpha/billing/credits` for the on-demand balances).\n */\nexport interface CommandCodeBillingAccess {\n /** Account plan tier weight on the {@link PLAN_ORDER} scale; undefined when the plan is unknown. */\n tierWeight: number | undefined\n /**\n * Purchased + free on-demand credit balance. The official access model\n * (`evaluateModelAccess` in the CLI) allows every model when the account\n * holds any on-demand credits — the plan gate only applies at zero balance.\n */\n onDemandCredits: number\n}\n\n/**\n * Whether the picker lists `modelId` for an account with the given billing\n * access. Fails open at every uncertainty: no billing data, an unknown plan,\n * or a model outside {@link KNOWN_PLANS} all keep the model visible — the\n * server remains the final gate (`403 MODEL_NOT_IN_PLAN`).\n */\nexport function modelVisibleInPlan(modelId: string, access: CommandCodeBillingAccess | undefined): boolean {\n if (access === undefined) return true\n if (access.onDemandCredits > 0) return true\n if (access.tierWeight === undefined) return true\n const tier = KNOWN_PLANS[modelId]\n if (tier === undefined) return true\n const weight = PLAN_ORDER[tier]\n if (weight === undefined) return true\n return weight <= access.tierWeight\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.27.1'\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/** How long the picker's plan-filter billing facts stay cached before refetching. */\nexport const BILLING_ACCESS_TTL_MS = 5 * 60_000\n\n/**\n * Subscription statuses the CLI treats as live (`Mr` in command-code's\n * cli.mjs): the plan gate applies only under one of these.\n */\nconst ACTIVE_SUBSCRIPTION_STATUSES: ReadonlySet<string> = new Set(['active', 'trialing', 'past_due'])\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/** Parse a billing-period timestamp (ISO string or millis) into millis; 0 when absent/invalid. */\nfunction periodEndValue(value: unknown): number {\n const asNumber = numberValue(value)\n if (asNumber !== undefined) return asNumber\n const asString = stringValue(value)\n if (asString === undefined) return 0\n const parsed = Date.parse(asString)\n return Number.isNaN(parsed) ? 0 : parsed\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\n/**\n * Collect the tool calls that have a paired tool result, plus each call's\n * name. The name map feeds the `toolName` of replayed tool results: some\n * backends (e.g. Google Gemini `functionResponse`) reject a result whose\n * function name is empty, so the real name must round-trip (the official\n * CLI does the same via its `tool_use_id -> toolName` map).\n */\nfunction pairedToolCalls(messages: readonly Message[]): {\n ids: Set<string>\n names: Map<string, string>\n} {\n const callIds = new Set<string>()\n const names = new Map<string, 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') {\n callIds.add(block.id)\n names.set(block.id, block.name)\n }\n if (block.type === 'tool-result') resultIds.add(block.toolCallId)\n }\n }\n return { ids: new Set([...callIds].filter((id) => resultIds.has(id))), names }\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 { ids: paired, names: toolNames } = pairedToolCalls(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 // `paired` guarantees a call with this id exists, so the map\n // always hits; `|| 'unknown'` also guards an empty call name\n // (matches the official CLI's `?? \"unknown\"` fallback).\n toolName: toolNames.get(block.toolCallId) || 'unknown',\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 * Whether the picker hides models above the account's subscription tier\n * (default true). The filter fails open: unknown plan, billing-endpoint\n * failure, a positive on-demand credit balance, or an unmapped model all\n * keep the full catalog visible. Set false to always list every model.\n */\n filterModelsByPlan?: boolean\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/** Subscription plan state from `/alpha/billing/subscriptions`. */\nexport interface CommandCodePlan {\n /** Raw subscription plan id (e.g. `individual-pro`); empty when unreported. */\n planId: string\n /** Display name (e.g. `Pro`); falls back to the raw id for unknown plans. */\n name: string\n /** Raw subscription status (`active`, `trialing`, `past_due`, …); empty when unreported. */\n status: string\n /** The plan's monthly credit total per {@link KNOWN_SUBSCRIPTION_PLANS}; null for unknown plans. */\n monthlyCredits: number | null\n /** Billing period end in millis; 0 when the endpoint did not report one. */\n currentPeriodEnd: number\n}\n\n/** Everything the usage endpoints report, fetched together. */\nexport interface CommandCodeUsageReport {\n account?: CommandCodeAccount\n usage?: CommandCodeUsage\n credits?: CommandCodeCredits\n plan?: CommandCodePlan\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 private billingAccess: { value: CommandCodeBillingAccess | undefined; at: number } | undefined\n private billingAccessInflight: Promise<CommandCodeBillingAccess | undefined> | 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 // Plan filter: hide models above the account's subscription tier. Fails\n // open — a billing-fetch problem, an unknown plan, or a positive\n // on-demand balance all keep the full catalog visible, and the server\n // remains the final gate (403 MODEL_NOT_IN_PLAN). The catalog itself is\n // never filtered: resolveModel still serves every model.\n const access = this.deps.options().filterModelsByPlan === false\n ? undefined\n : await this.loadBillingAccess()\n return catalog\n .filter((model) => modelVisibleInPlan(model.id, access))\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 /** The headers every authenticated account endpoint shares. */\n private async accountHeaders(): Promise<Record<string, string>> {\n const connection = this.deps.options()\n const apiKey = await this.deps.resolveApiKey(connection)\n return {\n Authorization: `Bearer ${apiKey}`,\n 'x-command-code-version': COMMAND_CODE_CLI_VERSION,\n 'x-cli-environment': 'production',\n ...attributionHeaders(),\n }\n }\n\n /**\n * The billing facts behind the picker's plan filter, cached for\n * {@link BILLING_ACCESS_TTL_MS} and shared across concurrent callers.\n * `undefined` means \"unknown — show everything\" (fail-open).\n */\n private async loadBillingAccess(): Promise<CommandCodeBillingAccess | undefined> {\n const cached = this.billingAccess\n if (cached !== undefined && Date.now() - cached.at < BILLING_ACCESS_TTL_MS) return cached.value\n this.billingAccessInflight ??= this.fetchBillingAccess()\n .then((value) => {\n this.billingAccess = { value, at: Date.now() }\n return value\n })\n .finally(() => {\n this.billingAccessInflight = undefined\n })\n return this.billingAccessInflight\n }\n\n /**\n * The billing facts behind the picker's plan filter, mirroring the CLI's\n * `createBilling` flow: whoami yields the org id, then the subscriptions\n * and credits endpoints answer in parallel. The plan id is honored only\n * when the subscription reports an active-ish status (the CLI's rule); when\n * the subscriptions endpoint fails entirely, `credits.planId` is the\n * fallback (the CLI stamps plan identity from it too). Any failure resolves\n * to `undefined` (fail-open) rather than breaking the picker.\n */\n private async fetchBillingAccess(): Promise<CommandCodeBillingAccess | undefined> {\n try {\n const connection = this.deps.options()\n const headers = await this.accountHeaders()\n const base = connection.apiBase\n const getJson = async (path: string): Promise<Record<string, unknown> | undefined> => {\n const response = await this.fetchImpl(`${base}${path}`, {\n headers,\n // A hung billing connection must not stall the picker forever.\n signal: AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) return undefined\n const parsed: unknown = await response.json()\n return isRecord(parsed) ? parsed : undefined\n }\n const whoami = await getJson('/alpha/whoami')\n const orgData = whoami && isRecord(whoami.org) ? whoami.org : undefined\n const orgId = orgData === undefined ? undefined : stringValue(orgData.id)\n const [subscription, credits] = await Promise.all([\n getJson(orgId === undefined\n ? '/alpha/billing/subscriptions'\n : `/alpha/billing/subscriptions?orgId=${encodeURIComponent(orgId)}`),\n getJson('/alpha/billing/credits'),\n ])\n const subData = subscription && isRecord(subscription.data) ? subscription.data : undefined\n const creditsData = credits && isRecord(credits.credits) ? credits.credits : undefined\n if (subData === undefined && creditsData === undefined) return undefined\n let planId: string | undefined\n if (subData !== undefined) {\n const status = stringValue(subData.status)\n if (status !== undefined && ACTIVE_SUBSCRIPTION_STATUSES.has(status)) planId = stringValue(subData.planId)\n } else {\n planId = stringValue(creditsData?.planId)\n }\n return {\n tierWeight: planId === undefined ? undefined : subscriptionPlanInfo(planId)?.tierWeight,\n onDemandCredits: (numberValue(creditsData?.purchasedCredits) ?? 0) + (numberValue(creditsData?.freeCredits) ?? 0),\n }\n } catch {\n return undefined\n }\n }\n\n /**\n * Fetch account, usage, credit, and subscription state from the Command\n * Code account endpoints (`/alpha/whoami`, `/alpha/usage/summary`,\n * `/alpha/billing/credits`, `/alpha/billing/subscriptions`).\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 base = connection.apiBase\n const headers = await this.accountHeaders()\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}`, {\n headers,\n // A hung account endpoint degrades into `failures` instead of\n // stalling the usage card / command forever.\n signal: AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\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 (+ org id for the billing endpoints).\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 const orgData = whoami && isRecord(whoami.org) ? whoami.org : undefined\n const orgId = orgData === undefined ? undefined : stringValue(orgData.id)\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 // billing/subscriptions -> plan identity + billing period. The credits\n // response may also carry a planId; it is the fallback when the\n // subscriptions endpoint fails. Mirrors the CLI: orgId rides as a query\n // param when whoami reported one.\n const subscription = await getJson(orgId === undefined\n ? '/alpha/billing/subscriptions'\n : `/alpha/billing/subscriptions?orgId=${encodeURIComponent(orgId)}`)\n const subData = subscription && isRecord(subscription.data) ? subscription.data : undefined\n const planId = stringValue(subData?.planId) ?? stringValue(creditsData?.planId)\n if (subData !== undefined || planId !== undefined) {\n const info = planId === undefined ? undefined : subscriptionPlanInfo(planId)\n report.plan = {\n planId: planId ?? '',\n name: info?.name ?? planId ?? '',\n status: stringValue(subData?.status) ?? '',\n monthlyCredits: info?.monthlyCredits ?? null,\n currentPeriodEnd: periodEndValue(subData?.currentPeriodEnd),\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.plan && report.plan.name !== '') {\n const p = report.plan\n const status = p.status !== '' && p.status !== 'active' ? ` (${p.status})` : ''\n const period = p.currentPeriodEnd > 0 ? ` · 账期截止 ${new Date(p.currentPeriodEnd).toLocaleDateString()}` : ''\n lines.push(` 📦 套餐 ${p.name}${status}${period}`, '')\n }\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 * Wire contract for the Command Code account-usage Remote\n * (`commandcode/report`).\n *\n * The settings page renders the same account/usage/credit facts the\n * `/commandcode` command prints, but the browser never holds the API key —\n * the report must be produced Host-side and cross the Connection RPC carrier.\n * The harness exposes plugin-defined Host methods through the Typert Gateway:\n * the Host half registers a strict invocation descriptor against a Cordis\n * service (`src/usage-remote.ts`), and the browser half mounts the matching\n * Remote contribution on `ctx.remote` (`src/client/index.ts`).\n *\n * This module is the single source both halves share: the result validator\n * (a hand-rolled {@link TypertSchema}, so neither half needs a schema library)\n * and the exact descriptor object, so the endpoint can never drift apart.\n * It is deliberately dependency-free — the client bundle inlines it, and only\n * `import type` edges leave it (erased at build).\n *\n * @module dsh-commandcode-provider/usage-wire\n */\n\nimport type { CommandCodeUsageReport } from './adapter.ts'\nimport type { InvocationDescriptor, TypertRemoteContribution, TypertSchema } from '@deepseek-ai/dsh-typert-protocol'\n\n/** The npm package identity both contribution registrations claim. */\nexport const USAGE_REMOTE_PACKAGE = '@mars-sea/dsh-commandcode-provider'\n\n/** Canonical `<namespace>/<method>` endpoint of the usage report Remote. */\nexport const USAGE_REPORT_ENDPOINT = 'commandcode/report'\n\n/** Reject one boundary value with a field-naming error. */\nfunction reject(field: string): never {\n throw new TypeError(`commandcode/report result: invalid ${field}`)\n}\n\n/** Read one required finite number field (`field` is the dotted error label). */\nfunction numberField(source: Record<string, unknown>, key: string, field: string): number {\n const value = source[key]\n if (typeof value !== 'number' || !Number.isFinite(value)) reject(field)\n return value\n}\n\n/** Read one required string field (`field` is the dotted error label). */\nfunction stringField(source: Record<string, unknown>, key: string, field: string): string {\n const value = source[key]\n if (typeof value !== 'string') reject(field)\n return value\n}\n\n/** Read one required boolean field (`field` is the dotted error label). */\nfunction booleanField(source: Record<string, unknown>, key: string, field: string): boolean {\n const value = source[key]\n if (typeof value !== 'boolean') reject(field)\n return value\n}\n\n/** Narrow an unknown value to a plain record, or reject. */\nfunction record(value: unknown, field: string): Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) reject(field)\n return value as Record<string, unknown>\n}\n\n/** Validate one window-limit block (`fiveHour` / `weekly`). */\nfunction windowLimit(value: unknown, field: string): { used: number; cap: number; exceeded: boolean; resetAt: number } {\n const source = record(value, field)\n return {\n used: numberField(source, 'used', `${field}.used`),\n cap: numberField(source, 'cap', `${field}.cap`),\n exceeded: booleanField(source, 'exceeded', `${field}.exceeded`),\n resetAt: numberField(source, 'resetAt', `${field}.resetAt`),\n }\n}\n\n/**\n * Parse one untrusted boundary value into a {@link CommandCodeUsageReport}.\n * Optional sections stay optional; every present field is shape-checked so a\n * malformed frame fails the boundary instead of rendering garbage.\n */\nfunction parseUsageReport(value: unknown): CommandCodeUsageReport {\n const source = record(value, 'report')\n const failures = source.failures\n if (!Array.isArray(failures) || failures.some((entry) => typeof entry !== 'string')) reject('failures')\n const report: CommandCodeUsageReport = { failures: failures as string[] }\n\n if (source.account !== undefined) {\n const account = record(source.account, 'account')\n report.account = {\n id: stringField(account, 'id', 'account.id'),\n name: stringField(account, 'name', 'account.name'),\n userName: stringField(account, 'userName', 'account.userName'),\n }\n }\n\n if (source.usage !== undefined) {\n const usage = record(source.usage, 'usage')\n report.usage = {\n totalCount: numberField(usage, 'totalCount', 'usage.totalCount'),\n totalCost: numberField(usage, 'totalCost', 'usage.totalCost'),\n successRate: numberField(usage, 'successRate', 'usage.successRate'),\n completedCount: numberField(usage, 'completedCount', 'usage.completedCount'),\n failedCount: numberField(usage, 'failedCount', 'usage.failedCount'),\n totalTokensIn: numberField(usage, 'totalTokensIn', 'usage.totalTokensIn'),\n totalTokensOut: numberField(usage, 'totalTokensOut', 'usage.totalTokensOut'),\n totalCredits: numberField(usage, 'totalCredits', 'usage.totalCredits'),\n periodBasis: stringField(usage, 'periodBasis', 'usage.periodBasis'),\n }\n }\n\n if (source.credits !== undefined) {\n const credits = record(source.credits, 'credits')\n report.credits = {\n monthlyCredits: numberField(credits, 'monthlyCredits', 'credits.monthlyCredits'),\n purchasedCredits: numberField(credits, 'purchasedCredits', 'credits.purchasedCredits'),\n freeCredits: numberField(credits, 'freeCredits', 'credits.freeCredits'),\n fiveHour: windowLimit(credits.fiveHour, 'credits.fiveHour'),\n weekly: windowLimit(credits.weekly, 'credits.weekly'),\n }\n }\n\n if (source.plan !== undefined) {\n const plan = record(source.plan, 'plan')\n const monthly = plan.monthlyCredits\n if (monthly !== null && (typeof monthly !== 'number' || !Number.isFinite(monthly))) reject('plan.monthlyCredits')\n report.plan = {\n planId: stringField(plan, 'planId', 'plan.planId'),\n name: stringField(plan, 'name', 'plan.name'),\n status: stringField(plan, 'status', 'plan.status'),\n monthlyCredits: monthly as number | null,\n currentPeriodEnd: numberField(plan, 'currentPeriodEnd', 'plan.currentPeriodEnd'),\n }\n }\n\n return report\n}\n\n/**\n * The strict result codec both halves attach to the descriptor. Hand-rolled:\n * the client bundle may not require a schema library, and `TypertSchema` is\n * deliberately minimal so one `parse` function satisfies it.\n */\nexport const usageReportSchema: TypertSchema<CommandCodeUsageReport> = {\n parse: parseUsageReport,\n}\n\n/**\n * The one invocation descriptor, shared verbatim by the Host registration and\n * the Client mount. `service` names the Cordis key the Gateway resolves the\n * receiver from; `namespace`/`method` name the wire endpoint.\n */\nexport const USAGE_REPORT_DESCRIPTOR: InvocationDescriptor = {\n id: `${USAGE_REMOTE_PACKAGE}#${USAGE_REPORT_ENDPOINT}`,\n service: 'commandcodeUsage',\n namespace: 'commandcode',\n method: 'report',\n invocation: { kind: 'direct' },\n parameters: [],\n result: {\n mode: 'strict',\n typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeUsageReport`,\n schema: usageReportSchema,\n },\n}\n\n/** The Host-face contribution registered on `ctx.typert`. */\nexport const USAGE_HOST_CONTRIBUTION = {\n package: USAGE_REMOTE_PACKAGE,\n face: 'host' as const,\n schemas: [],\n invocations: [USAGE_REPORT_DESCRIPTOR],\n}\n\n/** The Client-face contribution mounted on `ctx.remote`. */\nexport const USAGE_REMOTE_CONTRIBUTION: TypertRemoteContribution = {\n package: USAGE_REMOTE_PACKAGE,\n descriptors: [USAGE_REPORT_DESCRIPTOR],\n}\n","/**\n * Host half of the account-usage Remote (`commandcode/report`).\n *\n * The settings page's account card needs the same report the `/commandcode`\n * command prints, but the browser never holds the API key — the fetch must\n * run Host-side. This module exposes `adapter.getUsage()` through the Typert\n * Gateway: a `TypertRemoteService` provides the receiver the Gateway resolves,\n * and the shared strict descriptor (`src/usage-wire.ts`) is registered on the\n * `typert` registry so the Gateway claims the `commandcode/report` endpoint.\n *\n * The whole wiring rides an optional `ctx.inject(['typert'], ...)` fiber: a\n * profile without the web stack (no Typert registry, no Gateway) simply never\n * activates it, exactly like the `/commandcode` command rides `commands`.\n *\n * @module dsh-commandcode-provider/usage-remote\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'\nimport type { CommandCodeAdapter, CommandCodeConnectionOptions, CommandCodeUsageReport } from './adapter.ts'\nimport { USAGE_HOST_CONTRIBUTION } from './usage-wire.ts'\n\n/** Everything the usage service needs beyond its Cordis context. */\nexport interface CommandCodeUsageDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {\n /** The registered adapter (for getUsage). */\n adapter: CommandCodeAdapter<C>\n}\n\n/**\n * The registry method surface this module uses. `Context['typert']` is typed\n * as the read-only `TypertRegistryContract`; contribution registration lives\n * on the concrete registry service, so the cast is spelled out once here.\n */\ninterface TypertContributionRegistry {\n register(contribution: typeof USAGE_HOST_CONTRIBUTION): () => void | Promise<void>\n}\n\n/**\n * The Remote receiver: a Cordis service the Gateway resolves by key\n * (`commandcodeUsage`) and binds to the wire namespace (`commandcode`). The\n * base class stamps the `typertRemote` binding the Gateway validates on every\n * dispatch; no decorators are needed because the descriptor is registered\n * explicitly (strict path) rather than discovered from source markers.\n */\nexport class CommandCodeUsageService<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions>\n extends TypertRemoteService {\n private readonly deps: CommandCodeUsageDeps<C>\n\n constructor(ctx: Context, deps: CommandCodeUsageDeps<C>) {\n super(ctx, 'commandcodeUsage', { namespace: 'commandcode' })\n this.deps = deps\n }\n\n /**\n * Account, usage, and credit state for the settings page's account card.\n * Degrades per endpoint like the `/commandcode` command (failures land in\n * `report.failures`); throws `MISSING_CREDENTIAL` when no key resolves, which\n * the Gateway folds into the failure branch the page renders as a hint.\n */\n async report(): Promise<CommandCodeUsageReport> {\n return this.deps.adapter.getUsage()\n }\n}\n\n/**\n * Provide the usage service and register its Remote descriptor. The registry\n * contribution is tied to this fiber's lifetime: the registry's own\n * `register()` effect would otherwise outlive the plugin.\n */\nexport function applyUsageRemote<C extends CommandCodeConnectionOptions>(\n ctx: Context,\n deps: CommandCodeUsageDeps<C>,\n): void {\n ctx.inject(['typert'], (remoteCtx) => {\n new CommandCodeUsageService(remoteCtx, deps)\n const registry = remoteCtx.typert as unknown as TypertContributionRegistry\n const unregister = registry.register(USAGE_HOST_CONTRIBUTION)\n // The registry's own effect would outlive this fiber; withdraw the\n // contribution when the plugin unloads.\n remoteCtx.effect(() => () => void unregister(), 'dsh-commandcode-provider: usage remote')\n })\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'\nimport { applyUsageRemote } from './usage-remote.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_SUBSCRIPTION_PLANS,\n KNOWN_DEALS,\n KNOWN_PEAK_PRICING,\n PLAN_LABELS,\n PLAN_ORDER,\n BILLING_ACCESS_TTL_MS,\n capabilityDescription,\n compareByPlan,\n dealLabel,\n formatContext,\n modelVisibleInPlan,\n peakPricingLabel,\n peakPricingState,\n planLabel,\n projectSlugFromPath,\n resolveAuthFileApiKey,\n subscriptionPlanInfo,\n} from './adapter.ts'\nexport type { CommandCodeAdapterDeps, CommandCodeBillingAccess, CommandCodeConnectionOptions, CommandCodeUsageReport, ResolveAttachments } from './adapter.ts'\nexport { applyCommands, commandDefinition } from './commands.ts'\nexport type { CommandCodeCommandDeps } from './commands.ts'\nexport { applyUsageRemote, CommandCodeUsageService } from './usage-remote.ts'\nexport type { CommandCodeUsageDeps } from './usage-remote.ts'\nexport { USAGE_REPORT_ENDPOINT, usageReportSchema } from './usage-wire.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 * Whether the model picker hides models above the account's subscription\n * tier; defaults to true. The filter fails open (unknown plan, billing\n * endpoint failure, or a positive on-demand credit balance all keep the\n * full catalog visible). Set false to always list every model.\n */\n filterModelsByPlan?: boolean\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 filterModelsByPlan: z.boolean(),\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 filterModelsByPlan: config.filterModelsByPlan ?? true,\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 // The settings page's account card: getUsage exposed to the browser through\n // the Typert Gateway (`commandcode/report`). Rides the optional `typert`\n // registry service, so profiles without the web stack never activate it.\n applyUsageRemote(ctx, { adapter })\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.4.
|
|
3
|
+
"version": "0.4.2",
|
|
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",
|