@mars-sea/dsh-commandcode-provider 0.11.11 → 0.11.13

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,26 @@ 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.11.13] - 2026-09-24
8
+
9
+ ### Changed
10
+
11
+ - **The settings page's save bar only appears when there is something to save.** It used to float over the page at all times with disabled buttons and a separate status bubble. Now a centered capsule rises at the bottom while edits are pending and says what state they are in: unsaved changes, a field that needs fixing, or a failed save. After a save it briefly confirms "Settings saved" with a check mark, then sinks away. The confirmation shows only for a save made while the page is open, and no longer reappears when you switch settings pages or reopen settings. Its Discard and Save are capsule buttons drawn to sit concentrically inside the bar.
12
+ - **The settings page is restyled to match the harness's own settings pages.** The card boxes around each section are gone; each group (Accounts, Models, Privacy & security, Integrations & display, Advanced) is now a heading over plain rows separated by hairlines, with the title and description on the left and the control on the right — the layout of the General page. Fonts, sizes and colours use the platform's own scale (14/22 row titles, 12/18 descriptions, 0.5px hairlines, the real error/warning colour aliases), selectors and buttons are the platform's capsules, the auto-approve level is a sliding-pill segmented control like the platform's own, account rows look like the Models page's provider cards (with the same dashed "Add account" button), and the usage figures are filled tiles instead of outlined boxes.
13
+ - **An expanded account's usage figures line up in rows.** The four activity tiles sit in one row (two by two in a narrow window) and the three balances in the next, instead of wrapping three to a row with one left over.
14
+ - **The AI command guard has one tuning knob: an auto-approve threshold of High, Medium or Low.** The free-form `commandGuardThreshold` probability and the `commandGuardTimeoutMs` budget are gone. `commandGuardLevel` picks High (0.95), Medium (0.9, the default and the old default) or Low (0.8), shown as a three-way switch on the settings page and a select in the dsh-TUI. The decision budget is now fixed at 3 seconds (was 1500 ms by default), since a late verdict only falls back to the normal prompt. A previously stored numeric threshold or timeout is ignored, so a customized threshold returns to Medium.
15
+ - **Each account row on the settings page now also shows the monthly credits left**, as a balance after the 5-hour and weekly meters.
16
+ - **The Command Code settings page is reorganized around one account list.** Accounts, their usage and their model routing used to live on three separate cards; each account is now one row showing its plan, status and 5-hour/weekly meters, with a **⋯** menu (pin, sign in, replace key, rename, clear key, remove) and an expandable detail with the full usage report and its **dedicated models**. Account operations apply immediately: adding an account no longer needs a page Save before browser sign-in, a failed or cancelled sign-in leaves no empty account behind, and removing an account also drops its key, its dedicated models and a pin naming it. Routing rules are shown as per-account dedicated models (a model belongs to one account at a time; the stored `modelAccountRules` format is unchanged). The remaining settings are grouped into **Models**, **Privacy & security**, **Integrations & display** and a collapsed **Advanced** section, and the working directory is no longer on the page (`workingDir` in config still works).
17
+ - **The AI command guard now lets JEV explicitly control narrow sandbox escalations.** Ordinary approvals still use the one-question `safe` protocol. A call carrying `sandboxPermissions` now also asks `escalation_scope` and `escalation_necessity`; all three probabilities must reach the configured threshold before the guard returns `allowed-once`. This lets a conventional build/test command such as `go test ./...` proceed with an outside build cache when JEV agrees that the access is narrow and necessary, while broad, unsupported, malformed, or low-confidence decisions still fall back to the human prompt. The decision memo now retains the two escalation probabilities, and approval logs include them.
18
+
19
+ ## [0.11.12] - 2026-09-24
20
+
21
+ ### Changed
22
+
23
+ - **This release supports dsh 0.1.7-rc.1 alone, and the two-generation compatibility code is gone.** The plugin has carried a bridge between two Harness generations — the 0.1.2-0.1.6 line (settings.yaml document, `LegacySettingsSchema`, the pre-0.1.7 ApiProxy credential path, `legacy-credentials.ts`) and the 0.1.7 settings world (schema-derived Config forms, volatile fields, the `remote.settings` client scope) — and every release since 0.11.9 has paid for it twice: two schema registrations, two credential paths, a peer range that admitted nine engines and could pair with none of them exactly. This release drops the older line: every `@deepseek-ai/*` peer, `dsh.compatibility.dsh`, `engines.dsh` and the single `dshReleases` record now name `^0.1.7-rc.1` — a range semver resolves to that one release and nothing else — and `@deepseek-ai/schemastery` is tightened from `^3.18.2` to `~3.18.4`, because the unconditional `.volatile()` marking needs schemastery 3.18.3+ and a profile resolving 3.18.2 would mark nothing and render a blank settings form. The bridge itself is deleted, not disabled: `LegacySettingsSchema` and the duplicated config-fields factory (one schema now — every field volatile except the `apiKey` secret), `src/client/legacy-credentials.ts` and its tests, the deprecated `selectCommandCodeSearchProvider()` export (removed in command-code upstream and long superseded by `applyCommandCodeSearchSelection()`), and the legacy branches of the engine-load and install smoke scripts. **If you run dsh 0.1.2–0.1.6, stay on 0.11.11** (the 0.5.0-era Harness line's last release is 0.9.1); both are installed by exact version and unmaintained. On 0.1.7-rc.1 nothing changes behaviorally — same surfaces, same wire — the bundle is simply smaller and the pairing exact. `npm run test:engine` passes against 0.1.7-rc.1 (the published surface links and evaluates there — the durable request-image policy included — and the adapter is driven with the engine's own message constructors), and `npm run test:install` passes the pnpm 10 marketplace-generation smoke against the new peer metadata.
24
+
25
+ - **Synced with the official command-code@1.65.0 CLI** (2026-09-24 check of the npm `latest`; the official changelog page and RSS still top out at 1.64.0, so the evidence is the bundle diff, the live catalog and the pricing/docs pages). `COMMAND_CODE_CLI_VERSION` is now `1.65.0`. The release is additive with exactly one change: the CLI registry gains `stealth/space-bunny-alpha` (Space Bunny Alpha) — OpenRouter-served (`chatComplete`), text+image, 1M context, reasoning with the selectable `low`/`medium`/`high` set, available on every plan from Go up, and **free while the stealth preview lasts**. The public catalog serves it too (81 models, 80 + this one), so the picker shows it as `Go · FREE · Image` at $0 rates through the price table's free-model branch — no vendored price row, exactly like the other free models. It is also the **first change to the ZDR exception set since the 1.62.0 check**: the CLI's `modelSupportsZdr`/`knownModelSupportsZdr` negation sets both carry it and the pricing page says it plainly ("Not routed under ZDR"), so `KNOWN_NON_ZDR_MODELS` grows 20 → 21 and `tests/zdr.test.ts` pins the new membership deliberately. Everything else re-verified unchanged: the effort map (one key added, none edited), the Vision set, the plan tiers (no tier moves; the map is 51/58/71/81), the subscription-plan maps, every deal and price, the peak membership and schedule, and the whole wire protocol — every `/alpha/*` and `/provider/v1/*` call site, the `x-command-code-version` / `x-cmd-zdr` header table, the stream vocabulary and the browser-login flow are identical between the 1.64.0 and 1.65.0 bundles apart from minifier renames. The bundle does add a `/alpha/sandbox/*` route family, which belongs to the CLI's own remote-sandbox feature and is never called by this adapter.
26
+
7
27
  ## [0.11.11] - 2026-09-23
8
28
 
9
29
  ### Fixed
package/README.md CHANGED
@@ -17,7 +17,7 @@ Unofficial [DeepSeek Harness](https://deepseek-harness.github.io/deepseek-harnes
17
17
  ## What you get
18
18
 
19
19
  - **Plugin bundle** — install into any dsh profile with `dsh plugin add`; registers a `commandcode` provider route with a live model catalog.
20
- - **Dedicated settings page** — API key, connection options, a live account-usage card, and a "Hide out-of-plan models" toggle.
20
+ - **Dedicated settings page** — one account list (keys, sign-in, live quota, dedicated models), model visibility, privacy switches, and connection options.
21
21
  - **Works in the terminal too** — the same install serves a [dsh-TUI](#terminal-ui-dsh-tui) profile, with its own **`/settings` → Command Code** page for the API key and the model controls.
22
22
  - **Models-page key card** — the **Settings → Models → Command Code** card carries the key status, a paste field, and the sign-in button inline.
23
23
  - **In-browser sign-in for keys** — start the official authorization flow (the same one `cmd login` runs) from the settings page; the approved key lands in the local credential service automatically. Manual paste remains the fallback.
@@ -27,7 +27,7 @@ Unofficial [DeepSeek Harness](https://deepseek-harness.github.io/deepseek-harnes
27
27
  - **Plan-aware picker** — models above your subscription tier are hidden by default (toggleable); an optional **Model allowlist** keeps only your favorites in the picker.
28
28
  - **Reasoning-effort support** — models with selectable reasoning effort levels expose them in the picker.
29
29
  - **Image input** — Vision-capable models accept images.
30
- - **Plans & quota panel** — an optional Command Code card at the bottom of the sidebar (directly above Settings) shows the serving account's plan and its 5-hour and weekly windows; clicking it opens a dashboard with the billing period, both windows as progress bars with reset times, monthly credit consumption, and the purchased/free balances. The dashboard's **×** button hands the center column back to your conversation (the current session is untouched). **Off by default** — turn on *"Show the quota card in the sidebar"* under **Settings → Command Code → Advanced** to show it, and the same switch hides it again (a hidden card draws nothing at all and runs no background usage poll); the change lands as soon as you save. The panel follows your harness language (中文 / English) and needs dsh 0.1.5 (rc.1) or newer.
30
+ - **Plans & quota panel** — an optional Command Code card at the bottom of the sidebar (directly above Settings) shows the serving account's plan and its 5-hour and weekly windows; clicking it opens a dashboard with the billing period, both windows as progress bars with reset times, monthly credit consumption, and the purchased/free balances. The dashboard's **×** button hands the center column back to your conversation (the current session is untouched). **Off by default** — turn on *"Show the quota card in the sidebar"* under **Settings → Command Code → Integrations & display** to show it, and the same switch hides it again (a hidden card draws nothing at all and runs no background usage poll); the change lands as soon as you save. The panel follows your harness language (中文 / English).
31
31
  - **Session cost estimate** — published-rate estimates (`≈`) beside the composer token counter and in its usage dialog, using each request's model, request time and context tier from durable session history. Model switches and viewing the session later do not reprice earlier requests. Mixed-provider or unpriced usage shows a labeled subtotal (`≥`); missing history or wholly unpriceable usage stays hidden. These are estimates from the installed price snapshot, not provider invoices. Also English on every harness language.
32
32
  - **Web search** — the dsh `web_search` tool is backed by the Command Code Provider API (`/alpha/web-search`) with the same key/endpoint as chat, so no separate search key or base URL is needed. See [Web search](#web-search).
33
33
 
@@ -35,26 +35,29 @@ See [Screenshots](#screenshots) below for what the UI looks like.
35
35
 
36
36
  ## Install
37
37
 
38
- Pick the release line that matches your DeepSeek Harness version:
38
+ This release supports **dsh 0.1.7-rc.1 and nothing else** — the plugin's peer
39
+ range is that one version, and its compatibility record names it alone:
39
40
 
40
- - **dsh 0.1.2-rc.1 or later** (the current 0.1.2 line — what `@latest` installs today):
41
-
42
- ```sh
43
- dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@latest
44
- ```
41
+ ```sh
42
+ dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@latest
43
+ ```
45
44
 
46
- - **Older dsh releases** (the 0.5.0 line and earlier, which use the rc-era Host/browser APIs) — the last plugin version supporting them is 0.9.1, installed by exact version. That line is no longer under active maintenance:
45
+ - **Older dsh releases.** The 0.1.2–0.1.6 line is no longer supported: those
46
+ engines predate the 0.1.7 settings rewrite, the `RequestMessage` envelope, and
47
+ the durable image-offload contract, and the compatibility code that bridged
48
+ the two was removed. The last plugin release covering them is 0.11.11; the
49
+ 0.5.0-era Harness line's last release is 0.9.1. Both are installed by exact
50
+ version and neither is maintained:
47
51
 
48
52
  ```sh
49
- dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.9.1
53
+ dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.11.11 # dsh 0.1.2–0.1.6
54
+ dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.9.1 # dsh 0.5.0 line
50
55
  ```
51
56
 
52
- > The `latest` tag points at the current 0.1.2-line plugin release. Users on the old 0.5.0-era Harness line must pin `@0.9.1` explicitly.
53
-
54
57
  **pnpm 11 holds back new releases.** Its `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:
55
58
 
56
59
  ```sh
57
- dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.11.11
60
+ dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.11.13
58
61
  ```
59
62
 
60
63
  The same applies to every profile you install into, including the terminal UI below.
@@ -66,14 +69,14 @@ Fresh pnpm 10 marketplace generations are supported directly. Do not add a separ
66
69
  Update with the same tag you installed with:
67
70
 
68
71
  ```sh
69
- dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@latest # dsh 0.1.2-rc.1+
72
+ dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@latest # dsh 0.1.7-rc.1
70
73
  dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@0.9.1 # older dsh (0.5.0 line, unmaintained)
71
74
  ```
72
75
 
73
76
  Each profile updates separately — the terminal UI owns its own plugin list (see below):
74
77
 
75
78
  ```sh
76
- dsh plugin --profile dsh-tui update @mars-sea/dsh-commandcode-provider@0.11.11
79
+ dsh plugin --profile dsh-tui update @mars-sea/dsh-commandcode-provider@0.11.13
77
80
  ```
78
81
 
79
82
  To move to a version published less than 24 hours ago, name it exactly as in Install above; pnpm 11's age gate resolves `@latest` to the previous release instead.
@@ -102,7 +105,7 @@ After restart, enter your API key in **Settings → Command Code** and save; **S
102
105
  The plugin also works under a terminal front door. **Each dsh profile owns its own plugin list**, so the web install above does not reach the terminal — add the plugin to the `dsh-tui` profile as well:
103
106
 
104
107
  ```sh
105
- dsh plugin --profile dsh-tui add @mars-sea/dsh-commandcode-provider@0.11.11
108
+ dsh plugin --profile dsh-tui add @mars-sea/dsh-commandcode-provider@0.11.13
106
109
  ```
107
110
 
108
111
  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.
@@ -140,7 +143,7 @@ cmd login # writes ~/.commandcode/auth.json
140
143
  cwd: !!js process.cwd()
141
144
  ```
142
145
 
143
- **Engine version.** The plugin needs a dsh engine that exports `ToolCallId` from `@deepseek-ai/dsh-llm` — **dsh 0.1.2-alpha.3 or later**. That includes the engine dsh-TUI recommends (0.1.2-rc.1) and every later release, but *not* the oldest engines its peer range nominally allows: on dsh 0.1.0-rc.6 or 0.1.1-rc.2 the plugin's module import fails and the TUI will not start. Upgrade the engine, or use the web profile.
146
+ **Engine version.** The plugin is maintained against exactly one engine: **dsh 0.1.7-rc.1**. Its `@deepseek-ai/dsh-*` peer range is `^0.1.7-rc.1` (semver resolves that to 0.1.7-rc.1 alone), and `dsh.compatibility.dshReleases` records that single release. On an older engine the settings page, the message envelope, or the request-image budget will not line up — install the last release that supported your engine (see [Install](#install)) instead of forcing this one.
144
147
 
145
148
  ## Usage dashboard
146
149
 
@@ -156,11 +159,11 @@ The command's user-facing copy follows the shell's locale: explicit `lang: 'en'
156
159
 
157
160
  With several Command Code subscriptions, the plugin **switches to the next account automatically** when one hits its usage limit:
158
161
 
159
- - **Setup** — use the **Account rotation** card at Settings → **Command Code** to add an account and label it. Paste its API key, or use the page's global **Save** button, then **Sign in to Command Code** and open the authorization link shown on that account's row in a new browser tab. The global Save/Discard bar stays inside the settings panel, attached to the bottom of its scrolling area. The top-level key always serves first as the `default` account.
160
- - **Manual switching** — the **Active account** dropdown pins a preferred account; if it is exhausted, requests fall back to other accounts and return once its window resets.
161
- - **Route models to accounts** — the **Route models to accounts** card picks catalog models (multi-select, fetched from the live catalog) and routes them to an account. A request whose model is in a rule serves from that account while it is usable; an exhausted or invalid routed account falls back to the normal rotation. Rules match in list order — the first hit wins.
162
- - **Show only favorite models** — the **Model allowlist** card keeps only the checked models in the model picker; unchecked shows all (the default).
163
- - **Status** — the **Account usage** card and `/commandcode` report per-account state.
162
+ - **Setup** — click **Add account** in the **Accounts** card at Settings → **Command Code**, optionally name it, then either **Sign in to Command Code** (the key is stored when you approve in the browser; a sign-in that does not complete leaves no empty account behind) or paste an API key. Account actions — add, rename, replace or clear a key, remove, pin — apply immediately; only the other settings on the page wait for the Save bar. The top-level key always serves first as the `default` account.
163
+ - **Manual switching** — **Pin this account** in an account's **⋯** menu makes it the preferred account; if it is exhausted, requests fall back to other accounts and return once its window resets. **Unpin** returns to automatic rotation.
164
+ - **Dedicated models** — expand an account and pick its **Dedicated models** from the live catalog. A request for one of those models serves from that account while it is usable; an exhausted or invalid account falls back to the normal rotation. A model belongs to one account at a time — picking it for another account moves it. (Stored as `modelAccountRules`.)
165
+ - **Show only favorite models** — the **Visible models** picker in the **Models** card keeps only the checked models in the model picker; unchecked shows all (the default).
166
+ - **Status** — each account row shows its plan, status and 5-hour/weekly meters; expand it for the full report. `/commandcode` reports the same per-account state.
164
167
 
165
168
  The equivalent YAML (`$DSH_HOME/settings.yaml` or composition config):
166
169
 
@@ -188,7 +191,7 @@ llm-commandcode:
188
191
 
189
192
  ## Configure
190
193
 
191
- **Settings → Command Code** covers the API key, API base URL, working directory, and request/stream timeouts; once a key is saved, a live **Account usage** card appears at the top of the page. The **Advanced** card holds the toggles — hide out-of-plan models, serve web search with Command Code, show the quota card in the sidebar (off by default), the AI command guard (off by default, see below), and zero data retention (off by default, see below).
194
+ **Settings → Command Code** is organized as **Accounts** (keys, sign-in, live quota, pinning, dedicated models), **Models** (hide out-of-plan models, visible models), **Privacy & security** (zero data retention and the AI command guard, both 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). The working directory is no longer on the page; `workingDir` in config still works.
192
195
 
193
196
  The same options live in `$DSH_HOME/settings.yaml` (changes apply immediately, no restart):
194
197
 
@@ -202,8 +205,7 @@ llm-commandcode:
202
205
  streamIdleTimeoutMs: 300000 # default 300s
203
206
  showSidebarQuota: true # optional: show the plans & quota card in the sidebar (default off)
204
207
  commandGuard: true # optional: let the decision model auto-approve safe shell commands (default off)
205
- commandGuardThreshold: 0.9 # optional: probability of "safe" needed to skip the prompt (0.5-1, default 0.9)
206
- commandGuardTimeoutMs: 1500 # optional: decision budget in ms (200-10000, default 1500)
208
+ commandGuardLevel: medium # optional: auto-approve threshold, high (0.95) | medium (0.9, default) | low (0.8)
207
209
  zdr: true # optional: route requests only through zero-data-retention upstreams (default off)
208
210
  ```
209
211
 
@@ -223,21 +225,22 @@ When your deployment's dsh shell mounts the web capability (`@deepseek-ai/dsh-we
223
225
 
224
226
  When dsh is about to ask you to approve a shell command (`bash`/`pwsh`) — a permission preset, a `PreToolUse` hook, or a sandbox escalation — this plugin can ask the Command Code decision model `typesafe/jev` whether the command is safe to run without asking. A confident *yes* turns into a one-shot `allowed-once` grant; everything else asks you exactly as before.
225
227
 
226
- **Off by default.** Turn it on with the *"Let AI judge shell commands"* toggle (`commandGuard`) in the Advanced card, or in your profile config. What the guard does and does not do:
228
+ **Off by default.** Turn it on with the *"Let AI judge shell commands"* toggle (`commandGuard`) in the Privacy & security card, or in your profile config. What the guard does and does not do:
227
229
 
228
230
  - It only ever sees commands dsh had **already decided to ask about** — it never widens a permission policy, and it never answers a session whose policy is "never ask".
229
- - Only a `yes` with probability at least `commandGuardThreshold` (default 0.9) skips the prompt. A `no`, a low-confidence answer, a timeout (default 1500 ms), a rate limit, a missing key, an unreadable answer, a command longer than 6000 characters, or a match against the built-in denylist (`sudo`, `rm -rf /`, `git push`, publish/upload commands, piping a download into a shell, …) all fall back to the normal prompt.
230
- - The **command text** (plus the agent's own one-line description, the working directory and the asker's reason) is sent to Command Code to be judged — with the same API key and base URL as chat.
231
+ - A normal approval asks one `safe` question. A call carrying `sandboxPermissions` also asks `escalation_scope` and `escalation_necessity`; the primary safety probability and both escalation probabilities must reach the threshold of the chosen `commandGuardLevel` — **High** 0.95, **Medium** 0.9 (default) or **Low** 0.8; a higher level prompts more often. Thus a narrow case such as `go test ./...` needing an outside build cache can be approved by JEV without prompting the user every time.
232
+ - A low-confidence answer, a broad or unnecessary escalation, a timeout (fixed at 3 seconds), a rate limit, a missing key, an unreadable answer, a command longer than 6000 characters, or a match against the built-in denylist (`sudo`, `rm -rf /`, `git push`, publish/upload commands, piping a download into a shell, …) all fall back to the normal prompt.
233
+ - The **command text** (plus the agent's own one-line description, the working directory, the requested sandbox mode and the asker's reason) is sent to Command Code to be judged — with the same API key and base URL as chat.
231
234
  - The decision model has **no zero-data-retention upstream**, so this feature is incompatible with a ZDR-only policy. Leave it off if that matters to you.
232
235
  - The endpoint is free through 2026-09-24; after that it bills $0.042 per 1M input tokens (output free) — a single decision is a few hundred tokens, and an identical command with the same approval context in the same agent reuses the previous verdict for 10 minutes.
233
236
 
234
- Every AI decision is logged on the Host — `llm-commandcode: command guard auto-approved a bash call (safe probability 0.97, model): <the command>` for a grant, `… delegated a bash call: <reason> — <the command>` for everything that fell through — and the outcome lands in the session's own approval audit (`approval/asked` / `approval/decided`), so a grant can always be traced back to the verdict that produced it. The log goes to the Host's console (the terminal running `dsh web`, or the desktop app's log), not to the browser.
237
+ Every AI decision is logged on the Host — an ordinary grant is `llm-commandcode: command guard auto-approved a bash call (safe probability 0.97, model): <the command>`; a sandbox grant also records its `sandbox scope` and `necessity` probabilities; everything that fell through is `… delegated a bash call: <reason> — <the command>` — and the outcome lands in the session's own approval audit (`approval/asked` / `approval/decided`), so a grant can always be traced back to the verdict that produced it. The log goes to the Host's console (the terminal running `dsh web`, or the desktop app's log), not to the browser.
235
238
 
236
239
  ## Zero data retention (ZDR)
237
240
 
238
241
  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)).
239
242
 
240
- **Off by default.** Turn it on with the *"Zero data retention (ZDR)"* toggle (`zdr`) in the Advanced card, or in your profile config. How this plugin implements it:
243
+ **Off by default.** Turn it on with the *"Zero data retention (ZDR)"* toggle (`zdr`) in the Privacy & security card, or in your profile config. How this plugin implements it:
241
244
 
242
245
  - The header is sent on **every chat request** while ZDR is on. The plugin maintains an informational exception list (`KNOWN_NON_ZDR_MODELS`, synced from the official CLI — about 20 models, e.g. `xai/grok-4.5`, `stepfun/Step-3.7-Flash`, `meta/muse-spark-1.3`). A model without an available ZDR upstream fails with `422 cmd_zdr_no_providers`; the request is never retried without the header.
243
246
  - If a refusal still happens (coverage churn, or no ZDR upstream with spare capacity at that moment), the error names the cause and how to turn ZDR off, instead of surfacing as a bare HTTP 422.
@@ -307,6 +310,6 @@ MIT — see [LICENSE](./LICENSE). Portions ported from [pi-commandcode-provider]
307
310
 
308
311
  <img src="assets/screenshots/usage-dashboard.png" alt="Usage dashboard" width="520">
309
312
 
310
- **Settings page** — API key, connection knobs, account rotation and the live account-usage card:
313
+ **Settings page** — the account list with live quota, model visibility, privacy switches and connection options:
311
314
 
312
315
  <img src="assets/screenshots/settings-page.png" alt="Command Code settings page with the account usage card" width="640">
package/README.zh-CN.md CHANGED
@@ -17,7 +17,7 @@
17
17
  ## 功能一览
18
18
 
19
19
  - **插件包**:一条 `dsh plugin add` 命令安装到任意 dsh 配置,注册 `commandcode` provider 路由,带实时模型目录。
20
- - **专属设置页**:API key 输入、连接参数、实时「账户用量」卡片和「隐藏套餐外模型」开关。
20
+ - **专属设置页**:统一的账户列表(密钥、网页登录、实时额度、专用模型)、模型显示、隐私开关与连接参数。
21
21
  - **终端界面同样可用**:同一次安装即可服务 [dsh-TUI](#终端界面dsh-tui) 配置,终端里有自己的 **`/settings` → Command Code** 页面来填 key 和调模型。
22
22
  - **Models 页快捷卡片**:**设置 → Models → Command Code** 卡片内直接显示 key 状态、粘贴输入框和登录按钮。
23
23
  - **浏览器内登录获取 key**:设置页一键发起官方授权(与 `cmd login` 同一流程),完成后密钥自动写入本机凭据服务,无需手动创建或粘贴;不可用时随时退回手动粘贴。
@@ -27,32 +27,29 @@
27
27
  - **按套餐过滤**:默认隐藏超出订阅套餐的模型,可一键关闭;「模型白名单」可进一步只保留常用模型。
28
28
  - **推理强度支持**:支持推理强度的模型可在选择器中选择档位。
29
29
  - **图片输入**:Vision 模型支持发送图片。
30
- - **套餐与配额面板**:可选的 Command Code 卡片位于侧边栏底部(Settings 正上方),显示当前服务账号的套餐与 5 小时 / 每周两个配额窗口;点击后在中间栏打开面板,包含计费周期、两个窗口的进度条与重置时间、月度额度消耗,以及已购买 / 赠送余额。面板右上角的 **×** 按钮可随时把中间栏交还给会话(不会切换当前会话)。**默认关闭**——在 **设置 → Command Code → 高级设置** 中打开「在侧边栏显示额度卡片」即可显示,同一开关也能随时隐藏(隐藏时左侧不渲染任何内容,也不会为其后台刷新用量)。面板文案跟随 Harness 显示语言(中文 / English),需要 dsh 0.1.5(rc.1)或更高版本。
30
+ - **套餐与配额面板**:可选的 Command Code 卡片位于侧边栏底部(Settings 正上方),显示当前服务账号的套餐与 5 小时 / 每周两个配额窗口;点击后在中间栏打开面板,包含计费周期、两个窗口的进度条与重置时间、月度额度消耗,以及已购买 / 赠送余额。面板右上角的 **×** 按钮可随时把中间栏交还给会话(不会切换当前会话)。**默认关闭**——在 **设置 → Command Code → 集成与显示** 中打开「在侧边栏显示额度卡片」即可显示,同一开关也能随时隐藏(隐藏时左侧不渲染任何内容,也不会为其后台刷新用量)。面板文案跟随 Harness 显示语言(中文 / English)。
31
31
  - **会话费用估算**:在输入框下方的 token 计数旁及用量对话框中显示估算金额(`≈`),根据持久化历史中每次请求的模型、请求时间和上下文阶梯分别计价。切换模型或稍后查看不会重新定价之前的请求。混合供应商或缺少费率时显示已定价部分的小计(`≥`);缺少历史事实或完全无法定价时不显示金额。结果基于插件内的价格快照,不等同于供应商账单。同样固定为英文。
32
32
  - **联网搜索**:dsh 的 `web_search` 工具由 Command Code Provider API(`/alpha/web-search`)承载,复用聊天同一个 key 与端点,无需单独配置搜索 key 或地址。详见[联网搜索](#联网搜索)。
33
33
 
34
34
  ## 安装
35
35
 
36
- 按你的 DeepSeek Harness 版本选择对应的发布线:
36
+ 本版本**只支持 dsh 0.1.7-rc.1**:插件的 peer 范围就是这一个版本,兼容性记录里也只列它。
37
37
 
38
- - **dsh 0.1.2-rc.1 或更高版本**(当前 0.1.2 线,即 `@latest` 现在安装的版本):
39
-
40
- ```sh
41
- dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@latest
42
- ```
38
+ ```sh
39
+ dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@latest
40
+ ```
43
41
 
44
- - **更早的 dsh 版本**(0.5.0 线及更早,使用 rc 时代的 Host/浏览器 API)——支持它们的最后一个插件版本是 0.9.1,按精确版本安装。该线不再积极维护:
42
+ - **更早的 dsh 版本。** 0.1.2–0.1.6 线已不再支持:那些引擎早于 0.1.7 的设置重写、`RequestMessage` 消息封装和持久化图片卸载契约,用来桥接两代引擎的兼容代码已经删除。覆盖它们的最后一个插件版本是 0.11.11;0.5.0 时代 Harness 线的最后一个版本是 0.9.1。两者都按精确版本安装,且都不再维护:
45
43
 
46
44
  ```sh
47
- dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.9.1
45
+ dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.11.11 # dsh 0.1.2–0.1.6
46
+ dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.9.1 # dsh 0.5.0 线
48
47
  ```
49
48
 
50
- > `latest` tag 指向当前 0.1.2 线的插件版本。旧 0.5.0 时代的 Harness 用户必须显式钉住 `@0.9.1`。
51
-
52
49
  **pnpm 11 会拦下刚发布的新版本。** 它的 `minimumReleaseAge` 默认为 1440 分钟,发布不足一天的版本会被跳过,`@latest` 解析到**上一个**版本 —— 而且是静默的,命令照样以成功退出。想装 24 小时内发布的版本,必须写精确版本号:
53
50
 
54
51
  ```sh
55
- dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.11.11
52
+ dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.11.13
56
53
  ```
57
54
 
58
55
  这一点对每个 profile 都成立,包括下面的终端界面。
@@ -64,14 +61,14 @@ dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.11.11
64
61
  用与安装时相同的 tag 更新:
65
62
 
66
63
  ```sh
67
- dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@latest # dsh 0.1.2-rc.1 及以上
64
+ dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@latest # dsh 0.1.7-rc.1
68
65
  dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@0.9.1 # 更早的 dsh(0.5.0 线,不再维护)
69
66
  ```
70
67
 
71
68
  每个 profile 各自更新 —— 终端界面有独立的插件列表(见下文):
72
69
 
73
70
  ```sh
74
- dsh plugin --profile dsh-tui update @mars-sea/dsh-commandcode-provider@0.11.11
71
+ dsh plugin --profile dsh-tui update @mars-sea/dsh-commandcode-provider@0.11.13
75
72
  ```
76
73
 
77
74
  要更新到发布不足 24 小时的版本,和上面的安装一样写精确版本号;pnpm 11 的年龄门禁会把 `@latest` 解析成上一个版本。
@@ -100,7 +97,7 @@ cmd login # macOS/Linux;Windows 原生版:cmdc login
100
97
  插件同样支持终端前端。**每个 dsh profile 有独立的插件列表**,所以上面那条 Web 安装命令不会装到终端里 —— 还要把插件装进 `dsh-tui` profile:
101
98
 
102
99
  ```sh
103
- dsh plugin --profile dsh-tui add @mars-sea/dsh-commandcode-provider@0.11.11
100
+ dsh plugin --profile dsh-tui add @mars-sea/dsh-commandcode-provider@0.11.13
104
101
  ```
105
102
 
106
103
  这里请写精确版本号。新版本发布后的 24 小时内,只写包名(或 `@latest`)会被静默解析到上一个版本 —— 安装命令照样成功,但 profile 里拿到的是旧版本,结果就是全新的终端安装里既没有 **`/settings` → Command Code** 页面,也看不到任何 `commandcode` 模型。
@@ -138,7 +135,7 @@ cmd login # 写入 ~/.commandcode/auth.json
138
135
  cwd: !!js process.cwd()
139
136
  ```
140
137
 
141
- **引擎版本要求。** 插件需要导出了 `ToolCallId` 的 dsh 引擎,即 **dsh 0.1.2-alpha.3 或更高**。这覆盖了 dsh-TUI 推荐的引擎(0.1.2-rc.1)以及之后的所有版本,但不包含它 peer 范围里名义上允许的最老引擎:在 dsh 0.1.0-rc.6 / 0.1.1-rc.2 上,插件的模块导入会失败,TUI 无法启动。请升级引擎,或改用 web profile。
138
+ **引擎版本要求。** 插件只针对一个引擎维护:**dsh 0.1.7-rc.1**。它的 `@deepseek-ai/dsh-*` peer 范围是 `^0.1.7-rc.1`(按 semver,这只会解析到 0.1.7-rc.1),`dsh.compatibility.dshReleases` 也只记录这一个版本。在更早的引擎上,设置页、消息封装或请求图片预算总有一处对不上——请改装支持你所用引擎的最后一个版本,而不是硬装这一个。
142
139
 
143
140
  ## 用量面板
144
141
 
@@ -154,11 +151,11 @@ cmd login # 写入 ~/.commandcode/auth.json
154
151
 
155
152
  有多个 Command Code 订阅时,插件可以在一个账户达到用量限额后**自动切换到下一个账户**:
156
153
 
157
- - **配置**:在 **设置 → Command Code** 的「多账户轮换」卡片添加账户并填写备注名。可直接填写 API key,或先点击页面底部的全局「保存」,再在该账户行点击「登录 Command Code」并打开出现的授权链接,在新网页授权获取 key;全局「放弃 / 保存」操作栏在设置面板内部随滚动吸附于底部。顶层 key 始终是第一顺位的 `default` 账户。
158
- - **手动切换**:卡片上的「当前使用账户」下拉框可指定优先账户;所选账户耗尽时自动回落到其他账户,窗口重置后自动恢复。
159
- - **按模型切换账户**:在「按模型切换账户」卡片从实时模型目录**多选**模型并固定到某个账户。请求的模型在规则列表中且该账户可用时使用该账户;账户耗尽或密钥失效时自动回落到常规轮换。规则按列表顺序匹配,第一条命中生效。
160
- - **只显示常用模型**:在「模型白名单」卡片勾选要保留的模型,模型选择器只列出这些;不勾选则显示全部(默认行为不变)。
161
- - **状态展示**:「账户用量」卡片与 `/commandcode` 均按账户分别显示状态。
154
+ - **配置**:在 **设置 → Command Code** 的「账户」卡片点击「添加账户」,可填写备注名,然后选择「网页登录」(在浏览器授权后自动保存 key;登录未完成不会留下空账户)或「粘贴密钥」。添加、重命名、更换或清除密钥、移除、固定等账户操作**立即生效**,无需点击页面底部的「保存」;「保存」只作用于页面上的其他设置。顶层 key 始终是第一顺位的 `default` 账户。
155
+ - **手动切换**:在账户行的「⋯」菜单中选择「固定使用此账户」即可指定优先账户;所选账户耗尽时自动回落到其他账户,窗口重置后自动恢复。「取消固定」回到自动轮换。
156
+ - **专用模型**:展开某个账户,从实时模型目录**多选**它的「专用模型」。请求这些模型且该账户可用时使用该账户;账户耗尽或密钥失效时自动回落到常规轮换。一个模型同一时间只属于一个账户,给另一个账户选择它会自动移过去(仍保存为 `modelAccountRules`)。
157
+ - **只显示常用模型**:在「模型」卡片的「可见模型」中勾选要保留的模型,模型选择器只列出这些;不勾选则显示全部(默认行为不变)。
158
+ - **状态展示**:每个账户行直接显示套餐、状态以及 5 小时 / 每周额度条,展开可查看完整报告;`/commandcode` 同样按账户显示状态。
162
159
 
163
160
  等价的 YAML(`$DSH_HOME/settings.yaml` 或组合配置):
164
161
 
@@ -186,7 +183,7 @@ llm-commandcode:
186
183
 
187
184
  ## 配置
188
185
 
189
- **设置 → Command Code** 可配置 API key、API 地址、工作目录与请求/流超时;配置好 key 后,页面顶部会显示实时「账户用量」卡片。**高级设置**卡片里集中了各个开关:隐藏套餐外模型、用 Command Code 承载联网搜索、在侧边栏显示额度卡片(默认关闭)、AI 命令安全预判(默认关闭,见下),以及零数据保留 ZDR(默认关闭,见下)。
186
+ **设置 → Command Code** 分为:**账户**(密钥、网页登录、实时额度、固定账户、专用模型)、**模型**(隐藏套餐外模型、可见模型)、**隐私与安全**(零数据保留 ZDR 与 AI 命令安全预判,均默认关闭,见下)、**集成与显示**(用 Command Code 承载联网搜索、在侧边栏显示额度卡片,默认关闭),以及默认折叠的**高级设置**(API 地址、请求/流超时、传输重试次数)。工作目录已不在页面上显示,配置中的 `workingDir` 仍然有效。
190
187
 
191
188
  同一组选项也位于 `$DSH_HOME/settings.yaml`(修改即刻生效,无需重启):
192
189
 
@@ -200,8 +197,7 @@ llm-commandcode:
200
197
  streamIdleTimeoutMs: 300000 # 默认 300s
201
198
  showSidebarQuota: true # 可选:在侧边栏显示套餐与配额卡片(默认关闭)
202
199
  commandGuard: true # 可选:让决策模型自动放行安全的 shell 命令(默认关闭)
203
- commandGuardThreshold: 0.9 # 可选:跳过弹窗所需的「安全」概率(0.5-1,默认 0.9)
204
- commandGuardTimeoutMs: 1500 # 可选:决策等待上限(毫秒,200-10000,默认 1500)
200
+ commandGuardLevel: medium # 可选:自动放行阈值,high(0.95)| medium(0.9,默认)| low(0.8)
205
201
  zdr: true # 可选:请求只经由零数据保留上游(默认关闭)
206
202
  ```
207
203
 
@@ -221,21 +217,22 @@ llm-commandcode:
221
217
 
222
218
  当 dsh 准备就某条 shell 命令(`bash`/`pwsh`)征求你同意时——无论是权限预设、`PreToolUse` 钩子还是沙箱提权——本插件可以先让 Command Code 的决策模型 `typesafe/jev` 判断这条命令是否安全到无需询问。判断为「安全」且把握足够高时,直接放行这一次调用;其余情况一律照旧询问你。
223
219
 
224
- **默认关闭。** 在高级设置里打开「用 AI 预判命令是否安全」(`commandGuard`),或写进 profile 配置。它的行为边界:
220
+ **默认关闭。** 在「隐私与安全」卡片里打开「用 AI 预判命令是否安全」(`commandGuard`),或写进 profile 配置。它的行为边界:
225
221
 
226
222
  - 它只会看到 dsh **本来就要询问你**的命令——不会放宽任何权限策略,也不会替「从不询问」(policy 为 `never`)的会话作答。
227
- - 只有「安全」概率不低于 `commandGuardThreshold`(默认 0.9)时才跳过弹窗。判为不安全、把握不足、超时(默认 1500ms)、限流、缺 key、返回体读不懂、命令超过 6000 字符,或命中内置危险名单(`sudo`、`rm -rf /`、`git push`、发布/上传类命令、把下载内容管进 shell 等),全部回到普通弹窗。
228
- - 送往 Command Code 判断的内容包括**命令原文**、模型自己写的一行描述、工作目录与询问原因;使用与聊天相同的 API key 与 base URL。
223
+ - 普通审批只问一个 `safe` 问题;带有 `sandboxPermissions` 的沙箱提权会额外问 `escalation_scope` 与 `escalation_necessity`。只有主安全概率以及这两个提权概率都不低于所选「自动放行阈值」(`commandGuardLevel`:高 0.95、中 0.9(默认)、低 0.8;阈值越高弹窗越多)时才跳过弹窗;因此像 `go test ./...` 需要访问工作区外构建缓存的场景,只要 JEV 确认提权范围狭窄且必要,就能由 AI 放行,不必每次打扰用户。
224
+ - 任一概率不足、提权范围过宽或没有必要、超时(固定 3 秒)、限流、缺 key、返回体读不懂、命令超过 6000 字符,或命中内置危险名单(`sudo`、`rm -rf /`、`git push`、发布/上传类命令、把下载内容管进 shell 等),全部回到普通弹窗。
225
+ - 送往 Command Code 判断的内容包括**命令原文**、模型自己写的一行描述、工作目录、请求的 sandbox 模式与询问原因;使用与聊天相同的 API key 与 base URL。
229
226
  - 该决策模型**没有零数据保留(ZDR)上游**,因此本功能与「只走 ZDR」的合规要求不兼容;如果你在意这一点,请保持关闭。
230
227
  - 该端点 2026-09-24 前免费,之后按输入 $0.042/1M tokens 计费(输出免费)——单次判断只有几百 tokens;同一 agent 中命令和审批场景都相同时,10 分钟内复用上一次结论。
231
228
 
232
- 每次 AI 决策都会在 Host 侧写日志——放行是 `llm-commandcode: command guard auto-approved a bash call (safe probability 0.97, model): <命令>`,其余是 `… delegated a bash call: <原因> — <命令>`——并进入会话自身的审批审计(`approval/asked` / `approval/decided`),所以任何一次放行都能追溯到产生它的判断。日志打到 Host 控制台(运行 `dsh web` 的终端,或桌面端日志),不进浏览器。
229
+ 每次 AI 决策都会在 Host 侧写日志——普通放行是 `llm-commandcode: command guard auto-approved a bash call (safe probability 0.97, model): <命令>`;沙箱提权还会附带 `sandbox scope` 与 `necessity` 概率;其余是 `… delegated a bash call: <原因> — <命令>`——并进入会话自身的审批审计(`approval/asked` / `approval/decided`),所以任何一次放行都能追溯到产生它的判断。日志打到 Host 控制台(运行 `dsh web` 的终端,或桌面端日志),不进浏览器。
233
230
 
234
231
  ## 零数据保留(ZDR)
235
232
 
236
233
  Command Code 可以让请求只经由「不留存提示词与回复、也不用于训练」的上游——官方 CLI 的开关是 `CMD_ZDR=1`,Provider API 上则是在请求头发 `x-cmd-zdr: 1`([官方文档](https://commandcode.ai/docs/resources/zdr))。
237
234
 
238
- **默认关闭。** 在高级设置里打开「零数据保留(ZDR)」(`zdr`),或写进 profile 配置。本插件的实现方式:
235
+ **默认关闭。** 在「隐私与安全」卡片里打开「零数据保留(ZDR)」(`zdr`),或写进 profile 配置。本插件的实现方式:
239
236
 
240
237
  - 开启后,**每次聊天请求**都会带上 ZDR 请求头。插件仍维护官方 CLI 的例外名单(`KNOWN_NON_ZDR_MODELS`,约 20 个模型,例如 `xai/grok-4.5`、`stepfun/Step-3.7-Flash`、`meta/muse-spark-1.3`)供查询。没有可用 ZDR 上游时,服务端返回 `422 cmd_zdr_no_providers`;插件不会去掉请求头重试。
241
238
  - 万一仍被拒绝(名单过期,或那一刻没有空闲的 ZDR 上游容量),错误信息会说明原因并给出关闭 ZDR 的办法,而不是抛出一个光秃秃的 HTTP 422。
@@ -304,6 +301,6 @@ MIT —— 见 [LICENSE](./LICENSE)。部分内容移植自 [pi-commandcode-prov
304
301
 
305
302
  <img src="assets/screenshots/usage-dashboard.png" alt="用量面板" width="520">
306
303
 
307
- **设置页** —— API 密钥、连接参数、多账户轮换与实时账户用量卡片:
304
+ **设置页** —— 带实时额度的账户列表、模型显示、隐私开关与连接参数:
308
305
 
309
306
  <img src="assets/screenshots/settings-page.png" alt="Command Code 设置页面(含账户用量卡片)" width="640">