@feng0531/dsh-execution-bus 0.7.0 → 0.8.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 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.0**
7
+ DSH 独立插件:`@feng0531/dsh-execution-bus` · 当前版本 **0.8.0**
8
8
 
9
9
  > 萧何模式从宿主已声明的 PTC 组合派生,保留日常工具,再叠加可选执行总线。已验证隔离的真实 Node PTC → 原 read + 总线调用,以及脚本模型内存会话;真实模型、桌面界面与实际沙箱仍未验收。**不支持重启后恢复任务。**
10
10
 
@@ -85,10 +85,13 @@ flowchart TD
85
85
  |---|---|---|
86
86
  | `test`(诊断,非业务) | 仅在明确诊断时检查延迟、进度、成功、失败和取消 | `delayMs`:0–30000;`fail`:布尔值 |
87
87
  | `host.read` | 经由 DSH 现有 `read` 工具读取文本 | `file_path`;可选 `offset` 和 `limit`,最多 100 行 |
88
+ | `host.glob` | 经由 DSH 现有 `glob` 工具按路径模式查找文件(只读) | `pattern`;可选 `path` |
89
+ | `host.grep` | 经由 DSH 现有 `grep` 工具检索文件内容(只读) | `pattern`;可选 `path`、`include`(单个正向 glob) |
88
90
  | `host.edit` | 经由 DSH 现有 `edit` 工具替换文本(有副作用) | `file_path`、`old_string`、`new_string`;可选 `replace_all` |
89
91
  | `host.write` | 经由 DSH 现有 `write` 工具写入文本(有副作用) | `file_path`、`content` |
92
+ | `host.pwsh` | 经由 DSH 现有 `pwsh` 工具执行 PowerShell 命令(有副作用) | `description`、`command`;可选 `timeoutMs`、`workdir`、`run_in_background`、`sandbox_permissions`、`justification` |
90
93
 
91
- `host.read`、`host.edit` 与 `host.write` 在出队时重新进入宿主工具管线,沿用宿主当前权限、会话工作目录及输出限制。`host.edit`/`host.write` 有副作用,显式声明非幂等:同一 requestId 的终态结果不可复用,重复提交返回 `MUTATING_REUSE_DENIED`。插件不自行启动命令、不提供任意远程执行服务,也不会强制将现有工具改成总线调用。
94
+ `host.*` 在出队时重新进入宿主工具管线,沿用宿主当前权限、会话工作目录、沙箱与输出限制。`host.read`/`host.glob`/`host.grep` 只读且幂等,同一 requestId 的终态结果可复用;`host.edit`/`host.write`/`host.pwsh` 有副作用,显式声明非幂等:同一 requestId 的终态结果不可复用,重复提交返回 `MUTATING_REUSE_DENIED`。`host.pwsh` 的后台模式只返回宿主 Job ID,不代表命令完成。插件不自行实现文件或命令执行端,只转发到宿主现有工具;也不提供任意远程执行服务,不会强制将现有工具改成总线调用。
92
95
 
93
96
  ## 选择“萧何”预设
94
97
 
@@ -105,7 +108,7 @@ flowchart TD
105
108
 
106
109
  **0.3.0 起不再是只读验证模式。** 加载时读取宿主 `ptc` 预设的组合声明快照,保留原工具、平台表达式、禁用项和配置,只追加萧何总线与说明。不再强制 native 呈现或添加只读白名单;终端、写入、搜索、技能等能力是否可用,取决于原 PTC 配置和宿主服务。其他预设和默认模式不被修改,原 PTC 会话看不到新增总线。
107
110
 
108
- 普通任务仍通过 `run_code` 调用原工具;**总线目前只支持 test、host.read、host.edit 和 host.write,不接管任意命令、安装或全部工具**。例如更新插件应使用原终端能力并遵守宿主授权;专用插件管理工具若在源 PTC 中禁用,萧何不会擅自启用。命令受理、返回 Job ID 不等于执行完成。
111
+ 普通任务仍通过 `run_code` 调用原工具;**总线目前只支持 test 与 host.read/host.glob/host.grep/host.edit/host.write/host.pwsh,不接管其他工具、安装或全部能力**。例如更新插件应使用原终端能力并遵守宿主授权;专用插件管理工具若在源 PTC 中禁用,萧何不会擅自启用。命令受理或返回 Job ID 不等于执行完成。
109
112
 
110
113
  升级提示:预设 ID 保持兼容,但从旧版只读模式升级后能力范围扩大,使用者须审阅后加载;本次不自动升级日常配置。它不是进程沙箱,同一预设会话共享总线容量,结果按会话隔离。派生是加载时快照,不自动跟随源预设热编辑;源 PTC 更新后应按宿主正常流程重新加载派生行,旧会话遵循宿主版本保留规则。
111
114
 
@@ -115,9 +118,9 @@ flowchart TD
115
118
 
116
119
  ## 安装前先确认
117
120
 
118
- - 兼容目标:**DSH 0.2.0-rc.2 / Cordis 4.0.4**,Node.js 22 或以上。其他宿主版本未承诺兼容。
121
+ - 兼容目标:**DSH 0.2.1-rc.2 / Cordis 4.0.4**,Node.js 22 或以上。其他宿主版本未承诺兼容。
119
122
  - 建议先选择**隔离的 DSH 配置**试用,不直接更改日常环境。
120
- - 目标组合需要可见的工具注册表、Job 服务、现有 Job 控制工具;读取任务还需要宿主 `read`。
123
+ - 目标组合需要可见的工具注册表、Job 服务、现有 Job 控制工具;读取、搜索、编辑、写入或命令任务还需要宿主对应的 `read`/`glob`/`grep`/`edit`/`write`/`pwsh` 工具。
121
124
  - 安装 npm 包不等于插件已经加载;**只有当前会话能看到 `execution_bus` 工具,才可直接调用。**
122
125
 
123
126
  ### 安装步骤
@@ -126,7 +129,7 @@ flowchart TD
126
129
  2. 在你选定的隔离 DSH 配置依赖目录安装固定版本,不要在 DSH 程序安装目录执行:
127
130
 
128
131
  ```powershell
129
- npm install --ignore-scripts @feng0531/dsh-execution-bus@0.7.0
132
+ npm install --ignore-scripts @feng0531/dsh-execution-bus@0.8.0
130
133
  ```
131
134
 
132
135
  这是 npm 目录示例。若目标配置使用 pnpm,应沿用其包管理器,不混用锁文件。遇到宿主 peer 版本冲突就停止,不用强制安装绕过。
@@ -269,7 +272,7 @@ npm run test:install # 临时目录安装,不操作日常 DSH
269
272
 
270
273
  - [协议和投递语义](<docs/protocol.md>):字段、状态、重复处理与取消规则。
271
274
  - [宿主兼容性与源码调用链](<docs/host-compatibility.md>):为什么可以等待,为什么不能跨重启恢复。
272
- - [验证记录](<docs/validation.md>)、[0.7.0 发布说明](<docs/releases/0.7.0.md>):已验证与未验证范围。
275
+ - [验证记录](<docs/validation.md>)、[0.8.0 发布说明](<docs/releases/0.8.0.md>):已验证与未验证范围。
273
276
  - [同类项目源码整合](<docs/INTEGRATION.md>):固定来源、采用范围、许可与验证边界。
274
277
  - [维护者发布流程](<docs/RELEASING.md>):标签 CI、安装包校验与正式发布门禁。
275
278
 
@@ -51,6 +51,9 @@ export declare const ERRORS: Readonly<{
51
51
  INVALID_READ_INPUT: "INVALID_READ_INPUT";
52
52
  INVALID_EDIT_INPUT: "INVALID_EDIT_INPUT";
53
53
  INVALID_WRITE_INPUT: "INVALID_WRITE_INPUT";
54
+ INVALID_GLOB_INPUT: "INVALID_GLOB_INPUT";
55
+ INVALID_GREP_INPUT: "INVALID_GREP_INPUT";
56
+ INVALID_PWSH_INPUT: "INVALID_PWSH_INPUT";
54
57
  READ_LIMIT: "READ_LIMIT";
55
58
  CONTROLLED_FAILURE: "CONTROLLED_FAILURE";
56
59
  HOST_CAPABILITY_REQUIRED: "HOST_CAPABILITY_REQUIRED";
@@ -57,6 +57,9 @@ export const ERRORS = Object.freeze({
57
57
  INVALID_READ_INPUT: "INVALID_READ_INPUT",
58
58
  INVALID_EDIT_INPUT: "INVALID_EDIT_INPUT",
59
59
  INVALID_WRITE_INPUT: "INVALID_WRITE_INPUT",
60
+ INVALID_GLOB_INPUT: "INVALID_GLOB_INPUT",
61
+ INVALID_GREP_INPUT: "INVALID_GREP_INPUT",
62
+ INVALID_PWSH_INPUT: "INVALID_PWSH_INPUT",
60
63
  READ_LIMIT: "READ_LIMIT",
61
64
  CONTROLLED_FAILURE: "CONTROLLED_FAILURE",
62
65
  HOST_CAPABILITY_REQUIRED: "HOST_CAPABILITY_REQUIRED",
@@ -9,7 +9,13 @@ export declare function hostToolHandler(toolName: string, opts: {
9
9
  export declare const testHandler: Handler;
10
10
  /** 读取:无副作用,幂等,终态结果可复用。 */
11
11
  export declare const readHandler: Handler;
12
+ /** 文件名搜索:只读,幂等,终态结果可复用;搜索基数由宿主工具限制。 */
13
+ export declare const globHandler: Handler;
14
+ /** 内容搜索:只读,幂等,终态结果可复用;匹配上限由宿主工具限制。 */
15
+ export declare const grepHandler: Handler;
12
16
  /** 写入:有副作用,非幂等,终态结果不可复用。 */
13
17
  export declare const writeHandler: Handler;
14
18
  /** 编辑:有副作用,非幂等,终态结果不可复用。 */
15
19
  export declare const editHandler: Handler;
20
+ /** 命令执行:有副作用,非幂等,终态结果不可复用;后台模式返回 Job ID 不等于完成。 */
21
+ export declare const pwshHandler: Handler;
package/dist/handlers.js CHANGED
@@ -70,6 +70,49 @@ export const readHandler = hostToolHandler("read", {
70
70
  limit: input.limit ?? HANDLER_LIMITS.readLines,
71
71
  }),
72
72
  });
73
+ function validateGlob(input) {
74
+ if (Object.keys(input).some((k) => !["pattern", "path"].includes(k)) ||
75
+ typeof input.pattern !== "string" ||
76
+ input.pattern.trim().length === 0 ||
77
+ (input.path !== undefined &&
78
+ (typeof input.path !== "string" || input.path.trim().length === 0)))
79
+ throw Error(ERRORS.INVALID_GLOB_INPUT);
80
+ }
81
+ /** 文件名搜索:只读,幂等,终态结果可复用;搜索基数由宿主工具限制。 */
82
+ export const globHandler = hostToolHandler("glob", {
83
+ idempotent: true,
84
+ validate: validateGlob,
85
+ });
86
+ function validateGrep(input) {
87
+ if (Object.keys(input).some((k) => !["pattern", "path", "include"].includes(k)) ||
88
+ typeof input.pattern !== "string" ||
89
+ input.pattern.length === 0 ||
90
+ (input.path !== undefined &&
91
+ (typeof input.path !== "string" || input.path.trim().length === 0)))
92
+ throw Error(ERRORS.INVALID_GREP_INPUT);
93
+ if (input.include === undefined)
94
+ return;
95
+ const include = input.include;
96
+ if (typeof include !== "string" || include.trim().length === 0)
97
+ throw Error(ERRORS.INVALID_GREP_INPUT);
98
+ // 与宿主 grep 契约一致:只接受单个正向 glob,不支持取反或顶层逗号列表。
99
+ if (include.startsWith("!"))
100
+ throw Error(ERRORS.INVALID_GREP_INPUT);
101
+ let braceDepth = 0;
102
+ for (const char of include) {
103
+ if (char === "{")
104
+ braceDepth++;
105
+ else if (char === "}")
106
+ braceDepth = Math.max(0, braceDepth - 1);
107
+ else if (char === "," && braceDepth === 0)
108
+ throw Error(ERRORS.INVALID_GREP_INPUT);
109
+ }
110
+ }
111
+ /** 内容搜索:只读,幂等,终态结果可复用;匹配上限由宿主工具限制。 */
112
+ export const grepHandler = hostToolHandler("grep", {
113
+ idempotent: true,
114
+ validate: validateGrep,
115
+ });
73
116
  function validateWrite(input) {
74
117
  if (Object.keys(input).some((k) => !["file_path", "content"].includes(k)) ||
75
118
  typeof input.file_path !== "string" ||
@@ -88,3 +131,44 @@ export const editHandler = hostToolHandler("edit", {
88
131
  idempotent: false,
89
132
  validate: validateEdit,
90
133
  });
134
+ /** 与宿主 pwsh 工具一致的提权目标;沙箱组合未提供提权面时由宿主拒绝。 */
135
+ const PWSH_ESCALATION_TARGETS = Object.freeze([
136
+ "workspace-write",
137
+ "danger-full-access",
138
+ ]);
139
+ function validatePwsh(input) {
140
+ if (Object.keys(input).some((k) => ![
141
+ "description",
142
+ "command",
143
+ "timeoutMs",
144
+ "workdir",
145
+ "run_in_background",
146
+ "sandbox_permissions",
147
+ "justification",
148
+ ].includes(k)) ||
149
+ typeof input.command !== "string" ||
150
+ input.command.trim().length === 0 ||
151
+ typeof input.description !== "string" ||
152
+ input.description.trim().length === 0 ||
153
+ (input.timeoutMs !== undefined &&
154
+ (!Number.isFinite(input.timeoutMs) || Number(input.timeoutMs) <= 0)) ||
155
+ (input.workdir !== undefined && typeof input.workdir !== "string") ||
156
+ (input.run_in_background !== undefined &&
157
+ typeof input.run_in_background !== "boolean"))
158
+ throw Error(ERRORS.INVALID_PWSH_INPUT);
159
+ const permissions = input.sandbox_permissions, justification = input.justification;
160
+ if ((permissions !== undefined && justification === undefined) ||
161
+ (justification !== undefined && permissions === undefined) ||
162
+ (permissions !== undefined &&
163
+ (typeof permissions !== "string" ||
164
+ !PWSH_ESCALATION_TARGETS.includes(permissions))) ||
165
+ (justification !== undefined &&
166
+ (typeof justification !== "string" ||
167
+ justification.trim().length === 0)))
168
+ throw Error(ERRORS.INVALID_PWSH_INPUT);
169
+ }
170
+ /** 命令执行:有副作用,非幂等,终态结果不可复用;后台模式返回 Job ID 不等于完成。 */
171
+ export const pwshHandler = hostToolHandler("pwsh", {
172
+ idempotent: false,
173
+ validate: validatePwsh,
174
+ });
package/dist/plugin.js CHANGED
@@ -3,15 +3,18 @@ import { ADMISSION_DEFAULTS, REQUEST_DESCRIPTION, REQUEST_PARAMETERS, STATE_PARA
3
3
  import { ExecutionOwner } from "./execution.js";
4
4
  import { ExecutionBus, parse } from "./bus.js";
5
5
  import { ERRORS } from "./error-codes.js";
6
- import { testHandler, readHandler, editHandler, writeHandler, } from "./handlers.js";
6
+ import { testHandler, readHandler, globHandler, grepHandler, editHandler, writeHandler, pwshHandler, } from "./handlers.js";
7
7
  export const name = "execution-bus";
8
8
  export const inject = ["tools", "jobs"];
9
9
  export function apply(ctx) {
10
10
  const bus = new ExecutionBus(undefined, ADMISSION_DEFAULTS);
11
11
  bus.register("test", testHandler);
12
12
  bus.register("host.read", readHandler);
13
+ bus.register("host.glob", globHandler);
14
+ bus.register("host.grep", grepHandler);
13
15
  bus.register("host.edit", editHandler);
14
16
  bus.register("host.write", writeHandler);
17
+ bus.register("host.pwsh", pwshHandler);
15
18
  const executions = new ExecutionOwner();
16
19
  ctx.effect(() => () => executions.close(() => bus.close()));
17
20
  ctx.tools.register({
package/dist/product.d.ts CHANGED
@@ -52,5 +52,5 @@ export declare const STATE_PARAMETERS: {
52
52
  readonly properties: {};
53
53
  readonly additionalProperties: false;
54
54
  };
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. Reuse requestId only for the same logical operation. Business handlers: host.read {file_path,offset?,limit?<=100}; host.edit {file_path,old_string,new_string,replace_all?}; host.write {file_path,content} (mutating, terminal reuse denied). Diagnostic handler only: test {delayMs:0..30000,fail:boolean}; never use it to perform real work. Control status/result/cancel use empty payload. Acceptance is volatile, not success. No polling or restart resume.";
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. Reuse requestId only for the same logical operation. Business handlers: host.read {file_path,offset?,limit?<=100}, host.glob {pattern,path?}, host.grep {pattern,path?,include?} (read-only, terminal reuse allowed); host.edit {file_path,old_string,new_string,replace_all?}, host.write {file_path,content}, host.pwsh {description,command,timeoutMs?,workdir?,run_in_background?,sandbox_permissions?,justification?} (mutating, terminal reuse denied). Diagnostic handler only: test {delayMs:0..30000,fail:boolean}; never use it to perform real work. Control status/result/cancel use empty payload. Acceptance is volatile, not success. No polling or restart resume.";
56
56
  export declare const MODE_INSTRUCTIONS: string;
package/dist/product.js CHANGED
@@ -40,8 +40,8 @@ export const STATE_PARAMETERS = {
40
40
  properties: {},
41
41
  additionalProperties: false,
42
42
  };
43
- export const REQUEST_DESCRIPTION = "萧何 / Xiao He. Submit a version 1 request and WAIT for its terminal result in this tool call. Reuse requestId only for the same logical operation. Business handlers: host.read {file_path,offset?,limit?<=100}; host.edit {file_path,old_string,new_string,replace_all?}; host.write {file_path,content} (mutating, terminal reuse denied). Diagnostic handler only: test {delayMs:0..30000,fail:boolean}; never use it to perform real work. Control status/result/cancel use empty payload. Acceptance is volatile, not success. No polling or restart resume.";
44
- export const MODE_INSTRUCTIONS = "你正在萧何模式中。这不是角色扮演。保留宿主 PTC 的日常工具能力与权限规则。普通编辑、搜索、命令、安装和其他工作使用原工具,不要声称此模式只读。execution_bus 是可选协调入口,实际业务 Handler 为 host.read、host.edit 与 host.write(host.edit/host.write 有副作用,终态结果不可复用);test 仅用于用户明确要求的诊断,不做真实工作,不要强制所有任务走总线。通过 run_code 调用 await tools.execution_bus(...),受原有时间预算约束。每会话排队上限 " +
43
+ export const REQUEST_DESCRIPTION = "萧何 / Xiao He. Submit a version 1 request and WAIT for its terminal result in this tool call. Reuse requestId only for the same logical operation. Business handlers: host.read {file_path,offset?,limit?<=100}, host.glob {pattern,path?}, host.grep {pattern,path?,include?} (read-only, terminal reuse allowed); host.edit {file_path,old_string,new_string,replace_all?}, host.write {file_path,content}, host.pwsh {description,command,timeoutMs?,workdir?,run_in_background?,sandbox_permissions?,justification?} (mutating, terminal reuse denied). Diagnostic handler only: test {delayMs:0..30000,fail:boolean}; never use it to perform real work. Control status/result/cancel use empty payload. Acceptance is volatile, not success. No polling or restart resume.";
44
+ export const MODE_INSTRUCTIONS = "你正在萧何模式中。这不是角色扮演。保留宿主 PTC 的日常工具能力与权限规则。普通编辑、搜索、命令、安装和其他工作使用原工具,不要声称此模式只读。execution_bus 是可选协调入口,实际业务 Handler 为 host.read、host.glob、host.grep(只读,可复用终态结果)与 host.edit、host.write、host.pwsh(有副作用,终态结果不可复用);test 仅用于用户明确要求的诊断,不做真实工作,不要强制所有任务走总线。通过 run_code 调用 await tools.execution_bus(...),受原有时间预算约束。每会话排队上限 " +
45
45
  ADMISSION_DEFAULTS.sessionQueueLimit +
46
46
  ",排队超过 " +
47
47
  ADMISSION_DEFAULTS.maxQueueWaitMs / 1000 +
package/docs/FLOW-TEST.md CHANGED
@@ -33,7 +33,7 @@ npm run test:install
33
33
  - 合作取消、晚取消、未知结果不自动重跑。
34
34
  - 深层/非 JSON 结果拒绝,结果和通知不可变,异步观察者拒绝隔离。
35
35
  - 已受理 Handler 与替换注册并存,旧注销函数不破坏新注册。
36
- - 宿主 read 真正经过工具管线;前置拒绝仍生效。
36
+ - 宿主 read/glob/grep/edit/write/pwsh 真正经过工具管线;前置拒绝仍生效(搜索与命令的转发测试使用宿主工具桩,不代表真实工具实现)。
37
37
  - Job 先行移除、等待/清理异常与卸载交错。
38
38
  - 派生预设成功激活、原 ptc 声明不变、普通 Agent 不可见总线、write/edit 保留且宿主策略可拒绝。
39
39
  - 真实 Node PTC 进程调用原 read 与总线;测试使用显式非约束策略,不代表桌面沙箱通过。
@@ -42,7 +42,7 @@ npm run test:install
42
42
 
43
43
  ## 测试之外仍需注意
44
44
 
45
- - 宿主 read 的错误目前被适配层统一映射为 `HOST_READ_FAILED`;在取消后可能保守记为 `unknown`,不能把它当作取消已确认。
45
+ - 宿主工具调用失败在转发层使用固定码(host.read 为 `HOST_READ_FAILED`,其余为 `HOST_TOOL_FAILED`),进入总线后统一结算为 `failed` / `HANDLER_FAILED`,错误原文不保存;取消后可能保守记为 `unknown`,不能把它当作取消已确认。
46
46
  - 相同逻辑请求的取消是请求级取消,不能简单用 Promise.race 放弃执行来改成等待者级取消。
47
47
  - 当前没有远端 Handler 传输或持久化恢复;测试没有提供这些能力。
48
48
 
package/docs/PRODUCT.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  ## 产品边界
4
4
 
5
- 萧何是 DSH 内的可选执行协调插件,提供独立可选择的 PTC 派生预设,不是 PTC 替代传输层,也不全局接管终端、编辑或其他工具。实际业务 Handler 为 host.read、host.edit 与 host.write(host.edit/host.write 有副作用、非幂等);test 是兼容保留的诊断 Handler,只有明确诊断需求时使用。测试能力存在不代表其他命令已接入总线。
5
+ 萧何是 DSH 内的可选执行协调插件,提供独立可选择的 PTC 派生预设,不是 PTC 替代传输层,也不全局接管终端、编辑或其他工具。实际业务 Handler 为 host.read、host.glob、host.grep(只读、幂等)与 host.edit、host.write、host.pwsh(有副作用、非幂等);test 是兼容保留的诊断 Handler,只有明确诊断需求时使用。测试能力存在不代表其他工具或命令已接入总线。
6
6
 
7
- 0.7.0 在 DSH 0.2.1-rc.2 基线上接入 host.edit 与 host.write,并以幂等声明约束有副作用 Handler 的结果复用,不以更名宣称完成生产环境认证。当前真实模型、桌面 UI 和实际沙箱尚未完整验收;同进程内存状态不支持跨重启恢复。
7
+ 0.8.0 在 DSH 0.2.1-rc.2 基线上补入只读搜索 Handler host.glob / host.grep 与有副作用命令 Handler host.pwsh,沿用 0.7.0 的幂等声明与宿主工具工厂,不以更名宣称完成生产环境认证。当前真实模型、桌面 UI 和实际沙箱尚未完整验收;同进程内存状态不支持跨重启恢复。
8
8
 
9
9
  ## 入口及配置层次
10
10
 
@@ -25,10 +25,10 @@
25
25
  | product | 固定身份、容量/准入默认值、工具参数与提示契约 | 不提供用户可覆盖的运行时配置入口 |
26
26
  | preset | 声明派生、兼容检查和宿主注册 | 不偷偷重写源 ptc 或持久配置 |
27
27
  | mode / test-mode 兼容层 | 作用域说明与工具安装 | 不改宿主权限/沙箱/呈现,不加载第二套 PTC |
28
- | plugin | 工具身份校验、可信执行上下文和宿主 read 派发 | 不自行文件读取或创建通用命令执行端 |
28
+ | plugin | 工具身份校验、可信执行上下文和宿主工具派发 | 不自行文件读取、搜索或创建通用命令执行端 |
29
29
  | bus / json | 请求校验、幂等冲突、调度、取消、终态与有界状态 | 不以超时推定副作用失败、不自动重跑 |
30
30
  | execution | Job 投影、活跃工具交付与关闭所有权 | 不作为第二个执行状态机 |
31
- | handlers | 实际读取适配和明确诊断 Handler | 不把测试当成通用业务执行 |
31
+ | handlers | 宿主工具转发(read/glob/grep/edit/write/pwsh)和明确诊断 Handler | 不把测试当成通用业务执行 |
32
32
  | diagnostics | 有界数值轨迹 | 不保留请求内容、错误原文或充当授权审计 |
33
33
 
34
34
  ## 兼容和错误规则
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 兼容目标
4
4
 
5
- 源码调查基线为 **2026-10-15 的 DSH 0.2.0-rc.2、Cordis 4.0.4**。本项目用同版本 npm 组件编译和隔离测试;这不是对任意旧版、新版宿主的兼容保证,也不是对读者当前安装版本的自动检测。Node.js 要求为 22 或以上;CI 使用 Node 22、24。
5
+ 源码调查基线为 **2026-10-15 的 DSH 0.2.0-rc.2、Cordis 4.0.4**;0.6.0 起兼容目标与 npm 依赖升级为 **DSH 0.2.1-rc.2**(Cordis ~4.0.4),本文调用链行号仍来自 0.2.0-rc.2 调查快照,宿主升级后可能已变化,需按实际安装包复核。本项目用兼容目标版本的 npm 组件编译和隔离测试;这不是对任意旧版、新版宿主的兼容保证,也不是对读者当前安装版本的自动检测。Node.js 要求为 22 或以上;CI 使用 Node 22、24。
6
6
 
7
7
  本项目只做插件,没有修改宿主源码、ASAR 或其他插件。
8
8
 
@@ -13,7 +13,7 @@ AgentLoop 发起工具调用
13
13
  → ToolRuntime 校验、策略与可信身份绑定
14
14
  → execution_bus 工具体
15
15
  → 内存去重/排队,宿主 Job 记录和程序等待
16
- → test Handler 或经 ToolRuntime 再调用宿主 read
16
+ → test Handler 或经 ToolRuntime 再调用宿主工具(read/glob/grep/edit/write/pwsh)
17
17
  → 保存执行结果,清理 Job
18
18
  → 工具体返回
19
19
  → AgentLoop 关联原工具调用并继续会话
package/docs/protocol.md CHANGED
@@ -116,4 +116,4 @@ core 实例的 `diagnostics()` 返回只读用途的独立快照:阶段计数
116
116
 
117
117
  包的 `./core` 导出 ExecutionBus、Handler、Capability 类型。Handler 只接收输入、requestId、signal、progress 和可选最小 capability,不接收聊天历史。register 返回绑定唯一注册令牌的幂等注销函数,不会误删后来同名注册;已受理请求继续持有原 Handler。
118
118
 
119
- 内置 test 与 host.read 没有副作用;host.edit 与 host.write 是非幂等写 Handler,通过 `Handler.idempotent=false` 显式声明,其终态结果复用被 `MUTATING_REUSE_DENIED` 拒绝,运行中的重复附着仍只等待同一执行。当前没有 ctx.executionBus 服务、远端传输、跨插件动态注册或外部副作用对账契约。扩展有副作用 Handler 前必须显式声明幂等并另行设计授权与崩溃对账,不能仅依赖本版请求键。
119
+ 内置 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,18 @@
1
+ # 萧何 / Xiao He 0.8.0
2
+
3
+ ## 宿主工具覆盖面扩展:搜索与命令
4
+
5
+ 本版沿用 0.7.0 的通用 `hostToolHandler` 工厂与 `makeHostInvoke` 抽象,新增三个宿主工具 Handler。
6
+
7
+ - 新增 `host.glob`(`pattern` / `path?`)与 `host.grep`(`pattern` / `path?` / `include?`):只读、幂等,终态结果可复用;沿用宿主工具的工作目录、忽略规则与结果上限。`include` 只接受单个正向 glob,不支持取反(`!`)或顶层逗号列表。
8
+ - 新增 `host.pwsh`(`description` / `command` / `timeoutMs?` / `workdir?` / `run_in_background?` / `sandbox_permissions?` / `justification?`):有副作用、非幂等,同一 requestId 的终态结果不可复用,重复提交返回 `MUTATING_REUSE_DENIED`;运行中的重复附着仍只等待同一执行。`sandbox_permissions` 只接受 `workspace-write` / `danger-full-access`,且必须与 `justification` 成对出现,与宿主 pwsh/sandbox 契约一致。
9
+ - 命令仍由宿主 `pwsh` 工具经 shell 执行器、沙箱与审批链执行;插件不自行启动进程。后台模式只返回宿主 Job ID,不等于命令完成。
10
+ - 新增错误码 `INVALID_GLOB_INPUT`、`INVALID_GREP_INPUT`、`INVALID_PWSH_INPUT`;既有错误码、协议字段与 `host.read` / `host.edit` / `host.write` 行为不变。
11
+
12
+ ## 升级说明
13
+
14
+ 需要 DSH 0.2.1-rc.2。本版不强制把原工具改成总线调用,普通任务仍使用原工具;`host.glob` / `host.grep` / `host.pwsh` 只在你显式提交总线请求时执行。不自动安装、重写日常配置或重启 DSH。历史预设、配置行、工具名、协议字段与既有错误码均不变。
15
+
16
+ ## 验证与限制
17
+
18
+ 本地全量 93 项测试通过(含 host.glob / host.grep / host.pwsh 的转发、参数校验与幂等分流回归;搜索与命令 Handler 的转发测试使用宿主工具桩,不是真实搜索/命令实现),包白名单校验通过。真实 glob/grep/pwsh 工具实现、真实模型、桌面 UI 与实际沙箱仍未完整验收;状态为进程内存,不支持跨重启恢复。有副作用 Handler 的外部副作用对账仍不在本版范围。
@@ -1,13 +1,13 @@
1
1
  # 验证范围与使用限制
2
2
 
3
- 本文说明当前版本的证据边界,不是生产环境认证。当前能力基线为 **v0.5.0**,在此前生命周期、数值诊断及轮转上新增会话准入配额、排队期限和隔离状态工具;预设沿用 v0.3.0 的宿主 PTC 声明派生方式。验证环境为 Windows、Node.js 24.21.0,宿主组件锁定 DSH 0.2.0-rc.2、Cordis 4.0.4。
3
+ 本文说明当前版本的证据边界,不是生产环境认证。当前能力基线为 **v0.8.0**,在 0.5.0 的会话准入/排队与 0.7.0 的宿主工具转发上补入只读搜索(host.glob/host.grep)与命令(host.pwsh)Handler;预设沿用 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
 
7
7
  | 层次 | 检查内容 | 能说明什么 |
8
8
  |---|---|---|
9
9
  | 总线核心 | 参数、队列、并发、重复请求、冲突、取消竞争、结果保存、TTL、监听与注销 | 程序内部约束及已覆盖异常路径可重复检查 |
10
- | 真实宿主组件 | Cordis、ToolRuntime、LocalJobs、LocalFS、文件工具 | 请求经过真实工具管线;权限拒绝、Job 进度、共享任务与清理逻辑有效;Agent 身份为夹具 |
10
+ | 真实宿主组件 | Cordis、ToolRuntime、LocalJobs、LocalFS、文件工具;host.glob/host.grep/host.pwsh 的转发测试使用宿主工具桩 | 请求经过真实工具管线;权限拒绝、Job 进度、共享任务、参数校验、幂等分流与清理逻辑有效;Agent 身份与工具实现为夹具,桩不证明真实搜索/命令工具实现 |
11
11
  | 真实会话循环 | AgentLoop、AgentRegistry、SessionStore;脚本模型适配器 | 内存会话中原工具结果只提交一次,完成后再进入下一次适配器调用 |
12
12
  | 预设隔离 | AgentPresetRegistry 与 Loader | 派生预设可激活;源 ptc 声明不变、普通 Agent 不可见总线;原 write/edit/Job 工具保留,宿主前置策略拒绝仍有效 |
13
13
  | 故障注入 | 克隆失败、观察者拒绝、Job 等待/清理异常、先行移除与卸载交错 | 指定故障下的回归约束;不证明所有故障组合都已覆盖 |
@@ -42,6 +42,7 @@ eb95b4e51675f5f1821275e0812ef4dd4984b1aba45a52fbc6bab3518bbf6f38
42
42
  | 当前桌面预设卡片、进度界面、授权提示和实际沙箱 | 未验收;组件事件和 LocalFS 测试不等于桌面 UI/沙箱 |
43
43
  | 实际模型/桌面 PTC 与时间预算、沙箱行为 | 真实 Node PTC 隔离子进程已调用原 read 和总线;使用显式 danger-full-access 测试策略与测试 Agent,不是桌面沙箱/真实模型验收 |
44
44
  | 从真实 tgz 经宿主插件管理器加载预设、卸载与回滚 | 未完成完整桌面流程;源码工作区的 Loader 测试不能替代 |
45
+ | 真实 glob/grep/pwsh 工具实现 | 未在测试环境启用:真实搜索工具依赖打包 ripgrep 与 subprocess 服务,真实 pwsh 依赖 shell/sandbox/审批组合;本版只验证按 handler 名转发、输入校验、幂等分流与失败固定码 |
45
46
  | 磁盘会话结果提交及重启恢复原调用 | 未验收磁盘提交;本插件不支持跨重启恢复 |
46
47
  | 减少真实模型轮次、状态查询或总耗时的对照 | 未验证,不给提升比例 |
47
48
  | 长期运行、所有卸载/服务故障组合 | 未穷尽;持续故障仍有清理限制 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feng0531/dsh-execution-bus",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "license": "SEE LICENSE IN LICENSE",