@mars-sea/dsh-commandcode-provider 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +53 -13
- package/README.zh-CN.md +52 -13
- package/lib/client.js +57 -0
- package/lib/client.js.map +1 -0
- package/lib/index.d.ts +127 -1
- package/lib/index.js +363 -13
- package/lib/index.js.map +1 -1
- package/package.json +17 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,29 @@ 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.2.0] - 2026-08-16
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **`KNOWN_EFFORTS` was missing ten models that the official command-code@1.26.0 model table defines reasoning-effort levels for** (`claude-haiku-4-5-20251001`, `moonshotai/Kimi-K2.5`, `moonshotai/Kimi-K2.6`, `moonshotai/Kimi-K2.7-Code-Highspeed`, `MiniMaxAI/MiniMax-M2.5`, `xiaomi/mimo-v2.5`, `xiaomi/mimo-v2.5-pro`, `tencent/hy3-paid`, `tencent/Hy3`, `meta/muse-spark-1.2-contributor`). These models previously showed no reasoning-effort selector in the harness even though the official CLI exposes one; they now do. The snapshot was re-verified against the CLI's authoritative `ZA` model table (dist/cli.mjs) rather than the docs page alone.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`KNOWN_THINKING_MODELS`** — models the official registry marks `Reasoning` but for which the CLI defines no selectable effort levels (e.g. `MiniMaxAI/MiniMax-M3`, `moonshotai/Kimi-K3`, `Qwen/Qwen3.7-Max`, `thinkingmachines/inkling`). The model picker now labels these "Supports thinking (auto)" instead of the misleading "Text only", so a reasoning-capable model is no longer mistaken for a text-only one. Selectable efforts remain exclusively driven by `KNOWN_EFFORTS`, matching the official CLI (which omits `reasoning_effort` for these models too).
|
|
16
|
+
- **Plan-tier annotation in the model picker** (`KNOWN_PLANS` in `src/adapter.ts`, synced from the [official plan pages](https://commandcode.ai/docs/plans/go)) — every catalog model is tagged with the minimum plan that includes it, per the official plan model lists: **Go** (33 models), **GOAT** (+3), **Pro** (+14), and **Provider/Max** (+5, the Claude Opus/Fable and Fugu Ultra tier). The picker's `description` leads with the plan label — e.g. `Go · 50% off · Image · 1M`, `Pro · Image · 1M` — so "which plan do I need to actually use this model?" is answerable at a glance instead of only after a 403 `MODEL_NOT_IN_PLAN` on the first request. New `KNOWN_PLANS`, `PLAN_LABELS`, `planLabel()`, and `capabilityDescription()` exports.
|
|
17
|
+
- **Deal and free-model annotations** (`KNOWN_DEALS` in `src/adapter.ts`, synced from the [official pricing page](https://commandcode.ai/docs/resources/pricing-limits#deals)) — the picker now shows active discounts (`75% off`, `50% off`, `98% off`, `99% off`) and the `FREE` badge (Laguna S 2.1) next to the plan tier. **Expiry-aware**: each deal records its official end date; `dealLabel()` hides a deal the moment `Date.now()` passes that date, so an un-updated plugin never shows a lapsed discount as if it were still live (only Gemini 3.7 Flash's 50% off is time-limited — through December 31, 2026; the rest are permanent).
|
|
18
|
+
- **Compact Image + context-window markers** — the picker now shows `Image` for Vision-capable models (the verbose *"Supports image input"* is gone) and the context window in human form (`1M`, `256K`, `262K`) via `formatContext()`. Text-only models show no capability marker at all — plan tier (and deal, if any) plus context is enough.
|
|
19
|
+
- **`capabilityDescription()` is now compact**: `Go · 50% off · Image · 1M`, `Provider · 1M`, `Go · FREE · 256K` — plan tier first, then active deal, then `Image`, then context. Text-only models simply omit the Image marker.
|
|
20
|
+
- **The model picker sorts by plan tier, then name** (`compareByPlan()` in `src/adapter.ts`) — Go models lead the list, then GOAT, Pro, and Provider/Max last, alphabetically within each tier (new `PLAN_ORDER` weights + `compareByPlan()` exports). A Go-plan user sees the models they can actually use at the top instead of hunting through a flat alphabetical catalog; unknown/untracked models sort last.
|
|
21
|
+
|
|
22
|
+
## [0.1.9] - 2026-08-15
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **Image input for Vision-capable models.** Models the official Command Code registry lists with Vision (see `KNOWN_IMAGE_MODELS` in `src/adapter.ts`, synced from the [official model registry](https://commandcode.ai/docs/reference/cli/models)) now accept attached images: bytes resolve through the dsh attachment service (`ctx.attachments`) and are sent in the official CLI wire shape `{ type: 'image', source: { type: 'base64', media_type, data } }`. Text-only models (e.g. `deepseek/deepseek-v4-flash`) refuse images loudly (`UNSUPPORTED_CONTENT`) rather than silently dropping them; a request carrying images also requires the attachment service. The `CommandCodeAdapterDeps` seam gains an optional `resolveAttachments` resolver (used lazily, only when a request actually has images).
|
|
27
|
+
- **The model picker now shows each Command Code model's image capability** (`listModels`/`resolveModel` return a `description`: *"Supports image input"* / *"Text only"*), so switching in an image-bearing session is informed instead of surprising.
|
|
28
|
+
- **A client half for the bundle** (`dsh.client` + `exports["./client"]` → `lib/client.js`): it wraps the shared `session.selectModel` face and rewrites the harness's image-session `model-unavailable` rejection into a clear, actionable message — `当前会话已包含图片,而模型 <model> 不支持图片输入;请选择支持图片的模型,或先移除会话中的图片。` — while passing the error code and details through unchanged. The rejection itself is a deliberate `dsh-host-apiproxy` guard that cannot be relaxed from the plugin side; this makes it friendlier. Both READMEs document the behavior.
|
|
29
|
+
|
|
7
30
|
## [0.1.8] - 2026-08-15
|
|
8
31
|
|
|
9
32
|
### Fixed
|
|
@@ -16,6 +39,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
16
39
|
|
|
17
40
|
- `CommandCodeConnectionOptions` gains `requestTimeoutMs` and `streamIdleTimeoutMs`; both are optional in the `Config` schema and default to 60s/120s. New `DEFAULT_REQUEST_TIMEOUT_MS` / `DEFAULT_STREAM_IDLE_TIMEOUT_MS` exports.
|
|
18
41
|
- Both READMEs document the new knobs and the transport-failure troubleshooting entry (notably: Node's fetch ignores `HTTP_PROXY`/`HTTPS_PROXY`, so proxy-dependent networks fail here while the browser works).
|
|
42
|
+
- Both READMEs gain an **Updating** section: since the bundle patch layer is read from the installed package at boot, updating the package fixes the patch row automatically; the section covers npm/git/local update commands and the ≤0.1.6 hand-copied-patch caveat.
|
|
43
|
+
- Both READMEs restructure the install docs: **npm is now the recommended install path** (one command, always the latest published release), GitHub moves below it, and the uninstall command is documented (use the scoped name `@mars-sea/dsh-commandcode-provider`, since pnpm records dependencies under the real package name).
|
|
19
44
|
|
|
20
45
|
## [0.1.7] - 2026-08-15
|
|
21
46
|
|
package/README.md
CHANGED
|
@@ -16,7 +16,11 @@ 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.26.0 bundled
|
|
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`, `moonshotai/Kimi-K2.5`, …) via `KNOWN_EFFORTS`, matching the official command-code@1.26.0 bundled model table. Reasoning models without selectable effort levels (e.g. `MiniMaxAI/MiniMax-M3`, `moonshotai/Kimi-K3`) still think — Command Code drives their reasoning depth automatically, exactly like the official CLI.
|
|
20
|
+
- **Plan-tier annotation in the model picker**: every Command Code model is tagged with the minimum plan that includes it (`KNOWN_PLANS`, synced from the [official plan pages](https://commandcode.ai/docs/plans/go)) — **Go** (33 models), **GOAT** (+3), **Pro** (+14), or **Provider/Max** (+5: Claude Opus/Fable, Fugu Ultra). The picker's `description` leads with the plan label, e.g. *"Go · 50% off · Image · 1M"*, *"Pro · Image · 1M"*, so you know which plan a model needs before switching — no more 403 `MODEL_NOT_IN_PLAN` surprises. **The list itself is sorted by plan tier** (`compareByPlan()`): Go models first, then GOAT, Pro, Provider/Max, alphabetical within each tier — the models your plan can actually use lead the picker.
|
|
21
|
+
- **Deal and free-model annotations**: active discounts (`75% off`, `50% off`, `98% off`, `99% off`) and the `FREE` badge (Laguna S 2.1) show next to the plan tier (`KNOWN_DEALS`, synced from the [official pricing page](https://commandcode.ai/docs/resources/pricing-limits#deals)). **Expiry-aware**: each deal records its official end date and is hidden the moment it passes — an un-updated plugin never shows a lapsed discount as if it were live (only Gemini 3.7 Flash's 50% off is time-limited, through December 31, 2026; the rest are permanent).
|
|
22
|
+
- **Image + context markers**: the picker shows `Image` for Vision-capable models and the context window in human form (`1M`, `256K`, `262K`); text-only models show neither — plan tier plus context is enough.
|
|
23
|
+
- **Image input for Vision-capable models**: models the official registry lists with Vision (e.g. `claude-sonnet-5`, `gpt-5.4`, `google/gemini-3.5-flash`, …) accept attached images, resolved through the dsh attachment service and sent in the official Command Code wire format. Text-only models (e.g. `deepseek/deepseek-v4-flash`, `zai-org/GLM-5.3`) refuse images loudly rather than silently dropping them.
|
|
20
24
|
|
|
21
25
|
## Getting an API key
|
|
22
26
|
|
|
@@ -31,11 +35,19 @@ cmd login # macOS/Linux; native Windows: cmdc login
|
|
|
31
35
|
|
|
32
36
|
## Install
|
|
33
37
|
|
|
34
|
-
### From
|
|
38
|
+
### From npm (recommended)
|
|
39
|
+
|
|
40
|
+
The plugin is published to the npm registry as **`@mars-sea/dsh-commandcode-provider`** (the bare name `dsh-commandcode-provider` is taken by an unrelated package):
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
dsh plugin --profile web add @mars-sea/dsh-commandcode-provider
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### From GitHub
|
|
35
47
|
|
|
36
48
|
```sh
|
|
37
49
|
# Pin a release tag (recommended — readable and immutable)
|
|
38
|
-
dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#v0.1.
|
|
50
|
+
dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#v0.1.8
|
|
39
51
|
# Or pin any exact commit by its SHA
|
|
40
52
|
dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#<full-commit-sha>
|
|
41
53
|
```
|
|
@@ -51,14 +63,6 @@ allowBuilds:
|
|
|
51
63
|
|
|
52
64
|
and re-run the `add`. Only allow packages whose source you trust (and pin a commit).
|
|
53
65
|
|
|
54
|
-
### From npm
|
|
55
|
-
|
|
56
|
-
Published as **`@mars-sea/dsh-commandcode-provider`** (the bare name `dsh-commandcode-provider` is taken on the npm registry by an unrelated package):
|
|
57
|
-
|
|
58
|
-
```sh
|
|
59
|
-
dsh plugin --profile web add @mars-sea/dsh-commandcode-provider
|
|
60
|
-
```
|
|
61
|
-
|
|
62
66
|
### From a local checkout
|
|
63
67
|
|
|
64
68
|
```sh
|
|
@@ -90,6 +94,41 @@ dsh --profile web --dump-config # shows a "# == @mars-sea/dsh-commandco
|
|
|
90
94
|
dsh web # or restart your running instance
|
|
91
95
|
```
|
|
92
96
|
|
|
97
|
+
## Updating
|
|
98
|
+
|
|
99
|
+
The bundle's patch layer is read from the **installed package** at every boot, so updating the package brings in the fixed patch row automatically — you do not need to hand-edit `cordis.patch.yml` unless you copied its contents into your own profile layer.
|
|
100
|
+
|
|
101
|
+
Update according to how you installed it:
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
# From npm (recommended): always the latest published release
|
|
105
|
+
dsh plugin --profile web update @mars-sea/dsh-commandcode-provider
|
|
106
|
+
|
|
107
|
+
# From GitHub pinned to a tag: point at the new tag
|
|
108
|
+
# (no need to uninstall first — pnpm swaps the pinned revision in place,
|
|
109
|
+
# and the bundle layer is re-read from the installed package on next boot)
|
|
110
|
+
dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#v0.1.9
|
|
111
|
+
|
|
112
|
+
# From a local checkout: pull the new code, rebuild, restart
|
|
113
|
+
git -C /path/to/dsh-commandcode-provider pull
|
|
114
|
+
npm run build --prefix /path/to/dsh-commandcode-provider
|
|
115
|
+
dsh web
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Then restart the web app (`dsh web`, or restart the service). Verify the running version with `dsh --profile web --dump-config` — the layer should show `name: '@mars-sea/dsh-commandcode-provider'`.
|
|
119
|
+
|
|
120
|
+
> **`update` says "Already up to date" but the version did not move (pnpm ≥ 11)?** pnpm 11's `minimumReleaseAge` supply-chain policy can refuse to update to a freshly published version and report "Already up to date" even though a newer release exists. Pin the exact version instead:
|
|
121
|
+
>
|
|
122
|
+
> ```sh
|
|
123
|
+
> dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.1.9
|
|
124
|
+
> ```
|
|
125
|
+
>
|
|
126
|
+
> `add` with an explicit version installs it (and moves your spec to `^0.1.9`). If you trust your registry you can also disable the gate with `pnpm config set minimumReleaseAge 0 --location project` inside the profile directory (or delete the `minimumReleaseAgeExclude` entry pnpm wrote into `pnpm-workspace.yaml`).
|
|
127
|
+
|
|
128
|
+
> **Upgrading from ≤0.1.6** (or a broken hand-edited profile): the installed package's patch layer now carries the corrected, quoted `name`. If you previously *copied* the old patch row into your profile's own `cordis.patch.yml`, that copy still wins over the bundle layer — fix it manually to `name: "@mars-sea/dsh-commandcode-provider"` (see [Troubleshooting](#troubleshooting)) or remove it and let the bundle layer apply.
|
|
129
|
+
|
|
130
|
+
> **To uninstall instead of upgrading** (e.g. you are on a broken pre-0.1.7 tag and want to start clean): `dsh plugin --profile web remove @mars-sea/dsh-commandcode-provider` (the scoped name — pnpm records the dependency under its real package name, so the bare `dsh-commandcode-provider` form does not match). This removes the dependency and its layer; your API key in the dsh credential store and `~/.commandcode/auth.json` are left untouched. Then install the current version with the npm or GitHub command above.
|
|
131
|
+
|
|
93
132
|
## Verify it works
|
|
94
133
|
|
|
95
134
|
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).
|
|
@@ -154,11 +193,12 @@ The composition-entry config (`cordis.patch.yml` / your profile `cordis.patch.ym
|
|
|
154
193
|
- **`MISSING_CREDENTIAL`** — no key anywhere. Store one via the Models page card, export `COMMANDCODE_API_KEY`, set `config.apiKey`, or run `command-code login`. The route stays registered and the catalog stays browsable without a key.
|
|
155
194
|
- **The Models page card shows "not configured" but requests work** — the key came from `~/.commandcode/auth.json` (the `cmd login` fallback), not the dsh credential store. Paste it into the card once to make the card show as configured; both coexist fine.
|
|
156
195
|
- **A reasoning model returns no visible text on short requests** — reasoning models (e.g. `deepseek/deepseek-v4-*`) consume output tokens on reasoning first; a small `maxTokens` can be exhausted before any visible text. This is normal.
|
|
157
|
-
- **`allowBuilds` errors on `dsh plugin add` from git** — copy the exact package key pnpm printed (with the commit hash) into `pnpm-workspace.yaml` and re-run (see [Install](#from-github
|
|
196
|
+
- **`allowBuilds` errors on `dsh plugin add` from git** — copy the exact package key pnpm printed (with the commit hash) into `pnpm-workspace.yaml` and re-run (see [Install](#from-github)).
|
|
158
197
|
|
|
159
198
|
## Notes & limitations
|
|
160
199
|
|
|
161
|
-
- **
|
|
200
|
+
- **Image input is model-gated**: only models the official Command Code registry lists with Vision accept images (see the `KNOWN_IMAGE_MODELS` snapshot in `src/adapter.ts`, synced from the [official model registry](https://commandcode.ai/docs/reference/cli/models)). The model picker marks Vision-capable models with *`Image`* (e.g. *"Go · 50% off · Image · 1M"*); text-only models carry no marker, so the capability is visible before you switch. Sending an image to a text-only model throws `UNSUPPORTED_CONTENT`. Command Code's own CLI falls back to a client-side *VISION* side-call for text-only models; this adapter does **not** reproduce that interactive feature — switch to a Vision-capable model instead. Image input also requires the dsh **attachment service** (`ctx.attachments`); without it, requests carrying images throw `UNSUPPORTED_CONTENT`.
|
|
201
|
+
- **Switching to a text-only model in an image-bearing session is rejected by dsh itself** — a harness-level guard (`dsh-host-apiproxy`'s `selectModel` handler) refuses `model-unavailable` when the session history or the pending input already contains images and the target model does not declare `image` input. The rejection is intentional and cannot be relaxed from the plugin side (the picker rows this adapter provides are the input that makes the guard work — a text-only model correctly reports `inputModalities: ['text']`). What this bundle **does** do is make the message friendlier: its client half wraps `session.selectModel` and rewrites that rejection to `当前会话已包含图片,而模型 <model> 不支持图片输入;请选择支持图片的模型,或先移除会话中的图片。` (the error code and details pass through unchanged, so any caller switching on `error.code` keeps working). To keep using images, select a model the picker marks *`Image`*, or remove the images from the session first; alternatively an image-routing bundle (e.g. `@deepseek-ai/dsh-llm-image-routing`) can transparently route image turns to a vision fallback.
|
|
162
202
|
- **No `stop` sequences**: the wire format has no stop field; requests carrying one throw `UNSUPPORTED_OPTION`.
|
|
163
203
|
- Reasoning blocks are **not replayed** into later turns (matches the official CLI: prior private reasoning must not leak).
|
|
164
204
|
- Only tool calls with a paired tool result are replayed into the conversation.
|
package/README.zh-CN.md
CHANGED
|
@@ -16,7 +16,11 @@
|
|
|
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.26.0
|
|
19
|
+
- **推理强度(reasoning-effort)支持**:针对 Command Code 目录中标为推理模型的模型(如 `claude-opus-5`、`gpt-5.5`、`deepseek/deepseek-v4-pro`、`moonshotai/Kimi-K2.5` 等),通过 `KNOWN_EFFORTS` 实现,与官方 command-code@1.26.0 内置模型表一致。没有可选推理档位但仍支持思考的模型(如 `MiniMaxAI/MiniMax-M3`、`moonshotai/Kimi-K3`)同样会思考——由 Command Code 自动控制推理深度,与官方 CLI 行为完全一致。
|
|
20
|
+
- **模型选择器标注套餐档位**:每个 Command Code 模型都标注了包含它的最低套餐(`KNOWN_PLANS`,与[官方套餐页](https://commandcode.ai/docs/plans/go)同步)——**Go**(33 个)、**GOAT**(+3)、**Pro**(+14)、**Provider/Max**(+5:Claude Opus/Fable、Fugu Ultra)。选择器的 `description` 以套餐标签开头,例如 *"Go · 50% off · Image · 1M"*、*"Pro · Image · 1M"*,切换前即可知道该模型需要什么套餐——不再等到第一次请求才收到 403 `MODEL_NOT_IN_PLAN`。**列表本身也按套餐排序**(`compareByPlan()`):Go 模型在最前,随后 GOAT、Pro、Provider/Max,档内按字母序——你当前套餐能用的模型总是排在列表最前面。
|
|
21
|
+
- **折扣与免费标注**:活动折扣(`75% off`、`50% off`、`98% off`、`99% off`)与 `FREE` 徽章(Laguna S 2.1)会显示在套餐旁(`KNOWN_DEALS`,与[官方定价页](https://commandcode.ai/docs/resources/pricing-limits#deals)同步)。**到期感知**:每个折扣记录官方结束日期,一旦过期立即隐藏——插件未更新时也不会把已失效的折扣当成仍在生效(只有 Gemini 3.7 Flash 的 50% off 限时,至 2026 年 12 月 31 日;其余为永久)。
|
|
22
|
+
- **Image 与上下文标注**:支持视觉的模型显示 `Image`,并显示人类可读的上下文长度(`1M`、`256K`、`262K`);纯文本模型两者都不显示——套餐 + 上下文已足够。
|
|
23
|
+
- **支持视觉模型的图片输入**:官方注册表中带 Vision 能力的模型(如 `claude-sonnet-5`、`gpt-5.4`、`google/gemini-3.5-flash` 等)可接收附加图片——通过 dsh 附件服务解析字节,并以官方 Command Code wire 格式发送。纯文本模型(如 `deepseek/deepseek-v4-flash`、`zai-org/GLM-5.3`)会明确拒绝图片而非静默丢弃。
|
|
20
24
|
|
|
21
25
|
## 获取 API key
|
|
22
26
|
|
|
@@ -31,11 +35,19 @@ cmd login # macOS/Linux;Windows 原生版:cmdc login
|
|
|
31
35
|
|
|
32
36
|
## 安装
|
|
33
37
|
|
|
34
|
-
### 从
|
|
38
|
+
### 从 npm 安装(推荐)
|
|
39
|
+
|
|
40
|
+
插件发布在 npm 上,包名 **`@mars-sea/dsh-commandcode-provider`**(npm 上裸名 `dsh-commandcode-provider` 已被无关包占用):
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
dsh plugin --profile web add @mars-sea/dsh-commandcode-provider
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 从 GitHub 安装
|
|
35
47
|
|
|
36
48
|
```sh
|
|
37
49
|
# 推荐:锁定发布 tag(可读、不可变)
|
|
38
|
-
dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#v0.1.
|
|
50
|
+
dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#v0.1.9
|
|
39
51
|
# 或按完整 commit SHA 锁定任意提交
|
|
40
52
|
dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#<完整-commit-sha>
|
|
41
53
|
```
|
|
@@ -51,14 +63,6 @@ allowBuilds:
|
|
|
51
63
|
|
|
52
64
|
然后重新运行 `add`。只允许信任其源码的包(并固定 commit)。
|
|
53
65
|
|
|
54
|
-
### 从 npm 安装
|
|
55
|
-
|
|
56
|
-
发布为 **`@mars-sea/dsh-commandcode-provider`**(npm 上裸名 `dsh-commandcode-provider` 已被无关包占用):
|
|
57
|
-
|
|
58
|
-
```sh
|
|
59
|
-
dsh plugin --profile web add @mars-sea/dsh-commandcode-provider
|
|
60
|
-
```
|
|
61
|
-
|
|
62
66
|
### 从本地检出安装
|
|
63
67
|
|
|
64
68
|
```sh
|
|
@@ -90,6 +94,40 @@ dsh --profile web --dump-config # 会显示 "# == @mars-sea/dsh-command
|
|
|
90
94
|
dsh web # 或重启你正在运行的实例
|
|
91
95
|
```
|
|
92
96
|
|
|
97
|
+
## 更新
|
|
98
|
+
|
|
99
|
+
bundle 的 patch 层在每次启动时都从**已安装的包**读取,所以更新包本身就会带入修复后的 patch 行——**不需要**手工改 `cordis.patch.yml`(除非你把它的内容复制到了自己 profile 的层里)。
|
|
100
|
+
|
|
101
|
+
按安装方式选择更新命令:
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
# 从 npm 安装(推荐):总是升到最新发布版本
|
|
105
|
+
dsh plugin --profile web update @mars-sea/dsh-commandcode-provider
|
|
106
|
+
|
|
107
|
+
# 从 GitHub 按 tag 安装:指向新 tag
|
|
108
|
+
# (无需先卸载——pnpm 会就地替换固定的版本,下次启动时 bundle 层会从新安装的包重新读取)
|
|
109
|
+
dsh plugin --profile web add github:Mars-Sea/dsh-commandcode-provider#v0.1.9
|
|
110
|
+
|
|
111
|
+
# 从本地检出安装:拉取新代码、重新构建、重启
|
|
112
|
+
git -C /path/to/dsh-commandcode-provider pull
|
|
113
|
+
npm run build --prefix /path/to/dsh-commandcode-provider
|
|
114
|
+
dsh web
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
然后重启 Web 应用(`dsh web`,或重启服务)。用 `dsh --profile web --dump-config` 验证运行的版本——层里应显示 `name: '@mars-sea/dsh-commandcode-provider'`。
|
|
118
|
+
|
|
119
|
+
> **`update` 提示 "Already up to date" 但版本没变(pnpm ≥ 11)?** pnpm 11 的 `minimumReleaseAge` 供应链安全策略可能拒绝更新到刚发布的新版本,并报 "Already up to date",即使已经有更新的发布。请改用**显式版本**安装:
|
|
120
|
+
>
|
|
121
|
+
> ```sh
|
|
122
|
+
> dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.1.9
|
|
123
|
+
> ```
|
|
124
|
+
>
|
|
125
|
+
> `add` 加显式版本会真正装上新版本(并把你的 spec 升为 `^0.1.9`)。如果你信任所用 registry,也可以在 profile 目录里执行 `pnpm config set minimumReleaseAge 0 --location project` 关掉该门禁(或删除 pnpm 写进 `pnpm-workspace.yaml` 的 `minimumReleaseAgeExclude` 条目)。
|
|
126
|
+
|
|
127
|
+
> **从 ≤0.1.6 升级**(或手改坏的 profile):安装包自带的 patch 层现在已经带着修正后的带引号 `name`。如果你之前**手工复制**过旧的 patch 行到你 profile 自己的 `cordis.patch.yml`,那份拷贝会覆盖 bundle 层——请手动改成 `name: "@mars-sea/dsh-commandcode-provider"`(见[故障排查](#故障排查)),或删掉它让 bundle 层生效。
|
|
128
|
+
|
|
129
|
+
> **想卸载而不是升级**(例如正卡在 0.1.7 之前坏掉的 tag,想干净重来):`dsh plugin --profile web remove @mars-sea/dsh-commandcode-provider`(用 **scoped 名**——pnpm 按真实包名记录依赖,裸名 `dsh-commandcode-provider` 对不上)。这会移除依赖及其配置层;你在 dsh 凭据库和 `~/.commandcode/auth.json` 里的 API key 不受影响。然后用上面的 npm 或 GitHub 命令安装当前版本。
|
|
130
|
+
|
|
93
131
|
## 验证是否生效
|
|
94
132
|
|
|
95
133
|
重启后,在 Web UI 中:**设置 → Models** 会显示 **Command Code** 卡片;模型选择器会在 **commandcode** 下列出实时目录(撰写本文时有 54 个模型)。发送一条消息,选择你套餐中包含的模型——默认的 `deepseek/deepseek-v4-flash` 适用于入门级套餐;开放权重模型(DeepSeek/Qwen/Kimi/MiniMax)通常都可用,而前沿模型(Claude/GPT/Gemini/Grok)可能需要 Pro/Max 套餐或按需计费(见 FAQ)。
|
|
@@ -154,11 +192,12 @@ llm-commandcode:
|
|
|
154
192
|
- **`MISSING_CREDENTIAL`** ——任何地方都没有 key。通过 Models 页面卡片存储一个、`export COMMANDCODE_API_KEY`、设置 `config.apiKey`,或运行 `command-code login`。没有 key 时路由保持注册、目录保持可浏览。
|
|
155
193
|
- **Models 页面卡片显示"未配置"但请求可用** ——key 来自 `~/.commandcode/auth.json`(`cmd login` 兜底),而不是 dsh 凭据存储。把它粘贴到卡片一次即可让卡片显示为已配置;两者可以共存。
|
|
156
194
|
- **推理模型在短请求下不返回可见文本** ——推理模型(如 `deepseek/deepseek-v4-*`)会先消耗输出 token 进行推理;`maxTokens` 较小时可能在出现可见文本前就用完。这属于正常现象。
|
|
157
|
-
- **git 安装时 `dsh plugin add` 报 `allowBuilds` 错误** ——把 pnpm 打印的确切包 key(含 commit hash)复制到 `pnpm-workspace.yaml` 并重新运行(见[从 GitHub
|
|
195
|
+
- **git 安装时 `dsh plugin add` 报 `allowBuilds` 错误** ——把 pnpm 打印的确切包 key(含 commit hash)复制到 `pnpm-workspace.yaml` 并重新运行(见[从 GitHub 安装](#从-github-安装))。
|
|
158
196
|
|
|
159
197
|
## 注意事项与限制
|
|
160
198
|
|
|
161
|
-
-
|
|
199
|
+
- **图片输入按模型能力限制**:只有官方 Command Code 注册表标记为 Vision 的模型接受图片(见 `src/adapter.ts` 中的 `KNOWN_IMAGE_MODELS` 快照,与[官方模型注册表](https://commandcode.ai/docs/reference/cli/models)同步)。模型选择器会给支持视觉的模型标注 *`Image`*(如 *"Go · 50% off · Image · 1M"*),纯文本模型不带该标记,切换前即可看出能力。向纯文本模型发送图片会抛出 `UNSUPPORTED_CONTENT`。官方 CLI 对纯文本模型会回退到客户端 *VISION* 副调用转文字;本适配器**不**复现该交互功能——请改用支持 Vision 的模型。图片输入还需要 dsh 的**附件服务**(`ctx.attachments`);缺失时携带图片的请求会抛出 `UNSUPPORTED_CONTENT`。
|
|
200
|
+
- **在含图片的会话里切换到纯文本模型会被 dsh 自身拒绝**——这是 harness 层的守卫(`dsh-host-apiproxy` 的 `selectModel` 处理器):当会话历史或待处理输入已包含图片、而目标模型未声明 `image` 输入时,会返回 `model-unavailable`。该拒绝是刻意设计,无法从插件侧放宽(适配器提供的模型行正是让守卫生效的输入——纯文本模型如实上报 `inputModalities: ['text']`)。本 bundle **能**做的是让提示更友好:它的客户端插件会包装 `session.selectModel`,把这条拒绝改写为「当前会话已包含图片,而模型 `<model>` 不支持图片输入;请选择支持图片的模型,或先移除会话中的图片。」(错误码与 details 原样透传,按 `error.code` 分支的调用方不受影响)。要继续使用图片,请选择选择器中带 *`Image`* 标记的模型,或先清空会话中的图片;也可安装图片路由 bundle(如 `@deepseek-ai/dsh-llm-image-routing`)把图片轮透明路由到视觉回退模型。
|
|
162
201
|
- **不支持 `stop` 序列**:线上格式没有 stop 字段;携带它的请求会抛出 `UNSUPPORTED_OPTION`。
|
|
163
202
|
- 推理块**不会**重放到后续轮次(与官方 CLI 一致:先前的私有推理不得泄漏)。
|
|
164
203
|
- 只有带配对工具结果的工具调用会被重放到对话中。
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "@mars-sea/dsh-commandcode-provider",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
//#region src/client/index.ts
|
|
8
|
+
/** Whether a selectModel rejection is the harness's image-session gate. */
|
|
9
|
+
function isImageSessionRejection(result) {
|
|
10
|
+
return !result.result.ok && result.result.error.code === "model-unavailable" && result.result.error.message.includes("does not accept image input");
|
|
11
|
+
}
|
|
12
|
+
/** Wrap the shared sessions API so selectModel failures read friendlier. */
|
|
13
|
+
function withFriendlyImageError(sessions) {
|
|
14
|
+
const selectModel = sessions.selectModel.bind(sessions);
|
|
15
|
+
return {
|
|
16
|
+
...sessions,
|
|
17
|
+
selectModel: async (payload, signal) => {
|
|
18
|
+
const result = await selectModel(payload, signal);
|
|
19
|
+
if (!isImageSessionRejection(result)) return result;
|
|
20
|
+
const model = result.result.error.details?.model ?? payload.model;
|
|
21
|
+
return {
|
|
22
|
+
...result,
|
|
23
|
+
result: {
|
|
24
|
+
...result.result,
|
|
25
|
+
error: {
|
|
26
|
+
...result.result.error,
|
|
27
|
+
message: `当前会话已包含图片,而模型 ${model} 不支持图片输入;请选择支持图片的模型,或先移除会话中的图片。`
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Client plugin body: install the selectModel wrapper on the connection's
|
|
36
|
+
* shared api. `inject: ['connection']` gates activation until the connection
|
|
37
|
+
* service is provided (the same pattern the harness's own client plugins
|
|
38
|
+
* use), and `connection.api.sessions` is a stable object the model-selection
|
|
39
|
+
* UI reads fresh on every call — so wrapping it once covers both the /model
|
|
40
|
+
* popup and the composer seat, across reconnects.
|
|
41
|
+
*/
|
|
42
|
+
function apply(ctx) {
|
|
43
|
+
const connection = ctx.get("connection");
|
|
44
|
+
if (connection === void 0) return;
|
|
45
|
+
connection.api.sessions = withFriendlyImageError(connection.api.sessions);
|
|
46
|
+
}
|
|
47
|
+
const inject = ["connection"];
|
|
48
|
+
//#endregion
|
|
49
|
+
exports.apply = apply;
|
|
50
|
+
exports.inject = inject;
|
|
51
|
+
exports.isImageSessionRejection = isImageSessionRejection;
|
|
52
|
+
exports.withFriendlyImageError = withFriendlyImageError;
|
|
53
|
+
return module.exports;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","names":[],"sources":["../src/client/index.ts"],"sourcesContent":["/**\n * Browser half of the dsh-commandcode-provider bundle.\n *\n * The host rejects switching to a text-only model while the session already\n * contains images with a harness-level `model-unavailable` error\n * (`dsh-host-apiproxy`'s `session.selectModel` handler). That rejection is\n * intentional and cannot be relaxed from the plugin side — the adapter's\n * `inputModalities` is exactly what makes the guard work. What we CAN do is\n * make the error message friendlier: this client plugin wraps the shared\n * `connection.api.sessions.selectModel` face so a `model-unavailable`\n * rejection shows a clear, actionable hint (with the requested model name)\n * instead of the raw English harness message.\n *\n * The wrapper is deliberately narrow: only the `model-unavailable` code is\n * rewritten, only when the message matches the image-session gate, and only\n * the message text changes — the error code and details pass through\n * untouched so any caller that switches on `error.code` keeps working.\n *\n * The wire types are spelled structurally here (not imported from\n * `@deepseek-ai/dsh-host-apiproxy`) so this client bundle does not drag an\n * extra peer dependency into the package; the shapes are stable and the\n * client build inlines them anyway.\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\n\n/** The `model-unavailable` error details: provider + model id. */\ninterface ModelUnavailableDetails {\n provider: string\n model: string\n}\n\n/** The narrow slice of the RPC error we need to inspect and rewrite. */\ninterface RpcErrorLike {\n code: string\n message: string\n details?: ModelUnavailableDetails\n}\n\n/**\n * The narrow slice of a unary RPC result we need to inspect and rewrite.\n * The wire shape from `sessions.selectModel` (via `AbstractApiClient.callUnary`)\n * is the full envelope `{ rpcId, result: { ok, error? } }` — the error lives\n * under `result.result`, not at the top level. `RpcResultLike` models that.\n */\ninterface RpcResultLike {\n rpcId: string\n result:\n | { ok: true; value?: unknown }\n | { ok: false; error: RpcErrorLike }\n}\n\n/** One selectModel call: payload in, envelope out. */\ntype SelectModelCall = (\n payload: { sessionId: string; provider: string; model: string; reasoningEffort?: string },\n signal?: AbortSignal,\n) => Promise<RpcResultLike>\n\n/** The shared sessions wire face we wrap. */\ninterface SessionsLike {\n selectModel: SelectModelCall\n}\n\n/** The connection handle shape we read `api.sessions` from. */\ninterface ConnectionLike {\n api: { sessions: SessionsLike }\n}\n\n/** Whether a selectModel rejection is the harness's image-session gate. */\nexport function isImageSessionRejection(\n result: RpcResultLike,\n): result is RpcResultLike & { result: { ok: false; error: RpcErrorLike } } {\n return (\n !result.result.ok &&\n result.result.error.code === 'model-unavailable' &&\n result.result.error.message.includes('does not accept image input')\n )\n}\n\n/** Wrap the shared sessions API so selectModel failures read friendlier. */\nexport function withFriendlyImageError(sessions: SessionsLike): SessionsLike {\n const selectModel = sessions.selectModel.bind(sessions)\n return {\n ...sessions,\n selectModel: async (payload, signal) => {\n const result = await selectModel(payload, signal)\n if (!isImageSessionRejection(result)) return result\n const model = result.result.error.details?.model ?? payload.model\n return {\n ...result,\n result: {\n ...result.result,\n error: {\n ...result.result.error,\n message:\n `当前会话已包含图片,而模型 ${model} 不支持图片输入;`\n + '请选择支持图片的模型,或先移除会话中的图片。',\n },\n },\n }\n },\n }\n}\n\n/**\n * Client plugin body: install the selectModel wrapper on the connection's\n * shared api. `inject: ['connection']` gates activation until the connection\n * service is provided (the same pattern the harness's own client plugins\n * use), and `connection.api.sessions` is a stable object the model-selection\n * UI reads fresh on every call — so wrapping it once covers both the /model\n * popup and the composer seat, across reconnects.\n */\nexport function apply(ctx: Context): void {\n const connection = ctx.get('connection') as ConnectionLike | undefined\n if (connection === undefined) return\n connection.api.sessions = withFriendlyImageError(connection.api.sessions)\n}\n\nexport const inject: readonly string[] = ['connection']\n"],"mappings":";;;;;;;;EAqEA,SAAgB,wBACd,QAC0E;GAC1E,OACE,CAAC,OAAO,OAAO,MACf,OAAO,OAAO,MAAM,SAAS,uBAC7B,OAAO,OAAO,MAAM,QAAQ,SAAS,6BAA6B;EAEtE;;EAGA,SAAgB,uBAAuB,UAAsC;GAC3E,MAAM,cAAc,SAAS,YAAY,KAAK,QAAQ;GACtD,OAAO;IACL,GAAG;IACH,aAAa,OAAO,SAAS,WAAW;KACtC,MAAM,SAAS,MAAM,YAAY,SAAS,MAAM;KAChD,IAAI,CAAC,wBAAwB,MAAM,GAAG,OAAO;KAC7C,MAAM,QAAQ,OAAO,OAAO,MAAM,SAAS,SAAS,QAAQ;KAC5D,OAAO;MACL,GAAG;MACH,QAAQ;OACN,GAAG,OAAO;OACV,OAAO;QACL,GAAG,OAAO,OAAO;QACjB,SACE,iBAAiB,MAAM;OAE3B;MACF;KACF;IACF;GACF;EACF;;;;;;;;;EAUA,SAAgB,MAAM,KAAoB;GACxC,MAAM,aAAa,IAAI,IAAI,YAAY;GACvC,IAAI,eAAe,KAAA,GAAW;GAC9B,WAAW,IAAI,WAAW,uBAAuB,WAAW,IAAI,QAAQ;EAC1E;EAEA,MAAa,SAA4B,CAAC,YAAY"}
|
package/lib/index.d.ts
CHANGED
|
@@ -2,9 +2,100 @@ 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 { AttachmentStore } from "@deepseek-ai/dsh-attachment";
|
|
5
6
|
import { CommandDefinition } from "@deepseek-ai/dsh-commands";
|
|
6
7
|
//#region src/adapter.d.ts
|
|
7
8
|
declare const KNOWN_EFFORTS: Readonly<Record<string, readonly string[]>>;
|
|
9
|
+
/**
|
|
10
|
+
* Models whose Capabilities include Vision, per the official Command Code
|
|
11
|
+
* model registry (`https://commandcode.ai/docs/reference/cli/models`, generated
|
|
12
|
+
* from the same registry as `cmd --list-models` / the `/model` picker).
|
|
13
|
+
*
|
|
14
|
+
* The Provider API does not expose modality metadata, so this snapshot is the
|
|
15
|
+
* source of truth for image-input gating. Command Code's own CLI falls back to
|
|
16
|
+
* a client-side VISION side-call for text-only models; this adapter does not
|
|
17
|
+
* reproduce that interactive feature, so images sent to a model outside this
|
|
18
|
+
* list are refused loudly (`UNSUPPORTED_CONTENT`) instead of being dropped or
|
|
19
|
+
* sent to a model that cannot read them.
|
|
20
|
+
*
|
|
21
|
+
* Keep in sync with the official registry when new models ship (see the
|
|
22
|
+
* dsh-commandcode-upstream skill).
|
|
23
|
+
*/
|
|
24
|
+
declare const KNOWN_IMAGE_MODELS: ReadonlySet<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Models whose official registry entry lists the `Reasoning` capability but
|
|
27
|
+
* for which the official CLI defines no selectable `reasoning_effort` levels
|
|
28
|
+
* (they are absent from the CLI's model-table efforts; see the authoritative
|
|
29
|
+
* `ZA` table in command-code@1.26.0). The model still thinks — Command Code
|
|
30
|
+
* drives its reasoning depth automatically — so the picker labels them
|
|
31
|
+
* "Supports thinking (auto)" instead of the misleading "Text only", while
|
|
32
|
+
* `KNOWN_EFFORTS` (which mirrors the CLI's effort map exactly) stays the sole
|
|
33
|
+
* source for selectable effort levels.
|
|
34
|
+
*
|
|
35
|
+
* Source: https://commandcode.ai/docs/reference/cli/models (Reasoning flag) and
|
|
36
|
+
* the command-code@1.26.0 bundled model table. Keep in sync via the
|
|
37
|
+
* dsh-commandcode-upstream skill.
|
|
38
|
+
*/
|
|
39
|
+
declare const KNOWN_THINKING_MODELS: ReadonlySet<string>;
|
|
40
|
+
/**
|
|
41
|
+
* The minimum subscription plan a model is included in, per the official plan
|
|
42
|
+
* pages (`/docs/plans/go`, `/docs/plans/goat`, `/docs/plans/pro`, `/docs/plans/max`
|
|
43
|
+
* and `/docs/resources/pricing-limits`). Each plan's model list is a superset of
|
|
44
|
+
* the one below it: Go ⊂ GOAT ⊂ Pro ⊂ Provider/Max. Models absent from every
|
|
45
|
+
* plan list (Claude Opus/Fable, Fugu Ultra) are Provider-tier.
|
|
46
|
+
*
|
|
47
|
+
* The Provider API exposes no plan metadata, so this snapshot is the source of
|
|
48
|
+
* truth for the picker's plan annotation — it answers "which plan do I need to
|
|
49
|
+
* actually use this model?" at a glance. Plan labels use the official tier
|
|
50
|
+
* names (`Go`, `GOAT`, `Pro`, `Provider`), with `Max` implying Provider.
|
|
51
|
+
*
|
|
52
|
+
* Keep in sync with the official plan pages when they change (see the
|
|
53
|
+
* dsh-commandcode-upstream skill).
|
|
54
|
+
*/
|
|
55
|
+
declare const KNOWN_PLANS: Readonly<Record<string, string>>;
|
|
56
|
+
/** Official display labels for each plan tier. */
|
|
57
|
+
declare const PLAN_LABELS: Readonly<Record<string, string>>;
|
|
58
|
+
/**
|
|
59
|
+
* Plan-tier sort weights, low to high. Models outside the snapshot (unknown
|
|
60
|
+
* plans) sort after every known tier, keeping known models predictable.
|
|
61
|
+
*/
|
|
62
|
+
declare const PLAN_ORDER: Readonly<Record<string, number>>;
|
|
63
|
+
/**
|
|
64
|
+
* Comparator for the model picker: sort by plan tier (lowest first), then by
|
|
65
|
+
* model name, then by id as a tiebreak. Models with no known plan sort last.
|
|
66
|
+
*/
|
|
67
|
+
declare function compareByPlan(a: {
|
|
68
|
+
id: string;
|
|
69
|
+
name: string;
|
|
70
|
+
}, b: {
|
|
71
|
+
id: string;
|
|
72
|
+
name: string;
|
|
73
|
+
}): number;
|
|
74
|
+
/**
|
|
75
|
+
* Active pricing deals per the official pricing page
|
|
76
|
+
* (`/docs/resources/pricing-limits#deals`). Each entry records the model's
|
|
77
|
+
* promotional label and — critically — when it expires, so the picker never
|
|
78
|
+
* shows a stale discount after the plugin's snapshot has gone out of date.
|
|
79
|
+
*
|
|
80
|
+
* - `expiresAt` is an ISO timestamp. When it is in the past (checked at
|
|
81
|
+
* render time against `Date.now()`), the deal label is hidden until the
|
|
82
|
+
* snapshot is refreshed from the official page. `undefined` means
|
|
83
|
+
* "no expiry" (permanent).
|
|
84
|
+
* - `free` marks models whose requests cost no credits (Laguna S 2.1), shown
|
|
85
|
+
* as a `FREE` badge; it degrades to a plain discount once the deal lapses.
|
|
86
|
+
*
|
|
87
|
+
* Keep in sync with the official pricing page when deals change (see the
|
|
88
|
+
* dsh-commandcode-upstream skill).
|
|
89
|
+
*/
|
|
90
|
+
interface KnownDeal {
|
|
91
|
+
/** Promotional label, e.g. "50% off" or "2× usage". */
|
|
92
|
+
label: string;
|
|
93
|
+
/** Deal end date (ISO). `undefined` = permanent / no expiry. */
|
|
94
|
+
expiresAt?: string;
|
|
95
|
+
/** Model is free (requests cost no credits). */
|
|
96
|
+
free?: boolean;
|
|
97
|
+
}
|
|
98
|
+
declare const KNOWN_DEALS: Readonly<Record<string, KnownDeal>>;
|
|
8
99
|
declare const COMMAND_CODE_CLI_VERSION = "1.26.0";
|
|
9
100
|
declare const DEFAULT_API_BASE = "https://api.commandcode.ai";
|
|
10
101
|
declare const DEFAULT_GENERATE_MAX_TOKENS = 64000;
|
|
@@ -13,6 +104,32 @@ declare const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
|
|
|
13
104
|
declare const DEFAULT_REQUEST_TIMEOUT_MS = 60000;
|
|
14
105
|
/** Stream idle timeout: a generation that stalls this long is a dead connection. */
|
|
15
106
|
declare const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 120000;
|
|
107
|
+
/**
|
|
108
|
+
* Official display label for a model's minimum plan, or undefined for models
|
|
109
|
+
* outside the snapshot (e.g. future catalog additions).
|
|
110
|
+
*/
|
|
111
|
+
declare function planLabel(modelId: string): string | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* The active deal label for a model, or undefined when the model has no deal
|
|
114
|
+
* or the deal has expired. Expiry is judged against `now` (defaults to
|
|
115
|
+
* `Date.now()`), so a snapshot that has gone stale stops showing its discount
|
|
116
|
+
* the moment the official end date passes — the user never believes a lapsed
|
|
117
|
+
* deal is still live. Permanent deals (no `expiresAt`) never lapse.
|
|
118
|
+
*/
|
|
119
|
+
declare function dealLabel(modelId: string, now?: number): string | undefined;
|
|
120
|
+
/**
|
|
121
|
+
* Compact human-readable context window, e.g. `1_000_000 -> "1M"`,
|
|
122
|
+
* `256_000 -> "256K"`, `262_144 -> "256K"` (floor to the nearest K).
|
|
123
|
+
* Returns undefined for unknown/absent sizes.
|
|
124
|
+
*/
|
|
125
|
+
declare function formatContext(contextWindow: number | undefined): string | undefined;
|
|
126
|
+
/**
|
|
127
|
+
* Compact one-line summary for the model picker: plan tier, then any active
|
|
128
|
+
* deal (discount or FREE), then `Image` for Vision-capable models, then the
|
|
129
|
+
* context window. Text-only models simply omit the Image marker — "Text only"
|
|
130
|
+
* adds nothing the picker needs to show.
|
|
131
|
+
*/
|
|
132
|
+
declare function capabilityDescription(modelId: string, contextWindow?: number, now?: number): string;
|
|
16
133
|
declare function projectSlugFromPath(pathName: string): string;
|
|
17
134
|
/** Read a usable Command Code credential from the official CLI auth file. */
|
|
18
135
|
declare function resolveAuthFileApiKey(): string | undefined;
|
|
@@ -29,6 +146,12 @@ interface CommandCodeConnectionOptions {
|
|
|
29
146
|
/** Milliseconds a stream may stall before it is treated as a dead connection (default 120s). */
|
|
30
147
|
streamIdleTimeoutMs: number;
|
|
31
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Resolve the durable attachment service, or undefined when the host does not
|
|
151
|
+
* provide one. Called lazily only when a request actually carries images, so a
|
|
152
|
+
* text-only request never depends on the attachment seam.
|
|
153
|
+
*/
|
|
154
|
+
type ResolveAttachments = () => AttachmentStore | undefined;
|
|
32
155
|
/** Everything the adapter needs beyond the request itself. */
|
|
33
156
|
interface CommandCodeAdapterDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {
|
|
34
157
|
/** Resolve the current connection facts (fresh per request, settings-aware). */
|
|
@@ -37,6 +160,8 @@ interface CommandCodeAdapterDeps<C extends CommandCodeConnectionOptions = Comman
|
|
|
37
160
|
resolveApiKey: (connection: C) => Promise<string>;
|
|
38
161
|
/** HTTP transport override (tests); defaults to the global `fetch`. */
|
|
39
162
|
fetchImpl?: typeof fetch;
|
|
163
|
+
/** Resolve the optional durable attachment service for image input (tests); defaults to none. */
|
|
164
|
+
resolveAttachments?: ResolveAttachments;
|
|
40
165
|
}
|
|
41
166
|
/** Account identity from `/alpha/whoami`. */
|
|
42
167
|
interface CommandCodeAccount {
|
|
@@ -88,6 +213,7 @@ declare class CommandCodeAdapter<C extends CommandCodeConnectionOptions = Comman
|
|
|
88
213
|
private readonly deps;
|
|
89
214
|
private catalog;
|
|
90
215
|
private readonly fetchImpl;
|
|
216
|
+
private readonly resolveAttachments;
|
|
91
217
|
constructor(deps: CommandCodeAdapterDeps<C>);
|
|
92
218
|
/**
|
|
93
219
|
* Command Code is a metered subscription API: 429 (rate limit) and 5xx
|
|
@@ -168,5 +294,5 @@ interface ResolvedCommandCodeOptions extends CommandCodeConnectionOptions {
|
|
|
168
294
|
declare function resolveAdapterOptions(config: Config): ResolvedCommandCodeOptions;
|
|
169
295
|
declare function apply(ctx: Context, config: Config): void;
|
|
170
296
|
//#endregion
|
|
171
|
-
export { COMMAND_CODE_CLI_VERSION, CommandCodeAdapter, type CommandCodeAdapterDeps, type CommandCodeCommandDeps, type CommandCodeConnectionOptions, type CommandCodeUsageReport, Config, DEFAULT_API_BASE, DEFAULT_GENERATE_MAX_TOKENS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MODELS_CACHE_PATH, DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, KNOWN_EFFORTS, PROVIDER, ResolvedCommandCodeOptions, apply, applyCommands, commandDefinition, inject, name, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey };
|
|
297
|
+
export { COMMAND_CODE_CLI_VERSION, CommandCodeAdapter, type CommandCodeAdapterDeps, type CommandCodeCommandDeps, type CommandCodeConnectionOptions, type CommandCodeUsageReport, Config, DEFAULT_API_BASE, DEFAULT_GENERATE_MAX_TOKENS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MODELS_CACHE_PATH, DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, KNOWN_DEALS, KNOWN_EFFORTS, KNOWN_IMAGE_MODELS, KNOWN_PLANS, KNOWN_THINKING_MODELS, PLAN_LABELS, PLAN_ORDER, PROVIDER, type ResolveAttachments, ResolvedCommandCodeOptions, apply, applyCommands, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, name, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey };
|
|
172
298
|
//# sourceMappingURL=index.d.ts.map
|