@mars-sea/dsh-commandcode-provider 0.16.2 → 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 +11 -0
- package/lib/client.js +52 -20
- package/lib/index.d.ts +2 -2
- package/lib/index.js +103 -20
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,17 @@ 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
|
+
|
|
7
18
|
## [0.16.2] - 2026-10-30
|
|
8
19
|
|
|
9
20
|
### Changed
|
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
|
-
|
|
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
|
|
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 === "
|
|
798
|
-
|
|
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")
|
|
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")
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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:
|
|
1655
|
-
pro:
|
|
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:
|
|
1856
|
-
pro:
|
|
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.
|
|
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
|
-
|
|
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
|
|
9928
|
-
*
|
|
9929
|
-
*
|
|
9930
|
-
*
|
|
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
|
|
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
|
|
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
|
|
9962
|
-
*
|
|
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
|
-
|
|
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.
|
|
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",
|