@feng0531/dsh-execution-bus 0.9.0 → 0.11.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/README.md +6 -4
- package/dist/bus.d.ts +2 -0
- package/dist/bus.js +4 -2
- package/dist/plugin.js +45 -4
- package/dist/product.d.ts +169 -21
- package/dist/product.js +118 -12
- package/dist/protocol.d.ts +2 -0
- package/docs/FLOW-TEST.md +3 -0
- package/docs/PRODUCT.md +4 -0
- package/docs/protocol.md +5 -1
- package/docs/releases/0.10.0.md +19 -0
- package/docs/releases/0.11.0.md +19 -0
- package/docs/validation.md +5 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
“萧何”是产品与模式显示名,执行总线是其技术功能;不新增人物 Agent,不进行角色扮演。仓库 dsh-execution-bus、npm 包名、execution_bus 工具名及 execution-bus-test 预设 ID 保持不变。历史版本发布说明保留当时名称。
|
|
6
6
|
|
|
7
|
-
DSH 独立插件:`@feng0531/dsh-execution-bus` · 当前版本 **0.
|
|
7
|
+
DSH 独立插件:`@feng0531/dsh-execution-bus` · 当前版本 **0.11.0**
|
|
8
8
|
|
|
9
9
|
> 萧何模式从宿主已声明的 PTC 组合派生,保留日常工具,再叠加可选执行总线。已验证隔离的真实 Node PTC → 原 read + 总线调用,以及脚本模型内存会话;真实模型、桌面界面与实际沙箱仍未验收。**不支持重启后恢复任务。**
|
|
10
10
|
|
|
@@ -130,7 +130,7 @@ flowchart TD
|
|
|
130
130
|
2. 在你选定的隔离 DSH 配置依赖目录安装固定版本,不要在 DSH 程序安装目录执行:
|
|
131
131
|
|
|
132
132
|
```powershell
|
|
133
|
-
npm install --ignore-scripts @feng0531/dsh-execution-bus@0.
|
|
133
|
+
npm install --ignore-scripts @feng0531/dsh-execution-bus@0.11.0
|
|
134
134
|
```
|
|
135
135
|
|
|
136
136
|
这是 npm 目录示例。若目标配置使用 pnpm,应沿用其包管理器,不混用锁文件。遇到宿主 peer 版本冲突就停止,不用强制安装绕过。
|
|
@@ -201,6 +201,8 @@ flowchart TD
|
|
|
201
201
|
|
|
202
202
|
PTC 是 DSH 的程序化工具调用入口。在 `run_code` 内使用 `await tools.execution_bus(请求对象)`,而不是直接调用折叠后的工具名。执行总线不会解除 `run_code` 自身的时间预算。已有真实 Node PTC 隔离进程读文件和调用总线的验证,但尚未进行实际模型/桌面沙箱全链路验收。
|
|
203
203
|
|
|
204
|
+
**0.11.0 起,总线改为收益导向触发并支持简化调用。** 只在能获得协调收益时使用:同一逻辑操作可能重复提交或需要重试去重(沿用 requestId)、任务需要在 `run_code` 预算结束后继续/跨步骤取回、或多个步骤与等待者需要同一执行结果;**“操作耗时长”本身不是理由**,一次性长命令请用原工具或宿主后台 Job。工具入口支持简化调用 `{requestId, handler, input}`(messageId 可省略、自动生成)和控制 `{requestId, type:"status"|"result"|"cancel"}`,完整 v1 消息仍被接受;返回快照在复用时带 `reused: true`。工具声明仍是按 Handler 的判别联合,PTC SDK 与原生声明里可直接看到每个 Handler 的必填字段。
|
|
205
|
+
|
|
204
206
|
**0.9.0 起,预算到期不再连带取消已受理执行。** `run_code` 因时间预算到期或程序结束时,宿主会中断其中的工具子调用;总线把这种中断视为**只停止等待**:已受理执行与宿主 Job 继续,程序返回预算错误后,可在后续 `run_code` 中用同一 `requestId` 的 `status`/`result` 取回结果,或用 `cancel` 取消。用户主动中断、会话取消、沙箱模式变化等其他原因仍会请求取消整个执行。该识别依赖 DSH 0.2.1-rc.2 的中断原因字符串(见[宿主兼容性](<docs/host-compatibility.md>)),不是宿主公开稳定契约;进程退出仍会丢失全部内存状态,保留期一小时。
|
|
205
207
|
|
|
206
208
|
## 如何理解任务状态?
|
|
@@ -262,7 +264,7 @@ npm run verify:package # 检查公开包内容
|
|
|
262
264
|
npm run test:install # 临时目录安装,不操作日常 DSH
|
|
263
265
|
```
|
|
264
266
|
|
|
265
|
-
这些测试不等于“当前聊天会话直接调用插件”。真实 AgentLoop 测试使用脚本模型适配器;工具组件测试使用测试 Agent。具体边界见[流程测试说明](<docs/FLOW-TEST.md>)。构建候选安装包可运行 `npm run pack:candidate
|
|
267
|
+
这些测试不等于“当前聊天会话直接调用插件”。真实 AgentLoop 测试使用脚本模型适配器;工具组件测试使用测试 Agent。具体边界见[流程测试说明](<docs/FLOW-TEST.md>)。构建候选安装包可运行 `npm run pack:candidate`。观察本机真实会话的总线采用率可运行 `npm run metrics:sessions`(只读扫描会话日志,统计各会话的请求类型、Handler、复用标记与错误)。
|
|
266
268
|
|
|
267
269
|
## 卸载与回滚
|
|
268
270
|
|
|
@@ -276,7 +278,7 @@ npm run test:install # 临时目录安装,不操作日常 DSH
|
|
|
276
278
|
|
|
277
279
|
- [协议和投递语义](<docs/protocol.md>):字段、状态、重复处理与取消规则。
|
|
278
280
|
- [宿主兼容性与源码调用链](<docs/host-compatibility.md>):为什么可以等待,为什么不能跨重启恢复。
|
|
279
|
-
- [验证记录](<docs/validation.md>)、[0.
|
|
281
|
+
- [验证记录](<docs/validation.md>)、[0.11.0 发布说明](<docs/releases/0.11.0.md>):已验证与未验证范围。
|
|
280
282
|
- [同类项目源码整合](<docs/INTEGRATION.md>):固定来源、采用范围、许可与验证边界。
|
|
281
283
|
- [维护者发布流程](<docs/RELEASING.md>):标签 CI、安装包校验与正式发布门禁。
|
|
282
284
|
|
package/dist/bus.d.ts
CHANGED
|
@@ -65,6 +65,8 @@ export declare class ExecutionBus {
|
|
|
65
65
|
submit(owner: Owner, raw: unknown, onEvent?: (e: Event) => void, invoke?: Capability): {
|
|
66
66
|
accepted: Event;
|
|
67
67
|
done: Promise<RecordView>;
|
|
68
|
+
/** 本次附着是否复用已有逻辑执行(结果标记可见性用)。 */
|
|
69
|
+
reused: boolean;
|
|
68
70
|
/** 当前快照:供仅在停止等待时使用,不改变交付标记。 */
|
|
69
71
|
snapshot: () => RecordView;
|
|
70
72
|
cancel: () => void;
|
package/dist/bus.js
CHANGED
|
@@ -187,7 +187,7 @@ export class ExecutionBus {
|
|
|
187
187
|
if (!previous && e.messages.size >= LIMITS.messageAccountLimit)
|
|
188
188
|
throw Error(ERRORS.MESSAGE_LIMIT);
|
|
189
189
|
// 先取得附着,再提交消息身份:附着被拒(WAITER_LIMIT)时无副作用。
|
|
190
|
-
const attached = this.attachment(e, onEvent, m.messageId);
|
|
190
|
+
const attached = this.attachment(e, onEvent, m.messageId, true);
|
|
191
191
|
if (!previous)
|
|
192
192
|
e.messages.set(m.messageId, canonical(m));
|
|
193
193
|
this.telemetry.record(e.trace, "reused");
|
|
@@ -262,7 +262,7 @@ export class ExecutionBus {
|
|
|
262
262
|
};
|
|
263
263
|
e.queueTimer = setTimeout(expire, this.admission.maxQueueWaitMs);
|
|
264
264
|
}
|
|
265
|
-
attachment(e, onEvent, id) {
|
|
265
|
+
attachment(e, onEvent, id, reused = false) {
|
|
266
266
|
// 每次附着独立占配额,即使调用方复用同一个回调。
|
|
267
267
|
const listener = onEvent ? (event) => onEvent(event) : undefined;
|
|
268
268
|
if (listener && !isTerminal(e.view.state)) {
|
|
@@ -282,6 +282,8 @@ export class ExecutionBus {
|
|
|
282
282
|
return {
|
|
283
283
|
accepted,
|
|
284
284
|
done: e.done,
|
|
285
|
+
/** 本次附着是否复用已有逻辑执行(结果标记可见性用)。 */
|
|
286
|
+
reused,
|
|
285
287
|
/** 当前快照:供仅在停止等待时使用,不改变交付标记。 */
|
|
286
288
|
snapshot: () => this.view(e),
|
|
287
289
|
cancel: () => this.cancel(e),
|
package/dist/plugin.js
CHANGED
|
@@ -10,6 +10,43 @@ const PTC_PROGRAM_SETTLED = "run_code settled";
|
|
|
10
10
|
function isPtcProgramEnd(signal) {
|
|
11
11
|
return signal.aborted && signal.reason === PTC_PROGRAM_SETTLED;
|
|
12
12
|
}
|
|
13
|
+
const REQUEST_KEYS = new Set(["requestId", "messageId", "handler", "input"]);
|
|
14
|
+
const CONTROL_KEYS = new Set(["requestId", "messageId", "type"]);
|
|
15
|
+
/** 工具入口兼容两种形状:0.11.0 简化调用 {requestId,handler,input,messageId?}
|
|
16
|
+
* 或 {requestId,type,messageId?},以及完整 v1 消息。简化形状在进入总线前补齐协议字段。 */
|
|
17
|
+
function normalizeToolInput(raw) {
|
|
18
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
19
|
+
return raw;
|
|
20
|
+
const input = raw;
|
|
21
|
+
if (Object.hasOwn(input, "protocolVersion"))
|
|
22
|
+
return raw;
|
|
23
|
+
if (Object.keys(input).some((key) => !REQUEST_KEYS.has(key) && !CONTROL_KEYS.has(key)) ||
|
|
24
|
+
typeof input.requestId !== "string")
|
|
25
|
+
throw Error(ERRORS.INVALID_REQUEST);
|
|
26
|
+
const messageId = typeof input.messageId === "string" ? input.messageId : randomUUID();
|
|
27
|
+
if (Object.hasOwn(input, "handler")) {
|
|
28
|
+
if (Object.hasOwn(input, "type") ||
|
|
29
|
+
typeof input.handler !== "string")
|
|
30
|
+
throw Error(ERRORS.INVALID_REQUEST);
|
|
31
|
+
return {
|
|
32
|
+
protocolVersion: 1,
|
|
33
|
+
messageId,
|
|
34
|
+
requestId: input.requestId,
|
|
35
|
+
type: "request",
|
|
36
|
+
payload: { handler: input.handler, input: input.input },
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (typeof input.type !== "string" ||
|
|
40
|
+
!["status", "result", "cancel"].includes(input.type))
|
|
41
|
+
throw Error(ERRORS.INVALID_REQUEST);
|
|
42
|
+
return {
|
|
43
|
+
protocolVersion: 1,
|
|
44
|
+
messageId,
|
|
45
|
+
requestId: input.requestId,
|
|
46
|
+
type: input.type,
|
|
47
|
+
payload: {},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
13
50
|
export const name = "execution-bus";
|
|
14
51
|
export const inject = ["tools", "jobs"];
|
|
15
52
|
export function apply(ctx) {
|
|
@@ -69,7 +106,7 @@ export function apply(ctx) {
|
|
|
69
106
|
sessionId: String(agent.id),
|
|
70
107
|
callId: String(exec.callId),
|
|
71
108
|
};
|
|
72
|
-
const m = parse(raw);
|
|
109
|
+
const m = parse(normalizeToolInput(raw));
|
|
73
110
|
if (m.type !== "request")
|
|
74
111
|
return bus.command(owner, m);
|
|
75
112
|
// 宿主工具转发:仅 host.* handler 注入对应工具的 capability。
|
|
@@ -127,7 +164,7 @@ export function apply(ctx) {
|
|
|
127
164
|
try {
|
|
128
165
|
const value = await attached.done;
|
|
129
166
|
attached.returned();
|
|
130
|
-
return value;
|
|
167
|
+
return markReused(value, attached);
|
|
131
168
|
}
|
|
132
169
|
finally {
|
|
133
170
|
attached.detach();
|
|
@@ -154,6 +191,10 @@ export function apply(ctx) {
|
|
|
154
191
|
throw Error(ERRORS.HOST_JOB_UNAVAILABLE);
|
|
155
192
|
}
|
|
156
193
|
}
|
|
194
|
+
/** 本次调用是否复用了已有执行;仅在真复用时追加标记,保持首次快照形状不变。 */
|
|
195
|
+
function markReused(view, attached) {
|
|
196
|
+
return attached.reused ? { ...view, reused: true } : view;
|
|
197
|
+
}
|
|
157
198
|
/** 外层取消映射:PTC 程序结束(含预算到期)只停止本次等待,已受理执行与
|
|
158
199
|
* 宿主 Job 保留,同会话可用同 requestId 的 status/result 取回;其他取消原因
|
|
159
200
|
* (用户/会话中断)仍请求取消整个执行。 */
|
|
@@ -178,12 +219,12 @@ export function apply(ctx) {
|
|
|
178
219
|
detachedView.then((view) => ({ kind: "detached", view })),
|
|
179
220
|
]);
|
|
180
221
|
if (outcome.kind === "detached")
|
|
181
|
-
return outcome.view;
|
|
222
|
+
return markReused(outcome.view, attached);
|
|
182
223
|
if (outcome.kind === "error")
|
|
183
224
|
throw outcome.error;
|
|
184
225
|
const value = await attached.done;
|
|
185
226
|
attached.returned();
|
|
186
|
-
return value;
|
|
227
|
+
return markReused(value, attached);
|
|
187
228
|
}
|
|
188
229
|
finally {
|
|
189
230
|
exec.signal.removeEventListener("abort", abort);
|
package/dist/product.d.ts
CHANGED
|
@@ -24,33 +24,181 @@ export declare const HANDLER_LIMITS: Readonly<{
|
|
|
24
24
|
diagnosticDelayMs: 30000;
|
|
25
25
|
}>;
|
|
26
26
|
export declare const REQUEST_PARAMETERS: {
|
|
27
|
-
readonly
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
27
|
+
readonly oneOf: readonly [...{
|
|
28
|
+
type: "object";
|
|
29
|
+
additionalProperties: false;
|
|
30
|
+
required: string[];
|
|
31
|
+
properties: {
|
|
32
|
+
requestId: {
|
|
33
|
+
readonly type: "string";
|
|
34
|
+
};
|
|
35
|
+
messageId: {
|
|
36
|
+
readonly type: "string";
|
|
37
|
+
};
|
|
38
|
+
handler: {
|
|
39
|
+
type: "string";
|
|
40
|
+
const: "host.read" | "host.glob" | "host.grep" | "host.edit" | "host.write" | "host.pwsh" | "test";
|
|
41
|
+
};
|
|
42
|
+
input: {
|
|
43
|
+
readonly type: "object";
|
|
44
|
+
readonly additionalProperties: false;
|
|
45
|
+
readonly required: readonly ["delayMs", "fail"];
|
|
46
|
+
readonly properties: {
|
|
47
|
+
readonly delayMs: {
|
|
48
|
+
readonly type: "integer";
|
|
49
|
+
readonly description: "Diagnostic delay in milliseconds (0-30000).";
|
|
50
|
+
};
|
|
51
|
+
readonly fail: {
|
|
52
|
+
readonly type: "boolean";
|
|
53
|
+
readonly description: "Settle as a controlled failure when true.";
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
} | {
|
|
57
|
+
readonly type: "object";
|
|
58
|
+
readonly additionalProperties: false;
|
|
59
|
+
readonly required: readonly ["file_path"];
|
|
60
|
+
readonly properties: {
|
|
61
|
+
readonly file_path: {
|
|
62
|
+
readonly type: "string";
|
|
63
|
+
readonly description: "Path resolved against the session working directory.";
|
|
64
|
+
};
|
|
65
|
+
readonly offset: {
|
|
66
|
+
readonly type: "integer";
|
|
67
|
+
readonly description: "1-based first line to read.";
|
|
68
|
+
};
|
|
69
|
+
readonly limit: {
|
|
70
|
+
readonly type: "integer";
|
|
71
|
+
readonly description: "Maximum lines to read (<=100).";
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
} | {
|
|
75
|
+
readonly type: "object";
|
|
76
|
+
readonly additionalProperties: false;
|
|
77
|
+
readonly required: readonly ["pattern"];
|
|
78
|
+
readonly properties: {
|
|
79
|
+
readonly pattern: {
|
|
80
|
+
readonly type: "string";
|
|
81
|
+
readonly description: "Glob pattern; a bare pattern matches basenames at any depth.";
|
|
82
|
+
};
|
|
83
|
+
readonly path: {
|
|
84
|
+
readonly type: "string";
|
|
85
|
+
readonly description: "Directory to search; defaults to the session working directory.";
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
} | {
|
|
89
|
+
readonly type: "object";
|
|
90
|
+
readonly additionalProperties: false;
|
|
91
|
+
readonly required: readonly ["pattern"];
|
|
92
|
+
readonly properties: {
|
|
93
|
+
readonly pattern: {
|
|
94
|
+
readonly type: "string";
|
|
95
|
+
readonly description: "Ripgrep regular expression.";
|
|
96
|
+
};
|
|
97
|
+
readonly path: {
|
|
98
|
+
readonly type: "string";
|
|
99
|
+
readonly description: "File or directory to search; defaults to the session working directory.";
|
|
100
|
+
};
|
|
101
|
+
readonly include: {
|
|
102
|
+
readonly type: "string";
|
|
103
|
+
readonly description: "One positive glob filter; negation and comma lists are rejected.";
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
} | {
|
|
107
|
+
readonly type: "object";
|
|
108
|
+
readonly additionalProperties: false;
|
|
109
|
+
readonly required: readonly ["file_path", "old_string", "new_string"];
|
|
110
|
+
readonly properties: {
|
|
111
|
+
readonly file_path: {
|
|
112
|
+
readonly type: "string";
|
|
113
|
+
readonly description: "File to edit.";
|
|
114
|
+
};
|
|
115
|
+
readonly old_string: {
|
|
116
|
+
readonly type: "string";
|
|
117
|
+
readonly description: "Literal text to replace.";
|
|
118
|
+
};
|
|
119
|
+
readonly new_string: {
|
|
120
|
+
readonly type: "string";
|
|
121
|
+
readonly description: "Replacement text.";
|
|
122
|
+
};
|
|
123
|
+
readonly replace_all: {
|
|
124
|
+
readonly type: "boolean";
|
|
125
|
+
readonly description: "Replace every occurrence.";
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
} | {
|
|
129
|
+
readonly type: "object";
|
|
130
|
+
readonly additionalProperties: false;
|
|
131
|
+
readonly required: readonly ["file_path", "content"];
|
|
132
|
+
readonly properties: {
|
|
133
|
+
readonly file_path: {
|
|
134
|
+
readonly type: "string";
|
|
135
|
+
readonly description: "File to write.";
|
|
136
|
+
};
|
|
137
|
+
readonly content: {
|
|
138
|
+
readonly type: "string";
|
|
139
|
+
readonly description: "Full file content.";
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
} | {
|
|
143
|
+
readonly type: "object";
|
|
144
|
+
readonly additionalProperties: false;
|
|
145
|
+
readonly required: readonly ["description", "command"];
|
|
146
|
+
readonly properties: {
|
|
147
|
+
readonly description: {
|
|
148
|
+
readonly type: "string";
|
|
149
|
+
readonly description: "Clear, concise description of what the command does (shown in the UI).";
|
|
150
|
+
};
|
|
151
|
+
readonly command: {
|
|
152
|
+
readonly type: "string";
|
|
153
|
+
readonly description: "PowerShell command to execute.";
|
|
154
|
+
};
|
|
155
|
+
readonly timeoutMs: {
|
|
156
|
+
readonly type: "number";
|
|
157
|
+
readonly description: "Positive timeout in milliseconds.";
|
|
158
|
+
};
|
|
159
|
+
readonly workdir: {
|
|
160
|
+
readonly type: "string";
|
|
161
|
+
readonly description: "Working directory; defaults to the session working directory.";
|
|
162
|
+
};
|
|
163
|
+
readonly run_in_background: {
|
|
164
|
+
readonly type: "boolean";
|
|
165
|
+
readonly description: "Return a host Job id immediately instead of waiting.";
|
|
166
|
+
};
|
|
167
|
+
readonly sandbox_permissions: {
|
|
168
|
+
readonly type: "string";
|
|
169
|
+
readonly enum: readonly ["workspace-write", "danger-full-access"];
|
|
170
|
+
readonly description: "Narrowest wider sandbox mode; must be paired with justification.";
|
|
171
|
+
};
|
|
172
|
+
readonly justification: {
|
|
173
|
+
readonly type: "string";
|
|
174
|
+
readonly description: "Required with sandbox_permissions; one sentence of reason.";
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
};
|
|
44
178
|
};
|
|
45
|
-
|
|
46
|
-
|
|
179
|
+
}[], {
|
|
180
|
+
readonly type: "object";
|
|
181
|
+
readonly additionalProperties: false;
|
|
182
|
+
readonly required: readonly ["requestId", "type"];
|
|
183
|
+
readonly properties: {
|
|
184
|
+
readonly requestId: {
|
|
185
|
+
readonly type: "string";
|
|
186
|
+
};
|
|
187
|
+
readonly messageId: {
|
|
188
|
+
readonly type: "string";
|
|
189
|
+
};
|
|
190
|
+
readonly type: {
|
|
191
|
+
readonly type: "string";
|
|
192
|
+
readonly enum: readonly ["status", "result", "cancel"];
|
|
193
|
+
readonly description: "Read the saved snapshot or request cancellation for this requestId.";
|
|
194
|
+
};
|
|
47
195
|
};
|
|
48
|
-
};
|
|
196
|
+
}];
|
|
49
197
|
};
|
|
50
198
|
export declare const STATE_PARAMETERS: {
|
|
51
199
|
readonly type: "object";
|
|
52
200
|
readonly properties: {};
|
|
53
201
|
readonly additionalProperties: false;
|
|
54
202
|
};
|
|
55
|
-
export declare const REQUEST_DESCRIPTION = "\u8427\u4F55 / Xiao He. Submit a
|
|
203
|
+
export declare const REQUEST_DESCRIPTION = "\u8427\u4F55 / Xiao He. Submit a request and WAIT for its terminal snapshot; the simplified call takes {requestId, handler, input} (messageId optional) and control calls take {requestId, type:\"status\"|\"result\"|\"cancel\"}. Use only when coordination helps: the same logical operation may be retried or deduplicated (reuse requestId), work must outlive a run_code budget end, or multiple steps must await one execution. Duration alone is not a reason \u2014 for a one-off long command use the original tool or its background Job. A PTC program end only stops waiting: accepted work continues and the same requestId can be retrieved with type:\"result\" or cancelled. The snapshot may contain reused:true when this call attached to an existing execution. The full v1 envelope is still accepted. Diagnostic handler only: test {delayMs:0..30000,fail:boolean}; never use it for real work. Acceptance is volatile, not success. No polling or restart resume.";
|
|
56
204
|
export declare const MODE_INSTRUCTIONS: string;
|
package/dist/product.js
CHANGED
|
@@ -23,25 +23,131 @@ export const HANDLER_LIMITS = Object.freeze({
|
|
|
23
23
|
readPathChars: 2048,
|
|
24
24
|
diagnosticDelayMs: 30000,
|
|
25
25
|
});
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
/** 每个 Handler 的模型可见输入声明。只用于工具 schema/SDK 生成;运行时仍由 Handler.validate 严格校验。 */
|
|
27
|
+
const INPUT_SCHEMAS = {
|
|
28
|
+
test: {
|
|
29
|
+
type: "object",
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
required: ["delayMs", "fail"],
|
|
32
|
+
properties: {
|
|
33
|
+
delayMs: { type: "integer", description: "Diagnostic delay in milliseconds (0-30000)." },
|
|
34
|
+
fail: { type: "boolean", description: "Settle as a controlled failure when true." },
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
"host.read": {
|
|
38
|
+
type: "object",
|
|
39
|
+
additionalProperties: false,
|
|
40
|
+
required: ["file_path"],
|
|
41
|
+
properties: {
|
|
42
|
+
file_path: { type: "string", description: "Path resolved against the session working directory." },
|
|
43
|
+
offset: { type: "integer", description: "1-based first line to read." },
|
|
44
|
+
limit: { type: "integer", description: "Maximum lines to read (<=100)." },
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
"host.glob": {
|
|
48
|
+
type: "object",
|
|
49
|
+
additionalProperties: false,
|
|
50
|
+
required: ["pattern"],
|
|
51
|
+
properties: {
|
|
52
|
+
pattern: { type: "string", description: "Glob pattern; a bare pattern matches basenames at any depth." },
|
|
53
|
+
path: { type: "string", description: "Directory to search; defaults to the session working directory." },
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
"host.grep": {
|
|
57
|
+
type: "object",
|
|
58
|
+
additionalProperties: false,
|
|
59
|
+
required: ["pattern"],
|
|
60
|
+
properties: {
|
|
61
|
+
pattern: { type: "string", description: "Ripgrep regular expression." },
|
|
62
|
+
path: { type: "string", description: "File or directory to search; defaults to the session working directory." },
|
|
63
|
+
include: { type: "string", description: "One positive glob filter; negation and comma lists are rejected." },
|
|
64
|
+
},
|
|
36
65
|
},
|
|
66
|
+
"host.edit": {
|
|
67
|
+
type: "object",
|
|
68
|
+
additionalProperties: false,
|
|
69
|
+
required: ["file_path", "old_string", "new_string"],
|
|
70
|
+
properties: {
|
|
71
|
+
file_path: { type: "string", description: "File to edit." },
|
|
72
|
+
old_string: { type: "string", description: "Literal text to replace." },
|
|
73
|
+
new_string: { type: "string", description: "Replacement text." },
|
|
74
|
+
replace_all: { type: "boolean", description: "Replace every occurrence." },
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
"host.write": {
|
|
78
|
+
type: "object",
|
|
79
|
+
additionalProperties: false,
|
|
80
|
+
required: ["file_path", "content"],
|
|
81
|
+
properties: {
|
|
82
|
+
file_path: { type: "string", description: "File to write." },
|
|
83
|
+
content: { type: "string", description: "Full file content." },
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
"host.pwsh": {
|
|
87
|
+
type: "object",
|
|
88
|
+
additionalProperties: false,
|
|
89
|
+
required: ["description", "command"],
|
|
90
|
+
properties: {
|
|
91
|
+
description: { type: "string", description: "Clear, concise description of what the command does (shown in the UI)." },
|
|
92
|
+
command: { type: "string", description: "PowerShell command to execute." },
|
|
93
|
+
timeoutMs: { type: "number", description: "Positive timeout in milliseconds." },
|
|
94
|
+
workdir: { type: "string", description: "Working directory; defaults to the session working directory." },
|
|
95
|
+
run_in_background: { type: "boolean", description: "Return a host Job id immediately instead of waiting." },
|
|
96
|
+
sandbox_permissions: { type: "string", enum: ["workspace-write", "danger-full-access"], description: "Narrowest wider sandbox mode; must be paired with justification." },
|
|
97
|
+
justification: { type: "string", description: "Required with sandbox_permissions; one sentence of reason." },
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
/** Handler 名列表同时决定 request payload 的联合分支顺序。 */
|
|
102
|
+
const HANDLER_NAMES = [
|
|
103
|
+
"host.read",
|
|
104
|
+
"host.glob",
|
|
105
|
+
"host.grep",
|
|
106
|
+
"host.edit",
|
|
107
|
+
"host.write",
|
|
108
|
+
"host.pwsh",
|
|
109
|
+
"test",
|
|
110
|
+
];
|
|
111
|
+
/** 简化调用(0.11.0):{requestId, handler, input} 或 {requestId, type};
|
|
112
|
+
* 完整 v1 消息仍被运行时接受,但不再进入模型可见 schema。 */
|
|
113
|
+
const REQUEST_ID_PROP = { type: "string" };
|
|
114
|
+
const MESSAGE_ID_PROP = { type: "string" };
|
|
115
|
+
export const REQUEST_PARAMETERS = {
|
|
116
|
+
oneOf: [
|
|
117
|
+
...HANDLER_NAMES.map((handler) => ({
|
|
118
|
+
type: "object",
|
|
119
|
+
additionalProperties: false,
|
|
120
|
+
required: ["requestId", "handler", "input"],
|
|
121
|
+
properties: {
|
|
122
|
+
requestId: REQUEST_ID_PROP,
|
|
123
|
+
messageId: MESSAGE_ID_PROP,
|
|
124
|
+
handler: { type: "string", const: handler },
|
|
125
|
+
input: INPUT_SCHEMAS[handler],
|
|
126
|
+
},
|
|
127
|
+
})),
|
|
128
|
+
{
|
|
129
|
+
type: "object",
|
|
130
|
+
additionalProperties: false,
|
|
131
|
+
required: ["requestId", "type"],
|
|
132
|
+
properties: {
|
|
133
|
+
requestId: REQUEST_ID_PROP,
|
|
134
|
+
messageId: MESSAGE_ID_PROP,
|
|
135
|
+
type: {
|
|
136
|
+
type: "string",
|
|
137
|
+
enum: ["status", "result", "cancel"],
|
|
138
|
+
description: "Read the saved snapshot or request cancellation for this requestId.",
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
],
|
|
37
143
|
};
|
|
38
144
|
export const STATE_PARAMETERS = {
|
|
39
145
|
type: "object",
|
|
40
146
|
properties: {},
|
|
41
147
|
additionalProperties: false,
|
|
42
148
|
};
|
|
43
|
-
export const REQUEST_DESCRIPTION = "萧何 / Xiao He. Submit a
|
|
44
|
-
export const MODE_INSTRUCTIONS = "你正在萧何模式中。这不是角色扮演。保留宿主 PTC 的日常工具能力与权限规则。普通编辑、搜索、命令、安装和其他工作使用原工具,不要声称此模式只读。execution_bus
|
|
149
|
+
export const REQUEST_DESCRIPTION = "萧何 / Xiao He. Submit a request and WAIT for its terminal snapshot; the simplified call takes {requestId, handler, input} (messageId optional) and control calls take {requestId, type:\"status\"|\"result\"|\"cancel\"}. Use only when coordination helps: the same logical operation may be retried or deduplicated (reuse requestId), work must outlive a run_code budget end, or multiple steps must await one execution. Duration alone is not a reason — for a one-off long command use the original tool or its background Job. A PTC program end only stops waiting: accepted work continues and the same requestId can be retrieved with type:\"result\" or cancelled. The snapshot may contain reused:true when this call attached to an existing execution. The full v1 envelope is still accepted. Diagnostic handler only: test {delayMs:0..30000,fail:boolean}; never use it for real work. Acceptance is volatile, not success. No polling or restart resume.";
|
|
150
|
+
export const MODE_INSTRUCTIONS = "你正在萧何模式中。这不是角色扮演。保留宿主 PTC 的日常工具能力与权限规则。普通编辑、搜索、命令、安装和其他工作使用原工具,不要声称此模式只读。execution_bus 只在能获得协调收益时使用:① 同一逻辑操作可能重复提交或需要重试核对(沿用同一 requestId,只执行一次);② 任务需要在 run_code 时间预算结束后继续或跨步骤取回;③ 多个步骤/等待者需要同一执行结果。仅\"操作耗时长\"不是理由:一次性长命令用原工具或宿主后台 Job。其余普通任务直接用原工具,不要为简单调用增加包装。实际业务 Handler 为 host.read、host.glob、host.grep(只读,可复用终态结果)与 host.edit、host.write、host.pwsh(有副作用,终态结果不可复用);test 仅用于用户明确要求的诊断,不做真实工作。简化调用示例:await tools.execution_bus({requestId:\"<逻辑操作编号>\", handler:\"host.pwsh\", input:{description:\"运行测试\", command:\"pnpm test\", timeoutMs:120000}});预算中断后用 await tools.execution_bus({requestId:\"<同一编号>\", type:\"result\"}) 取回;同一逻辑操作重发沿用 requestId,messageId 可省略(自动生成)。返回快照出现 reused:true 表示本次调用复用了已有执行。通过 run_code 调用,受原有时间预算约束。每会话排队上限 " +
|
|
45
151
|
ADMISSION_DEFAULTS.sessionQueueLimit +
|
|
46
152
|
",排队超过 " +
|
|
47
153
|
ADMISSION_DEFAULTS.maxQueueWaitMs / 1000 +
|
package/dist/protocol.d.ts
CHANGED
|
@@ -41,6 +41,8 @@ export interface RecordView {
|
|
|
41
41
|
result?: unknown;
|
|
42
42
|
error?: string;
|
|
43
43
|
progress?: number;
|
|
44
|
+
/** true 表示本次调用附着到已存在的逻辑执行,而不是新建执行(0.11.0 新增,可选)。 */
|
|
45
|
+
reused?: true;
|
|
44
46
|
}
|
|
45
47
|
export declare function object(v: unknown): Record<string, unknown>;
|
|
46
48
|
/** 规范排序后的稳定摘要,只用于同 requestId 的冲突比较,不用于跨请求去重。 */
|
package/docs/FLOW-TEST.md
CHANGED
|
@@ -22,9 +22,12 @@ npm run test:install
|
|
|
22
22
|
| `check` | 编译并运行全部测试;包括后续 Job 故障、卸载、预设隔离等回归 |
|
|
23
23
|
| `verify:package` | 检查候选打包清单及导出,不安装日常宿主 |
|
|
24
24
|
| `test:install` | 在临时目录安装生产依赖并验证根入口/简化注册,结束后清理 |
|
|
25
|
+
| `metrics:sessions` | 只读扫描本机会话日志,汇总总线请求/Handler/复用标记/错误,用于采用率观察 |
|
|
25
26
|
|
|
26
27
|
`test:flow` 不是全部集成测试的别名;发布前必须运行 `check`。临时安装不是桌面插件管理器安装。完整验证层次见[验证范围](<validation.md>)。
|
|
27
28
|
|
|
29
|
+
`metrics:sessions` 只读取本地会话日志,不发送网络请求,也不代表模型效果对比;它是采用率与异常观察工具,不是 A/B 基准。
|
|
30
|
+
|
|
28
31
|
## 已覆盖的代表场景
|
|
29
32
|
|
|
30
33
|
- 正常受理与异步返回,两个会话不串线,同键冲突拒绝。
|
package/docs/PRODUCT.md
CHANGED
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
0.9.0 增加 PTC 预算到期后的分离等待:宿主中断 PTC 子调用时,已受理执行只解除等待、继续运行,可用同 requestId 的 status/result 取回或用 cancel 取消;其他中断原因仍按取消处理。该区分依据 DSH 0.2.1-rc.2 的中断原因字符串,不是公开稳定契约,宿主升级需复核。
|
|
10
10
|
|
|
11
|
+
0.10.0 改善模型侧的采用条件:模式说明写明使用场景并给出调用示例;工具声明把 payload 改为按 Handler 的判别联合,PTC SDK 与原生声明直接显示每个 Handler 的必填/可选字段。wire 协议、字段、错误码与 Handler 行为不变,只改变模型可见的提示与 schema。
|
|
12
|
+
|
|
13
|
+
0.11.0 根据 pilot 收紧为收益导向触发:重复提交/重试去重、预算结束后继续/跨步骤取回、多等待者同一执行才用总线,时长本身不是理由;新增简化调用(requestId+handler+input,messageId 自动生成)与控制(requestId+type),完整 v1 消息仍兼容;快照在复用时带 reused:true,并新增只读的会话采用率统计脚本。
|
|
14
|
+
|
|
11
15
|
## 入口及配置层次
|
|
12
16
|
|
|
13
17
|
| 入口 | 谁使用 | 责任 |
|
package/docs/protocol.md
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
**工具 request 不提前返回 accepted 或仅 taskId。** 它异步等待后返回执行快照;校验、容量、宿主服务等也可能令外层工具调用返回错误,而非执行快照。
|
|
40
40
|
|
|
41
|
-
快照字段:`requestId`、`state`、`sequence`、`cancelRequested`、`delivery`,以及可选 `result`、`error`、`progress`。`status`、`result`、`cancel` 均返回当前快照;`result` 在运行中也只返回当前状态,不额外等待。
|
|
41
|
+
快照字段:`requestId`、`state`、`sequence`、`cancelRequested`、`delivery`,以及可选 `result`、`error`、`progress`;0.11.0 起,附着到已有执行的返回快照可带可选 `reused:true`。`status`、`result`、`cancel` 均返回当前快照;`result` 在运行中也只返回当前状态,不额外等待。
|
|
42
42
|
|
|
43
43
|
core 的 `submit()` 返回 `accepted`、`done` Promise、只读 `snapshot()` 及取消/解除通知/返回标记句柄。accepted 只是内存受理或已有记录的快照,`durable:false`,不代表执行成功;终态重取也不代表重新执行。0.9.0 的 `snapshot()` 只供停止等待时读取当前视图,不改变交付标记。
|
|
44
44
|
|
|
@@ -122,4 +122,8 @@ core 实例的 `diagnostics()` 返回只读用途的独立快照:阶段计数
|
|
|
122
122
|
|
|
123
123
|
包的 `./core` 导出 ExecutionBus、Handler、Capability 类型。Handler 只接收输入、requestId、signal、progress 和可选最小 capability,不接收聊天历史。register 返回绑定唯一注册令牌的幂等注销函数,不会误删后来同名注册;已受理请求继续持有原 Handler。
|
|
124
124
|
|
|
125
|
+
0.10.0 起,模型可见的工具体声明把 `payload` 改为按 Handler 的判别联合(每个 `host.*`/test 的 `input` 字段与必填项);这是提示与 SDK 类型层的变化,wire 结构、校验、错误码与保存语义不变。
|
|
126
|
+
|
|
127
|
+
0.11.0 起,模型可传简化输入:请求 `{requestId, handler, input, messageId?}`、控制 `{requestId, type, messageId?}`;插件在进入总线前补齐完整 v1 消息,完整 v1 消息仍被接受。返回快照在附着已有执行时追加可选 `reused:true`,只表示复用了逻辑执行,不代表外部副作用对账。
|
|
128
|
+
|
|
125
129
|
内置 test、host.read、host.glob 与 host.grep 没有副作用;host.edit、host.write 与 host.pwsh 是非幂等写/命令 Handler,通过 `Handler.idempotent=false` 显式声明,其终态结果复用被 `MUTATING_REUSE_DENIED` 拒绝,运行中的重复附着仍只等待同一执行。0.8.0 新增宿主工具输入错误码 INVALID_GLOB_INPUT、INVALID_GREP_INPUT 与 INVALID_PWSH_INPUT;协议既有错误码不改名。host.pwsh 的后台结果只是宿主 Job ID,不是完成回执。当前没有 ctx.executionBus 服务、远端传输、跨插件动态注册或外部副作用对账契约。扩展有副作用 Handler 前必须显式声明幂等并另行设计授权与崩溃对账,不能仅依赖本版请求键。
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# 萧何 / Xiao He 0.10.0
|
|
2
|
+
|
|
3
|
+
## 让总线可被采用:触发条件与类型化声明
|
|
4
|
+
|
|
5
|
+
本版不改变执行机制,专门改善“模式被选中但总线从未被调用”的采用问题。
|
|
6
|
+
|
|
7
|
+
- 模式说明新增明确触发条件:仅在预计单次宿主操作超过约 30 秒、同一逻辑操作可能重复提交(沿用 requestId)、任务需要在 `run_code` 时间预算结束后继续、或多个步骤需要等待同一执行时才使用总线;其余任务继续直接用原工具,并给出一条调用示例与 messageId/requestId 语义。
|
|
8
|
+
- `execution_bus` 的模型可见参数从泛型 `payload: Record<string, JsonValue>` 改为按 Handler 的判别联合(`host.read` / `host.glob` / `host.grep` / `host.edit` / `host.write` / `host.pwsh` / `test` + 空控制 payload)。PTC SDK 与原生工具声明现在直接显示每个 Handler 的必填/可选字段;wire 结构、校验、错误码、状态机与 Handler 行为不变。
|
|
9
|
+
- 工具描述同步写明触发条件与编号语义;诊断 Handler 仍标注仅用于明确诊断。
|
|
10
|
+
- 代价:模型可见声明变大。模式说明 916 字符(+319),`execution_bus` 的 SDK 参数声明约 4.1KB(原泛型声明约 1.3KB);是否换来更高的真实采用率与更好的结果,需要 pilot 与同任务 A/B 对照验证。
|
|
11
|
+
- 新增 4 项回归(判别联合结构、合法/未知 Handler 校验、SDK 渲染、提示触发条件),并扩展真实 Node PTC 用例断言装配后的 SDK 含类型化声明。
|
|
12
|
+
|
|
13
|
+
## 升级说明
|
|
14
|
+
|
|
15
|
+
需要 DSH 0.2.1-rc.2。本版只有模型可见提示与工具 schema 变化;请求结构、字段、预设、工具名、错误码与 Handler 行为均不变。不自动安装、重写日常配置或重启 DSH。
|
|
16
|
+
|
|
17
|
+
## 验证与限制
|
|
18
|
+
|
|
19
|
+
本地全量 105 项测试通过。真实模型采用率、轮次/耗时收益未验证,需 pilot 与 A/B 对照;真实模型、桌面 UI 与实际沙箱仍未完整验收。若 pilot 显示声明开销不值得,可回退为较短的泛型声明。
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# 萧何 / Xiao He 0.11.0
|
|
2
|
+
|
|
3
|
+
## 收益导向触发、简化调用与复用可见
|
|
4
|
+
|
|
5
|
+
根据 0.10.0 的采用率 pilot(4 个全新队友会话)结果,本版收紧触发条件并降低调用摩擦。
|
|
6
|
+
|
|
7
|
+
- **触发收紧**:只在能获得协调收益时使用总线——同一逻辑操作可能重复提交或需要重试去重(沿用 requestId);任务需要在 `run_code` 预算结束后继续或跨步骤取回;多个步骤/等待者需要同一执行结果。**仅“操作耗时长”不再作为理由**:一次性长命令使用原工具或宿主后台 Job(pilot 中一次性 40 秒命令被包装后没有协调收益)。
|
|
8
|
+
- **简化调用**:请求可传 `{requestId, handler, input, messageId?}`,控制可传 `{requestId, type:"status"|"result"|"cancel", messageId?}`;`messageId` 省略时自动生成。完整 v1 消息仍被接受(向后兼容)。工具 schema 改为简化调用的 Handler 判别联合,PTC SDK 不再要求构造完整消息。
|
|
9
|
+
- **复用可见**:附着到已有执行(终态复用或运行中重发)时,返回快照追加 `reused:true`;首次执行不带该字段。该标记只表示复用了逻辑执行,不代表外部副作用对账。
|
|
10
|
+
- **采用率观察**:新增只读命令 `npm run metrics:sessions`,扫描本地会话日志并汇总总线请求/Handler/复用/错误,供后续两臂 A/B 比较。
|
|
11
|
+
- 新增/重写 9 项回归(简化请求与控制、完整 v1 兼容、复用标记、非法形状拒绝、schema/SDK 渲染、收益导向提示),全量 **110** 项测试通过。
|
|
12
|
+
|
|
13
|
+
## 升级说明
|
|
14
|
+
|
|
15
|
+
需要 DSH 0.2.1-rc.2。wire 协议结构、预设、工具名、错误码与 Handler 行为不变;工具入口新增简化形状并保留完整 v1 消息。不自动安装、重写日常配置或重启 DSH。
|
|
16
|
+
|
|
17
|
+
## 验证与限制
|
|
18
|
+
|
|
19
|
+
本地全量 110 项测试通过。0.10.0 pilot 样本小且任务由本仓库构造:符合条件任务 2/3 使用总线,不是 A/B 结论;0.11.0 收紧后的采用率与轮次/耗时收益仍需两臂复测。真实模型、桌面 UI 与实际沙箱仍未完整验收。
|
package/docs/validation.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 验证范围与使用限制
|
|
2
2
|
|
|
3
|
-
本文说明当前版本的证据边界,不是生产环境认证。当前能力基线为 **v0.
|
|
3
|
+
本文说明当前版本的证据边界,不是生产环境认证。当前能力基线为 **v0.11.0**,在 0.5.0 的会话准入/排队、0.7.0 的宿主工具转发、0.8.0 的搜索/命令 Handler、0.9.0 的预算分离等待与 0.10.0 的采用面改造上,收紧为收益导向触发并加入简化调用、复用标记与本地采用率统计;预设沿用 v0.3.0 的宿主 PTC 声明派生方式。验证环境为 Windows、Node.js 24.21.0,宿主组件锁定 DSH 0.2.1-rc.2、Cordis 4.0.4。
|
|
4
4
|
|
|
5
5
|
## 已验证什么?
|
|
6
6
|
|
|
@@ -10,10 +10,13 @@
|
|
|
10
10
|
| 真实宿主组件 | Cordis、ToolRuntime、LocalJobs、LocalFS、文件工具;host.glob/host.grep/host.pwsh 的转发测试使用宿主工具桩 | 请求经过真实工具管线;权限拒绝、Job 进度、共享任务、参数校验、幂等分流与清理逻辑有效;Agent 身份与工具实现为夹具,桩不证明真实搜索/命令工具实现 |
|
|
11
11
|
| 真实会话循环 | AgentLoop、AgentRegistry、SessionStore;脚本模型适配器 | 内存会话中原工具结果只提交一次,完成后再进入下一次适配器调用 |
|
|
12
12
|
| PTC 预算分离等待 | 真实 Node PTC `run_code` 以 2 秒预算等待 5 秒总线执行:预算到期后执行继续、宿主 Job 保留、同 requestId 取回结果;外部中断仍取消执行 | 在 DSH 0.2.1-rc.2 实际中断原因下成立;固定字符串不是跨版本契约 |
|
|
13
|
+
| 简化调用与复用标记 | 简化请求/控制、完整 v1 消息兼容、终态与运行中复用返回 `reused:true`、非法形状拒绝 | 组件级测试确认;不改变 wire 语义与副作用边界 |
|
|
13
14
|
| 预设隔离 | AgentPresetRegistry 与 Loader | 派生预设可激活;源 ptc 声明不变、普通 Agent 不可见总线;原 write/edit/Job 工具保留,宿主前置策略拒绝仍有效 |
|
|
14
15
|
| 故障注入 | 克隆失败、观察者拒绝、Job 等待/清理异常、先行移除与卸载交错 | 指定故障下的回归约束;不证明所有故障组合都已覆盖 |
|
|
15
16
|
| 候选包 | 严格文件白名单、临时目录生产依赖安装、入口注册 | 包可安装和加载;安装验证使用简化宿主夹具,不是桌面插件管理器验收 |
|
|
16
17
|
|
|
18
|
+
2026-10-18 采用率 pilot(0.10.0,4 个全新队友会话):符合条件的长命令/跨预算任务 **2/3** 真实调用了总线;1 个一次性 40 秒命令属于无收益包装,1 个跨步骤任务改用宿主后台 Job。样本小、非 A/B,0.11.0 收紧触发后需复测。
|
|
19
|
+
|
|
17
20
|
此前 v0.3.0 本地回归为 **51/51 通过**;本轮新增生命周期与多会话压力回归,最新数量以命令输出为准。测试项数量是用例数量,不是全部产品验收条数。当前结果请重新运行下述命令;文档测试数不应代替实际输出。
|
|
18
21
|
|
|
19
22
|
```powershell
|
|
@@ -45,6 +48,7 @@ eb95b4e51675f5f1821275e0812ef4dd4984b1aba45a52fbc6bab3518bbf6f38
|
|
|
45
48
|
| 从真实 tgz 经宿主插件管理器加载预设、卸载与回滚 | 未完成完整桌面流程;源码工作区的 Loader 测试不能替代 |
|
|
46
49
|
| 真实 glob/grep/pwsh 工具实现 | 未在测试环境启用:真实搜索工具依赖打包 ripgrep 与 subprocess 服务,真实 pwsh 依赖 shell/sandbox/审批组合;本版只验证按 handler 名转发、输入校验、幂等分流与失败固定码 |
|
|
47
50
|
| 跨版本 PTC 中断原因 | 分离等待只识别 DSH 0.2.1-rc.2 实际使用的固定中断原因字符串;宿主升级后未知原因保守按取消处理,需复核 |
|
|
51
|
+
| 模式采用率与效果 | 未完成 A/B。0.10.0 pilot 显示采用面改造能让总线被真实使用(2/3 符合条件任务),但样本小、任务由本仓库构造;0.11.0 收益导向收紧后的采用率与轮次/耗时收益仍未知,需两臂复测,不能由 schema 或单元测试推断 |
|
|
48
52
|
| 磁盘会话结果提交及重启恢复原调用 | 未验收磁盘提交;本插件不支持跨重启恢复 |
|
|
49
53
|
| 减少真实模型轮次、状态查询或总耗时的对照 | 未验证,不给提升比例 |
|
|
50
54
|
| 长期运行、所有卸载/服务故障组合 | 未穷尽;持续故障仍有清理限制 |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@feng0531/dsh-execution-bus",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
"verify:package": "node scripts/verify-package.mjs",
|
|
48
48
|
"test:install": "node scripts/test-install.mjs",
|
|
49
49
|
"pack:candidate": "node scripts/pack.mjs",
|
|
50
|
-
"verify:release": "node scripts/release-preflight.mjs"
|
|
50
|
+
"verify:release": "node scripts/release-preflight.mjs",
|
|
51
|
+
"metrics:sessions": "node scripts/session-metrics.mjs"
|
|
51
52
|
},
|
|
52
53
|
"peerDependencies": {
|
|
53
54
|
"@deepseek-ai/cordis": "~4.0.4",
|