@mars-sea/dsh-commandcode-provider 0.15.1 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +110 -198
- package/README.zh-CN.md +96 -165
- package/lib/client.js +88 -73
- package/lib/index.d.ts +1 -1
- package/lib/index.js +2 -68
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,27 @@ 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.15.2] - 2026-10-23
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **「模型白名单」说明精简成一句**:「只列出勾选的模型,都不勾选=显示全部。网页与终端共用。」(27 字,合并回单键 `visibleModelsHint`)。纯呈现层,白名单的暂存、校验与提交路径不动。
|
|
12
|
+
- **设置页尺寸回到设计画布**(用户反馈「整体大小好像被改掉了,没有那么协调了」):撤回同批早先加的两类调整——① 分组头、账户卡片列表、「添加账户」操作行的 `padding-right:36px` 右内缩,卡片与分组头恢复满宽;② API 地址行与模型白名单行的 `cc-rowFluid`(不折行、API 地址输入框拉伸到约 380–600px),API 地址输入框回到 280px,两行恢复普通行。
|
|
13
|
+
|
|
14
|
+
- **同步 Command Code CLI `1.87.1` → `1.87.3`,并清理四个已下线模型(纯请求头 + 快照清理)。** `1.87.2`(10-22T20:43Z)四条修复、`1.87.3`(10-22T21:30Z)两条新功能,两条都有官方变更条目——`cmd acp` 可加载 mod 选项、无效推理档位不再让所有请求失败、进程名不再每 5 秒重设、流中途失败显示供应商真实错误;`--permission-mode` 接受 Claude Code 的权限模式别名、更新 BYOK 包——全部属 CLI 自身行为,插件不经过这些路径。产物级比对:端点集合(64 个)、自定义请求头(5 个)、`/alpha/generate` 调用点、`promptCache` 与 `reasoning_effort` 字面量、模型注册表、efforts(推理档位)、订阅表与 ZDR(零数据保留)例外集逐项相同(审计 `cliDiff` 四类全空),故 `COMMAND_CODE_CLI_VERSION` 只随请求头更新。服务端目录 `catalogVersion` 由 `501a4bf9…` 变为 `02bfc7ac…`,默认视图 96 → 92 而 `?view=client` 仍 104:两个限时免费促销到期(`ornith/ornith-1.5-122b:free` `2026-10-22T06:00Z`、`minimax/minimax-m3.1-flash:free` `2026-10-22T10:45Z`),MiMo V2.5 两款下架(`xiaomi/mimo-v2.5`、`xiaomi/mimo-v2.5-pro`——V2.6 以原促销价作为常规价,属同价换代而非临时隐藏)。官方 models / pricing 页与 go / goat / pro / max 计划页同步删除这些行与小米合作区块,ZDR 页与 What's New 无变化。快照随之清理:`KNOWN_PLANS` 96 → 92、`KNOWN_EFFORTS` 66 → 65、`KNOWN_IMAGE_MODELS` 74 → 71、`KNOWN_THINKING_MODELS` 17 → 16、`KNOWN_DEALS` 8 → 4、内置价格行 94 → 92、输出上限行 82 → 79,ZDR 例外集 18 不变;其余 88 个模型的价格、上下文、计划档位与输入模态零变化。**证据边界**:公开 GET 采集 14 个源全部 HTTP 200;审计 `incomplete` 的 2 条 error 是 MiniMax M3.1 Flash 与 Ornith 缺定价别名(上一轮 4 条,随两个 `:free` 行下线减为 2 条),非抓取失败;未做真实账号登录、付费生成、浏览器渲染与服务端协议验证。
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **设置页右侧只剩一条边界**(用户反馈「右侧没有设计图好看」):此前每行控件后都留 28px「恢复默认」空位,控件比账户卡片、分组头「刷新」、「查看模型用量」那一行多缩进 36px,形成两条右边界。现在「恢复默认」改为标题行「已自定义」徽标后的 20px 圆形图标按钮(只在字段被改过时出现),行末不再留空位,控件、卡片、分组头动作全部贴内容右缘;`FieldOverride` 组件与 `cc-resetSlot` 样式删除。
|
|
19
|
+
|
|
20
|
+
- **窄设置面板下宽控件不再折到第二行**(用户截图:约 560px 内容区里,模型白名单的「显示全部」+ 下拉框、API 地址输入框都掉到第二行右侧):设置行文字列下限从 300px 降到 200px,控件保持设计稿尺寸(输入框 280px、下拉 200px)并始终与标题同行,代价是窄面板下说明文字多折一两行;门槛由约 640px 降到约 540px。
|
|
21
|
+
- **服务状态行不再从中间断开「13 小时前更新」**:「打开状态页」链接移到「服务状态」标题行右侧(带外链图标),两行状态获得整行宽度;官方行的可用率、平均响应、更新时间各为不可断开的一段(视图字段 `detail` 改为 `detailParts`),放不下时整段换到下一行,换行后的行首不会是「·」。
|
|
22
|
+
|
|
23
|
+
### Verification
|
|
24
|
+
|
|
25
|
+
- `npm run typecheck` 通过;`npm test` **1111/1111** 通过;`npm run build` 完成,`lib/client.js` 已不含 `cc-rowFluid` 与 `padding-right:36px`。**未做**:在运行中的 dsh web 宿主内实测(宿主重启后需新的带令牌地址)。
|
|
26
|
+
- 上游同步同批:`npm run typecheck` 退出码 0、`npm test` **1111/1111**、`npm run build` 两段 `Build complete`(`lib/` 已重建,含 `1.87.3`、不含 `xiaomi/mimo-v2.5`);`node scripts/sync-model-prices.mjs --check` 报 `up to date (92 rows)`、`node scripts/sync-output-limits.mjs --check` 报 `table already up to date`,退出码均 0。
|
|
27
|
+
|
|
7
28
|
## [0.15.1] - 2026-10-22
|
|
8
29
|
|
|
9
30
|
### Changed
|
package/README.md
CHANGED
|
@@ -12,136 +12,106 @@
|
|
|
12
12
|
|
|
13
13
|
Unofficial [DeepSeek Harness](https://deepseek-harness.github.io/deepseek-harness/) LLM provider plugin for **Command Code**, ported from [pi-commandcode-provider](https://github.com/patlux/pi-commandcode-provider) (MIT).
|
|
14
14
|
|
|
15
|
-
>
|
|
16
|
-
|
|
17
|
-
##
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
- **
|
|
31
|
-
- **
|
|
32
|
-
- **
|
|
33
|
-
- **
|
|
34
|
-
- **
|
|
35
|
-
- **
|
|
36
|
-
|
|
37
|
-
|
|
15
|
+
> Community integration. You need your own Command Code account, API key or subscription, and Command Code's terms apply. Not affiliated with Command Code, Inc.
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
| | |
|
|
20
|
+
|---|---|
|
|
21
|
+
| Verified engines | dsh `0.2.0-rc.2` (npm `latest`) · dsh `0.2.1-rc.2` (npm `next`) |
|
|
22
|
+
| Install — web | `dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@latest` |
|
|
23
|
+
| Install — terminal | `dsh plugin --profile dsh-tui add @mars-sea/dsh-commandcode-provider@latest` |
|
|
24
|
+
| Config file | `$DSH_HOME/settings.yaml` → `llm-commandcode:` |
|
|
25
|
+
| API key env | `COMMANDCODE_API_KEY` |
|
|
26
|
+
| Usage dashboard | `/commandcode` |
|
|
27
|
+
|
|
28
|
+
## Features
|
|
29
|
+
|
|
30
|
+
- **Plugin bundle** — one `dsh plugin add` installs a `commandcode` provider route with the live model catalog.
|
|
31
|
+
- **Settings page** — accounts (keys, browser sign-in, live quota, dedicated models), model visibility, privacy switches, connection options.
|
|
32
|
+
- **Annotated catalog** — plan tier, deal/`FREE` badge, peak/off-peak, image support and context window in the picker; free models first.
|
|
33
|
+
- **Multi-account rotation** — an exhausted account hands over to the next one; pin a preferred account or route models to dedicated ones.
|
|
34
|
+
- **Browser sign-in** — run the official authorization flow from the settings page; the approved key lands in the local credential store.
|
|
35
|
+
- **Plans & quota panel** — optional sidebar card with the serving account's plan, 5-hour and weekly windows, balances and reset times.
|
|
36
|
+
- **Session cost estimate** — published-rate estimates (`≈`) beside the composer token counter, priced per request from durable session history.
|
|
37
|
+
- **Model analysis** — tokens, estimated cost, response timing and failures by session or date range. [Scope](docs/模型成本与性能分析.md).
|
|
38
|
+
- **Web search** — the dsh `web_search` tool is served by Command Code (`/alpha/web-search`) with the same key and endpoint as chat.
|
|
39
|
+
- **Zero data retention** — optional ZDR routing (`x-cmd-zdr: 1`), off by default.
|
|
40
|
+
- **Context & output limits** — override the metered context window globally or per model, and cap or omit the per-turn `max_tokens`.
|
|
41
|
+
- **Reasoning effort & images** — effort levels in the picker; Vision models accept images.
|
|
42
|
+
- **Terminal UI** — the same install serves a [dsh-TUI](#terminal-ui-dsh-tui) profile with its own `/settings` → Command Code page.
|
|
38
43
|
|
|
39
|
-
##
|
|
44
|
+
## Screenshots
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
(release-candidate) channel. `0.2.0-rc.2` is what npm `latest` still points at (re-checked
|
|
43
|
-
2026-10-18), so it is the engine an official default install runs; `0.2.1-rc.2` ships on the `next`
|
|
44
|
-
tag. The peer range and the compatibility records name both as exact versions, and no alpha release
|
|
45
|
-
is retained: nothing has been verified since `0.2.1-alpha.5`. `@deepseek-ai/cordis` /
|
|
46
|
-
`@deepseek-ai/schemastery` carry the paired disjunction `~4.0.4 || ~4.0.5` / `~3.18.4 || ~3.18.5`,
|
|
47
|
-
because the two engines pair differently (`0.2.0-rc.2` needs cordis `~4.0.4` and schemastery
|
|
48
|
-
`~3.18.4`, `0.2.1-rc.2` ships `4.0.5` / `3.18.5`) and one branch cannot resolve both. Note that
|
|
49
|
-
**dsh 0.2.1-rc.2 reads
|
|
50
|
-
`engines.dsh` alone** when it decides whether a plugin is compatible; the dsh peer ranges are
|
|
51
|
-
consulted only when that field is absent, so a build that declares the wrong `engines.dsh` is refused
|
|
52
|
-
outright there — while on `0.2.0-rc.2` the peer ranges are what decides. A profile on
|
|
53
|
-
`0.2.1-alpha.5` or any earlier release must upgrade its engine before installing this build:
|
|
46
|
+
**Model picker** — plan tier, deal/FREE, peak/off-peak, Image and context annotations:
|
|
54
47
|
|
|
55
|
-
|
|
56
|
-
dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@latest
|
|
57
|
-
```
|
|
48
|
+
<img src="assets/screenshots/model-picker.png" alt="Model picker with plan, deal, image and context annotations" width="320">
|
|
58
49
|
|
|
59
|
-
|
|
60
|
-
engines predate the 0.1.7 settings rewrite, the `RequestMessage` envelope, and
|
|
61
|
-
the durable image-offload contract, and the compatibility code that bridged
|
|
62
|
-
the two was removed. The last plugin release covering 0.1.7 is 0.11.17; the
|
|
63
|
-
0.1.2–0.1.6 line's last release is 0.11.11; the 0.5.0-era Harness line's last
|
|
64
|
-
release is 0.9.1. All are installed by exact version and none is maintained:
|
|
50
|
+
**Usage dashboard** — `/commandcode` per-account report:
|
|
65
51
|
|
|
66
|
-
|
|
67
|
-
dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.11.17 # dsh 0.1.7
|
|
68
|
-
dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.11.11 # dsh 0.1.2–0.1.6
|
|
69
|
-
dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.9.1 # dsh 0.5.0 line
|
|
70
|
-
```
|
|
52
|
+
<img src="assets/screenshots/usage-dashboard.png" alt="Usage dashboard" width="520">
|
|
71
53
|
|
|
72
|
-
**
|
|
54
|
+
**Settings page** — accounts with live quota, model visibility, privacy switches, connection options:
|
|
55
|
+
|
|
56
|
+
<img src="assets/screenshots/settings-page.png" alt="Command Code settings page with the account usage card" width="640">
|
|
57
|
+
|
|
58
|
+
## Install
|
|
73
59
|
|
|
74
60
|
```sh
|
|
75
|
-
dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@
|
|
61
|
+
dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@latest
|
|
76
62
|
```
|
|
77
63
|
|
|
78
|
-
|
|
64
|
+
This build targets **dsh `0.2.0-rc.2` and `0.2.1-rc.2`** — two verified engines, both on the RC channel. `0.2.0-rc.2` is what npm `latest` points at, so it is the engine a default install runs; `0.2.1-rc.2` ships on `next`. A profile on `0.2.1-alpha.5` or older must upgrade its engine first. Compatibility details — peer ranges, the `engines.dsh` admission rule, per-engine package pairings — live in [engine compatibility](docs/agent-reference/engine-compatibility.md).
|
|
79
65
|
|
|
80
|
-
|
|
66
|
+
**Older dsh releases** are no longer supported: the last plugin release for dsh 0.1.7 is `0.11.17`, for 0.1.2–0.1.6 it is `0.11.11`, and for the 0.5.0-era line `0.9.1` — all installed by exact version, none maintained.
|
|
81
67
|
|
|
82
|
-
|
|
68
|
+
> **pnpm 11 holds back new releases.** `minimumReleaseAge` defaults to 1440 minutes, so a version published less than a day ago is skipped and `@latest` resolves to the *previous* release — silently, with a success exit code. To install a release from the last 24 hours, name it exactly: `@mars-sea/dsh-commandcode-provider@0.11.15`. This applies to every profile, including the terminal UI below.
|
|
83
69
|
|
|
84
|
-
|
|
70
|
+
**Updating** — same tag, then restart the web app. Each profile updates separately, because the terminal UI owns its own plugin list:
|
|
85
71
|
|
|
86
72
|
```sh
|
|
87
|
-
dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@latest
|
|
88
|
-
dsh plugin --profile
|
|
73
|
+
dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@latest
|
|
74
|
+
dsh plugin --profile dsh-tui update @mars-sea/dsh-commandcode-provider@latest
|
|
89
75
|
```
|
|
90
76
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
```sh
|
|
94
|
-
dsh plugin --profile dsh-tui update @mars-sea/dsh-commandcode-provider@0.11.15
|
|
95
|
-
```
|
|
77
|
+
## Get an API key and verify it works
|
|
96
78
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
Then restart the web app.
|
|
100
|
-
|
|
101
|
-
## Getting an API key
|
|
102
|
-
|
|
103
|
-
The easiest path is the official CLI (Node.js 22+):
|
|
79
|
+
Easiest via the official CLI (Node.js 22+):
|
|
104
80
|
|
|
105
81
|
```sh
|
|
106
82
|
npm i -g command-code@latest
|
|
107
83
|
cmd login # macOS/Linux; native Windows: cmdc login
|
|
108
84
|
```
|
|
109
85
|
|
|
110
|
-
Or skip the CLI: click **Sign in to Command Code** under **Settings → Command Code** —
|
|
86
|
+
Or skip the CLI: click **Sign in to Command Code** under **Settings → Command Code** — the browser opens the commandcode.ai authorization page (the same flow `cmd login` runs) and the key is stored locally once you approve. You can also create a key on the [Keys page](https://commandcode.ai/mars-sea/settings/keys) and paste it, or `export COMMANDCODE_API_KEY="user_..."`.
|
|
111
87
|
|
|
112
88
|
> The sign-in flow needs the Host and your browser on the same machine (loopback callback). With a remote Host, paste the key manually; a literal composition-level `apiKey`, if set, still takes precedence over a signed-in credential.
|
|
113
89
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
After restart, enter your API key in **Settings → Command Code** and save; **Settings → Models** shows a **Command Code** card, and the model picker lists the live catalog under **commandcode**. Send a message with a model your plan includes.
|
|
90
|
+
**To verify:** after restart, enter your API key in **Settings → Command Code** and save. **Settings → Models** shows a **Command Code** card, and the model picker lists the live catalog under **commandcode**. Send a message with a model your plan includes.
|
|
117
91
|
|
|
118
92
|
## Terminal UI (dsh-TUI)
|
|
119
93
|
|
|
120
|
-
|
|
94
|
+
**Each dsh profile owns its own plugin list**, so the web install does not reach the terminal — add the plugin to the `dsh-tui` profile as well, pinned to an exact version (within 24 hours of a release a bare name resolves to the previous build, leaving a fresh install with no `/settings` → Command Code page and no `commandcode` models):
|
|
121
95
|
|
|
122
96
|
```sh
|
|
123
|
-
dsh plugin --profile dsh-tui add @mars-sea/dsh-commandcode-provider@
|
|
97
|
+
dsh plugin --profile dsh-tui add @mars-sea/dsh-commandcode-provider@latest
|
|
124
98
|
```
|
|
125
99
|
|
|
126
|
-
Pin the exact version here. For the first 24 hours after a release, a bare package name (or `@latest`) is silently resolved to the previous one: the install succeeds, but the profile gets the older build — which is how a fresh terminal install ends up with no **`/settings` → Command Code** page and no `commandcode` models at all.
|
|
127
|
-
|
|
128
100
|
Then pick the provider in the model selector, or name it directly:
|
|
129
101
|
|
|
130
102
|
```text
|
|
131
103
|
/model commandcode/deepseek/deepseek-v4.1-flash
|
|
132
104
|
```
|
|
133
105
|
|
|
134
|
-
`/model` lists every registered provider, with
|
|
135
|
-
|
|
136
|
-
**Entering the key.** The TUI has no web Models page, so the plugin declares its own page in the TUI settings screen — **`/settings` → Command Code** — with the API key, the API base, the out-of-plan model filter, the active account, and the command language. The key field is write-only: it shows whether a key is configured and writes what you type to the credential store, never to a settings document. The same page is the only place a TUI-only user needs to visit.
|
|
106
|
+
`/model` lists every registered provider, with the live catalog and its plan/deal/context annotations; the `/commandcode` dashboard works there too.
|
|
137
107
|
|
|
138
|
-
**
|
|
108
|
+
**Entering the key.** The TUI has no web Models page, so the plugin declares its own page — **`/settings` → Command Code** — with the API key, API base, out-of-plan filter, active account and command language. The key field is write-only: it shows whether a key is configured and writes what you type to the credential store, never to a settings document. The same page lists the whole catalog as checkboxes grouped by plan tier, free models first; everything starts checked, and the choice is stored as per-model overrides next to the `visibleModels` list the web page edits.
|
|
139
109
|
|
|
140
|
-
Alternatively
|
|
110
|
+
Alternatively set the key outside the TUI. The first match wins:
|
|
141
111
|
|
|
142
|
-
- A literal `apiKey`
|
|
143
|
-
- Otherwise the credential reference is resolved (`apiKeyEnv`, `COMMANDCODE_API_KEY` by default). In a profile that
|
|
144
|
-
- A **headless profile
|
|
112
|
+
- A literal `apiKey` in the composition config wins over everything and is always used.
|
|
113
|
+
- Otherwise the credential reference is resolved (`apiKeyEnv`, `COMMANDCODE_API_KEY` by default). In a profile that mounts the credentials service (Web, desktop, SDK, ACP) that service owns the order: **since 0.2.1-alpha.3 a saved credential wins over the launching environment**; earlier releases had the environment first.
|
|
114
|
+
- A **headless profile mounts no credentials service on purpose**, so only the launching environment, the project `.env` and `$DSH_HOME/.env` apply — **a key saved on the page never reaches a headless run**.
|
|
145
115
|
- The last resort is `~/.commandcode/auth.json`, written by the official CLI.
|
|
146
116
|
|
|
147
117
|
```sh
|
|
@@ -149,7 +119,7 @@ export COMMANDCODE_API_KEY="user_..." # launching environment
|
|
|
149
119
|
cmd login # writes ~/.commandcode/auth.json
|
|
150
120
|
```
|
|
151
121
|
|
|
152
|
-
**Making Command Code the default.** dsh-TUI pins its own agent route,
|
|
122
|
+
**Making Command Code the default.** dsh-TUI pins its own agent route, so its `agent-default-model` setting does not override it. Override the `agent-loop` row in your profile patch (`$DSH_HOME/profiles/dsh-tui/cordis.patch.yml`):
|
|
153
123
|
|
|
154
124
|
```yaml
|
|
155
125
|
- id: agent-loop
|
|
@@ -163,8 +133,6 @@ cmd login # writes ~/.commandcode/auth.json
|
|
|
163
133
|
cwd: !!js process.cwd()
|
|
164
134
|
```
|
|
165
135
|
|
|
166
|
-
**Engine version.** The plugin is maintained against **two verified engines: dsh `0.2.0-rc.2` and dsh `0.2.1-rc.2`**. Its `@deepseek-ai/dsh-*` peers use the exact-version disjunction `0.2.0-rc.2 || 0.2.1-rc.2`, while `@deepseek-ai/cordis` and `@deepseek-ai/schemastery` use the paired disjunctions `~4.0.4 || ~4.0.5` and `~3.18.4 || ~3.18.5` — one branch per engine, because `0.2.0-rc.2` was published against cordis `~4.0.4` / schemastery `~3.18.4` and `0.2.1-rc.2` against the stable `4.0.5` / `3.18.5`. Compatibility records contain exactly these two engines — both RC, with no alpha channel, because nothing has been verified since `0.2.1-alpha.5`. `0.2.0-rc.2` is retained deliberately even though it is the older of the two: it is still what npm `latest` resolves to, so a build that dropped it would be refused by the host's `engines.dsh` admission on every default install. Every declared branch must stay a bare version, so unverified neighbours (`0.2.0-rc.1`, `0.2.1-rc.1`, `0.3.0-alpha.1`) are still rejected. Both `npm run test:engine` and `npm run test:install` verify every declared engine in turn rather than one of them, and `test:engine` also calls that engine's own `evaluatePluginCompatibility` on the published manifest — from alpha.4 on, that verdict reads `engines.dsh` alone, so a wrong engine declaration fails there instead of only at install time. See [Install](#install) for older engines.
|
|
167
|
-
|
|
168
136
|
## Usage dashboard
|
|
169
137
|
|
|
170
138
|
The plugin registers a `/commandcode` slash command showing per-account usage:
|
|
@@ -173,98 +141,66 @@ The plugin registers a `/commandcode` slash command showing per-account usage:
|
|
|
173
141
|
/commandcode (or /commandcode status)
|
|
174
142
|
```
|
|
175
143
|
|
|
176
|
-
|
|
144
|
+
Its copy follows the shell's locale: explicit `lang: 'en' | 'zh'` in the `llm-commandcode` plugin config wins, otherwise `LC_ALL`/`LANG` is read, otherwise it falls back to `zh`. The web settings page is independent — it follows the browser's language preference.
|
|
177
145
|
|
|
178
146
|
## Account rotation
|
|
179
147
|
|
|
180
148
|
With several Command Code subscriptions, the plugin **switches to the next account automatically** when one hits its usage limit:
|
|
181
149
|
|
|
182
|
-
- **Setup** —
|
|
183
|
-
- **Manual switching** — **Pin this account** in an account's **⋯** menu makes it
|
|
184
|
-
- **Dedicated models** — expand an account and pick its **Dedicated models** from the live catalog.
|
|
185
|
-
- **Show only favorite models** — the **Visible models** picker in the **Models & context** card keeps only the checked models in the
|
|
186
|
-
|
|
150
|
+
- **Setup** — **Add account** in the **Accounts** card at Settings → **Command Code**, then sign in or paste an API key. Account actions (add, rename, replace or clear a key, remove, pin) apply immediately; only the other settings wait for the Save bar. The top-level key always serves first as the `default` account.
|
|
151
|
+
- **Manual switching** — **Pin this account** in an account's **⋯** menu makes it preferred; if it is exhausted, requests fall back to the others and return once its window resets. **Unpin** returns to automatic rotation.
|
|
152
|
+
- **Dedicated models** — expand an account and pick its **Dedicated models** from the live catalog. Those requests serve from that account while it is usable; an exhausted account falls back to the normal rotation. A model belongs to one account at a time (stored as `modelAccountRules`).
|
|
153
|
+
- **Show only favorite models** — the **Visible models** picker in the **Models & context** card keeps only the checked models in the picker; unchecked shows all (the default).
|
|
154
|
+
|
|
155
|
+
Each account row shows its plan, status and 5-hour/weekly meters; expand it for the full report, or run `/commandcode`. The equivalent YAML is in [Configure](#configure).
|
|
187
156
|
|
|
188
|
-
|
|
157
|
+
## Configure
|
|
158
|
+
|
|
159
|
+
**Settings → Command Code** groups the options as **Accounts** (keys, sign-in, live quota, pinning, dedicated models), **Models & context** (out-of-plan filter, visible models, context length, output limit), **Privacy & security** (zero data retention), **Integrations & display** (web search, sidebar quota card) and **Advanced** (API base URL, timeouts, transport retries, image offload). The same options live in `$DSH_HOME/settings.yaml` and apply immediately, without a restart:
|
|
189
160
|
|
|
190
161
|
```yaml
|
|
191
162
|
llm-commandcode:
|
|
192
163
|
apiKeyEnv: COMMANDCODE_API_KEY # first (default) account
|
|
193
|
-
activeAccount: COMMANDCODE_API_KEY_2 # optional: pin the active account
|
|
194
|
-
accounts: # rotation order after it
|
|
164
|
+
activeAccount: COMMANDCODE_API_KEY_2 # optional: pin the active account
|
|
165
|
+
accounts: # optional: rotation order after it
|
|
195
166
|
- label: Go #2
|
|
196
167
|
apiKeyEnv: COMMANDCODE_API_KEY_2
|
|
197
|
-
- label: Go #3
|
|
198
|
-
apiKeyEnv: COMMANDCODE_API_KEY_3
|
|
199
168
|
modelAccountRules: # optional: route models to accounts (first match wins)
|
|
200
169
|
- models: # catalog model ids (multi-select)
|
|
201
170
|
- deepseek/deepseek-v4-pro
|
|
202
|
-
- deepseek/deepseek-v4-flash-vision-exp
|
|
203
171
|
account: COMMANDCODE_API_KEY_2
|
|
204
|
-
|
|
205
|
-
- tencent/hy4-preview
|
|
206
|
-
account: default
|
|
207
|
-
visibleModels: # optional: show only these models in pickers (catalog model ids); unset shows all
|
|
172
|
+
visibleModels: # optional: only these models in pickers; unset shows all
|
|
208
173
|
- deepseek/deepseek-v4-pro
|
|
209
|
-
- tencent/hy4-preview
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
## Configure
|
|
213
|
-
|
|
214
|
-
**Settings → Command Code** is organized as **Accounts** (keys, sign-in, live quota, pinning, dedicated models), a collapsed **Models & context** group (click its heading to unfold: hide out-of-plan models, visible models, then the **Custom context length** field and the **Per-model overrides** rows right after the allowlist — global and per model, see below), **Privacy & security** (zero data retention, off by default, see below), **Integrations & display** (serve web search with Command Code, show the quota card in the sidebar, off by default), and a collapsed **Advanced** section (API base URL, request/stream timeouts, transport retries, cache-aware image offload). Both foldable groups toggle from their whole heading row, and neither remembers its expanded state across visits. The working directory is no longer on the page; `workingDir` in config still works.
|
|
215
|
-
|
|
216
|
-
The same options live in `$DSH_HOME/settings.yaml` (changes apply immediately, no restart):
|
|
217
|
-
|
|
218
|
-
```yaml
|
|
219
|
-
llm-commandcode:
|
|
220
|
-
apiKeyEnv: COMMANDCODE_API_KEY # credential reference
|
|
221
174
|
apiBase: https://api.commandcode.ai
|
|
222
|
-
workingDir: /path/to/project
|
|
175
|
+
workingDir: /path/to/project # optional
|
|
223
176
|
modelsCachePath: ~/.commandcode/models-cache.json
|
|
224
|
-
requestTimeoutMs: 300000
|
|
225
|
-
streamIdleTimeoutMs: 300000
|
|
226
|
-
# offloadSeenImagesForCache: true
|
|
227
|
-
showSidebarQuota: true
|
|
228
|
-
zdr: true
|
|
229
|
-
# contextWindow: 131072
|
|
230
|
-
# contextWindowOverrides:
|
|
177
|
+
requestTimeoutMs: 300000 # default 300s (the official CLI's own budget)
|
|
178
|
+
streamIdleTimeoutMs: 300000 # default 300s
|
|
179
|
+
# offloadSeenImagesForCache: true # opt in to CLI cache mitigation
|
|
180
|
+
showSidebarQuota: true # optional: sidebar plans & quota card (default off)
|
|
181
|
+
zdr: true # optional: zero-data-retention upstreams only (default off)
|
|
182
|
+
# contextWindow: 131072 # optional: custom context length for every model
|
|
183
|
+
# contextWindowOverrides: # optional: per-model context lengths; wins over contextWindow
|
|
231
184
|
# deepseek/deepseek-v4-pro: 65536
|
|
232
|
-
# maxOutputTokens: 65536
|
|
185
|
+
# maxOutputTokens: 65536 # optional: per-turn output limit; 0 sends no max_tokens
|
|
233
186
|
```
|
|
234
187
|
|
|
235
|
-
###
|
|
236
|
-
|
|
237
|
-
The context window the harness meters against — and when it compacts — normally comes from the model catalog's `context_length`. The opt-in **Custom context length** field and **Per-model overrides** rows inside **Settings → Command Code → Models & context**, directly after the visible-models allowlist (or the two config fields above, issue #86), replace it per your own numbers: `contextWindow` is the global custom value applied to every model without its own row, and `contextWindowOverrides` sets one model by catalog id, winning over the global value. Unset follows the catalog; nothing changes by default.
|
|
238
|
-
|
|
239
|
-
- **When it helps**: a catalog window that over-reports turns into `context_length_exceeded` failures once a session grows past the model's real capacity — advertise the lower real number and the harness compacts before the gateway refuses. An under-reported window makes long sessions compact earlier than they need to; raise it to match the model's true capacity.
|
|
240
|
-
- The model-picker context annotation, `defaultMaxTokens` default and actual requests follow the same resolution. Raising the window removes the old catalog-window output cap while retaining the model's independent output ceiling, runtime-learned ceiling and gateway-wide cap; explicit output counts obey those caps too. Session-cost tier pricing keeps using each request's actual token counts.
|
|
241
|
-
- Values must be whole token counts in 1 – 10,000,000. The page blocks invalid input; config-file non-numbers, fractions and out-of-range values fail schema validation rather than silently falling back. Only programmatic calls that bypass the schema discard invalid values and fall through valid per-model override → valid global value → catalog. A model the catalog does not list keeps its "no context advertised" shape.
|
|
242
|
-
- The inputs accept compact shorthand in binary units: `32K` = 32,768 and `1M` = 1,048,576 (so `128K`/`256K` write the exact power-of-two windows 131,072/262,144); the stored value is always a plain number. The per-model override's model dropdown lists only the models kept by the **visible-models allowlist** (the whole catalog while showing all), and the rows carry "Model / Context length" column heads.
|
|
243
|
-
|
|
244
|
-
### Per-turn output limit
|
|
245
|
-
|
|
246
|
-
Every request carries `max_tokens`, resolved as the smallest of the model's published output ceiling, the ceiling learned at runtime, and the gateway-wide cap of 131,072. That field is a **passive hard limit**: the platform cuts the answer when it is reached, and the model receives no "nearly out of room" signal. The **Output limit per turn** field (**Settings → Command Code → Models & context**, or the `maxOutputTokens` config key) offers three choices:
|
|
247
|
-
|
|
248
|
-
- **Empty (default)**: exactly the derivation above, so nothing changes.
|
|
249
|
-
- **A positive number**: taken as a cap alongside that derived value. It can only **tighten** — it never exceeds the model ceiling or the gateway's `131072`, and out-of-range input fails config validation. Shorthand like `64K` is accepted.
|
|
250
|
-
- **`0`**: sends **no** `max_tokens` field at all, leaving the per-turn output size to the platform. This is the fix for answers being cut off mid-sentence, because while the field is present the cut happens at some point no matter how large the figure is.
|
|
251
|
-
|
|
252
|
-
`0` only takes effect on the two transports that accept an absent field: the CLI (`/alpha/generate`) and OpenAI (`/provider/v1/chat/completions`). The Anthropic Messages endpoint Claude uses **requires** the field — omitting it is refused upstream with `Invalid input: expected number, received undefined at max_tokens` — so that route keeps sending its derived budget and `0` has no effect for Claude. Auxiliary calls whose budget the host fixes itself (the session title is pinned at 64 tokens) also outrank this setting and are not unbound by `0`.
|
|
253
|
-
|
|
254
|
-
An empty field **clears** the setting back to the derived default; it is not the same as writing `0`.
|
|
188
|
+
### Context, output and image tuning
|
|
255
189
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
190
|
+
| Option | Effect |
|
|
191
|
+
|---|---|
|
|
192
|
+
| `contextWindow`, `contextWindowOverrides` | Replace the catalog `context_length` the harness meters and compacts on (issue #86). Use it when the catalog over-reports the window (sessions then fail with `context_length_exceeded`) or under-reports it (sessions compact too early). Whole tokens in 1 – 10,000,000; `32K`/`1M` shorthand accepted. |
|
|
193
|
+
| `maxOutputTokens` | Per-turn `max_tokens` cap. Every request already carries `max_tokens`, resolved as the smallest of the model's published ceiling, the runtime-learned ceiling and the gateway cap of 131,072 — a passive hard limit that cuts the answer with no warning to the model. A positive number can only **tighten** it; `0` sends **no** field at all, which is the fix for answers cut off mid-sentence (`0` affects the CLI and OpenAI transports only; Claude's Anthropic Messages endpoint requires the field). An empty field clears the setting — it is not the same as writing `0`. |
|
|
194
|
+
| `offloadSeenImagesForCache` | On the CLI transport a new image can make the reported prompt cache retreat to the first historical image even when every previous request message is byte-identical. Enabling it replaces an older image with a stable text placeholder once this model has answered with it, so later text stays cached without replaying old pixels. It mitigates the cost spike but does not repair Command Code's multimodal cache behavior, and the model cannot inspect an offloaded image again without rereading the source file. Off by default. [Live evidence](docs/issue-64-cache-review.md). |
|
|
259
195
|
|
|
260
196
|
## Web search
|
|
261
197
|
|
|
262
|
-
When your deployment
|
|
198
|
+
When your deployment mounts the web capability (`@deepseek-ai/dsh-web` + `@deepseek-ai/dsh-tool-web`), the model's `web_search` tool is served by this plugin's `commandcode` search provider — it calls the Command Code Provider API's `/alpha/web-search` endpoint with the **same API key and base URL** as chat, so no separate search key, endpoint or model is needed.
|
|
263
199
|
|
|
264
|
-
**On by default.** The
|
|
200
|
+
**On by default.** The *"Serve dsh web search with Command Code"* toggle (`webSearch`) selects `commandcode` as the active search backend; turning it off hands the selection back to whichever backend was there before (a sibling search plugin such as modsearch keeps working). The change takes effect on the next search — no restart.
|
|
265
201
|
|
|
266
202
|
- The provider registers as `commandcode` on `ctx.web` only when the web service is present; without it this stays a chat-only plugin.
|
|
267
|
-
-
|
|
203
|
+
- When the official **Web search** settings already pin another backend, that explicit choice wins: the plugin keeps `commandcode` registered but unselected and reports that state. It takes over only while nothing else pins the field, remembers the backend it displaced, and restores it when the toggle goes off or the plugin unloads. To pin it durably, set `searchProvider: commandcode` (or `$DSH_WEB_SEARCH_PROVIDER=commandcode`).
|
|
268
204
|
- `numResults` from the dsh tool is clamped to the Command Code range (1–10, default 5); results map to the dsh `WebSearchSource` shape (`url`/`title`/`snippet`).
|
|
269
205
|
|
|
270
206
|
> This reuses the Command Code Provider API directly (like the official CLI's built-in `web_search`), so it is distinct from a DeepSeek-native search backend.
|
|
@@ -273,38 +209,28 @@ When your deployment's dsh shell mounts the web capability (`@deepseek-ai/dsh-we
|
|
|
273
209
|
|
|
274
210
|
Command Code can serve a request only through upstreams that retain no prompts or completions and never train on them — the same opt-in the official CLI exposes as `CMD_ZDR=1`, and the `x-cmd-zdr: 1` header on the Provider API ([official docs](https://commandcode.ai/docs/resources/zdr)).
|
|
275
211
|
|
|
276
|
-
**Off by default.** Turn it on with the *"Zero data retention (ZDR)"* toggle (`zdr`) in the Privacy & security card, or in your profile config.
|
|
212
|
+
**Off by default.** Turn it on with the *"Zero data retention (ZDR)"* toggle (`zdr`) in the Privacy & security card, or in your profile config.
|
|
277
213
|
|
|
278
|
-
- The header is sent on **every chat request** while ZDR is on.
|
|
279
|
-
- If a refusal still happens (coverage churn, or no ZDR
|
|
214
|
+
- The header is sent on **every chat request** while ZDR is on. A model without an available ZDR upstream fails with `422 cmd_zdr_no_providers`; the request is never retried without the header.
|
|
215
|
+
- If a refusal still happens (coverage churn, or no spare ZDR capacity at that moment), the error names the cause and how to turn ZDR off instead of surfacing as a bare HTTP 422.
|
|
280
216
|
- **ZDR usually costs more**: capacity is limited and billed at each upstream's pass-through rates, and which upstream serves a request can change per request. The session-cost readout keeps quoting the ordinary catalog rates; the real per-request price shows in Command Code's Studio usage page.
|
|
281
|
-
- Works on every plan; plan credits meter ZDR requests at the plan's default allowance.
|
|
282
217
|
|
|
283
218
|
## Notes & limitations
|
|
284
219
|
|
|
285
|
-
- **Image input is model-gated** — only Vision models accept images; text-only models refuse them.
|
|
286
|
-
- **Image size is reported as sent** — the adapter overrides `imageRequestTarget` with the target this route actually puts on the wire: long edge 1568, encoded bytes capped at 1 MiB. The harness's screenshot callers therefore size against what the gateway receives instead of the normalized original.
|
|
287
|
-
- Switching to a text-only model in an image-bearing session is rejected by dsh — pick a model marked *`Image`* or remove the images first.
|
|
288
|
-
- **Long image-heavy sessions keep working** — the provider caps the size of a single request (around 50 MB, and it is undocumented), so a session that accumulates many screenshots would otherwise start failing every request once it grew past that. The oldest images beyond the budget are replaced by a short "image omitted" note that names the attachment, the newest ones are sent as usual, and a request the provider still rejects as too large is retried once with a much smaller image budget before failing.
|
|
220
|
+
- **Image input is model-gated** — only Vision models accept images; text-only models refuse them, and dsh rejects switching a text-only model into an image-bearing session. The adapter reports the size actually put on the wire (long edge 1568, encoded bytes capped at 1 MiB), and the provider caps a single request (around 50 MB, undocumented); images beyond that budget are replaced by a short "image omitted" note, and an over-sized request is retried once with a smaller image budget.
|
|
289
221
|
- **No `stop` sequences** — requests carrying one fail.
|
|
290
|
-
- Historical reasoning is replayed on both transports so a tool-calling loop keeps its chain of thought: `/provider/v1/chat/completions` passes it back as `reasoning_content`,
|
|
291
|
-
-
|
|
222
|
+
- **Historical reasoning is replayed on both transports** so a tool-calling loop keeps its chain of thought: `/provider/v1/chat/completions` passes it back as `reasoning_content`, `/alpha/generate` carries it as a `reasoning` block inside the rebuilt assistant turn. Only tool calls with a paired tool result are replayed.
|
|
223
|
+
- **Tool parameter schemas are normalized** to the object root the provider requires, so a tool declared without one (a third-party plugin's hand-written schema, an MCP server's `inputSchema`, a generated root `$ref`) no longer fails the turn with `schema must be a JSON Schema of 'type: "object"'`.
|
|
292
224
|
- The model catalog is browsable without a key; chat requests need one.
|
|
293
225
|
|
|
294
226
|
## Permissions & privacy
|
|
295
227
|
|
|
296
|
-
The plugin only communicates between your local dsh profile and your Command Code account: locally it touches only the credential store and the models cache (plus `~/.commandcode/auth.json` as a last-resort fallback); on the network it calls only the Command Code API. No telemetry. With **zero data retention** on
|
|
228
|
+
The plugin only communicates between your local dsh profile and your Command Code account: locally it touches only the credential store and the models cache (plus `~/.commandcode/auth.json` as a last-resort fallback); on the network it calls only the Command Code API. No telemetry. With **zero data retention** on, chat requests require a ZDR upstream; models without one fail instead of running without the protection.
|
|
297
229
|
|
|
298
230
|
## Disabling / uninstalling
|
|
299
231
|
|
|
300
232
|
- **Disable** without removing: edit your profile's `cordis.patch.yml` and comment out (or remove) the `llm-commandcode` row, or set `disabled: true`, then restart.
|
|
301
|
-
- **Uninstall** completely:
|
|
302
|
-
|
|
303
|
-
```sh
|
|
304
|
-
dsh plugin --profile web remove @mars-sea/dsh-commandcode-provider
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
Your API key in the dsh credential store and `~/.commandcode/auth.json` are left untouched.
|
|
233
|
+
- **Uninstall** completely: `dsh plugin --profile web remove @mars-sea/dsh-commandcode-provider`. Your API key in the dsh credential store and `~/.commandcode/auth.json` are left untouched.
|
|
308
234
|
|
|
309
235
|
## Development
|
|
310
236
|
|
|
@@ -314,39 +240,25 @@ npm run typecheck # tsc --noEmit
|
|
|
314
240
|
npm run build # tsdown -> lib/
|
|
315
241
|
```
|
|
316
242
|
|
|
317
|
-
To try a local build in a profile:
|
|
243
|
+
To try a local build in a profile: `dsh plugin --profile web add /path/to/dsh-commandcode-provider`. After changing `src/`, re-run `npm run build` and restart the app.
|
|
318
244
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
245
|
+
The package exports the plugin root, `/client`, `/locale/*.json`, and `/package.json`. Source remains in the repository; the unpackaged `./src/*` export was removed. `npm run test:pack` checks declared entry points against the actual packed file list.
|
|
246
|
+
|
|
247
|
+
## Reference docs
|
|
248
|
+
|
|
249
|
+
The engineering detail behind this README lives under [`docs/agent-reference/`](docs/agent-reference/):
|
|
322
250
|
|
|
323
|
-
|
|
251
|
+
- [adapter and wire contracts](docs/agent-reference/adapter-protocol.md) — transports, streaming, images, tool calls, reasoning replay, output budget, ZDR header
|
|
252
|
+
- [accounts and retry](docs/agent-reference/accounts-and-retry.md) — credential resolution, account rotation, rate limits, web search selection
|
|
253
|
+
- [client and settings](docs/agent-reference/client-and-settings.md) — settings pages, browser sign-in, TUI settings, model selection
|
|
254
|
+
- [usage and cost](docs/agent-reference/usage-and-cost.md) — session cost readout, price snapshot, compaction accounting
|
|
255
|
+
- [engine compatibility](docs/agent-reference/engine-compatibility.md) — supported dsh versions, peer ranges, `engines.dsh` admission
|
|
256
|
+
- [model catalog](docs/agent-reference/model-catalog.md) — catalog sync, plan tiers, effort levels, deals, ZDR exception set
|
|
324
257
|
|
|
325
258
|
## Community & feedback
|
|
326
259
|
|
|
327
|
-
|
|
328
|
-
- <img src="https://cdn.simpleicons.org/github/111827" width="16" alt="Releases" /> [GitHub Releases](https://github.com/Mars-Sea/dsh-commandcode-provider/releases)
|
|
329
|
-
- <img src="https://cdn.simpleicons.org/npm/111827" width="16" alt="npm" /> [npm Package](https://www.npmjs.com/package/@mars-sea/dsh-commandcode-provider)
|
|
330
|
-
- <img src="https://cdn.simpleicons.org/discourse/111827" width="16" alt="Linux.do" /> [Linux.do 社区](https://linux.do/)
|
|
260
|
+
[GitHub Repository](https://github.com/Mars-Sea/dsh-commandcode-provider) · [GitHub Releases](https://github.com/Mars-Sea/dsh-commandcode-provider/releases) · [npm Package](https://www.npmjs.com/package/@mars-sea/dsh-commandcode-provider) · [Linux.do 社区](https://linux.do/)
|
|
331
261
|
|
|
332
262
|
## License
|
|
333
263
|
|
|
334
264
|
MIT — see [LICENSE](./LICENSE). Portions ported from [pi-commandcode-provider](https://github.com/patlux/pi-commandcode-provider) (MIT).
|
|
335
|
-
|
|
336
|
-
## Screenshots
|
|
337
|
-
|
|
338
|
-
**Model picker** — plan tier, deal/FREE, peak/off-peak, Image and context annotations:
|
|
339
|
-
|
|
340
|
-
<img src="assets/screenshots/model-picker.png" alt="Model picker with plan, deal, image and context annotations" width="320">
|
|
341
|
-
|
|
342
|
-
**Usage dashboard** — `/commandcode` per-account report:
|
|
343
|
-
|
|
344
|
-
<img src="assets/screenshots/usage-dashboard.png" alt="Usage dashboard" width="520">
|
|
345
|
-
|
|
346
|
-
**Settings page** — the account list with live quota, model visibility, privacy switches and connection options:
|
|
347
|
-
|
|
348
|
-
<img src="assets/screenshots/settings-page.png" alt="Command Code settings page with the account usage card" width="640">
|
|
349
|
-
|
|
350
|
-
### Package entry points
|
|
351
|
-
|
|
352
|
-
The package exports the plugin root, `/client`, `/locale/*.json`, and `/package.json`. Source remains in the repository; the unpackaged `./src/*` export was removed. `npm run test:pack` checks declared entry points against the actual packed file list.
|