@mars-sea/dsh-commandcode-provider 0.12.9 → 0.12.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +8 -6
- package/README.zh-CN.md +4 -4
- package/lib/client.js +1 -1
- package/lib/index.js +43 -14
- package/lib/index.js.map +1 -1
- package/package.json +39 -38
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,27 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.12.10] - 2026-10-10
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **引擎兼容范围增加 `0.2.1-alpha.2`,业务代码零改动。** 15 个 `@deepseek-ai/dsh-*` peer 的析取由 `0.2.0-rc.2 || 0.2.1-alpha.1` 扩为 `0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2`,`dsh.compatibility.dsh`、`engines.dsh`、`devDependencies`、`package-lock.json` 与 `dsh.compatibility.dshReleases` 同批同步;既有两个分支保留,`@deepseek-ai/cordis`(`~4.0.4 || ~4.0.5-alpha.1`)与 `@deepseek-ai/schemastery`(`~3.18.4 || ~3.18.5-alpha.1`)不用改——alpha.2 与 alpha.1 同批发布的正是这两个版本。逐文件对比 alpha.1 → alpha.2 的公开源码后确认无需改代码:`RequestMessage`/`GenerateOptions`/`ContentBlock`/`LlmError` 结构未变,Agent 事件、设置、凭据、附件与 Typert 严格描述符未变,五个客户端插槽的声明与 Web 预置模块表也未变。
|
|
12
|
+
- alpha.2 有三处宿主内部行为变化,插件按现有接口继续工作,边界已记入参考文档:模型调用准备新增可选回调 `prepareCall(config, signal?, configure?)`(普通适配器不必调用)、请求准备完成后会刷新运行时上下文、代理卸载改为先停流再排空事件。上游 `idleWatchdog` 那处「挂起读取也能按期结束」的修复**不覆盖**插件自己的读流实现,因此本轮按同一目标单独补齐(见下方 Fixed)。
|
|
13
|
+
- `npm run test:install` 改为**逐引擎矩阵**:每个已声明兼容版本各建一个全新的 pnpm 10.34.5 generation,安装时把该版本的必需 Harness peer 一起钉死,再断言锁文件解析出的 `@deepseek-ai/dsh-llm` 恰好是目标版本。此前单次安装只会命中范围里最新的那个分支,全绿并不能证明另外两个引擎装得上。
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **读取卡住的响应不再拖住收束。** 读循环每次读取改用一个「唤醒闸门」:空闲期限到期与调用者取消都先解开闸门,再尽力取消底层读取。此前只有 `reader.cancel()` 能把挂起的 `read()` 唤醒,遇到被包装或被垫片替换、既不结算读取也不响应取消的响应体时,空闲期限、调用者取消和消费方 `return()` 三条路径会一起卡死——期限到了不报错,取消也不返回。现在闸门自己结束等待:调用者取消原样传播(归类 `aborted`),否则以既有 `TIMEOUT` 失败;被放弃的读取结果丢弃,其迟到拒绝就地吞掉(真实读取器在释放锁时会以 `Invalid state: Releasing reader` 拒绝挂起的读取),读取锁仍只释放一次。`tests/adapter.test.ts` 新增三个用例固定这三种收束。
|
|
18
|
+
|
|
19
|
+
### 已知边界
|
|
20
|
+
|
|
21
|
+
- 真实引擎检查通过的是发布入口加载、静态具名导入、客户端 `require()` 种子、易变设置契约与 22 个流终态场景;浏览器实际渲染、真实账号请求、卸载期间最终事件排空与长期运行仍需实际环境验收。
|
|
22
|
+
|
|
23
|
+
### 刻意未采纳
|
|
24
|
+
|
|
25
|
+
- `systemPromptUpdate: 'in-history'`(历史内系统提示替换)与原生工具延迟激活语义:插件继续用前导系统提示与 `addition-only`(仅新增)工具声明,每次请求发送完整活跃工具列表。能力标记与实际 wire 行为必须一致,未实现前不宣告。
|
|
26
|
+
- 新版 `prepareCall` 的可选准备回调:它是给需要注入辅助调用元数据的场景用的,本适配器不使用第三参数即可保持既有行为。
|
|
27
|
+
|
|
7
28
|
## [0.12.9] - 2026-10-09
|
|
8
29
|
|
|
9
30
|
### Changed
|
package/README.md
CHANGED
|
@@ -35,11 +35,13 @@ See [Screenshots](#screenshots) below for what the UI looks like.
|
|
|
35
35
|
|
|
36
36
|
## Install
|
|
37
37
|
|
|
38
|
-
This release supports **dsh 0.2.0-rc.2 and dsh 0.2.1-alpha.
|
|
39
|
-
the plugin's peer range is exactly those
|
|
38
|
+
This release supports **dsh 0.2.0-rc.2, dsh 0.2.1-alpha.1 and dsh 0.2.1-alpha.2, and nothing else** —
|
|
39
|
+
the plugin's peer range is exactly those three verified versions, and its
|
|
40
40
|
compatibility records name them alone. `0.2.0-rc.2` is what
|
|
41
41
|
`npm i -g @deepseek-ai/dsh@latest` and the official desktop build ship, so it is
|
|
42
|
-
the version most users are on; `0.2.1-alpha.
|
|
42
|
+
the version most users are on; `0.2.1-alpha.2` is the upstream `alpha` channel
|
|
43
|
+
today, and `0.2.1-alpha.1` stays in the range because it was already verified, so
|
|
44
|
+
a profile pinned to it keeps working:
|
|
43
45
|
|
|
44
46
|
```sh
|
|
45
47
|
dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@latest
|
|
@@ -66,14 +68,14 @@ dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.11.15
|
|
|
66
68
|
|
|
67
69
|
The same applies to every profile you install into, including the terminal UI below.
|
|
68
70
|
|
|
69
|
-
Fresh pnpm 10 marketplace generations are supported directly. Every Harness package
|
|
71
|
+
Fresh pnpm 10 marketplace generations are supported directly. Every Harness package is declared by the plugin as a Host peer, so the active dsh profile remains their owner; do not add a separate dependency for any of them. The `@deepseek-ai/dsh-*` packages share one exact-version disjunction; `@deepseek-ai/cordis` and `@deepseek-ai/schemastery` carry the paired ranges `~4.0.4 || ~4.0.5-alpha.1` and `~3.18.4 || ~3.18.5-alpha.1` instead, because publishing an engine rewrites both to the version that shipped alongside it. Upstream removed the `@deepseek-ai/dsh-invariants` package in `0.2.1-alpha.1`, so the plugin no longer declares it.
|
|
70
72
|
|
|
71
73
|
## Updating
|
|
72
74
|
|
|
73
75
|
Update with the same tag you installed with:
|
|
74
76
|
|
|
75
77
|
```sh
|
|
76
|
-
dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@latest # dsh 0.2.0-rc.2 or 0.2.1-alpha.
|
|
78
|
+
dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@latest # dsh 0.2.0-rc.2, 0.2.1-alpha.1 or 0.2.1-alpha.2
|
|
77
79
|
dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@0.9.1 # older dsh (0.5.0 line, unmaintained)
|
|
78
80
|
```
|
|
79
81
|
|
|
@@ -147,7 +149,7 @@ cmd login # writes ~/.commandcode/auth.json
|
|
|
147
149
|
cwd: !!js process.cwd()
|
|
148
150
|
```
|
|
149
151
|
|
|
150
|
-
**Engine version.** The plugin is maintained against exactly
|
|
152
|
+
**Engine version.** The plugin is maintained against exactly three engines: **dsh 0.2.0-rc.2**, **dsh 0.2.1-alpha.1** and **dsh 0.2.1-alpha.2**. Its `@deepseek-ai/dsh-*` peers use the disjunction `0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2`, `@deepseek-ai/cordis` is pinned to `~4.0.4 || ~4.0.5-alpha.1` and `@deepseek-ai/schemastery` to `~3.18.4 || ~3.18.5-alpha.1` (each branch shipped with its engine), and `dsh.compatibility.dshReleases` records exactly those three releases. That disjunction is deliberate and load-bearing: unlike a caret or a `>=` range it admits **no** adjacent prerelease, release candidate, or stable patch version, every branch is a bare version, and `npm run test:engine` runs the whole suite against **all three** engines before a release. DSH itself refuses to load a plugin whose `@deepseek-ai/dsh*` peers do not admit the running engine, so a range that silently admitted an unverified neighbour would be worse than no range at all. On any other engine the settings page, the message envelope, or the request-image budget may not line up — install the last release that supported your engine (see [Install](#install)) instead of forcing this one.
|
|
151
153
|
|
|
152
154
|
## Usage dashboard
|
|
153
155
|
|
package/README.zh-CN.md
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
|
|
34
34
|
## 安装
|
|
35
35
|
|
|
36
|
-
本版本**只支持 dsh 0.2.0-rc.2 与 dsh 0.2.1-alpha.
|
|
36
|
+
本版本**只支持 dsh 0.2.0-rc.2、dsh 0.2.1-alpha.1 与 dsh 0.2.1-alpha.2 这三个版本**:插件的 peer 范围就是这三个已验证版本的析取,兼容性记录里也只列它们。`0.2.0-rc.2` 正是 `npm i -g @deepseek-ai/dsh@latest` 与官方桌面端放出的版本,多数用户都在它上面;`0.2.1-alpha.2` 是上游 `alpha` 通道当前提供的版本,`0.2.1-alpha.1` 因为已经验证过而保留在范围内,钉在它上面的 profile 可以继续使用:
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
39
|
dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@latest
|
|
@@ -55,14 +55,14 @@ dsh plugin --profile web add @mars-sea/dsh-commandcode-provider@0.11.15
|
|
|
55
55
|
|
|
56
56
|
这一点对每个 profile 都成立,包括下面的终端界面。
|
|
57
57
|
|
|
58
|
-
插件可直接在 pnpm 10 的全新插件市场 generation 中安装。所有 Harness
|
|
58
|
+
插件可直接在 pnpm 10 的全新插件市场 generation 中安装。所有 Harness 包都由插件声明为 Host peer,由当前 dsh profile 统一管理,不要另行添加 dependency。其中 `@deepseek-ai/dsh-*` 共用同一个精确版本析取;`@deepseek-ai/cordis` 与 `@deepseek-ai/schemastery` 则分别写成配对范围 `~4.0.4 || ~4.0.5-alpha.1` 与 `~3.18.4 || ~3.18.5-alpha.1`——上游每次发引擎都会把这两个包重写成随引擎发布的版本。上游曾在 `0.2.1-alpha.1` 删除 `@deepseek-ai/dsh-invariants` 这个包,因此插件不再声明它。
|
|
59
59
|
|
|
60
60
|
## 更新
|
|
61
61
|
|
|
62
62
|
用与安装时相同的 tag 更新:
|
|
63
63
|
|
|
64
64
|
```sh
|
|
65
|
-
dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@latest # dsh 0.2.0-rc.2 或 0.2.1-alpha.
|
|
65
|
+
dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@latest # dsh 0.2.0-rc.2、0.2.1-alpha.1 或 0.2.1-alpha.2
|
|
66
66
|
dsh plugin --profile web update @mars-sea/dsh-commandcode-provider@0.9.1 # 更早的 dsh(0.5.0 线,不再维护)
|
|
67
67
|
```
|
|
68
68
|
|
|
@@ -136,7 +136,7 @@ cmd login # 写入 ~/.commandcode/auth.json
|
|
|
136
136
|
cwd: !!js process.cwd()
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
-
**引擎版本要求。**
|
|
139
|
+
**引擎版本要求。** 插件针对三个引擎维护:**dsh 0.2.0-rc.2**、**dsh 0.2.1-alpha.1** 与 **dsh 0.2.1-alpha.2**。它的 `@deepseek-ai/dsh-*` 对等依赖写成三者的析取 `0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2`,`@deepseek-ai/cordis` 固定为 `~4.0.4 || ~4.0.5-alpha.1`、`@deepseek-ai/schemastery` 固定为 `~3.18.4 || ~3.18.5-alpha.1`(每个分支都与对应引擎同批发布),`dsh.compatibility.dshReleases` 也只记录这三个版本。这个析取写法是刻意的、且是承重的:它不像 `^` 或 `>=` 那样放行任何相邻的预发布版、候选发布或稳定补丁版,每个分支都是一个裸版本号,且发版前 `npm run test:engine` 会对**三个引擎各跑一遍**完整套件。DSH 本身会拒绝加载 `@deepseek-ai/dsh*` peer 不接纳当前引擎的插件——所以一个静默放行未验证邻居的范围,比没有范围更糟。在其它引擎上,设置页、消息封装或请求图片预算总有一处对不上——请改装支持你所用引擎的最后一个版本,而不是硬装这一个。
|
|
140
140
|
|
|
141
141
|
## 用量面板
|
|
142
142
|
|
package/lib/client.js
CHANGED
|
@@ -3273,7 +3273,7 @@ window.__ModuleLoader__.load({
|
|
|
3273
3273
|
}
|
|
3274
3274
|
//#endregion
|
|
3275
3275
|
//#region package.json
|
|
3276
|
-
var version = "0.12.
|
|
3276
|
+
var version = "0.12.10";
|
|
3277
3277
|
var repository = {
|
|
3278
3278
|
"type": "git",
|
|
3279
3279
|
"url": "git+https://github.com/Mars-Sea/dsh-commandcode-provider.git"
|
package/lib/index.js
CHANGED
|
@@ -3970,6 +3970,11 @@ function openStreamTrace(scope, options = {}) {
|
|
|
3970
3970
|
/** 仅供本次消费生命周期使用,不作为服务商错误或用户取消向外传播。 */
|
|
3971
3971
|
var ConsumerStreamClosed = class extends Error {};
|
|
3972
3972
|
/**
|
|
3973
|
+
* 读循环唤醒闸门的标记值:底层 read() 既不结算、取消也叫不醒时,由闸门结束这次等待。
|
|
3974
|
+
* 它不是错误,只在读循环内部出现,用来把「读取完成」与「读取卡住」区分开。
|
|
3975
|
+
*/
|
|
3976
|
+
const READ_STALLED = Symbol("readStalled");
|
|
3977
|
+
/**
|
|
3973
3978
|
* 异步生成器的 return 会排在正在等待的 next 后面,因此必须先通过独立信号
|
|
3974
3979
|
* 唤醒当前读取,再让生成器执行 finally。消费方已结束时不再交付用量或错误。
|
|
3975
3980
|
*/
|
|
@@ -4031,7 +4036,12 @@ async function* readResponse(response, context) {
|
|
|
4031
4036
|
reader.cancel().catch(() => void 0);
|
|
4032
4037
|
} catch {}
|
|
4033
4038
|
};
|
|
4034
|
-
|
|
4039
|
+
let openGate;
|
|
4040
|
+
const wakeRead = () => openGate?.();
|
|
4041
|
+
const onAbort = () => {
|
|
4042
|
+
wakeRead();
|
|
4043
|
+
cancelReader();
|
|
4044
|
+
};
|
|
4035
4045
|
const decoder = new TextDecoder();
|
|
4036
4046
|
let buffer = "";
|
|
4037
4047
|
const streamStartedAt = Date.now();
|
|
@@ -4044,6 +4054,7 @@ async function* readResponse(response, context) {
|
|
|
4044
4054
|
if (idleTimer !== void 0) clearTimeout(idleTimer);
|
|
4045
4055
|
idleTimer = setTimeout(() => {
|
|
4046
4056
|
idleFired = true;
|
|
4057
|
+
wakeRead();
|
|
4047
4058
|
cancelReader();
|
|
4048
4059
|
}, streamIdleTimeoutMs);
|
|
4049
4060
|
};
|
|
@@ -4053,12 +4064,24 @@ async function* readResponse(response, context) {
|
|
|
4053
4064
|
idleTimer = void 0;
|
|
4054
4065
|
}
|
|
4055
4066
|
};
|
|
4067
|
+
/** 空闲期限结束读循环时的唯一错误文本;读取结算与读取卡住两条路径共用。 */
|
|
4068
|
+
const idleTimeoutError = () => bilingual("TIMEOUT", `Command Code API stream from ${apiBase} was idle for ${streamIdleTimeoutMs}ms (no events) and was treated as a dead connection`, `Command Code API 流式响应已 ${streamIdleTimeoutMs} 毫秒无任何事件,被判定为死连接——长思考模型可在设置中调大流空闲超时`);
|
|
4056
4069
|
const asm = createBlockAssembler();
|
|
4057
4070
|
let finish;
|
|
4058
4071
|
let usage;
|
|
4059
4072
|
let usageEmitted = false;
|
|
4060
4073
|
let endRecorded = false;
|
|
4061
4074
|
let protocolStopped = false;
|
|
4075
|
+
/** 读循环收束(读到 EOF 或读取卡住)共用的诊断事实,两处记录字段保持一致。 */
|
|
4076
|
+
const eofFacts = () => ({
|
|
4077
|
+
chunks: chunkCount,
|
|
4078
|
+
bytes: totalBytes,
|
|
4079
|
+
silentMs: Date.now() - lastChunkAt,
|
|
4080
|
+
totalMs: Date.now() - streamStartedAt,
|
|
4081
|
+
finishSeen: finish !== void 0,
|
|
4082
|
+
idleFired,
|
|
4083
|
+
buffered: buffer.length
|
|
4084
|
+
});
|
|
4062
4085
|
function* handle(event) {
|
|
4063
4086
|
captureResponseIdentifiers(responseMetadata, event);
|
|
4064
4087
|
if (isRecord(event) && (protocol === "messages" && event.type === "message_stop" || protocol === "cli" && event.type === "finish")) protocolStopped = true;
|
|
@@ -4084,9 +4107,14 @@ async function* readResponse(response, context) {
|
|
|
4084
4107
|
for (;;) {
|
|
4085
4108
|
signal?.throwIfAborted();
|
|
4086
4109
|
let read;
|
|
4110
|
+
const gate = new Promise((resolve) => {
|
|
4111
|
+
openGate = () => resolve(READ_STALLED);
|
|
4112
|
+
});
|
|
4087
4113
|
armIdle();
|
|
4088
4114
|
try {
|
|
4089
|
-
|
|
4115
|
+
const pending = reader.read();
|
|
4116
|
+
pending.catch(() => void 0);
|
|
4117
|
+
read = await Promise.race([pending, gate]);
|
|
4090
4118
|
} catch (error) {
|
|
4091
4119
|
signal?.throwIfAborted();
|
|
4092
4120
|
trace.record("read-error", {
|
|
@@ -4098,20 +4126,21 @@ async function* readResponse(response, context) {
|
|
|
4098
4126
|
throw bilingual("TRANSPORT", `Command Code API stream from ${apiBase} failed while reading: ${errorChain(error)}`, "Command Code API 流式响应中途断开——网络波动所致,重试通常可恢复", { cause: error });
|
|
4099
4127
|
} finally {
|
|
4100
4128
|
clearIdle();
|
|
4129
|
+
openGate = void 0;
|
|
4130
|
+
}
|
|
4131
|
+
if (read === READ_STALLED) {
|
|
4132
|
+
trace.record("eof", {
|
|
4133
|
+
...eofFacts(),
|
|
4134
|
+
readStalled: true
|
|
4135
|
+
});
|
|
4136
|
+
signal?.throwIfAborted();
|
|
4137
|
+
throw idleTimeoutError();
|
|
4101
4138
|
}
|
|
4102
4139
|
signal?.throwIfAborted();
|
|
4103
4140
|
const { done, value } = read;
|
|
4104
4141
|
if (done) {
|
|
4105
|
-
trace.record("eof",
|
|
4106
|
-
|
|
4107
|
-
bytes: totalBytes,
|
|
4108
|
-
silentMs: Date.now() - lastChunkAt,
|
|
4109
|
-
totalMs: Date.now() - streamStartedAt,
|
|
4110
|
-
finishSeen: finish !== void 0,
|
|
4111
|
-
idleFired,
|
|
4112
|
-
buffered: buffer.length
|
|
4113
|
-
});
|
|
4114
|
-
if (idleFired) throw bilingual("TIMEOUT", `Command Code API stream from ${apiBase} was idle for ${streamIdleTimeoutMs}ms (no events) and was treated as a dead connection`, `Command Code API 流式响应已 ${streamIdleTimeoutMs} 毫秒无任何事件,被判定为死连接——长思考模型可在设置中调大流空闲超时`);
|
|
4142
|
+
trace.record("eof", eofFacts());
|
|
4143
|
+
if (idleFired) throw idleTimeoutError();
|
|
4115
4144
|
if (buffer.trim()) yield* handleLine(buffer);
|
|
4116
4145
|
break;
|
|
4117
4146
|
}
|
|
@@ -9922,8 +9951,8 @@ function transportBudgetMessage(failureMessage, maxRetries) {
|
|
|
9922
9951
|
/**
|
|
9923
9952
|
* Mark one schema field volatile.
|
|
9924
9953
|
*
|
|
9925
|
-
* `.volatile()` is unconditional: it is a schemastery 3.18.3 feature and
|
|
9926
|
-
*
|
|
9954
|
+
* `.volatile()` is unconditional: it is a schemastery 3.18.3 feature and every
|
|
9955
|
+
* supported engine ships `~3.18.4` or `~3.18.5-alpha.1`, so the
|
|
9927
9956
|
* method is always present. It is reached through a structural member so the caller's
|
|
9928
9957
|
* declared field type survives — the mark changes what the schema PARSES to (a
|
|
9929
9958
|
* live reference), not the plugin-facing `Config` shape.
|