@feng0531/dsh-execution-bus 0.9.0 → 0.10.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 +5 -3
- package/dist/product.d.ts +311 -2
- package/dist/product.js +117 -6
- package/docs/PRODUCT.md +2 -0
- package/docs/protocol.md +2 -0
- package/docs/releases/0.10.0.md +19 -0
- package/docs/validation.md +2 -1
- package/package.json +1 -1
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.10.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.10.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.10.0 起,模式说明与工具声明给出明确触发条件。** 仅当预计单次宿主操作超过约 30 秒、同一逻辑操作可能重复提交(沿用 requestId)、任务需要在 `run_code` 预算结束后继续、或多个步骤需要等待同一执行时,才使用 `execution_bus`;其余任务继续用原工具,避免为简单调用增加包装。工具声明改为按 Handler 的判别联合(`host.read`/`host.glob`/`host.grep`/`host.edit`/`host.write`/`host.pwsh`/`test`),PTC SDK 与原生声明里可直接看到每个 Handler 的必填字段,而不是泛型 `payload`。
|
|
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
|
## 如何理解任务状态?
|
|
@@ -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.10.0 发布说明](<docs/releases/0.10.0.md>):已验证与未验证范围。
|
|
280
282
|
- [同类项目源码整合](<docs/INTEGRATION.md>):固定来源、采用范围、许可与验证边界。
|
|
281
283
|
- [维护者发布流程](<docs/RELEASING.md>):标签 CI、安装包校验与正式发布门禁。
|
|
282
284
|
|
package/dist/product.d.ts
CHANGED
|
@@ -23,6 +23,161 @@ export declare const HANDLER_LIMITS: Readonly<{
|
|
|
23
23
|
readPathChars: 2048;
|
|
24
24
|
diagnosticDelayMs: 30000;
|
|
25
25
|
}>;
|
|
26
|
+
/** request 的 {handler,input} 判别联合;控制消息为空对象。 */
|
|
27
|
+
export declare const PAYLOAD_SCHEMA: {
|
|
28
|
+
readonly description: "request 必须匹配某个 Handler 的 {handler,input};status/result/cancel 的 payload 必须为空对象 {}。";
|
|
29
|
+
readonly oneOf: readonly [...{
|
|
30
|
+
type: "object";
|
|
31
|
+
additionalProperties: false;
|
|
32
|
+
required: string[];
|
|
33
|
+
properties: {
|
|
34
|
+
handler: {
|
|
35
|
+
type: "string";
|
|
36
|
+
const: "host.read" | "host.glob" | "host.grep" | "host.edit" | "host.write" | "host.pwsh" | "test";
|
|
37
|
+
};
|
|
38
|
+
input: {
|
|
39
|
+
readonly type: "object";
|
|
40
|
+
readonly additionalProperties: false;
|
|
41
|
+
readonly required: readonly ["delayMs", "fail"];
|
|
42
|
+
readonly properties: {
|
|
43
|
+
readonly delayMs: {
|
|
44
|
+
readonly type: "integer";
|
|
45
|
+
readonly description: "Diagnostic delay in milliseconds (0-30000).";
|
|
46
|
+
};
|
|
47
|
+
readonly fail: {
|
|
48
|
+
readonly type: "boolean";
|
|
49
|
+
readonly description: "Settle as a controlled failure when true.";
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
} | {
|
|
53
|
+
readonly type: "object";
|
|
54
|
+
readonly additionalProperties: false;
|
|
55
|
+
readonly required: readonly ["file_path"];
|
|
56
|
+
readonly properties: {
|
|
57
|
+
readonly file_path: {
|
|
58
|
+
readonly type: "string";
|
|
59
|
+
readonly description: "Path resolved against the session working directory.";
|
|
60
|
+
};
|
|
61
|
+
readonly offset: {
|
|
62
|
+
readonly type: "integer";
|
|
63
|
+
readonly description: "1-based first line to read.";
|
|
64
|
+
};
|
|
65
|
+
readonly limit: {
|
|
66
|
+
readonly type: "integer";
|
|
67
|
+
readonly description: "Maximum lines to read (<=100).";
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
} | {
|
|
71
|
+
readonly type: "object";
|
|
72
|
+
readonly additionalProperties: false;
|
|
73
|
+
readonly required: readonly ["pattern"];
|
|
74
|
+
readonly properties: {
|
|
75
|
+
readonly pattern: {
|
|
76
|
+
readonly type: "string";
|
|
77
|
+
readonly description: "Glob pattern; a bare pattern matches basenames at any depth.";
|
|
78
|
+
};
|
|
79
|
+
readonly path: {
|
|
80
|
+
readonly type: "string";
|
|
81
|
+
readonly description: "Directory to search; defaults to the session working directory.";
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
} | {
|
|
85
|
+
readonly type: "object";
|
|
86
|
+
readonly additionalProperties: false;
|
|
87
|
+
readonly required: readonly ["pattern"];
|
|
88
|
+
readonly properties: {
|
|
89
|
+
readonly pattern: {
|
|
90
|
+
readonly type: "string";
|
|
91
|
+
readonly description: "Ripgrep regular expression.";
|
|
92
|
+
};
|
|
93
|
+
readonly path: {
|
|
94
|
+
readonly type: "string";
|
|
95
|
+
readonly description: "File or directory to search; defaults to the session working directory.";
|
|
96
|
+
};
|
|
97
|
+
readonly include: {
|
|
98
|
+
readonly type: "string";
|
|
99
|
+
readonly description: "One positive glob filter; negation and comma lists are rejected.";
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
} | {
|
|
103
|
+
readonly type: "object";
|
|
104
|
+
readonly additionalProperties: false;
|
|
105
|
+
readonly required: readonly ["file_path", "old_string", "new_string"];
|
|
106
|
+
readonly properties: {
|
|
107
|
+
readonly file_path: {
|
|
108
|
+
readonly type: "string";
|
|
109
|
+
readonly description: "File to edit.";
|
|
110
|
+
};
|
|
111
|
+
readonly old_string: {
|
|
112
|
+
readonly type: "string";
|
|
113
|
+
readonly description: "Literal text to replace.";
|
|
114
|
+
};
|
|
115
|
+
readonly new_string: {
|
|
116
|
+
readonly type: "string";
|
|
117
|
+
readonly description: "Replacement text.";
|
|
118
|
+
};
|
|
119
|
+
readonly replace_all: {
|
|
120
|
+
readonly type: "boolean";
|
|
121
|
+
readonly description: "Replace every occurrence.";
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
} | {
|
|
125
|
+
readonly type: "object";
|
|
126
|
+
readonly additionalProperties: false;
|
|
127
|
+
readonly required: readonly ["file_path", "content"];
|
|
128
|
+
readonly properties: {
|
|
129
|
+
readonly file_path: {
|
|
130
|
+
readonly type: "string";
|
|
131
|
+
readonly description: "File to write.";
|
|
132
|
+
};
|
|
133
|
+
readonly content: {
|
|
134
|
+
readonly type: "string";
|
|
135
|
+
readonly description: "Full file content.";
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
} | {
|
|
139
|
+
readonly type: "object";
|
|
140
|
+
readonly additionalProperties: false;
|
|
141
|
+
readonly required: readonly ["description", "command"];
|
|
142
|
+
readonly properties: {
|
|
143
|
+
readonly description: {
|
|
144
|
+
readonly type: "string";
|
|
145
|
+
readonly description: "Clear, concise description of what the command does (shown in the UI).";
|
|
146
|
+
};
|
|
147
|
+
readonly command: {
|
|
148
|
+
readonly type: "string";
|
|
149
|
+
readonly description: "PowerShell command to execute.";
|
|
150
|
+
};
|
|
151
|
+
readonly timeoutMs: {
|
|
152
|
+
readonly type: "number";
|
|
153
|
+
readonly description: "Positive timeout in milliseconds.";
|
|
154
|
+
};
|
|
155
|
+
readonly workdir: {
|
|
156
|
+
readonly type: "string";
|
|
157
|
+
readonly description: "Working directory; defaults to the session working directory.";
|
|
158
|
+
};
|
|
159
|
+
readonly run_in_background: {
|
|
160
|
+
readonly type: "boolean";
|
|
161
|
+
readonly description: "Return a host Job id immediately instead of waiting.";
|
|
162
|
+
};
|
|
163
|
+
readonly sandbox_permissions: {
|
|
164
|
+
readonly type: "string";
|
|
165
|
+
readonly enum: readonly ["workspace-write", "danger-full-access"];
|
|
166
|
+
readonly description: "Narrowest wider sandbox mode; must be paired with justification.";
|
|
167
|
+
};
|
|
168
|
+
readonly justification: {
|
|
169
|
+
readonly type: "string";
|
|
170
|
+
readonly description: "Required with sandbox_permissions; one sentence of reason.";
|
|
171
|
+
};
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
}[], {
|
|
176
|
+
readonly type: "object";
|
|
177
|
+
readonly additionalProperties: false;
|
|
178
|
+
readonly properties: {};
|
|
179
|
+
}];
|
|
180
|
+
};
|
|
26
181
|
export declare const REQUEST_PARAMETERS: {
|
|
27
182
|
readonly type: "object";
|
|
28
183
|
readonly additionalProperties: false;
|
|
@@ -34,16 +189,170 @@ export declare const REQUEST_PARAMETERS: {
|
|
|
34
189
|
};
|
|
35
190
|
readonly messageId: {
|
|
36
191
|
readonly type: "string";
|
|
192
|
+
readonly description: "Unique id of this message; reuse only when redelivering the same message.";
|
|
37
193
|
};
|
|
38
194
|
readonly requestId: {
|
|
39
195
|
readonly type: "string";
|
|
196
|
+
readonly description: "Stable id of one logical operation; reuse it when the same operation is submitted again.";
|
|
40
197
|
};
|
|
41
198
|
readonly type: {
|
|
42
199
|
readonly type: "string";
|
|
43
200
|
readonly enum: readonly ["request", "status", "result", "cancel"];
|
|
201
|
+
readonly description: "request submits work; status/result read the saved snapshot; cancel requests cancellation.";
|
|
44
202
|
};
|
|
45
203
|
readonly payload: {
|
|
46
|
-
readonly
|
|
204
|
+
readonly description: "request 必须匹配某个 Handler 的 {handler,input};status/result/cancel 的 payload 必须为空对象 {}。";
|
|
205
|
+
readonly oneOf: readonly [...{
|
|
206
|
+
type: "object";
|
|
207
|
+
additionalProperties: false;
|
|
208
|
+
required: string[];
|
|
209
|
+
properties: {
|
|
210
|
+
handler: {
|
|
211
|
+
type: "string";
|
|
212
|
+
const: "host.read" | "host.glob" | "host.grep" | "host.edit" | "host.write" | "host.pwsh" | "test";
|
|
213
|
+
};
|
|
214
|
+
input: {
|
|
215
|
+
readonly type: "object";
|
|
216
|
+
readonly additionalProperties: false;
|
|
217
|
+
readonly required: readonly ["delayMs", "fail"];
|
|
218
|
+
readonly properties: {
|
|
219
|
+
readonly delayMs: {
|
|
220
|
+
readonly type: "integer";
|
|
221
|
+
readonly description: "Diagnostic delay in milliseconds (0-30000).";
|
|
222
|
+
};
|
|
223
|
+
readonly fail: {
|
|
224
|
+
readonly type: "boolean";
|
|
225
|
+
readonly description: "Settle as a controlled failure when true.";
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
} | {
|
|
229
|
+
readonly type: "object";
|
|
230
|
+
readonly additionalProperties: false;
|
|
231
|
+
readonly required: readonly ["file_path"];
|
|
232
|
+
readonly properties: {
|
|
233
|
+
readonly file_path: {
|
|
234
|
+
readonly type: "string";
|
|
235
|
+
readonly description: "Path resolved against the session working directory.";
|
|
236
|
+
};
|
|
237
|
+
readonly offset: {
|
|
238
|
+
readonly type: "integer";
|
|
239
|
+
readonly description: "1-based first line to read.";
|
|
240
|
+
};
|
|
241
|
+
readonly limit: {
|
|
242
|
+
readonly type: "integer";
|
|
243
|
+
readonly description: "Maximum lines to read (<=100).";
|
|
244
|
+
};
|
|
245
|
+
};
|
|
246
|
+
} | {
|
|
247
|
+
readonly type: "object";
|
|
248
|
+
readonly additionalProperties: false;
|
|
249
|
+
readonly required: readonly ["pattern"];
|
|
250
|
+
readonly properties: {
|
|
251
|
+
readonly pattern: {
|
|
252
|
+
readonly type: "string";
|
|
253
|
+
readonly description: "Glob pattern; a bare pattern matches basenames at any depth.";
|
|
254
|
+
};
|
|
255
|
+
readonly path: {
|
|
256
|
+
readonly type: "string";
|
|
257
|
+
readonly description: "Directory to search; defaults to the session working directory.";
|
|
258
|
+
};
|
|
259
|
+
};
|
|
260
|
+
} | {
|
|
261
|
+
readonly type: "object";
|
|
262
|
+
readonly additionalProperties: false;
|
|
263
|
+
readonly required: readonly ["pattern"];
|
|
264
|
+
readonly properties: {
|
|
265
|
+
readonly pattern: {
|
|
266
|
+
readonly type: "string";
|
|
267
|
+
readonly description: "Ripgrep regular expression.";
|
|
268
|
+
};
|
|
269
|
+
readonly path: {
|
|
270
|
+
readonly type: "string";
|
|
271
|
+
readonly description: "File or directory to search; defaults to the session working directory.";
|
|
272
|
+
};
|
|
273
|
+
readonly include: {
|
|
274
|
+
readonly type: "string";
|
|
275
|
+
readonly description: "One positive glob filter; negation and comma lists are rejected.";
|
|
276
|
+
};
|
|
277
|
+
};
|
|
278
|
+
} | {
|
|
279
|
+
readonly type: "object";
|
|
280
|
+
readonly additionalProperties: false;
|
|
281
|
+
readonly required: readonly ["file_path", "old_string", "new_string"];
|
|
282
|
+
readonly properties: {
|
|
283
|
+
readonly file_path: {
|
|
284
|
+
readonly type: "string";
|
|
285
|
+
readonly description: "File to edit.";
|
|
286
|
+
};
|
|
287
|
+
readonly old_string: {
|
|
288
|
+
readonly type: "string";
|
|
289
|
+
readonly description: "Literal text to replace.";
|
|
290
|
+
};
|
|
291
|
+
readonly new_string: {
|
|
292
|
+
readonly type: "string";
|
|
293
|
+
readonly description: "Replacement text.";
|
|
294
|
+
};
|
|
295
|
+
readonly replace_all: {
|
|
296
|
+
readonly type: "boolean";
|
|
297
|
+
readonly description: "Replace every occurrence.";
|
|
298
|
+
};
|
|
299
|
+
};
|
|
300
|
+
} | {
|
|
301
|
+
readonly type: "object";
|
|
302
|
+
readonly additionalProperties: false;
|
|
303
|
+
readonly required: readonly ["file_path", "content"];
|
|
304
|
+
readonly properties: {
|
|
305
|
+
readonly file_path: {
|
|
306
|
+
readonly type: "string";
|
|
307
|
+
readonly description: "File to write.";
|
|
308
|
+
};
|
|
309
|
+
readonly content: {
|
|
310
|
+
readonly type: "string";
|
|
311
|
+
readonly description: "Full file content.";
|
|
312
|
+
};
|
|
313
|
+
};
|
|
314
|
+
} | {
|
|
315
|
+
readonly type: "object";
|
|
316
|
+
readonly additionalProperties: false;
|
|
317
|
+
readonly required: readonly ["description", "command"];
|
|
318
|
+
readonly properties: {
|
|
319
|
+
readonly description: {
|
|
320
|
+
readonly type: "string";
|
|
321
|
+
readonly description: "Clear, concise description of what the command does (shown in the UI).";
|
|
322
|
+
};
|
|
323
|
+
readonly command: {
|
|
324
|
+
readonly type: "string";
|
|
325
|
+
readonly description: "PowerShell command to execute.";
|
|
326
|
+
};
|
|
327
|
+
readonly timeoutMs: {
|
|
328
|
+
readonly type: "number";
|
|
329
|
+
readonly description: "Positive timeout in milliseconds.";
|
|
330
|
+
};
|
|
331
|
+
readonly workdir: {
|
|
332
|
+
readonly type: "string";
|
|
333
|
+
readonly description: "Working directory; defaults to the session working directory.";
|
|
334
|
+
};
|
|
335
|
+
readonly run_in_background: {
|
|
336
|
+
readonly type: "boolean";
|
|
337
|
+
readonly description: "Return a host Job id immediately instead of waiting.";
|
|
338
|
+
};
|
|
339
|
+
readonly sandbox_permissions: {
|
|
340
|
+
readonly type: "string";
|
|
341
|
+
readonly enum: readonly ["workspace-write", "danger-full-access"];
|
|
342
|
+
readonly description: "Narrowest wider sandbox mode; must be paired with justification.";
|
|
343
|
+
};
|
|
344
|
+
readonly justification: {
|
|
345
|
+
readonly type: "string";
|
|
346
|
+
readonly description: "Required with sandbox_permissions; one sentence of reason.";
|
|
347
|
+
};
|
|
348
|
+
};
|
|
349
|
+
};
|
|
350
|
+
};
|
|
351
|
+
}[], {
|
|
352
|
+
readonly type: "object";
|
|
353
|
+
readonly additionalProperties: false;
|
|
354
|
+
readonly properties: {};
|
|
355
|
+
}];
|
|
47
356
|
};
|
|
48
357
|
};
|
|
49
358
|
};
|
|
@@ -52,5 +361,5 @@ export declare const STATE_PARAMETERS: {
|
|
|
52
361
|
readonly properties: {};
|
|
53
362
|
readonly additionalProperties: false;
|
|
54
363
|
};
|
|
55
|
-
export declare const REQUEST_DESCRIPTION = "\u8427\u4F55 / Xiao He. Submit a version 1 request and WAIT for its terminal result in this tool call.
|
|
364
|
+
export declare const REQUEST_DESCRIPTION = "\u8427\u4F55 / Xiao He. Submit a version 1 request and WAIT for its terminal result in this tool call. Use only when a host operation is expected to exceed ~30s, may be retried as the same logical operation (reuse requestId), must outlive a run_code budget end, or several steps must await one execution; otherwise call the original tool directly. messageId is per message; requestId is per logical operation. Control status/result/cancel use an empty payload; their snapshot is read-only. A PTC program end (including run_code budget expiry) only stops waiting: accepted work continues and the same requestId can be retrieved with status/result or cancelled. Diagnostic handler only: test {delayMs:0..30000,fail:boolean}; never use it to perform real work. Acceptance is volatile, not success. No polling or restart resume.";
|
|
56
365
|
export declare const MODE_INSTRUCTIONS: string;
|
package/dist/product.js
CHANGED
|
@@ -23,16 +23,127 @@ export const HANDLER_LIMITS = Object.freeze({
|
|
|
23
23
|
readPathChars: 2048,
|
|
24
24
|
diagnosticDelayMs: 30000,
|
|
25
25
|
});
|
|
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
|
+
},
|
|
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
|
+
/** request 的 {handler,input} 判别联合;控制消息为空对象。 */
|
|
112
|
+
export const PAYLOAD_SCHEMA = {
|
|
113
|
+
description: "request 必须匹配某个 Handler 的 {handler,input};status/result/cancel 的 payload 必须为空对象 {}。",
|
|
114
|
+
oneOf: [
|
|
115
|
+
...HANDLER_NAMES.map((handler) => ({
|
|
116
|
+
type: "object",
|
|
117
|
+
additionalProperties: false,
|
|
118
|
+
required: ["handler", "input"],
|
|
119
|
+
properties: {
|
|
120
|
+
handler: { type: "string", const: handler },
|
|
121
|
+
input: INPUT_SCHEMAS[handler],
|
|
122
|
+
},
|
|
123
|
+
})),
|
|
124
|
+
{ type: "object", additionalProperties: false, properties: {} },
|
|
125
|
+
],
|
|
126
|
+
};
|
|
26
127
|
export const REQUEST_PARAMETERS = {
|
|
27
128
|
type: "object",
|
|
28
129
|
additionalProperties: false,
|
|
29
130
|
required: ["protocolVersion", "messageId", "requestId", "type", "payload"],
|
|
30
131
|
properties: {
|
|
31
132
|
protocolVersion: { type: "integer", const: 1 },
|
|
32
|
-
messageId: {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
133
|
+
messageId: {
|
|
134
|
+
type: "string",
|
|
135
|
+
description: "Unique id of this message; reuse only when redelivering the same message.",
|
|
136
|
+
},
|
|
137
|
+
requestId: {
|
|
138
|
+
type: "string",
|
|
139
|
+
description: "Stable id of one logical operation; reuse it when the same operation is submitted again.",
|
|
140
|
+
},
|
|
141
|
+
type: {
|
|
142
|
+
type: "string",
|
|
143
|
+
enum: ["request", "status", "result", "cancel"],
|
|
144
|
+
description: "request submits work; status/result read the saved snapshot; cancel requests cancellation.",
|
|
145
|
+
},
|
|
146
|
+
payload: PAYLOAD_SCHEMA,
|
|
36
147
|
},
|
|
37
148
|
};
|
|
38
149
|
export const STATE_PARAMETERS = {
|
|
@@ -40,8 +151,8 @@ export const STATE_PARAMETERS = {
|
|
|
40
151
|
properties: {},
|
|
41
152
|
additionalProperties: false,
|
|
42
153
|
};
|
|
43
|
-
export const REQUEST_DESCRIPTION = "萧何 / Xiao He. Submit a version 1 request and WAIT for its terminal result in this tool call.
|
|
44
|
-
export const MODE_INSTRUCTIONS = "你正在萧何模式中。这不是角色扮演。保留宿主 PTC 的日常工具能力与权限规则。普通编辑、搜索、命令、安装和其他工作使用原工具,不要声称此模式只读。execution_bus
|
|
154
|
+
export const REQUEST_DESCRIPTION = "萧何 / Xiao He. Submit a version 1 request and WAIT for its terminal result in this tool call. Use only when a host operation is expected to exceed ~30s, may be retried as the same logical operation (reuse requestId), must outlive a run_code budget end, or several steps must await one execution; otherwise call the original tool directly. messageId is per message; requestId is per logical operation. Control status/result/cancel use an empty payload; their snapshot is read-only. A PTC program end (including run_code budget expiry) only stops waiting: accepted work continues and the same requestId can be retrieved with status/result or cancelled. Diagnostic handler only: test {delayMs:0..30000,fail:boolean}; never use it to perform real work. Acceptance is volatile, not success. No polling or restart resume.";
|
|
155
|
+
export const MODE_INSTRUCTIONS = "你正在萧何模式中。这不是角色扮演。保留宿主 PTC 的日常工具能力与权限规则。普通编辑、搜索、命令、安装和其他工作使用原工具,不要声称此模式只读。execution_bus 是可选协调入口,只在以下情况使用:预计单次宿主操作超过约 30 秒;同一逻辑操作可能重复提交或需要重试核对(沿用 requestId);任务需要在 run_code 时间预算结束后继续或取回结果;多个步骤需要等待同一执行。其余情况直接用原工具,不要为简单调用增加总线包装。实际业务 Handler 为 host.read、host.glob、host.grep(只读,可复用终态结果)与 host.edit、host.write、host.pwsh(有副作用,终态结果不可复用);test 仅用于用户明确要求的诊断,不做真实工作。示例:await tools.execution_bus({protocolVersion:1,messageId:\"<消息编号>\",requestId:\"<逻辑操作编号>\",type:\"request\",payload:{handler:\"host.read\",input:{file_path:\"README.md\"}}});messageId 每条消息唯一,同一逻辑操作重发沿用 requestId。通过 run_code 调用 await tools.execution_bus(...),受原有时间预算约束。每会话排队上限 " +
|
|
45
156
|
ADMISSION_DEFAULTS.sessionQueueLimit +
|
|
46
157
|
",排队超过 " +
|
|
47
158
|
ADMISSION_DEFAULTS.maxQueueWaitMs / 1000 +
|
package/docs/PRODUCT.md
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
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 改善模型侧的采用条件:模式说明写明仅在预计 >30 秒、可能重复提交、预算结束后继续或跨步骤等待同一执行时使用总线,并给出调用示例;工具声明把 payload 改为按 Handler 的判别联合,PTC SDK 与原生声明直接显示每个 Handler 的必填/可选字段。wire 协议、字段、错误码与 Handler 行为不变,只改变模型可见的提示与 schema。
|
|
12
|
+
|
|
11
13
|
## 入口及配置层次
|
|
12
14
|
|
|
13
15
|
| 入口 | 谁使用 | 责任 |
|
package/docs/protocol.md
CHANGED
|
@@ -122,4 +122,6 @@ 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
|
+
|
|
125
127
|
内置 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 显示声明开销不值得,可回退为较短的泛型声明。
|
package/docs/validation.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 验证范围与使用限制
|
|
2
2
|
|
|
3
|
-
本文说明当前版本的证据边界,不是生产环境认证。当前能力基线为 **v0.
|
|
3
|
+
本文说明当前版本的证据边界,不是生产环境认证。当前能力基线为 **v0.10.0**,在 0.5.0 的会话准入/排队、0.7.0 的宿主工具转发、0.8.0 的搜索/命令 Handler 与 0.9.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
|
|
|
@@ -45,6 +45,7 @@ eb95b4e51675f5f1821275e0812ef4dd4984b1aba45a52fbc6bab3518bbf6f38
|
|
|
45
45
|
| 从真实 tgz 经宿主插件管理器加载预设、卸载与回滚 | 未完成完整桌面流程;源码工作区的 Loader 测试不能替代 |
|
|
46
46
|
| 真实 glob/grep/pwsh 工具实现 | 未在测试环境启用:真实搜索工具依赖打包 ripgrep 与 subprocess 服务,真实 pwsh 依赖 shell/sandbox/审批组合;本版只验证按 handler 名转发、输入校验、幂等分流与失败固定码 |
|
|
47
47
|
| 跨版本 PTC 中断原因 | 分离等待只识别 DSH 0.2.1-rc.2 实际使用的固定中断原因字符串;宿主升级后未知原因保守按取消处理,需复核 |
|
|
48
|
+
| 模式采用率与效果 | 未验证。0.10.0 只改善触发说明与工具声明可读性;真实模型是否更常使用总线、是否带来更少轮次/更短耗时,需要 pilot 与同任务 A/B 对照,不能由 schema 或测试推断 |
|
|
48
49
|
| 磁盘会话结果提交及重启恢复原调用 | 未验收磁盘提交;本插件不支持跨重启恢复 |
|
|
49
50
|
| 减少真实模型轮次、状态查询或总耗时的对照 | 未验证,不给提升比例 |
|
|
50
51
|
| 长期运行、所有卸载/服务故障组合 | 未穷尽;持续故障仍有清理限制 |
|