@mars-sea/dsh-commandcode-provider 0.16.1 → 0.16.3

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,23 @@ 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.16.3] - 2026-10-31
8
+
9
+ ### Changed
10
+
11
+ - **同步 Command Code CLI `1.88.1` → `1.88.2`(纯请求头同步)。** npm `latest` 于 `2026-10-29T02:05Z` 前进到 `1.88.2`。CLI 的变更日志在 npm 包内 `CHANGELOG.md`(官网 `/changelog` 只覆盖 Desktop 应用),该版本只有一条 patch:「修复全新安装或更新后启动崩溃」。产物级比对:包内 80 个文件只有 `CHANGELOG.md`、`dist/cli.mjs`、`package.json`(仅版本号)与 VSIX 变化,依赖零变化;请求路径(193)、自定义请求头(13)、环境变量(48)集合相同,`/alpha/generate` 调用点在屏蔽混淆标识符后相似度 1.0,`promptCache`(5)/`reasoning_effort`(7)/`max_tokens`(12)/`cache_control`(1)计数相同,审计 `cliDiff`(模型、档位、订阅、ZDR 例外集)为空。服务端目录未动(`?view=client` 的 `catalogVersion` 仍 `7f405e24…`,默认 94、client 106 行),所有能力快照零变化,`COMMAND_CODE_CLI_VERSION` 只随请求头更新,运行时行为不变。
12
+ - **同步定价页两条模型额度(`planAllowanceUsd`)。** 官网把 DeepSeek V4.1 Flash 与 GLM-5.3 Flash 的加成月度额度从 GOAT `$80`/Pro `$90` 上调到 GOAT `$100`/Pro `$110`(Go `$10` 不变),per-token 价格、Peak 时段与套餐可用性均未变;设置页「模型额度」随之显示新值。价格表由 `node scripts/sync-model-prices.mjs` 重新生成,全表只有这两行变化。GLM-5.3 Flash 仍标注 `while capacity lasts`;V4.1 Flash 的文案从「with no end date」改为「comes with bigger monthly credits」,官方未给结束时间,若之后回调按同一脚本再同步。**验证**:`typecheck` 退出码 0,`npm test` 1142/1142,`build` 两段 `Build complete`;未做真实账号登录与付费生成验证。
13
+
14
+ ### Fixed
15
+
16
+ - **探活丢路径前缀、断连与保存失败提示不可诊断(#111、#110)。** 探活原先用 `new URL('/', apiBase)` 探 API base 根,会丢掉带路径前缀的反向代理前缀(如 `http://127.0.0.1:18797/bili/https://api.commandcode.ai`),状态行必然误报「本机无法连接」;现在改探真实端点 `${apiBase}/alpha/whoami` 并用与真实请求相同的字符串拼接保留前缀,未认证的 401/403 计为「可达」(探活刻意不带凭据),404/429/5xx 仍判异常,超时与传输失败继续分开。用量报告的每条端点失败在原文后追加中文原因与目标 `scheme://host:port`(映射 fetch `error.cause` 的 `ECONNREFUSED`/`ENOTFOUND`/连接超时等,原始错误码入括号),反代换端口、代理未启动与 API 故障因此可区分。设置保存的「配置提交未获确认」不再固定说「密钥未写入」:只有本次提交带密钥时才提密钥,否则只报配置未写入;宿主拒绝的原文(如 profile 写锁超时)以「宿主返回:…」附在提示后,折叠为一行并限长 240 字符。**验证**:`typecheck` 退出码 0,`npm test` 1153/1153,`build` 两段 `Build complete`;另在隔离 `DSH_HOME` + 真实宿主(`dsh 0.2.2-alpha.2`)+ 带路径前缀反代 + 无头 Chrome 下端到端复现:反代在线时状态行「本机 连通正常 · 781 ms」(旧探测目标反代根 `/` 返回 404),停反代后「本机无法连接」且失败详情带目标与 `ECONNREFUSED`,写锁超时保存提示带宿主原文;再用真实密钥复验:只读接口全部 200、状态行「连通正常」、真实生成 `POST /alpha/generate` 返回 200(会话费用 `≈$0.0015` 与上游扣减 `0.001471284` 一致);最后复验浏览器登录链路:隔离宿主用凭据库中不存在的引用起步(界面「未配置」),点「网页登录」后按 Studio 回调契约提交真实密钥,回调 `200 {"success":true}`、校验请求经反代 `/alpha/whoami` 200、凭据落库且界面转为「已登录为 mars-sea」。Studio 页面本身的账号登录与 Cloudflare 挑战需真人完成,不在自动验证范围内。
17
+
18
+ ## [0.16.2] - 2026-10-30
19
+
20
+ ### Changed
21
+
22
+ - **补入 DSH `0.2.1-rc.5` 兼容记录(无代码改动)。** npm `latest` 与 `next` 从 `0.2.1-rc.4` 前进到 `0.2.1-rc.5`,发布说明只有一条社区改进「优化对话中思考内容的展示」。源码 delta 采集到 368 个变更路径、349 份包清单(错误为空):包清单只有版本号变化,依赖与 peer 区间零变化;19 个非清单文件集中在推理展示——`client/ui-chat` 新增 `reasoning-text.ts` 并给 `conversation.chat.reasoning.body` 的 owner props 加上 `rawText`、`text` 改为显示文本,`experimental/client-ui-cot-translation` 跟随适配,其余是 slot 目录与测试/文档。**破坏面只在该推理插槽,插件不使用它**;插件导入的 16 个宿主包仅版本号变化,`ui-primitives` 的 `Switch` 未变。`dsh.compatibility.dshReleases` 补入 `0.2.1-rc.5`,引擎矩阵 5/5 通过;准入区间不变,用户升级到 rc.5 无需更新插件。
23
+
7
24
  ## [0.16.1] - 2026-10-30
8
25
 
9
26
  ### Changed
package/README.md CHANGED
@@ -18,8 +18,8 @@ Unofficial [DeepSeek Harness](https://deepseek-harness.github.io/deepseek-harnes
18
18
 
19
19
  | | |
20
20
  |---|---|
21
- | Verified engines | dsh `0.2.1-rc.2`, `0.2.1-rc.3`, `0.2.1-rc.4`, `0.2.2-alpha.2` |
22
- | Node.js | **`>=24.9`** — raised from 22 in this release, see [Node.js 24.9 or newer](#nodejs-249-or-newer-is-required) |
21
+ | Verified engines | dsh `0.2.1-rc.2`, `0.2.1-rc.3`, `0.2.1-rc.4`, `0.2.1-rc.5`, `0.2.2-alpha.2` |
22
+ | Node.js | **`>=24.9`** — raised from 22 in 0.16.0, see [Node.js 24.9 or newer](#nodejs-249-or-newer-is-required) |
23
23
  | Install — web | `dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@latest` |
24
24
  | Install — terminal | `dsh plugin --profile dsh-tui add @mars-sea/dsh-commandcode-provider@latest` |
25
25
  | Config file | `$DSH_HOME/settings.yaml` → `llm-commandcode:` |
@@ -62,11 +62,11 @@ Unofficial [DeepSeek Harness](https://deepseek-harness.github.io/deepseek-harnes
62
62
  dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@latest
63
63
  ```
64
64
 
65
- This build admits **dsh `>=0.2.1-rc.2 <0.2.2-0`** — every RC of the `0.2.1` channel from `0.2.1-rc.2` onward — **and `>=0.2.2-alpha.2 <0.2.3-0`**, the `0.2.2` channel from its current alpha. `0.2.1-rc.2` is what npm `latest` runs, `0.2.1-rc.4` ships on `next`, and `0.2.2-alpha.2` is on `alpha`. All four are covered by the full engine matrix (`npm run test:engine`, `npm run test:install`). A later release of either channel is admitted without a plugin update, but stays unverified until a record is added to `dsh.compatibility.dshReleases`. `0.2.3` and later are deliberately excluded — the upper bounds are written `<0.2.2-0` / `<0.2.3-0` for exactly that reason. A profile on `0.2.0-rc.2`, `0.2.1-alpha.5` or older must upgrade its engine first. Compatibility details — the `engines.dsh` admission rule, package pairings, evidence — live in [engine compatibility](docs/agent-reference/engine-compatibility.md).
65
+ This build admits **dsh `>=0.2.1-rc.2 <0.2.2-0`** — every RC of the `0.2.1` channel from `0.2.1-rc.2` onward — **and `>=0.2.2-alpha.2 <0.2.3-0`**, the `0.2.2` channel from its current alpha. `0.2.1-rc.5` is what npm `latest` and `next` run, and `0.2.2-alpha.2` is on `alpha`. All five are covered by the full engine matrix (`npm run test:engine`, `npm run test:install`). A later release of either channel is admitted without a plugin update, but stays unverified until a record is added to `dsh.compatibility.dshReleases`. `0.2.3` and later are deliberately excluded — the upper bounds are written `<0.2.2-0` / `<0.2.3-0` for exactly that reason. A profile on `0.2.0-rc.2`, `0.2.1-alpha.5` or older must upgrade its engine first. Compatibility details — the `engines.dsh` admission rule, package pairings, evidence — live in [engine compatibility](docs/agent-reference/engine-compatibility.md).
66
66
 
67
67
  ### Node.js 24.9 or newer is required
68
68
 
69
- **This release raises the Node.js floor from 22 to 24.9. On Node 22 or 23, upgrade Node before updating this plugin.**
69
+ **The Node.js floor was raised from 22 to 24.9 in 0.16.0. On Node 22 or 23, upgrade Node before updating this plugin.**
70
70
 
71
71
  dsh `0.2.2-alpha.2` declares `engines.node >=24.9.0` and this plugin admits that engine, so the package-wide floor had to follow: a plugin that claims to support an engine must not be installable on a Node version that engine cannot start on. What that means in practice:
72
72
 
package/README.zh-CN.md CHANGED
@@ -18,8 +18,8 @@
18
18
 
19
19
  | | |
20
20
  |---|---|
21
- | 已验证引擎 | dsh `0.2.1-rc.2`、`0.2.1-rc.3`、`0.2.1-rc.4`、`0.2.2-alpha.2` |
22
- | Node.js | **`>=24.9`** —— 本版从 22 提高,见[需要 Node.js 24.9 或更高版本](#需要-nodejs-249-或更高版本) |
21
+ | 已验证引擎 | dsh `0.2.1-rc.2`、`0.2.1-rc.3`、`0.2.1-rc.4`、`0.2.1-rc.5`、`0.2.2-alpha.2` |
22
+ | Node.js | **`>=24.9`** —— 0.16.0 起从 22 提高,见[需要 Node.js 24.9 或更高版本](#需要-nodejs-249-或更高版本) |
23
23
  | 安装 —— 网页端 | `dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@latest` |
24
24
  | 安装 —— 终端端 | `dsh plugin --profile dsh-tui add @mars-sea/dsh-commandcode-provider@latest` |
25
25
  | 配置文件 | `$DSH_HOME/settings.yaml` → `llm-commandcode:` |
@@ -62,11 +62,11 @@
62
62
  dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@latest
63
63
  ```
64
64
 
65
- 本构建准入 **dsh `>=0.2.1-rc.2 <0.2.2-0`** —— `0.2.1` 通道中 `0.2.1-rc.2` 及以后的每个 RC —— **以及 `>=0.2.2-alpha.2 <0.2.3-0`**,即 `0.2.2` 通道从当前 alpha 起的每个版本。`0.2.1-rc.2` 是 npm `latest` 指向的版本,`0.2.1-rc.4` 挂在 `next`,`0.2.2-alpha.2` 挂在 `alpha`;这四个版本都跑过完整引擎矩阵(`npm run test:engine`、`npm run test:install`)。两个通道中更晚的版本无需更新插件即可准入,但在 `dsh.compatibility.dshReleases` 补上记录之前不算已验证。`0.2.3` 及以后被刻意排除 —— 两个区间上界分别写成 `<0.2.2-0` 与 `<0.2.3-0` 正是为了这一点。使用 `0.2.0-rc.2`、`0.2.1-alpha.5` 或更早版本的配置需先升级引擎,再安装本构建。兼容性细节 —— `engines.dsh` 准入规则、按引擎配对的包版本、验证证据 —— 见[引擎兼容](docs/agent-reference/engine-compatibility.md)。
65
+ 本构建准入 **dsh `>=0.2.1-rc.2 <0.2.2-0`** —— `0.2.1` 通道中 `0.2.1-rc.2` 及以后的每个 RC —— **以及 `>=0.2.2-alpha.2 <0.2.3-0`**,即 `0.2.2` 通道从当前 alpha 起的每个版本。`0.2.1-rc.5` 是 npm `latest` 与 `next` 指向的版本,`0.2.2-alpha.2` 挂在 `alpha`;这五个版本都跑过完整引擎矩阵(`npm run test:engine`、`npm run test:install`)。两个通道中更晚的版本无需更新插件即可准入,但在 `dsh.compatibility.dshReleases` 补上记录之前不算已验证。`0.2.3` 及以后被刻意排除 —— 两个区间上界分别写成 `<0.2.2-0` 与 `<0.2.3-0` 正是为了这一点。使用 `0.2.0-rc.2`、`0.2.1-alpha.5` 或更早版本的配置需先升级引擎,再安装本构建。兼容性细节 —— `engines.dsh` 准入规则、按引擎配对的包版本、验证证据 —— 见[引擎兼容](docs/agent-reference/engine-compatibility.md)。
66
66
 
67
67
  ### 需要 Node.js 24.9 或更高版本
68
68
 
69
- **本版把 Node.js 下界从 22 提到 24.9。如果你在用 Node 22 或 23,请先升级 Node,再更新本插件。**
69
+ **Node.js 下界已在 0.16.0 从 22 提到 24.9。如果你在用 Node 22 或 23,请先升级 Node,再更新本插件。**
70
70
 
71
71
  dsh `0.2.2-alpha.2` 自己声明 `engines.node >=24.9.0`,而本插件准入这个引擎,所以整包的 Node 下界必须跟着抬到同一水位:一个声称支持某引擎的插件,不该能被装到一个那个引擎根本起不来的 Node 上。实际影响:
72
72
 
package/lib/client.js CHANGED
@@ -76,6 +76,13 @@ window.__ModuleLoader__.load({
76
76
  }
77
77
  //#endregion
78
78
  //#region src/client/settings-scope.ts
79
+ /** 组装报告;没有原文时不带 `message` 键(`exactOptionalPropertyTypes`)。 */
80
+ function mutationReport(result, message) {
81
+ return message === void 0 ? { result } : {
82
+ result,
83
+ message
84
+ };
85
+ }
79
86
  /**
80
87
  * Backoff before re-reading a directory whose FIRST read failed, in millis.
81
88
  *
@@ -328,19 +335,20 @@ window.__ModuleLoader__.load({
328
335
  const response = await this.mutateRemote(ownedOps, revision);
329
336
  if (!response.ok) {
330
337
  await this.recover(generation);
331
- return response.error?.message?.includes("SETTINGS_CONFLICT") ? "conflict" : "failed";
338
+ const message = response.error?.message;
339
+ return message?.includes("SETTINGS_CONFLICT") ? mutationReport("conflict", message) : mutationReport("failed", message);
332
340
  }
333
341
  const row = response.value;
334
342
  if (row?.ns !== this.namespace || decodeRow(row.value) === void 0 || typeof row.revision !== "number") {
335
343
  await this.recover(generation);
336
- return "failed";
344
+ return mutationReport("failed");
337
345
  }
338
- if (this.disposed) return "accepted";
346
+ if (this.disposed) return mutationReport("accepted");
339
347
  if (generation === this.writeGeneration) {
340
348
  this.pendingRevision = void 0;
341
349
  this.mirror.acceptView(row);
342
350
  } else this.pendingRevision = typeof row.revision === "number" ? row.revision : void 0;
343
- return "accepted";
351
+ return mutationReport("accepted");
344
352
  });
345
353
  }
346
354
  async mutateRemote(ops, revision) {
@@ -406,9 +414,9 @@ window.__ModuleLoader__.load({
406
414
  }
407
415
  /** Queue operations one at a time; disposal makes the queue inert. */
408
416
  enqueue(operation) {
409
- if (this.disposed) return Promise.resolve("cancelled");
417
+ if (this.disposed) return Promise.resolve(mutationReport("cancelled"));
410
418
  const task = this.tail.then(async () => {
411
- if (this.disposed) return "cancelled";
419
+ if (this.disposed) return mutationReport("cancelled");
412
420
  return operation();
413
421
  });
414
422
  this.tail = task.then(() => {}, () => {});
@@ -780,22 +788,26 @@ window.__ModuleLoader__.load({
780
788
  return success;
781
789
  }
782
790
  async commit(ops, baseline) {
783
- if (this.closed) return "cancelled";
791
+ if (this.closed) return { result: "cancelled" };
784
792
  const snapshot = this.scope.getSnapshot();
785
- if (!snapshot.writable || this.scope.mutate === void 0) return "failed";
786
- if (baseline && [...baseline].some(([field, before]) => !sameValue(before, fieldBaseline(snapshot, field)))) return "conflict";
793
+ if (!snapshot.writable || this.scope.mutate === void 0) return { result: "failed" };
794
+ if (baseline && [...baseline].some(([field, before]) => !sameValue(before, fieldBaseline(snapshot, field)))) return { result: "conflict" };
787
795
  try {
788
796
  return await this.scope.mutate(ops, snapshot.revision);
789
- } catch {
790
- return "failed";
797
+ } catch (error) {
798
+ return {
799
+ result: "failed",
800
+ message: readableErrorText(error)
801
+ };
791
802
  }
792
803
  }
793
804
  async configure(outcome, ops, baseline) {
794
805
  if (ops.length === 0) return true;
795
806
  const confirmation = await this.commit(ops, baseline);
796
- outcome.config = confirmation === "accepted" ? "confirmed" : confirmation === "conflict" ? "conflict" : "unconfirmed";
797
- if (confirmation === "cancelled" || this.closed) outcome.issue = "closed";
798
- return confirmation === "accepted" && !this.closed;
807
+ outcome.config = confirmation.result === "accepted" ? "confirmed" : confirmation.result === "conflict" ? "conflict" : "unconfirmed";
808
+ if (confirmation.result === "failed" && confirmation.message !== void 0) outcome.hostError = confirmation.message;
809
+ if (confirmation.result === "cancelled" || this.closed) outcome.issue = "closed";
810
+ return confirmation.result === "accepted" && !this.closed;
799
811
  }
800
812
  async changeCredential(outcome, ref, value, defaultRef) {
801
813
  outcome.credential = "not-issued";
@@ -963,9 +975,15 @@ window.__ModuleLoader__.load({
963
975
  path: ["credentialCleanupRefs"],
964
976
  value: this.cleanupRefs().filter((entry) => entry !== ref)
965
977
  }])) {
966
- if (outcome.config === "none") outcome.config = cleanup.config;
978
+ if (outcome.config === "none") {
979
+ outcome.config = cleanup.config;
980
+ if (cleanup.hostError !== void 0) outcome.hostError = cleanup.hostError;
981
+ }
967
982
  outcome.issue = cleanup.issue ?? "cleanup-pending";
968
- } else if (outcome.config === "none") outcome.config = cleanup.config;
983
+ } else if (outcome.config === "none") {
984
+ outcome.config = cleanup.config;
985
+ if (cleanup.hostError !== void 0) outcome.hostError = cleanup.hostError;
986
+ }
969
987
  }
970
988
  };
971
989
  //#endregion
@@ -3243,7 +3261,9 @@ window.__ModuleLoader__.load({
3243
3261
  saved: "设置已保存",
3244
3262
  saveFailed: "保存失败,请重试。",
3245
3263
  writeConflict: "待提交字段已被其他操作修改,配置未写入;请核对后再保存。",
3246
- writeConfigUnconfirmed: "配置提交未获确认;密钥未写入,请核对宿主状态后重试。",
3264
+ writeConfigUnconfirmed: "配置提交未获确认,未写入宿主;请核对后重试。",
3265
+ writeConfigUnconfirmedKey: "配置与密钥均未写入宿主;请核对后重试。",
3266
+ writeHostError: "宿主返回:{message}",
3247
3267
  writeConfigSaved: "配置已保存。",
3248
3268
  writeKeyNotIssued: "密钥操作尚未发出;请核对后重试。",
3249
3269
  writeKeyUnconfirmed: "密钥操作未获确认;请核对后手动重试。",
@@ -3514,7 +3534,9 @@ window.__ModuleLoader__.load({
3514
3534
  saved: "Settings saved",
3515
3535
  saveFailed: "Save failed, please retry.",
3516
3536
  writeConflict: "Pending fields were modified by another operation; the configuration was not written. Please review and save again.",
3517
- writeConfigUnconfirmed: "The configuration submission was not confirmed; the key was not written. Please check the host state and retry.",
3537
+ writeConfigUnconfirmed: "The configuration submission was not confirmed and was not written. Please review and retry.",
3538
+ writeConfigUnconfirmedKey: "Neither the configuration nor the key was written. Please review and retry.",
3539
+ writeHostError: "Host returned: {message}",
3518
3540
  writeConfigSaved: "Configuration saved.",
3519
3541
  writeKeyNotIssued: "The key operation has not been issued; please review and retry.",
3520
3542
  writeKeyUnconfirmed: "The key operation was not confirmed; please review and retry manually.",
@@ -3699,7 +3721,7 @@ window.__ModuleLoader__.load({
3699
3721
  else if (result.issue === "target-changed") key = result.credential === "not-issued" ? "writeTargetBefore" : "writeTargetAfter";
3700
3722
  else if (result.issue === "cleanup-pending") key = "writeCleanupPending";
3701
3723
  else if (result.config === "conflict") key = "writeConflict";
3702
- else if (result.config === "unconfirmed") key = "writeConfigUnconfirmed";
3724
+ else if (result.config === "unconfirmed") key = result.credential === "not-issued" ? "writeConfigUnconfirmedKey" : "writeConfigUnconfirmed";
3703
3725
  else if (result.credential === "unconfirmed") key = "writeKeyUnconfirmed";
3704
3726
  else if (result.credential === "not-issued") key = "writeKeyNotIssued";
3705
3727
  const messages = key ? [t(key)] : [];
@@ -3709,8 +3731,18 @@ window.__ModuleLoader__.load({
3709
3731
  }
3710
3732
  if (key && result.config === "confirmed" && result.issue !== "cleanup-pending") messages.unshift(t("writeConfigSaved"));
3711
3733
  if (result.refreshFailed) messages.push(t("writeRefreshFailed"));
3734
+ const hostError = result.hostError;
3735
+ if (hostError !== void 0 && hostError.trim() !== "") messages.push(t("writeHostError").replace("{message}", () => hostErrorText(hostError)));
3712
3736
  return messages.join(" ");
3713
3737
  }
3738
+ /**
3739
+ * 宿主原文压成一行并限长:锁超时、写权限这类诊断足够;换行会撑高提示区,
3740
+ * 超长正文(整页 HTML、大对象)也不该被原样铺到设置页上。
3741
+ */
3742
+ function hostErrorText(message) {
3743
+ const oneLine = message.replace(/\s+/g, " ").trim();
3744
+ return oneLine.length > 240 ? `${oneLine.slice(0, 240)}…` : oneLine;
3745
+ }
3714
3746
  //#endregion
3715
3747
  //#region src/plan-tiers.ts
3716
3748
  /** Shared plan-tier presentation facts; safe to inline into the browser bundle. */
@@ -3864,7 +3896,7 @@ window.__ModuleLoader__.load({
3864
3896
  }
3865
3897
  //#endregion
3866
3898
  //#region package.json
3867
- var version = "0.16.1";
3899
+ var version = "0.16.3";
3868
3900
  var repository = {
3869
3901
  "type": "git",
3870
3902
  "url": "git+https://github.com/Mars-Sea/dsh-commandcode-provider.git"
package/lib/index.d.ts CHANGED
@@ -61,7 +61,7 @@ type CommandCodeProtocol = 'cli' | 'openai' | 'messages';
61
61
  declare const DEFAULT_MAX_OUTPUT_TOKENS = 131072;
62
62
  //#endregion
63
63
  //#region src/adapter.d.ts
64
- declare const COMMAND_CODE_CLI_VERSION = "1.88.1";
64
+ declare const COMMAND_CODE_CLI_VERSION = "1.88.2";
65
65
  declare const DEFAULT_API_BASE = "https://api.commandcode.ai";
66
66
  /**
67
67
  * The output budget this bundle asks for, and the ceiling it will never exceed.
@@ -1232,7 +1232,7 @@ declare const KNOWN_THINKING_MODELS: ReadonlySet<string>;
1232
1232
  * `/docs/plans/max` and `/docs/resources/pricing-limits`). Each plan's model
1233
1233
  * list is a superset of the one below it: Go ⊂ GOAT ⊂ Pro ⊂ Provider/Max.
1234
1234
  * Models absent from every plan list (Claude Opus/Fable, Fugu Ultra) are
1235
- * Provider-tier. Re-verified at command-code@1.88.1 (2026-10-28) against the
1235
+ * Provider-tier. Re-verified at command-code@1.88.2 (2026-10-31) against the
1236
1236
  * live `?view=client` catalog: 106 ids, still a strict superset chain. Mistral
1237
1237
  * Large 4 (1.75.0) was the only addition at the 1.77.0 check; the 1.78.0/1.79.0 pair
1238
1238
  * added Claude Haiku 5.5 at Pro and the free Glyph Cluster preview at Go.
package/lib/index.js CHANGED
@@ -123,7 +123,7 @@ const PLAN_ORDER = Object.fromEntries(PLAN_TIER_ORDER.map((tier, index) => [tier
123
123
  * subscription-plan labels, deals, and hourly (peak/off-peak) pricing.
124
124
  *
125
125
  * Everything here is synced from official sources — the command-code CLI
126
- * bundle's model table (`dist/cli.mjs`, re-verified at command-code@1.88.1), the
126
+ * bundle's model table (`dist/cli.mjs`, re-verified at command-code@1.88.2), the
127
127
  * live model catalog (`GET /provider/v1/models?view=client`, the authority for
128
128
  * capability fields since 1.82.4), and the official plan/pricing/model docs; see
129
129
  * the dsh-commandcode-upstream skill for the extraction procedures. The
@@ -145,7 +145,11 @@ const PLAN_ORDER = Object.fromEntries(PLAN_TIER_ORDER.map((tier, index) => [tier
145
145
  * step and `$2/$7.5` beyond. The 2026-10-28 check moves the constant to 1.88.1,
146
146
  * whose registry now names both catalog-only rows (Kimi K3.1 Pro and GPT-6.1
147
147
  * Terra) with efforts and context identical to this snapshot, so no table
148
- * changes. Keeping the snapshot in its own module
148
+ * changes. The 2026-10-31 check moves it to 1.88.2 — the npm package's own
149
+ * CHANGELOG names its sole change as a launch-crash fix after a fresh install
150
+ * or update — and again leaves every table here identical; that round's only
151
+ * data change is two per-model allowances in ./model-prices.ts. Keeping the
152
+ * snapshot in its own module
149
153
  * confines those frequent sync diffs here: src/adapter.ts holds only the stable
150
154
  * wire/runtime logic. The read helpers live here too, for the same reason.
151
155
  *
@@ -948,7 +952,7 @@ const MODEL_OUTPUT_TOKEN_LIMITS = /* @__PURE__ */ new Map([
948
952
  * `/docs/plans/max` and `/docs/resources/pricing-limits`). Each plan's model
949
953
  * list is a superset of the one below it: Go ⊂ GOAT ⊂ Pro ⊂ Provider/Max.
950
954
  * Models absent from every plan list (Claude Opus/Fable, Fugu Ultra) are
951
- * Provider-tier. Re-verified at command-code@1.88.1 (2026-10-28) against the
955
+ * Provider-tier. Re-verified at command-code@1.88.2 (2026-10-31) against the
952
956
  * live `?view=client` catalog: 106 ids, still a strict superset chain. Mistral
953
957
  * Large 4 (1.75.0) was the only addition at the 1.77.0 check; the 1.78.0/1.79.0 pair
954
958
  * added Claude Haiku 5.5 at Pro and the free Glyph Cluster preview at Go.
@@ -1651,8 +1655,8 @@ const MODEL_PRICE_ROWS = [
1651
1655
  ],
1652
1656
  allowance: {
1653
1657
  go: 10,
1654
- goat: 80,
1655
- pro: 90
1658
+ goat: 100,
1659
+ pro: 110
1656
1660
  }
1657
1661
  },
1658
1662
  {
@@ -1852,8 +1856,8 @@ const MODEL_PRICE_ROWS = [
1852
1856
  ],
1853
1857
  allowance: {
1854
1858
  go: 10,
1855
- goat: 80,
1856
- pro: 90
1859
+ goat: 100,
1860
+ pro: 110
1857
1861
  }
1858
1862
  },
1859
1863
  {
@@ -3934,6 +3938,76 @@ function readableErrorText(error) {
3934
3938
  }
3935
3939
  return String(error);
3936
3940
  }
3941
+ //#endregion
3942
+ //#region src/transport-failure.ts
3943
+ /**
3944
+ * Transport failure reasons for the usage and settings diagnostics.
3945
+ *
3946
+ * Node's fetch rejects with `TypeError('fetch failed')` and keeps the real
3947
+ * cause one level down (`error.cause`): `ECONNREFUSED` when nothing listens on
3948
+ * the port, `ENOTFOUND` on DNS, a connect timeout behind a dead proxy. That
3949
+ * message alone cannot tell "the reverse proxy changed port" from "the proxy is
3950
+ * not running" from "the API is down", so per-endpoint failure lines and the
3951
+ * settings notice append a short Chinese reason plus the raw code (issue #111).
3952
+ *
3953
+ * Only the code is quoted back, never the system message: those may embed
3954
+ * internal paths, and the original message stays available through
3955
+ * `readableErrorText` for the detail line. An error with no code yields no
3956
+ * reason — the caller still renders what it has instead of an invented guess.
3957
+ *
3958
+ * @module dsh-commandcode-provider/transport-failure
3959
+ */
3960
+ /** 原始错误码 → 界面原因;未列出的码只回显错误码,不做猜测。 */
3961
+ const REASONS$1 = {
3962
+ ECONNREFUSED: "连接被拒绝",
3963
+ ECONNRESET: "连接被重置",
3964
+ ENOTFOUND: "域名解析失败",
3965
+ EAI_AGAIN: "域名解析临时失败",
3966
+ EHOSTUNREACH: "主机不可达",
3967
+ ENETUNREACH: "网络不可达",
3968
+ ETIMEDOUT: "连接超时",
3969
+ UND_ERR_CONNECT_TIMEOUT: "连接超时",
3970
+ UND_ERR_SOCKET: "连接中断",
3971
+ UND_ERR_CLOSED: "连接已关闭",
3972
+ CERT_HAS_EXPIRED: "证书已过期",
3973
+ DEPTH_ZERO_SELF_SIGNED_CERT: "自签名证书不受信任",
3974
+ SELF_SIGNED_CERT_IN_CHAIN: "证书链中有自签名证书",
3975
+ UNABLE_TO_VERIFY_LEAF_SIGNATURE: "无法验证证书"
3976
+ };
3977
+ /** 取错误链上的第一个错误码:先看自身,再看 AggregateError 子项,最后看 cause。 */
3978
+ function codeOf(value, depth = 0) {
3979
+ if (depth > 4 || value === null || typeof value !== "object") return void 0;
3980
+ const entry = value;
3981
+ if (typeof entry.code === "string" && entry.code !== "") return entry.code;
3982
+ if (Array.isArray(entry.errors)) for (const nested of entry.errors) {
3983
+ const code = codeOf(nested, depth + 1);
3984
+ if (code !== void 0) return code;
3985
+ }
3986
+ return codeOf(entry.cause, depth + 1);
3987
+ }
3988
+ /**
3989
+ * One diagnostic clause for a transport failure, or undefined when the error
3990
+ * carries no recognizable code.
3991
+ */
3992
+ function transportFailureReason(error) {
3993
+ const code = codeOf(error);
3994
+ if (code === void 0) return void 0;
3995
+ const reason = REASONS$1[code];
3996
+ return reason === void 0 ? `网络错误(${code})` : `${reason}(${code})`;
3997
+ }
3998
+ /**
3999
+ * `scheme://host:port` of a base, with path and query dropped: enough to name
4000
+ * the endpoint a failed request aimed at without echoing proxy prefixes, and
4001
+ * without any chance of a token riding along in a path.
4002
+ */
4003
+ function httpOrigin(base) {
4004
+ try {
4005
+ const url = new URL(base);
4006
+ return `${url.protocol}//${url.host}`;
4007
+ } catch {
4008
+ return;
4009
+ }
4010
+ }
3937
4011
  const THROTTLED_CODE = "THROTTLED";
3938
4012
  const boundedCodes = /* @__PURE__ */ new Set([
3939
4013
  "EMPTY_RESPONSE",
@@ -6535,7 +6609,7 @@ var GatewayFacts = class {
6535
6609
  * per-request options thunk and an API-key resolver from the plugin entry
6536
6610
  * (src/index.ts), so a settings change reaches the very next request.
6537
6611
  */
6538
- const COMMAND_CODE_CLI_VERSION = "1.88.1";
6612
+ const COMMAND_CODE_CLI_VERSION = "1.88.2";
6539
6613
  const DEFAULT_API_BASE = "https://api.commandcode.ai";
6540
6614
  /**
6541
6615
  * The output budget this bundle asks for, and the ceiling it will never exceed.
@@ -8719,7 +8793,9 @@ var CommandCodeAdapter = class CommandCodeAdapter extends LlmAdapter {
8719
8793
  }
8720
8794
  return record;
8721
8795
  } catch (error) {
8722
- failures.push(`${path}: ${readableErrorText(error)}`);
8796
+ const reason = transportFailureReason(error);
8797
+ const origin = httpOrigin(base);
8798
+ failures.push(`${path}: ${readableErrorText(error)}${reason === void 0 ? "" : `;${reason}`}${origin === void 0 ? "" : `;目标 ${origin}`}`);
8723
8799
  failed.push({ kind: "transport" });
8724
8800
  return;
8725
8801
  }
@@ -9923,13 +9999,18 @@ function applyUsageRemote(ctx, deps) {
9923
9999
  remoteCtx.effect(() => () => void unregister(), "dsh-commandcode-provider: usage remote");
9924
10000
  });
9925
10001
  }
10002
+ /** The endpoint whose answer proves the API's auth layer is reachable. */
10003
+ const PROBE_PATH = "/alpha/whoami";
9926
10004
  /**
9927
- * HTTP statuses Upptime's default monitor accepts as `up` (from
9928
- * `uptime-monitor`'s `expectedStatusCodes` fallback). Kept in sync with the
9929
- * page's monitor rather than invented here: a 401 or 404 means the endpoint
9930
- * answered but is not the surface the official check calls healthy.
10005
+ * HTTP statuses that prove the probed endpoint answered.
10006
+ *
10007
+ * 2xx/3xx are the positive answers. 401/403 belong here because the probe is
10008
+ * deliberately credential-less: the expected answer to an unauthenticated GET
10009
+ * of `/alpha/whoami` IS 401, and treating it as a failure would report every
10010
+ * healthy host as down. Everything else (404 from a wrong base path, 429, 5xx)
10011
+ * means the endpoint the plugin actually uses did not answer as a live API.
9931
10012
  */
9932
- const UP_STATUSES = /* @__PURE__ */ new Set([
10013
+ const REACHABLE_STATUSES = /* @__PURE__ */ new Set([
9933
10014
  200,
9934
10015
  201,
9935
10016
  202,
@@ -9948,25 +10029,27 @@ const UP_STATUSES = /* @__PURE__ */ new Set([
9948
10029
  305,
9949
10030
  306,
9950
10031
  307,
9951
- 308
10032
+ 308,
10033
+ 401,
10034
+ 403
9952
10035
  ]);
9953
10036
  /** Turn the response status into the outcome the row renders. */
9954
10037
  function probeOutcomeForStatus(status) {
9955
- return UP_STATUSES.has(status) ? "ok" : "http-error";
10038
+ return REACHABLE_STATUSES.has(status) ? "ok" : "http-error";
9956
10039
  }
9957
10040
  /**
9958
10041
  * Probe the configured API base once. Never rejects: an invalid base, a
9959
10042
  * timeout and a transport failure all resolve to an outcome.
9960
10043
  *
9961
- * `redirect: 'manual'` keeps the classification on the FIRST response, exactly
9962
- * like the monitor's HTTP client; following a redirect would report the final
9963
- * destination's status as if it were the API's own.
10044
+ * `redirect: 'manual'` keeps the classification on the FIRST response; the
10045
+ * probe reports what this Host reached, not where a redirect chain ends up.
9964
10046
  */
9965
10047
  async function probeCommandCode(options) {
9966
10048
  const now = options.now ?? Date.now;
9967
10049
  let url;
9968
10050
  try {
9969
- url = new URL("/", options.apiBase).toString();
10051
+ if (!URL.canParse(options.apiBase)) throw new TypeError("invalid api base");
10052
+ url = `${options.apiBase}${PROBE_PATH}`;
9970
10053
  } catch {
9971
10054
  return {
9972
10055
  outcome: "unreachable",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mars-sea/dsh-commandcode-provider",
3
- "version": "0.16.1",
3
+ "version": "0.16.3",
4
4
  "description": "Unofficial DeepSeek Harness LLM provider plugin for Command Code, ported from pi-commandcode-provider (MIT). Registers the 'commandcode' provider route with a Models-page card and live model catalog.",
5
5
  "icon": "./icon.svg",
6
6
  "type": "module",
@@ -26,6 +26,7 @@
26
26
  "0.2.1-rc.2": "compatible",
27
27
  "0.2.1-rc.3": "compatible",
28
28
  "0.2.1-rc.4": "compatible",
29
+ "0.2.1-rc.5": "compatible",
29
30
  "0.2.2-alpha.2": "compatible"
30
31
  },
31
32
  "dsh": ">=0.2.1-rc.2 <0.2.2-0 || >=0.2.2-alpha.2 <0.2.3-0"