@mars-sea/dsh-commandcode-provider 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,25 @@ 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.1.5] - 2026-08-15
8
+
9
+ ### Added
10
+
11
+ - **Usage dashboard**: `CommandCodeAdapter.getUsage()` queries the official Command Code account endpoints (`/alpha/whoami`, `/alpha/usage/summary`, `/alpha/billing/credits`) that the official CLI uses. Each endpoint degrades independently.
12
+ - **`/commandcode` slash command** (requires the dsh `commands` service; degrades silently when absent) shows account, request counts, cost, tokens, credit balance, and 5-hour/weekly window limits. Verified against a live account.
13
+ - Unit tests for `getUsage()` and the command (`tests/commands.test.ts`, stubbed fetch, 6 cases).
14
+
15
+ ### Changed
16
+
17
+ - `@deepseek-ai/dsh-commands` added back to peerDependencies (optional at runtime for the command).
18
+
19
+ ## [0.1.4] - 2026-08-14
20
+
21
+ ### Changed
22
+
23
+ - `COMMAND_CODE_CLI_VERSION` bumped from `1.24.0` to `1.26.0` (current official CLI version).
24
+ - `KNOWN_EFFORTS` refreshed against the official command-code@1.26.0 bundled catalog: adds `zai-org/GLM-5.3` (`low/high/max`). All previously listed models verified unchanged.
25
+
7
26
  ## [0.1.3] - 2026-08-14
8
27
 
9
28
  ### Changed
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
  [![npm](https://img.shields.io/badge/npm-@mars--sea%2Fdsh--commandcode--provider-blue.svg)](https://www.npmjs.com/package/@mars-sea/dsh-commandcode-provider)
8
8
 
9
- 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` model provider whose requests are translated to Command Code's Provider API (`POST /alpha/generate`, reverse-engineered by the pi plugin, `command-code@1.24.0`).
9
+ 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` model provider whose requests are translated to Command Code's Provider API (`POST /alpha/generate`, reverse-engineered by the pi plugin, `command-code@1.26.0`).
10
10
 
11
11
  > 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.
12
12
 
@@ -16,7 +16,7 @@ Unofficial [DeepSeek Harness](https://deepseek-harness.github.io/deepseek-harnes
16
16
  - A **`commandcode` provider route** registered on the `llm` service, selectable in the model picker, with the **live model catalog** fetched from `GET {apiBase}/provider/v1/models` (cached at `~/.commandcode/models-cache.json`).
17
17
  - A **Models-page card** ("Command Code") with an API-key field — credentials are stored through the dsh credentials service, same as the DeepSeek card.
18
18
  - **API key resolution** in this order: `config.apiKey` → credential reference `apiKeyEnv` (the web Models page writes it, default `COMMANDCODE_API_KEY`) → the launching environment → the official Command Code CLI auth file (`~/.commandcode/auth.json`, written by `command-code login`).
19
- - **Reasoning-effort support** for the models Command Code's catalog marks as such (e.g. `claude-opus-5`, `gpt-5.5`, `deepseek/deepseek-v4-pro`, …) via `KNOWN_EFFORTS`, matching the official command-code@1.24.0 bundled catalog.
19
+ - **Reasoning-effort support** for the models Command Code's catalog marks as such (e.g. `claude-opus-5`, `gpt-5.5`, `deepseek/deepseek-v4-pro`, …) via `KNOWN_EFFORTS`, matching the official command-code@1.26.0 bundled catalog.
20
20
 
21
21
  ## Getting an API key
22
22
 
@@ -35,7 +35,7 @@ cmd login # macOS/Linux; native Windows: cmdc login
35
35
 
36
36
  ```sh
37
37
  # Pin a release tag (recommended — readable and immutable)
38
- dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#v0.1.1
38
+ dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#v0.1.4
39
39
  # Or pin any exact commit by its SHA
40
40
  dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#<full-commit-sha>
41
41
  ```
@@ -92,6 +92,37 @@ dsh web # or restart your running instance
92
92
 
93
93
  After restart, in the web UI: **Settings → Models** shows a **Command Code** card; the model picker lists the live catalog under **commandcode** (54 models at the time of writing). Send a message with a model your plan includes — the default `deepseek/deepseek-v4-flash` works on entry-level plans; open-weight models (DeepSeek/Qwen/Kimi/MiniMax) generally do, while frontier models (Claude/GPT/Gemini/Grok) may require Pro/Max plans or on-demand usage (see FAQ).
94
94
 
95
+ ## Usage dashboard
96
+
97
+ The plugin registers a `/commandcode` slash command (requires the dsh `commands` service, present in the standard web profile) that shows your Command Code account state straight from the official account endpoints:
98
+
99
+ ```text
100
+ /commandcode (or /commandcode status)
101
+ ```
102
+
103
+ Example output (structured text with Unicode bar charts):
104
+
105
+ ```text
106
+ 📊 Command Code 用量 (mars-sea)
107
+
108
+ ── 请求 ──────────────────────────────
109
+ 💬 请求 992 次 / 失败 0 成功率 100%
110
+ 💰 花费 $1.4446 ($1.44 credits)
111
+ 🔤 Token 205.3M 入 / 808.8K 出
112
+
113
+ ── 信用 ──────────────────────────────
114
+ 💳 月额度 $8.54 (已购 $0.00 / 赠送 $0.00)
115
+ └ ██████████ 100%
116
+
117
+ ── 窗口用量 ──────────────────────────
118
+ ⏱ 5 小时 $0.18 / $3.00
119
+ └ █░░░░░░░░░ 重置 8/15/2026, 2:39:36 PM
120
+ 📅 每周 $1.46 / $6.00
121
+ └ ██░░░░░░░░ 重置 8/21/2026, 7:10:57 PM
122
+ ```
123
+
124
+ Each endpoint degrades independently: a temporary failure of one (e.g. the credits endpoint) leaves the rest visible and notes the failure inline.
125
+
95
126
  ## Configure
96
127
 
97
128
  The Command Code card takes your API key (stored in `$DSH_HOME/.credentials.yaml`; the model catalog is browsable without one). Advanced knobs live in the `llm-commandcode` section of `$DSH_HOME/settings.yaml` (overrides the bundle defaults per request, no restart needed):
@@ -122,6 +153,31 @@ The composition-entry config (`cordis.patch.yml` / your profile `cordis.patch.ym
122
153
  - Only tool calls with a paired tool result are replayed into the conversation.
123
154
  - The model catalog endpoint is public; requests to `/alpha/generate` require the key above.
124
155
 
156
+ ## Permissions & privacy
157
+
158
+ This plugin operates entirely within your dsh profile and your Command Code account. What it touches:
159
+
160
+ - **Local files**
161
+ - Reads `~/.commandcode/auth.json` (the official CLI login) **only** as a last-resort key fallback.
162
+ - Reads/writes `~/.commandcode/models-cache.json` (model catalog cache).
163
+ - Reads your API key from the dsh credential store (`$DSH_HOME/.credentials.yaml`) via the standard credential seam — the key is never logged or sent anywhere but the Command Code API.
164
+ - **Network**
165
+ - `GET {apiBase}/provider/v1/models` — public model catalog (no key required).
166
+ - `POST {apiBase}/alpha/generate` — the model requests themselves, authenticated with your key.
167
+ - The request body includes the `workingDir` (project path) you configure (defaults to the process cwd), sent as Command Code's `config.workingDir`.
168
+ - **No telemetry**: no analytics, no tracking, no third-party endpoints. The only outbound hosts are the Command Code API (`api.commandcode.ai` by default, configurable via `apiBase`).
169
+
170
+ ## Disabling / uninstalling
171
+
172
+ - **Disable** the provider without removing it: edit your profile's `cordis.patch.yml` and comment out (or remove) the `llm-commandcode` row, or set `disabled: true` on it, then restart the web app.
173
+ - **Uninstall** completely:
174
+
175
+ ```sh
176
+ dsh plugin --profile web remove dsh-commandcode-provider
177
+ ```
178
+
179
+ This removes the bundle dependency and its layer. Your API key in the dsh credential store and `~/.commandcode/auth.json` are left untouched (you can remove them manually if you want to revoke access).
180
+
125
181
  ## Development
126
182
 
127
183
  ```sh
package/README.zh-CN.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
  [![npm](https://img.shields.io/badge/npm-@mars--sea%2Fdsh--commandcode--provider-blue.svg)](https://www.npmjs.com/package/@mars-sea/dsh-commandcode-provider)
8
8
 
9
- 非官方 [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.24.0`)。
9
+ 非官方 [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.26.0`)。
10
10
 
11
11
  > 这是一个社区集成。你需要自己的 Command Code 账号、API key 或订阅,并遵守 Command Code 的服务条款。本项目与 Command Code, Inc. 无关。
12
12
 
@@ -16,7 +16,7 @@
16
16
  - **`commandcode` provider 路由**:注册在 `llm` 服务上,可在模型选择器中选择,并带 **实时模型目录**(从 `GET {apiBase}/provider/v1/models` 拉取,缓存于 `~/.commandcode/models-cache.json`)。
17
17
  - **Models 页面卡片**("Command Code")带 API key 输入框——凭据通过 dsh 凭据服务存储,与 DeepSeek 卡片一致。
18
18
  - **API key 解析顺序**:`config.apiKey` → 凭据引用 `apiKeyEnv`(Web Models 页面写入,默认 `COMMANDCODE_API_KEY`)→ 启动环境变量 → 官方 Command Code CLI 认证文件(`~/.commandcode/auth.json`,由 `command-code login` 写入)。
19
- - **推理强度(reasoning-effort)支持**:针对 Command Code 目录中标为推理模型的模型(如 `claude-opus-5`、`gpt-5.5`、`deepseek/deepseek-v4-pro` 等),通过 `KNOWN_EFFORTS` 实现,与官方 command-code@1.24.0 内置目录一致。
19
+ - **推理强度(reasoning-effort)支持**:针对 Command Code 目录中标为推理模型的模型(如 `claude-opus-5`、`gpt-5.5`、`deepseek/deepseek-v4-pro` 等),通过 `KNOWN_EFFORTS` 实现,与官方 command-code@1.26.0 内置目录一致。
20
20
 
21
21
  ## 获取 API key
22
22
 
@@ -35,7 +35,7 @@ cmd login # macOS/Linux;Windows 原生版:cmdc login
35
35
 
36
36
  ```sh
37
37
  # 推荐:锁定发布 tag(可读、不可变)
38
- dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#v0.1.1
38
+ dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#v0.1.5
39
39
  # 或按完整 commit SHA 锁定任意提交
40
40
  dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#<完整-commit-sha>
41
41
  ```
@@ -92,6 +92,37 @@ dsh web # 或重启你正在运行的实例
92
92
 
93
93
  重启后,在 Web UI 中:**设置 → Models** 会显示 **Command Code** 卡片;模型选择器会在 **commandcode** 下列出实时目录(撰写本文时有 54 个模型)。发送一条消息,选择你套餐中包含的模型——默认的 `deepseek/deepseek-v4-flash` 适用于入门级套餐;开放权重模型(DeepSeek/Qwen/Kimi/MiniMax)通常都可用,而前沿模型(Claude/GPT/Gemini/Grok)可能需要 Pro/Max 套餐或按需计费(见 FAQ)。
94
94
 
95
+ ## 用量面板
96
+
97
+ 插件注册了一个 `/commandcode` 斜杠命令(需要 dsh 的 `commands` 服务,标准 web profile 自带),直接从官方账户端点显示你的 Command Code 账户状态:
98
+
99
+ ```text
100
+ /commandcode (或 /commandcode status)
101
+ ```
102
+
103
+ 输出示例(结构化文本 + Unicode 条形图):
104
+
105
+ ```text
106
+ 📊 Command Code 用量 (mars-sea)
107
+
108
+ ── 请求 ──────────────────────────────
109
+ 💬 请求 992 次 / 失败 0 成功率 100%
110
+ 💰 花费 $1.4446 ($1.44 credits)
111
+ 🔤 Token 205.3M 入 / 808.8K 出
112
+
113
+ ── 信用 ──────────────────────────────
114
+ 💳 月额度 $8.54 (已购 $0.00 / 赠送 $0.00)
115
+ └ ██████████ 100%
116
+
117
+ ── 窗口用量 ──────────────────────────
118
+ ⏱ 5 小时 $0.18 / $3.00
119
+ └ █░░░░░░░░░ 重置 8/15/2026, 2:39:36 PM
120
+ 📅 每周 $1.46 / $6.00
121
+ └ ██░░░░░░░░ 重置 8/21/2026, 7:10:57 PM
122
+ ```
123
+
124
+ 每个端点独立降级:某个端点临时失败(如 credits 端点)不会影响其他数据,并会在末尾内联提示失败。
125
+
95
126
  ## 配置
96
127
 
97
128
  Command Code 卡片接收你的 API key(存储在 `$DSH_HOME/.credentials.yaml`;没有 key 也可以浏览模型目录)。高级选项位于 `$DSH_HOME/settings.yaml` 的 `llm-commandcode` 一节(按请求覆盖 bundle 默认值,无需重启):
@@ -122,6 +153,31 @@ llm-commandcode:
122
153
  - 只有带配对工具结果的工具调用会被重放到对话中。
123
154
  - 模型目录端点是公开的;对 `/alpha/generate` 的请求需要上述 key。
124
155
 
156
+ ## 权限与隐私
157
+
158
+ 本插件完全在你的 dsh profile 和你的 Command Code 账号内运行。它触及的内容:
159
+
160
+ - **本地文件**
161
+ - 仅在**最后兜底**时读取 `~/.commandcode/auth.json`(官方 CLI 登录文件)。
162
+ - 读写 `~/.commandcode/models-cache.json`(模型目录缓存)。
163
+ - 通过标准凭据 seam 从 dsh 凭据库(`$DSH_HOME/.credentials.yaml`)读取 API key——key 永不记录日志,也只会发送给 Command Code API。
164
+ - **网络**
165
+ - `GET {apiBase}/provider/v1/models` —— 公开模型目录(无需 key)。
166
+ - `POST {apiBase}/alpha/generate` —— 模型请求本身,使用你的 key 认证。
167
+ - 请求体包含你配置的 `workingDir`(项目路径,默认进程 cwd),作为 Command Code 的 `config.workingDir` 发送。
168
+ - **无遥测**:无分析、无追踪、无第三方端点。唯一的对外主机是 Command Code API(默认 `api.commandcode.ai`,可通过 `apiBase` 配置)。
169
+
170
+ ## 关闭 / 卸载
171
+
172
+ - **禁用**(不删除):编辑你 profile 的 `cordis.patch.yml`,注释掉(或移除)`llm-commandcode` 行,或对其设置 `disabled: true`,然后重启 web 应用。
173
+ - **完全卸载**:
174
+
175
+ ```sh
176
+ dsh plugin --profile web remove dsh-commandcode-provider
177
+ ```
178
+
179
+ 这会移除 bundle 依赖及其配置层。你在 dsh 凭据库和 `~/.commandcode/auth.json` 中的 API key 不会被改动(如需撤销访问权限,可手动删除)。
180
+
125
181
  ## 开发
126
182
 
127
183
  ```sh
package/lib/index.d.ts CHANGED
@@ -2,9 +2,10 @@ import z from "@deepseek-ai/schemastery";
2
2
  import { GenerateOptions, LlmAdapter, LlmModelInfo, LlmResolvedModelInfo, ResolvedRetryPolicy, StreamChunk } from "@deepseek-ai/dsh-llm";
3
3
  import { CredentialRef } from "@deepseek-ai/dsh-credentials";
4
4
  import { Context } from "@deepseek-ai/cordis";
5
+ import { CommandDefinition } from "@deepseek-ai/dsh-commands";
5
6
  //#region src/adapter.d.ts
6
7
  declare const KNOWN_EFFORTS: Readonly<Record<string, readonly string[]>>;
7
- declare const COMMAND_CODE_CLI_VERSION = "1.24.0";
8
+ declare const COMMAND_CODE_CLI_VERSION = "1.26.0";
8
9
  declare const DEFAULT_API_BASE = "https://api.commandcode.ai";
9
10
  declare const DEFAULT_GENERATE_MAX_TOKENS = 64000;
10
11
  declare const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
@@ -29,6 +30,52 @@ interface CommandCodeAdapterDeps<C extends CommandCodeConnectionOptions = Comman
29
30
  /** HTTP transport override (tests); defaults to the global `fetch`. */
30
31
  fetchImpl?: typeof fetch;
31
32
  }
33
+ /** Account identity from `/alpha/whoami`. */
34
+ interface CommandCodeAccount {
35
+ id: string;
36
+ name: string;
37
+ userName: string;
38
+ }
39
+ /** Usage summary from `/alpha/usage/summary`. */
40
+ interface CommandCodeUsage {
41
+ totalCount: number;
42
+ totalCost: number;
43
+ successRate: number;
44
+ completedCount: number;
45
+ failedCount: number;
46
+ totalTokensIn: number;
47
+ totalTokensOut: number;
48
+ totalCredits: number;
49
+ periodBasis: string;
50
+ }
51
+ /** Credit/limit state from `/alpha/billing/credits`. */
52
+ interface CommandCodeCredits {
53
+ monthlyCredits: number;
54
+ purchasedCredits: number;
55
+ freeCredits: number;
56
+ /** Five-hour rolling window limits. */
57
+ fiveHour: {
58
+ used: number;
59
+ cap: number;
60
+ exceeded: boolean;
61
+ resetAt: number;
62
+ };
63
+ /** Weekly window limits. */
64
+ weekly: {
65
+ used: number;
66
+ cap: number;
67
+ exceeded: boolean;
68
+ resetAt: number;
69
+ };
70
+ }
71
+ /** Everything the usage endpoints report, fetched together. */
72
+ interface CommandCodeUsageReport {
73
+ account?: CommandCodeAccount;
74
+ usage?: CommandCodeUsage;
75
+ credits?: CommandCodeCredits;
76
+ /** Endpoint failures degrade the report instead of failing it. */
77
+ failures: string[];
78
+ }
32
79
  declare class CommandCodeAdapter<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> extends LlmAdapter {
33
80
  private readonly deps;
34
81
  private catalog;
@@ -47,9 +94,28 @@ declare class CommandCodeAdapter<C extends CommandCodeConnectionOptions = Comman
47
94
  private loadCatalog;
48
95
  listModels(provider: string): Promise<readonly LlmModelInfo[]>;
49
96
  resolveModel(provider: string, model: string, signal?: AbortSignal): Promise<LlmResolvedModelInfo>;
97
+ /**
98
+ * Fetch account, usage, and credit state from the Command Code account
99
+ * endpoints (`/alpha/whoami`, `/alpha/usage/summary`, `/alpha/billing/credits`).
100
+ * Each endpoint degrades independently: a failed one lands in `failures`
101
+ * while the rest still report, so a transient outage never blanks the whole
102
+ * view. Requires a usable API key (throws `MISSING_CREDENTIAL` otherwise).
103
+ */
104
+ getUsage(): Promise<CommandCodeUsageReport>;
50
105
  stream(options: GenerateOptions): AsyncIterable<StreamChunk>;
51
106
  }
52
107
  //#endregion
108
+ //#region src/commands.d.ts
109
+ /** Everything the command needs beyond the adapter itself. */
110
+ interface CommandCodeCommandDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {
111
+ /** The registered adapter (for getUsage / listModels). */
112
+ adapter: CommandCodeAdapter<C>;
113
+ }
114
+ /** The one registered `/commandcode` command. */
115
+ declare function commandDefinition<C extends CommandCodeConnectionOptions>(deps: CommandCodeCommandDeps<C>): CommandDefinition;
116
+ /** Register the command on `ctx.commands` (called from the plugin entry). */
117
+ declare function applyCommands<C extends CommandCodeConnectionOptions>(ctx: Context, deps: CommandCodeCommandDeps<C>): void;
118
+ //#endregion
53
119
  //#region src/index.d.ts
54
120
  declare const name = "llm-commandcode";
55
121
  declare const inject: string[];
@@ -90,5 +156,5 @@ interface ResolvedCommandCodeOptions extends CommandCodeConnectionOptions {
90
156
  declare function resolveAdapterOptions(config: Config): ResolvedCommandCodeOptions;
91
157
  declare function apply(ctx: Context, config: Config): void;
92
158
  //#endregion
93
- export { COMMAND_CODE_CLI_VERSION, CommandCodeAdapter, type CommandCodeAdapterDeps, type CommandCodeConnectionOptions, Config, DEFAULT_API_BASE, DEFAULT_GENERATE_MAX_TOKENS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MODELS_CACHE_PATH, KNOWN_EFFORTS, PROVIDER, ResolvedCommandCodeOptions, apply, inject, name, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey };
159
+ export { COMMAND_CODE_CLI_VERSION, CommandCodeAdapter, type CommandCodeAdapterDeps, type CommandCodeCommandDeps, type CommandCodeConnectionOptions, type CommandCodeUsageReport, Config, DEFAULT_API_BASE, DEFAULT_GENERATE_MAX_TOKENS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MODELS_CACHE_PATH, KNOWN_EFFORTS, PROVIDER, ResolvedCommandCodeOptions, apply, applyCommands, commandDefinition, inject, name, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey };
94
160
  //# sourceMappingURL=index.d.ts.map
package/lib/index.js CHANGED
@@ -16,7 +16,7 @@ import { randomUUID } from "node:crypto";
16
16
  * community-maintained integration; you need your own Command Code account
17
17
  * and API key or subscription, and Command Code's terms apply.
18
18
  *
19
- * Wire protocol (reverse-engineered by the pi plugin, command-code@1.24.0):
19
+ * Wire protocol (reverse-engineered by the pi plugin, command-code@1.26.0):
20
20
  * POST {apiBase}/alpha/generate
21
21
  * body: { config, memory, taste, skills, params: { model, messages, tools,
22
22
  * system, max_tokens, temperature, stream, reasoning_effort? }, threadId }
@@ -159,9 +159,14 @@ const KNOWN_EFFORTS = {
159
159
  "high",
160
160
  "xhigh"
161
161
  ],
162
- "zai-org/GLM-5.2": ["high", "max"]
162
+ "zai-org/GLM-5.2": ["high", "max"],
163
+ "zai-org/GLM-5.3": [
164
+ "low",
165
+ "high",
166
+ "max"
167
+ ]
163
168
  };
164
- const COMMAND_CODE_CLI_VERSION = "1.24.0";
169
+ const COMMAND_CODE_CLI_VERSION = "1.26.0";
165
170
  const DEFAULT_API_BASE = "https://api.commandcode.ai";
166
171
  const DEFAULT_GENERATE_MAX_TOKENS = 64e3;
167
172
  const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
@@ -402,6 +407,82 @@ var CommandCodeAdapter = class extends LlmAdapter {
402
407
  })) } } : {}
403
408
  };
404
409
  }
410
+ /**
411
+ * Fetch account, usage, and credit state from the Command Code account
412
+ * endpoints (`/alpha/whoami`, `/alpha/usage/summary`, `/alpha/billing/credits`).
413
+ * Each endpoint degrades independently: a failed one lands in `failures`
414
+ * while the rest still report, so a transient outage never blanks the whole
415
+ * view. Requires a usable API key (throws `MISSING_CREDENTIAL` otherwise).
416
+ */
417
+ async getUsage() {
418
+ const connection = this.deps.options();
419
+ const apiKey = await this.deps.resolveApiKey(connection);
420
+ const base = connection.apiBase;
421
+ const headers = {
422
+ Authorization: `Bearer ${apiKey}`,
423
+ "x-command-code-version": COMMAND_CODE_CLI_VERSION,
424
+ "x-cli-environment": "production",
425
+ ...attributionHeaders()
426
+ };
427
+ const failures = [];
428
+ const getJson = async (path) => {
429
+ try {
430
+ const response = await this.fetchImpl(`${base}${path}`, { headers });
431
+ if (!response.ok) {
432
+ failures.push(`${path}: HTTP ${response.status}`);
433
+ return;
434
+ }
435
+ const parsed = await response.json();
436
+ return isRecord(parsed) ? parsed : void 0;
437
+ } catch (error) {
438
+ failures.push(`${path}: ${error instanceof Error ? error.message : String(error)}`);
439
+ return;
440
+ }
441
+ };
442
+ const report = { failures };
443
+ const whoami = await getJson("/alpha/whoami");
444
+ const whoamiData = whoami && isRecord(whoami.user) ? whoami.user : void 0;
445
+ if (whoamiData) report.account = {
446
+ id: stringValue(whoamiData.id) ?? "",
447
+ name: stringValue(whoamiData.name) ?? "",
448
+ userName: stringValue(whoamiData.userName) ?? ""
449
+ };
450
+ const usage = await getJson("/alpha/usage/summary");
451
+ if (usage) report.usage = {
452
+ totalCount: numberValue(usage.totalCount) ?? 0,
453
+ totalCost: numberValue(usage.totalCost) ?? 0,
454
+ successRate: numberValue(usage.successRate) ?? 0,
455
+ completedCount: numberValue(usage.completedCount) ?? 0,
456
+ failedCount: numberValue(usage.failedCount) ?? 0,
457
+ totalTokensIn: numberValue(usage.totalTokensIn) ?? 0,
458
+ totalTokensOut: numberValue(usage.totalTokensOut) ?? 0,
459
+ totalCredits: numberValue(usage.totalCredits) ?? 0,
460
+ periodBasis: stringValue(usage.periodBasis) ?? "billing-period"
461
+ };
462
+ const credits = await getJson("/alpha/billing/credits");
463
+ const creditsData = credits && isRecord(credits.credits) ? credits.credits : void 0;
464
+ const windowLimits = credits && isRecord(credits.windowLimits) ? credits.windowLimits : void 0;
465
+ const fiveHour = windowLimits && isRecord(windowLimits.fiveHour) ? windowLimits.fiveHour : void 0;
466
+ const weekly = windowLimits && isRecord(windowLimits.weekly) ? windowLimits.weekly : void 0;
467
+ if (creditsData || fiveHour || weekly) report.credits = {
468
+ monthlyCredits: numberValue(creditsData?.monthlyCredits) ?? 0,
469
+ purchasedCredits: numberValue(creditsData?.purchasedCredits) ?? 0,
470
+ freeCredits: numberValue(creditsData?.freeCredits) ?? 0,
471
+ fiveHour: {
472
+ used: numberValue(fiveHour?.used) ?? 0,
473
+ cap: numberValue(fiveHour?.cap) ?? 0,
474
+ exceeded: fiveHour?.exceeded === true,
475
+ resetAt: numberValue(fiveHour?.resetAt) ?? 0
476
+ },
477
+ weekly: {
478
+ used: numberValue(weekly?.used) ?? 0,
479
+ cap: numberValue(weekly?.cap) ?? 0,
480
+ exceeded: weekly?.exceeded === true,
481
+ resetAt: numberValue(weekly?.resetAt) ?? 0
482
+ }
483
+ };
484
+ return report;
485
+ }
405
486
  async *stream(options) {
406
487
  if (options.stop?.length) throw new LlmError("Command Code adapter does not support stop sequences", "UNSUPPORTED_OPTION");
407
488
  if (options.messages.some(hasImageContent)) throw new LlmError("Image input is not wired to the attachment service in this adapter yet", "UNSUPPORTED_CONTENT");
@@ -671,6 +752,83 @@ function mapFinishReason(reason) {
671
752
  return { kind: "stop" };
672
753
  }
673
754
  //#endregion
755
+ //#region src/commands.ts
756
+ /** Format a dollar amount. */
757
+ function money(value) {
758
+ return `$${value.toFixed(4)}`;
759
+ }
760
+ /** Format a dollar amount compactly (2 decimals). */
761
+ function moneyShort(value) {
762
+ return `$${value.toFixed(2)}`;
763
+ }
764
+ /** Format a token count with thousands separators. */
765
+ /** Format a large token count compactly (1.9亿 style). */
766
+ function tokensCompact(value) {
767
+ if (value >= 1e9) return `${(value / 1e9).toFixed(1)}B`;
768
+ if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
769
+ if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`;
770
+ return String(value);
771
+ }
772
+ /** Format a millis timestamp as a local date. */
773
+ function resetLabel(ms) {
774
+ if (ms <= 0) return "n/a";
775
+ return new Date(ms).toLocaleString();
776
+ }
777
+ /**
778
+ * A 10-cell horizontal bar: `██████████` for 100%, `███░░░░░░░` for ~33%.
779
+ * Handles caps of 0 (no limit) and out-of-range values.
780
+ */
781
+ function bar(used, cap) {
782
+ if (cap <= 0) return "—";
783
+ const ratio = Math.max(0, Math.min(1, used / cap));
784
+ const filled = Math.round(ratio * 10);
785
+ return "█".repeat(filled) + "░".repeat(10 - filled);
786
+ }
787
+ /** Render the usage report as a structured, aligned, bar-chart text view. */
788
+ function renderReport(report) {
789
+ const lines = [];
790
+ const account = report.account ? ` (${report.account.userName || report.account.name})` : "";
791
+ lines.push(`📊 Command Code 用量${account}`, "");
792
+ if (report.usage) {
793
+ const u = report.usage;
794
+ lines.push("── 请求 ──────────────────────────────", ` 💬 请求 ${u.completedCount} 次 / 失败 ${u.failedCount} 成功率 ${u.successRate}%`, ` 💰 花费 ${money(u.totalCost)} (${moneyShort(u.totalCredits)} credits)`, ` 🔤 Token ${tokensCompact(u.totalTokensIn)} 入 / ${tokensCompact(u.totalTokensOut)} 出`, "");
795
+ }
796
+ if (report.credits) {
797
+ const c = report.credits;
798
+ const monthlyPct = c.monthlyCredits > 0 ? `${(c.monthlyCredits / (c.monthlyCredits + c.purchasedCredits) * 100).toFixed(0)}%` : "—";
799
+ lines.push("── 信用 ──────────────────────────────", ` 💳 月额度 ${moneyShort(c.monthlyCredits)} (已购 ${moneyShort(c.purchasedCredits)} / 赠送 ${moneyShort(c.freeCredits)})`, ` └ ${bar(c.monthlyCredits, c.monthlyCredits + c.purchasedCredits)} ${monthlyPct}`, "", "── 窗口用量 ──────────────────────────", ` ⏱ 5 小时 ${moneyShort(c.fiveHour.used)} / ${moneyShort(c.fiveHour.cap)}${c.fiveHour.exceeded ? " ⚠️ 超限!" : ""}`, ` └ ${bar(c.fiveHour.used, c.fiveHour.cap)} 重置 ${resetLabel(c.fiveHour.resetAt)}`, ` 📅 每周 ${moneyShort(c.weekly.used)} / ${moneyShort(c.weekly.cap)}${c.weekly.exceeded ? " ⚠️ 超限!" : ""}`, ` └ ${bar(c.weekly.used, c.weekly.cap)} 重置 ${resetLabel(c.weekly.resetAt)}`, "");
800
+ }
801
+ if (report.failures.length > 0) lines.push(`⚠️ 部分端点失败: ${report.failures.join("; ")}`, "");
802
+ if (!report.account && !report.usage && !report.credits) lines.push("(no data — check your API key)", "");
803
+ return lines.join("\n").trimEnd();
804
+ }
805
+ /** The one registered `/commandcode` command. */
806
+ function commandDefinition(deps) {
807
+ const { adapter } = deps;
808
+ return {
809
+ name: "commandcode",
810
+ description: "Command Code account usage dashboard",
811
+ input: { hint: "[status]" },
812
+ handler: async () => {
813
+ try {
814
+ return {
815
+ kind: "success",
816
+ text: renderReport(await adapter.getUsage())
817
+ };
818
+ } catch (error) {
819
+ return {
820
+ kind: "error",
821
+ text: `Could not fetch Command Code usage: ${error instanceof Error ? error.message : String(error)}`
822
+ };
823
+ }
824
+ }
825
+ };
826
+ }
827
+ /** Register the command on `ctx.commands` (called from the plugin entry). */
828
+ function applyCommands(ctx, deps) {
829
+ ctx.commands.register(commandDefinition(deps));
830
+ }
831
+ //#endregion
674
832
  //#region src/index.ts
675
833
  /**
676
834
  * dsh-commandcode-provider — DeepSeek Harness LLM provider plugin for Command
@@ -762,6 +920,9 @@ function apply(ctx, config) {
762
920
  settingsPath: []
763
921
  }]);
764
922
  ctx.llm.registerAdapter([PROVIDER], adapter);
923
+ ctx.inject(["commands"], (commandCtx) => {
924
+ applyCommands(commandCtx, { adapter });
925
+ });
765
926
  installSettingsSection(ctx, NS, Config, config, {
766
927
  setSource: (source) => {
767
928
  current = source;
@@ -770,6 +931,6 @@ function apply(ctx, config) {
770
931
  });
771
932
  }
772
933
  //#endregion
773
- export { COMMAND_CODE_CLI_VERSION, CommandCodeAdapter, Config, DEFAULT_API_BASE, DEFAULT_GENERATE_MAX_TOKENS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MODELS_CACHE_PATH, KNOWN_EFFORTS, PROVIDER, apply, inject, name, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey };
934
+ export { COMMAND_CODE_CLI_VERSION, CommandCodeAdapter, Config, DEFAULT_API_BASE, DEFAULT_GENERATE_MAX_TOKENS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MODELS_CACHE_PATH, KNOWN_EFFORTS, PROVIDER, apply, applyCommands, commandDefinition, inject, name, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey };
774
935
 
775
936
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/adapter.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.24.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 {\n attributionHeaders,\n CallId,\n LlmAdapter,\n LlmError,\n ReasoningEffortId,\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.24.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 '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}\n\nexport const COMMAND_CODE_CLI_VERSION = '1.24.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\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\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 recordOrEmpty(value: unknown): Record<string, unknown> {\n if (isRecord(value)) return value\n if (typeof value === 'string') {\n try {\n const parsed: unknown = JSON.parse(value)\n if (isRecord(parsed)) return parsed\n } catch {\n // Some providers stream incomplete JSON argument fragments.\n }\n }\n return {}\n}\n\nexport function projectSlugFromPath(pathName: string): string {\n const slug = pathName\n .toLowerCase()\n .replace(/^[a-z]:/i, '')\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n return slug || 'project'\n}\n\nfunction parseStreamEventLine(line: string): unknown | undefined {\n let trimmed = line.trim()\n if (!trimmed || trimmed.startsWith(':') || trimmed.startsWith('event:')) return undefined\n if (trimmed.startsWith('data:')) trimmed = trimmed.slice(5).trim()\n if (!trimmed || trimmed === '[DONE]') return undefined\n try {\n return JSON.parse(trimmed) as unknown\n } catch {\n return undefined\n }\n}\n\n// ---------------------------------------------------------------------------\n// Credential fallback from the official Command Code CLI auth file. Used as\n// the last fallback by the plugin entry, so a user who already logged in with\n// `command-code login` can reuse that credential. Only the official CLI's own\n// file is read — pi/OMP auth files are intentionally not scanned, so their\n// credentials and formats cannot surprise this adapter.\n// ---------------------------------------------------------------------------\n\n/** Extract the key from the CLI's nested credential records (`command-code`). */\nfunction apiKeyFromCredentialRecord(value: unknown): string | undefined {\n if (!isRecord(value)) return undefined\n const type = stringValue(value.type)\n if (type === 'api') return stringValue(value.key)\n if (type === 'oauth') return stringValue(value.access)\n return stringValue(value.key) ?? stringValue(value.access)\n}\n\n/** Read a usable Command Code credential from the official CLI auth file. */\nexport function resolveAuthFileApiKey(): string | undefined {\n const authPath = join(homedir(), '.commandcode', 'auth.json')\n try {\n if (!existsSync(authPath)) return undefined\n const parsed: unknown = JSON.parse(readFileSync(authPath, 'utf-8'))\n if (!isRecord(parsed)) return undefined\n const direct = stringValue(parsed.apiKey) ?? stringValue(parsed.commandcode)\n if (direct) return direct\n const nested =\n apiKeyFromCredentialRecord(parsed.commandcode) ??\n apiKeyFromCredentialRecord(parsed['command-code'])\n return nested\n } catch {\n // Ignore malformed or unreadable auth file.\n }\n return undefined\n}\n\n// ---------------------------------------------------------------------------\n// Model catalog discovery with on-disk cache fallback (ported from models.ts)\n// ---------------------------------------------------------------------------\n\ninterface CommandCodeModel {\n id: string\n name: string\n contextWindow: number\n maxTokens: number\n}\n\nfunction parseCatalogResponse(value: unknown): CommandCodeModel[] {\n if (!isRecord(value) || value.object !== 'list' || !Array.isArray(value.data)) {\n throw new LlmError('Unexpected Command Code models response shape', 'PROVIDER_PROTOCOL_ERROR')\n }\n const models: CommandCodeModel[] = []\n for (const entry of value.data) {\n if (!isRecord(entry)) continue\n const id = stringValue(entry.id)\n const name = stringValue(entry.name)\n const contextLength = numberValue(entry.context_length)\n if (!id || !name || !contextLength || contextLength <= 0) continue\n models.push({\n id,\n name,\n contextWindow: contextLength,\n maxTokens: Math.min(contextLength, DEFAULT_MAX_OUTPUT_TOKENS),\n })\n }\n if (models.length === 0) {\n throw new LlmError('Command Code returned an empty model catalog', 'PROVIDER_PROTOCOL_ERROR')\n }\n return models\n}\n\nasync function readModelsCache(cachePath: string): Promise<CommandCodeModel[]> {\n const parsed: unknown = JSON.parse(await readFile(cachePath, 'utf-8'))\n if (!isRecord(parsed) || parsed.version !== MODEL_CACHE_VERSION || !Array.isArray(parsed.models)) {\n throw new Error(`Invalid model cache at ${cachePath}`)\n }\n return parsed.models as CommandCodeModel[]\n}\n\nasync function writeModelsCache(cachePath: string, models: CommandCodeModel[]): Promise<void> {\n await mkdir(dirname(cachePath), { recursive: true })\n const tmp = `${cachePath}.${process.pid}.tmp`\n try {\n await writeFile(tmp, `${JSON.stringify({ version: MODEL_CACHE_VERSION, models }, null, 2)}\\n`, {\n encoding: 'utf-8',\n mode: 0o600,\n })\n await rename(tmp, cachePath)\n } finally {\n await rm(tmp, { force: true }).catch(() => undefined)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Message conversion: harness Message[] -> Command Code wire messages.\n// Reasoning blocks are intentionally NOT replayed (matches the pi plugin and\n// the official CLI: prior private reasoning must not leak into later turns).\n// Only tool calls with a paired tool result are replayed.\n// ---------------------------------------------------------------------------\n\nfunction pairedToolCallIds(messages: readonly Message[]): Set<string> {\n const callIds = new Set<string>()\n const resultIds = new Set<string>()\n for (const message of messages) {\n for (const block of message.content) {\n if (message.role === 'assistant' && block.type === 'tool-call') callIds.add(block.id)\n if (block.type === 'tool-result') resultIds.add(block.toolCallId)\n }\n }\n return new Set([...callIds].filter((id) => resultIds.has(id)))\n}\n\nfunction blockText(block: ContentBlock): string {\n return block.type === 'text' || block.type === 'reasoning' ? block.text : ''\n}\n\nfunction toolResultText(block: Extract<ContentBlock, { type: 'tool-result' }>): string {\n return block.content.map(blockText).filter(Boolean).join('\\n')\n}\n\nfunction hasImageContent(message: Message): boolean {\n const check = (blocks: readonly ContentBlock[]): boolean =>\n blocks.some(\n (b) => b.type === 'image' || (b.type === 'tool-result' && check(b.content)),\n )\n return check(message.content)\n}\n\nfunction messagesToCC(messages: readonly Message[]): 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 // ImageBlock carries an attachment ref owned by the attachment\n // service; resolving it to bytes requires that service. Fail loudly\n // instead of silently dropping (adapter contract).\n throw new LlmError(\n 'Image input is not wired to the attachment service in this adapter yet',\n 'UNSUPPORTED_CONTENT',\n )\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\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\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}\n\nexport class CommandCodeAdapter<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> extends LlmAdapter {\n private catalog: CommandCodeModel[] = []\n private readonly fetchImpl: typeof fetch\n\n constructor(private readonly deps: CommandCodeAdapterDeps<C>) {\n super()\n this.fetchImpl = deps.fetchImpl ?? fetch\n }\n\n /**\n * Command Code is a metered subscription API: 429 (rate limit) and 5xx\n * (transient server errors) are worth retrying at the agent-step boundary,\n * which is where dsh-llm-retry executes the policy returned here. The\n * default policy already retries `RATE_LIMIT` and `SERVER`; declaring it\n * explicitly documents the intent and gives the plugin entry a stable hook\n * to override (e.g. a stricter cap for a metered plan).\n */\n override providerRetryPolicy(_provider: string): ResolvedRetryPolicy {\n return resolveRetryPolicy(undefined, 'llm-commandcode: retryPolicy')\n }\n\n /** Refresh the catalog (live fetch, cache fallback) and return it. */\n private async loadCatalog(signal?: AbortSignal): Promise<CommandCodeModel[]> {\n const { apiBase, modelsCachePath } = this.deps.options()\n try {\n const response = await this.fetchImpl(`${apiBase}/provider/v1/models`, {\n headers: { accept: 'application/json', ...attributionHeaders() },\n signal: signal ?? AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) {\n throw new Error(`models endpoint returned ${response.status}`)\n }\n this.catalog = parseCatalogResponse(await response.json())\n await writeModelsCache(modelsCachePath, this.catalog).catch(() => undefined)\n } catch (error) {\n if (signal?.aborted) throw error\n // A catalog refresh failure is a degradation, not a request failure:\n // fall back to the last successful catalog on disk (or the in-memory\n // one from an earlier successful load). The adapter still serves any\n // model the user names; only the advisory selector loses entries.\n this.catalog = await readModelsCache(modelsCachePath).catch(() => this.catalog)\n }\n return this.catalog\n }\n\n override async listModels(provider: string): Promise<readonly LlmModelInfo[]> {\n const catalog = await this.loadCatalog()\n return catalog.map((model) => ({\n provider,\n id: model.id,\n name: `${model.name} (CC)`,\n inputModalities: ['text' as const],\n }))\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 return {\n provider,\n id: model,\n name: entry ? `${entry.name} (CC)` : model,\n inputModalities: ['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 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 if (options.messages.some(hasImageContent)) {\n throw new LlmError(\n 'Image input is not wired to the attachment service in this adapter yet',\n 'UNSUPPORTED_CONTENT',\n )\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: messagesToCC(options.messages),\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 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 ...(options.signal ? { signal: options.signal } : {}),\n })\n } catch (error: unknown) {\n // Caller cancellation must propagate as-is, not be relabeled.\n if (options.signal?.aborted) throw error\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`. Wrapping with the endpoint and chaining the\n // cause lets `errorChain` render the full diagnosis at every reporting\n // boundary, and gives the retry policy a stable `TRANSPORT` code.\n throw new LlmError(\n `Command Code API request to ${connection.apiBase}/alpha/generate failed`,\n 'TRANSPORT',\n { cause: error },\n )\n }\n\n if (!response.ok) {\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 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 // 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 const detail = isRecord(event.error)\n ? (stringValue(event.error.message) ?? JSON.stringify(event.error))\n : (stringValue(event.error) ?? stringValue(event.message) ?? 'Stream error')\n throw new LlmError(`Command Code stream error: ${detail}`, 'PROVIDER_STREAM_ERROR')\n }\n }\n return chunks\n }\n\n try {\n let finished = false\n for (;;) {\n let read: ReadableStreamReadResult<Uint8Array>\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; anything\n // else is a transport failure with a stable code.\n if (options.signal?.aborted) throw error\n throw new LlmError(\n `Command Code API stream from ${connection.apiBase} failed while reading`,\n 'TRANSPORT',\n { cause: error },\n )\n }\n const { done, value } = read\n if (done) {\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 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 * 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: dsh-commandcode-provider\n * config:\n * apiKeyEnv: COMMANDCODE_API_KEY\n * ```\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 { 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 type { CommandCodeConnectionOptions } from './adapter.ts'\n\nexport {\n COMMAND_CODE_CLI_VERSION,\n DEFAULT_API_BASE,\n DEFAULT_GENERATE_MAX_TOKENS,\n DEFAULT_MAX_OUTPUT_TOKENS,\n CommandCodeAdapter,\n KNOWN_EFFORTS,\n projectSlugFromPath,\n resolveAuthFileApiKey,\n} from './adapter.ts'\nexport type { CommandCodeAdapterDeps, CommandCodeConnectionOptions } from './adapter.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}\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})\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 }\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({ options, resolveApiKey })\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 installSettingsSection(ctx, NS, Config, config, {\n setSource: (source) => {\n current = source\n },\n // Everything the adapter reads is resolved per request, so a settings\n // change needs no registration-level action.\n onChange: () => {},\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/adapter.ts","../src/commands.ts","../src/index.ts"],"sourcesContent":["/**\n * DeepSeek Harness LLM adapter for the Command Code Provider API.\n *\n * Ported from pi-commandcode-provider@0.5.1 (MIT). This is an unofficial,\n * community-maintained integration; you need your own Command Code account\n * and API key or subscription, and Command Code's terms apply.\n *\n * Wire protocol (reverse-engineered by the pi plugin, command-code@1.26.0):\n * POST {apiBase}/alpha/generate\n * body: { config, memory, taste, skills, params: { model, messages, tools,\n * system, max_tokens, temperature, stream, reasoning_effort? }, threadId }\n * SSE-ish JSONL events: text-delta | reasoning-start/delta/end | tool-call\n * | tool-result | finish | error\n * Model catalog: GET {apiBase}/provider/v1/models -> { object: 'list', data: [...] }\n *\n * The adapter is deliberately free of cordis/schemastery: it receives a\n * per-request options thunk and an API-key resolver from the plugin entry\n * (src/index.ts), so a settings change reaches the very next request.\n */\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { randomUUID } from 'node:crypto'\n\nimport {\n attributionHeaders,\n CallId,\n LlmAdapter,\n LlmError,\n ReasoningEffortId,\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 '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\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\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\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 recordOrEmpty(value: unknown): Record<string, unknown> {\n if (isRecord(value)) return value\n if (typeof value === 'string') {\n try {\n const parsed: unknown = JSON.parse(value)\n if (isRecord(parsed)) return parsed\n } catch {\n // Some providers stream incomplete JSON argument fragments.\n }\n }\n return {}\n}\n\nexport function projectSlugFromPath(pathName: string): string {\n const slug = pathName\n .toLowerCase()\n .replace(/^[a-z]:/i, '')\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n return slug || 'project'\n}\n\nfunction parseStreamEventLine(line: string): unknown | undefined {\n let trimmed = line.trim()\n if (!trimmed || trimmed.startsWith(':') || trimmed.startsWith('event:')) return undefined\n if (trimmed.startsWith('data:')) trimmed = trimmed.slice(5).trim()\n if (!trimmed || trimmed === '[DONE]') return undefined\n try {\n return JSON.parse(trimmed) as unknown\n } catch {\n return undefined\n }\n}\n\n// ---------------------------------------------------------------------------\n// Credential fallback from the official Command Code CLI auth file. Used as\n// the last fallback by the plugin entry, so a user who already logged in with\n// `command-code login` can reuse that credential. Only the official CLI's own\n// file is read — pi/OMP auth files are intentionally not scanned, so their\n// credentials and formats cannot surprise this adapter.\n// ---------------------------------------------------------------------------\n\n/** Extract the key from the CLI's nested credential records (`command-code`). */\nfunction apiKeyFromCredentialRecord(value: unknown): string | undefined {\n if (!isRecord(value)) return undefined\n const type = stringValue(value.type)\n if (type === 'api') return stringValue(value.key)\n if (type === 'oauth') return stringValue(value.access)\n return stringValue(value.key) ?? stringValue(value.access)\n}\n\n/** Read a usable Command Code credential from the official CLI auth file. */\nexport function resolveAuthFileApiKey(): string | undefined {\n const authPath = join(homedir(), '.commandcode', 'auth.json')\n try {\n if (!existsSync(authPath)) return undefined\n const parsed: unknown = JSON.parse(readFileSync(authPath, 'utf-8'))\n if (!isRecord(parsed)) return undefined\n const direct = stringValue(parsed.apiKey) ?? stringValue(parsed.commandcode)\n if (direct) return direct\n const nested =\n apiKeyFromCredentialRecord(parsed.commandcode) ??\n apiKeyFromCredentialRecord(parsed['command-code'])\n return nested\n } catch {\n // Ignore malformed or unreadable auth file.\n }\n return undefined\n}\n\n// ---------------------------------------------------------------------------\n// Model catalog discovery with on-disk cache fallback (ported from models.ts)\n// ---------------------------------------------------------------------------\n\ninterface CommandCodeModel {\n id: string\n name: string\n contextWindow: number\n maxTokens: number\n}\n\nfunction parseCatalogResponse(value: unknown): CommandCodeModel[] {\n if (!isRecord(value) || value.object !== 'list' || !Array.isArray(value.data)) {\n throw new LlmError('Unexpected Command Code models response shape', 'PROVIDER_PROTOCOL_ERROR')\n }\n const models: CommandCodeModel[] = []\n for (const entry of value.data) {\n if (!isRecord(entry)) continue\n const id = stringValue(entry.id)\n const name = stringValue(entry.name)\n const contextLength = numberValue(entry.context_length)\n if (!id || !name || !contextLength || contextLength <= 0) continue\n models.push({\n id,\n name,\n contextWindow: contextLength,\n maxTokens: Math.min(contextLength, DEFAULT_MAX_OUTPUT_TOKENS),\n })\n }\n if (models.length === 0) {\n throw new LlmError('Command Code returned an empty model catalog', 'PROVIDER_PROTOCOL_ERROR')\n }\n return models\n}\n\nasync function readModelsCache(cachePath: string): Promise<CommandCodeModel[]> {\n const parsed: unknown = JSON.parse(await readFile(cachePath, 'utf-8'))\n if (!isRecord(parsed) || parsed.version !== MODEL_CACHE_VERSION || !Array.isArray(parsed.models)) {\n throw new Error(`Invalid model cache at ${cachePath}`)\n }\n return parsed.models as CommandCodeModel[]\n}\n\nasync function writeModelsCache(cachePath: string, models: CommandCodeModel[]): Promise<void> {\n await mkdir(dirname(cachePath), { recursive: true })\n const tmp = `${cachePath}.${process.pid}.tmp`\n try {\n await writeFile(tmp, `${JSON.stringify({ version: MODEL_CACHE_VERSION, models }, null, 2)}\\n`, {\n encoding: 'utf-8',\n mode: 0o600,\n })\n await rename(tmp, cachePath)\n } finally {\n await rm(tmp, { force: true }).catch(() => undefined)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Message conversion: harness Message[] -> Command Code wire messages.\n// Reasoning blocks are intentionally NOT replayed (matches the pi plugin and\n// the official CLI: prior private reasoning must not leak into later turns).\n// Only tool calls with a paired tool result are replayed.\n// ---------------------------------------------------------------------------\n\nfunction pairedToolCallIds(messages: readonly Message[]): Set<string> {\n const callIds = new Set<string>()\n const resultIds = new Set<string>()\n for (const message of messages) {\n for (const block of message.content) {\n if (message.role === 'assistant' && block.type === 'tool-call') callIds.add(block.id)\n if (block.type === 'tool-result') resultIds.add(block.toolCallId)\n }\n }\n return new Set([...callIds].filter((id) => resultIds.has(id)))\n}\n\nfunction blockText(block: ContentBlock): string {\n return block.type === 'text' || block.type === 'reasoning' ? block.text : ''\n}\n\nfunction toolResultText(block: Extract<ContentBlock, { type: 'tool-result' }>): string {\n return block.content.map(blockText).filter(Boolean).join('\\n')\n}\n\nfunction hasImageContent(message: Message): boolean {\n const check = (blocks: readonly ContentBlock[]): boolean =>\n blocks.some(\n (b) => b.type === 'image' || (b.type === 'tool-result' && check(b.content)),\n )\n return check(message.content)\n}\n\nfunction messagesToCC(messages: readonly Message[]): 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 // ImageBlock carries an attachment ref owned by the attachment\n // service; resolving it to bytes requires that service. Fail loudly\n // instead of silently dropping (adapter contract).\n throw new LlmError(\n 'Image input is not wired to the attachment service in this adapter yet',\n 'UNSUPPORTED_CONTENT',\n )\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\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\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}\n\n/** Account identity from `/alpha/whoami`. */\nexport interface CommandCodeAccount {\n id: string\n name: string\n userName: string\n}\n\n/** Usage summary from `/alpha/usage/summary`. */\nexport interface CommandCodeUsage {\n totalCount: number\n totalCost: number\n successRate: number\n completedCount: number\n failedCount: number\n totalTokensIn: number\n totalTokensOut: number\n totalCredits: number\n periodBasis: string\n}\n\n/** Credit/limit state from `/alpha/billing/credits`. */\nexport interface CommandCodeCredits {\n monthlyCredits: number\n purchasedCredits: number\n freeCredits: number\n /** Five-hour rolling window limits. */\n fiveHour: { used: number; cap: number; exceeded: boolean; resetAt: number }\n /** Weekly window limits. */\n weekly: { used: number; cap: number; exceeded: boolean; resetAt: number }\n}\n\n/** Everything the usage endpoints report, fetched together. */\nexport interface CommandCodeUsageReport {\n account?: CommandCodeAccount\n usage?: CommandCodeUsage\n credits?: CommandCodeCredits\n /** Endpoint failures degrade the report instead of failing it. */\n failures: string[]\n}\n\nexport class CommandCodeAdapter<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> extends LlmAdapter {\n private catalog: CommandCodeModel[] = []\n private readonly fetchImpl: typeof fetch\n\n constructor(private readonly deps: CommandCodeAdapterDeps<C>) {\n super()\n this.fetchImpl = deps.fetchImpl ?? fetch\n }\n\n /**\n * Command Code is a metered subscription API: 429 (rate limit) and 5xx\n * (transient server errors) are worth retrying at the agent-step boundary,\n * which is where dsh-llm-retry executes the policy returned here. The\n * default policy already retries `RATE_LIMIT` and `SERVER`; declaring it\n * explicitly documents the intent and gives the plugin entry a stable hook\n * to override (e.g. a stricter cap for a metered plan).\n */\n override providerRetryPolicy(_provider: string): ResolvedRetryPolicy {\n return resolveRetryPolicy(undefined, 'llm-commandcode: retryPolicy')\n }\n\n /** Refresh the catalog (live fetch, cache fallback) and return it. */\n private async loadCatalog(signal?: AbortSignal): Promise<CommandCodeModel[]> {\n const { apiBase, modelsCachePath } = this.deps.options()\n try {\n const response = await this.fetchImpl(`${apiBase}/provider/v1/models`, {\n headers: { accept: 'application/json', ...attributionHeaders() },\n signal: signal ?? AbortSignal.timeout(MODELS_TIMEOUT_MS),\n })\n if (!response.ok) {\n throw new Error(`models endpoint returned ${response.status}`)\n }\n this.catalog = parseCatalogResponse(await response.json())\n await writeModelsCache(modelsCachePath, this.catalog).catch(() => undefined)\n } catch (error) {\n if (signal?.aborted) throw error\n // A catalog refresh failure is a degradation, not a request failure:\n // fall back to the last successful catalog on disk (or the in-memory\n // one from an earlier successful load). The adapter still serves any\n // model the user names; only the advisory selector loses entries.\n this.catalog = await readModelsCache(modelsCachePath).catch(() => this.catalog)\n }\n return this.catalog\n }\n\n override async listModels(provider: string): Promise<readonly LlmModelInfo[]> {\n const catalog = await this.loadCatalog()\n return catalog.map((model) => ({\n provider,\n id: model.id,\n name: `${model.name} (CC)`,\n inputModalities: ['text' as const],\n }))\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 return {\n provider,\n id: model,\n name: entry ? `${entry.name} (CC)` : model,\n inputModalities: ['text' as const],\n ...(entry\n ? {\n context: { contextWindow: entry.contextWindow },\n defaultMaxTokens: Math.min(entry.maxTokens, DEFAULT_GENERATE_MAX_TOKENS),\n }\n : {}),\n // Omit `reasoning` entirely for models without known effort support:\n // the harness then treats the model as having no selectable efforts.\n ...(efforts\n ? {\n reasoning: {\n efforts: efforts.map((effort) => ({\n id: ReasoningEffortId(effort),\n name: effort,\n })),\n },\n }\n : {}),\n }\n }\n\n /**\n * Fetch account, usage, and credit state from the Command Code account\n * endpoints (`/alpha/whoami`, `/alpha/usage/summary`, `/alpha/billing/credits`).\n * Each endpoint degrades independently: a failed one lands in `failures`\n * while the rest still report, so a transient outage never blanks the whole\n * view. Requires a usable API key (throws `MISSING_CREDENTIAL` otherwise).\n */\n async getUsage(): Promise<CommandCodeUsageReport> {\n const connection = this.deps.options()\n const apiKey = await this.deps.resolveApiKey(connection)\n const base = connection.apiBase\n const headers = {\n Authorization: `Bearer ${apiKey}`,\n 'x-command-code-version': COMMAND_CODE_CLI_VERSION,\n 'x-cli-environment': 'production',\n ...attributionHeaders(),\n }\n const failures: string[] = []\n\n const getJson = async (path: string): Promise<Record<string, unknown> | undefined> => {\n try {\n const response = await this.fetchImpl(`${base}${path}`, { headers })\n if (!response.ok) {\n failures.push(`${path}: HTTP ${response.status}`)\n return undefined\n }\n const parsed: unknown = await response.json()\n return isRecord(parsed) ? parsed : undefined\n } catch (error: unknown) {\n failures.push(`${path}: ${error instanceof Error ? error.message : String(error)}`)\n return undefined\n }\n }\n\n const report: CommandCodeUsageReport = { failures }\n\n // whoami -> account identity.\n const whoami = await getJson('/alpha/whoami')\n const whoamiData = whoami && isRecord(whoami.user) ? whoami.user : undefined\n if (whoamiData) {\n report.account = {\n id: stringValue(whoamiData.id) ?? '',\n name: stringValue(whoamiData.name) ?? '',\n userName: stringValue(whoamiData.userName) ?? '',\n }\n }\n\n // usage/summary -> totals.\n const usage = await getJson('/alpha/usage/summary')\n if (usage) {\n report.usage = {\n totalCount: numberValue(usage.totalCount) ?? 0,\n totalCost: numberValue(usage.totalCost) ?? 0,\n successRate: numberValue(usage.successRate) ?? 0,\n completedCount: numberValue(usage.completedCount) ?? 0,\n failedCount: numberValue(usage.failedCount) ?? 0,\n totalTokensIn: numberValue(usage.totalTokensIn) ?? 0,\n totalTokensOut: numberValue(usage.totalTokensOut) ?? 0,\n totalCredits: numberValue(usage.totalCredits) ?? 0,\n periodBasis: stringValue(usage.periodBasis) ?? 'billing-period',\n }\n }\n\n // billing/credits -> credit + window limits.\n const credits = await getJson('/alpha/billing/credits')\n const creditsData = credits && isRecord(credits.credits) ? credits.credits : undefined\n const windowLimits = credits && isRecord(credits.windowLimits) ? credits.windowLimits : undefined\n const fiveHour = windowLimits && isRecord(windowLimits.fiveHour) ? windowLimits.fiveHour : undefined\n const weekly = windowLimits && isRecord(windowLimits.weekly) ? windowLimits.weekly : undefined\n if (creditsData || fiveHour || weekly) {\n report.credits = {\n monthlyCredits: numberValue(creditsData?.monthlyCredits) ?? 0,\n purchasedCredits: numberValue(creditsData?.purchasedCredits) ?? 0,\n freeCredits: numberValue(creditsData?.freeCredits) ?? 0,\n fiveHour: {\n used: numberValue(fiveHour?.used) ?? 0,\n cap: numberValue(fiveHour?.cap) ?? 0,\n exceeded: fiveHour?.exceeded === true,\n resetAt: numberValue(fiveHour?.resetAt) ?? 0,\n },\n weekly: {\n used: numberValue(weekly?.used) ?? 0,\n cap: numberValue(weekly?.cap) ?? 0,\n exceeded: weekly?.exceeded === true,\n resetAt: numberValue(weekly?.resetAt) ?? 0,\n },\n }\n }\n\n return report\n }\n\n async *stream(options: GenerateOptions): AsyncIterable<StreamChunk> {\n if (options.stop?.length) {\n // The Command Code wire format has no documented stop field; refuse\n // loudly instead of silently dropping a request field.\n throw new LlmError('Command Code adapter does not support stop sequences', 'UNSUPPORTED_OPTION')\n }\n if (options.messages.some(hasImageContent)) {\n throw new LlmError(\n 'Image input is not wired to the attachment service in this adapter yet',\n 'UNSUPPORTED_CONTENT',\n )\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: messagesToCC(options.messages),\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 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 ...(options.signal ? { signal: options.signal } : {}),\n })\n } catch (error: unknown) {\n // Caller cancellation must propagate as-is, not be relabeled.\n if (options.signal?.aborted) throw error\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`. Wrapping with the endpoint and chaining the\n // cause lets `errorChain` render the full diagnosis at every reporting\n // boundary, and gives the retry policy a stable `TRANSPORT` code.\n throw new LlmError(\n `Command Code API request to ${connection.apiBase}/alpha/generate failed`,\n 'TRANSPORT',\n { cause: error },\n )\n }\n\n if (!response.ok) {\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 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 // 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 const detail = isRecord(event.error)\n ? (stringValue(event.error.message) ?? JSON.stringify(event.error))\n : (stringValue(event.error) ?? stringValue(event.message) ?? 'Stream error')\n throw new LlmError(`Command Code stream error: ${detail}`, 'PROVIDER_STREAM_ERROR')\n }\n }\n return chunks\n }\n\n try {\n let finished = false\n for (;;) {\n let read: ReadableStreamReadResult<Uint8Array>\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; anything\n // else is a transport failure with a stable code.\n if (options.signal?.aborted) throw error\n throw new LlmError(\n `Command Code API stream from ${connection.apiBase} failed while reading`,\n 'TRANSPORT',\n { cause: error },\n )\n }\n const { done, value } = read\n if (done) {\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 await reader.cancel().catch(() => undefined)\n reader.releaseLock()\n }\n }\n}\n\nfunction mapFinishReason(reason: unknown): FinishReason {\n if (reason === 'tool-calls') return { kind: 'tool-calls' }\n if (\n reason === 'length' ||\n reason === 'max_tokens' ||\n reason === 'max-tokens' ||\n reason === 'max_output_tokens'\n ) {\n return { kind: 'max-tokens' }\n }\n return { kind: 'stop' }\n}\n","/**\n * `/commandcode` slash command — account usage dashboard.\n *\n * /commandcode show account, usage, and credit state\n * /commandcode status same as bare `/commandcode`\n *\n * Backed by the Command Code account endpoints the official CLI uses\n * (`/alpha/whoami`, `/alpha/usage/summary`, `/alpha/billing/credits`),\n * exposed through `CommandCodeAdapter.getUsage()`.\n *\n * @module dsh-commandcode-provider/commands\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\n// Type-only import that loads the module augmentation (`ctx.commands`).\nimport type { CommandDefinition } from '@deepseek-ai/dsh-commands'\nimport { CommandCodeAdapter } from './adapter.ts'\nimport type { CommandCodeConnectionOptions, CommandCodeUsageReport } from './adapter.ts'\n\n/** Everything the command needs beyond the adapter itself. */\nexport interface CommandCodeCommandDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {\n /** The registered adapter (for getUsage / listModels). */\n adapter: CommandCodeAdapter<C>\n}\n\n/** Format a dollar amount. */\nfunction money(value: number): string {\n return `$${value.toFixed(4)}`\n}\n\n/** Format a dollar amount compactly (2 decimals). */\nfunction moneyShort(value: number): string {\n return `$${value.toFixed(2)}`\n}\n\n/** Format a token count with thousands separators. */\n/** Format a large token count compactly (1.9亿 style). */\nfunction tokensCompact(value: number): string {\n if (value >= 1e9) return `${(value / 1e9).toFixed(1)}B`\n if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`\n if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`\n return String(value)\n}\n\n/** Format a millis timestamp as a local date. */\nfunction resetLabel(ms: number): string {\n if (ms <= 0) return 'n/a'\n return new Date(ms).toLocaleString()\n}\n\n/**\n * A 10-cell horizontal bar: `██████████` for 100%, `███░░░░░░░` for ~33%.\n * Handles caps of 0 (no limit) and out-of-range values.\n */\nfunction bar(used: number, cap: number): string {\n if (cap <= 0) return '—'\n const ratio = Math.max(0, Math.min(1, used / cap))\n const filled = Math.round(ratio * 10)\n return '█'.repeat(filled) + '░'.repeat(10 - filled)\n}\n\n/** Render the usage report as a structured, aligned, bar-chart text view. */\nfunction renderReport(report: CommandCodeUsageReport): string {\n const lines: string[] = []\n const account = report.account ? ` (${report.account.userName || report.account.name})` : ''\n\n lines.push(`📊 Command Code 用量${account}`, '')\n\n if (report.usage) {\n const u = report.usage\n lines.push(\n '── 请求 ──────────────────────────────',\n ` 💬 请求 ${u.completedCount} 次 / 失败 ${u.failedCount} 成功率 ${u.successRate}%`,\n ` 💰 花费 ${money(u.totalCost)} (${moneyShort(u.totalCredits)} credits)`,\n ` 🔤 Token ${tokensCompact(u.totalTokensIn)} 入 / ${tokensCompact(u.totalTokensOut)} 出`,\n '',\n )\n }\n\n if (report.credits) {\n const c = report.credits\n const monthlyPct = c.monthlyCredits > 0\n ? `${((c.monthlyCredits / (c.monthlyCredits + c.purchasedCredits)) * 100).toFixed(0)}%`\n : '—'\n lines.push(\n '── 信用 ──────────────────────────────',\n ` 💳 月额度 ${moneyShort(c.monthlyCredits)} (已购 ${moneyShort(c.purchasedCredits)} / 赠送 ${moneyShort(c.freeCredits)})`,\n ` └ ${bar(c.monthlyCredits, c.monthlyCredits + c.purchasedCredits)} ${monthlyPct}`,\n '',\n '── 窗口用量 ──────────────────────────',\n ` ⏱ 5 小时 ${moneyShort(c.fiveHour.used)} / ${moneyShort(c.fiveHour.cap)}${c.fiveHour.exceeded ? ' ⚠️ 超限!' : ''}`,\n ` └ ${bar(c.fiveHour.used, c.fiveHour.cap)} 重置 ${resetLabel(c.fiveHour.resetAt)}`,\n ` 📅 每周 ${moneyShort(c.weekly.used)} / ${moneyShort(c.weekly.cap)}${c.weekly.exceeded ? ' ⚠️ 超限!' : ''}`,\n ` └ ${bar(c.weekly.used, c.weekly.cap)} 重置 ${resetLabel(c.weekly.resetAt)}`,\n '',\n )\n }\n\n if (report.failures.length > 0) {\n lines.push(`⚠️ 部分端点失败: ${report.failures.join('; ')}`, '')\n }\n if (!report.account && !report.usage && !report.credits) {\n lines.push('(no data — check your API key)', '')\n }\n\n return lines.join('\\n').trimEnd()\n}\n\n/** The one registered `/commandcode` command. */\nexport function commandDefinition<C extends CommandCodeConnectionOptions>(\n deps: CommandCodeCommandDeps<C>,\n): CommandDefinition {\n const { adapter } = deps\n return {\n name: 'commandcode',\n description: 'Command Code account usage dashboard',\n input: { hint: '[status]' },\n handler: async () => {\n try {\n const report = await adapter.getUsage()\n return { kind: 'success', text: renderReport(report) }\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n kind: 'error',\n text: `Could not fetch Command Code usage: ${message}`,\n }\n }\n },\n }\n}\n\n/** Register the command on `ctx.commands` (called from the plugin entry). */\nexport function applyCommands<C extends CommandCodeConnectionOptions>(\n ctx: Context,\n deps: CommandCodeCommandDeps<C>,\n): void {\n ctx.commands.register(commandDefinition(deps))\n}\n","/**\n * dsh-commandcode-provider — DeepSeek Harness LLM provider plugin for Command\n * Code (unofficial; ported from pi-commandcode-provider@0.5.1).\n *\n * Registers the `commandcode` provider route on `ctx.llm` and declares it in\n * the configurable-provider directory, so the web Models page shows a\n * \"Command Code\" card with an API-key field and the model picker lists the\n * live Command Code model catalog. Connection facts resolve per request over\n * the optional `llm-commandcode` user-settings section and the credential\n * seam, so a changed key, endpoint, or cache path reaches the next request\n * without a restart.\n *\n * ```yaml\n * - id: llm-commandcode\n * name: dsh-commandcode-provider\n * config:\n * apiKeyEnv: COMMANDCODE_API_KEY\n * ```\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 { 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 type { CommandCodeConnectionOptions } from './adapter.ts'\nimport { applyCommands } from './commands.ts'\n\nexport {\n COMMAND_CODE_CLI_VERSION,\n DEFAULT_API_BASE,\n DEFAULT_GENERATE_MAX_TOKENS,\n DEFAULT_MAX_OUTPUT_TOKENS,\n CommandCodeAdapter,\n KNOWN_EFFORTS,\n projectSlugFromPath,\n resolveAuthFileApiKey,\n} from './adapter.ts'\nexport type { CommandCodeAdapterDeps, CommandCodeConnectionOptions, CommandCodeUsageReport } from './adapter.ts'\nexport { applyCommands, commandDefinition } from './commands.ts'\nexport type { CommandCodeCommandDeps } from './commands.ts'\n\nexport const name = 'llm-commandcode'\nexport const inject = ['llm']\n\nconst NS = settingsNamespace('llm-commandcode')\nconst DEFAULT_API_KEY_ENV = 'COMMANDCODE_API_KEY'\n\n/** The single provider route this plugin owns. */\nexport const PROVIDER = 'commandcode'\n/** Default models cache path (mirrors the pi plugin's on-disk cache). */\nexport const DEFAULT_MODELS_CACHE_PATH = join(homedir(), '.commandcode', 'models-cache.json')\n\n/**\n * Plugin config, validated by the same-named schemastery schema and doubling\n * as the `llm-commandcode` settings-section shape. Every field is optional:\n * a missing API key resolves through {@link Config.apiKeyEnv} at each request\n * (the web Models page writes it), with the official Command Code CLI auth\n * file (`~/.commandcode/auth.json`) as the last fallback.\n */\nexport interface Config {\n /** Credential reference (environment-variable name) resolved per request; defaults to `COMMANDCODE_API_KEY`. */\n apiKeyEnv?: string\n /** Literal API key override (composition config only); takes precedence over `apiKeyEnv`. */\n apiKey?: string\n /** API base; defaults to the public Command Code Provider API. */\n apiBase?: string\n /** Working directory reported to the API; defaults to the process cwd. */\n workingDir?: string\n /** Model catalog cache path; defaults to `~/.commandcode/models-cache.json`. */\n modelsCachePath?: string\n}\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})\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 }\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({ options, resolveApiKey })\n // The Models page card: a configurable provider with a settings address.\n // settingsPath [] means the whole `llm-commandcode` section configures it.\n ctx.llm.registerConfigurableProviders([\n { provider: PROVIDER, displayName: 'Command Code', settingsNs: NS, settingsPath: [] },\n ])\n // The live route: this is what makes models requestable under `commandcode`.\n ctx.llm.registerAdapter([PROVIDER], adapter)\n\n // The /commandcode usage command rides the optional `commands` service: a\n // child fiber injects it, so it registers whenever the profile mounts\n // dsh-commands and the fiber simply never activates when it does not.\n ctx.inject(['commands'], (commandCtx) => {\n applyCommands(commandCtx, { adapter })\n })\n\n installSettingsSection(ctx, NS, Config, config, {\n setSource: (source) => {\n current = source\n },\n // Everything the adapter reads is resolved per request, so a settings\n // change needs no registration-level action.\n onChange: () => {},\n })\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mars-sea/dsh-commandcode-provider",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
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",
@@ -60,6 +60,7 @@
60
60
  "license": "MIT",
61
61
  "peerDependencies": {
62
62
  "@deepseek-ai/cordis": "^4.0.1",
63
+ "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
63
64
  "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6",
64
65
  "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.6",
65
66
  "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
@@ -68,6 +69,7 @@
68
69
  },
69
70
  "devDependencies": {
70
71
  "@deepseek-ai/cordis": "^4.0.1",
72
+ "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
71
73
  "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6",
72
74
  "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.6",
73
75
  "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",