@feng0531/dsh-execution-bus 0.2.6 → 0.2.8
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 +3 -3
- package/dist/bus.js +22 -4
- package/dist/plugin.js +12 -0
- package/docs/protocol.md +2 -2
- package/docs/releases/0.2.7.md +12 -0
- package/docs/releases/0.2.8.md +15 -0
- package/docs/validation.md +1 -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.2.
|
|
7
|
+
DSH 独立插件:`@feng0531/dsh-execution-bus` · 当前版本 **0.2.8**
|
|
8
8
|
|
|
9
9
|
> 当前是早期可运行版本,不是完整生产验收版。已验证真实 DSH 组件和脚本模型驱动的内存会话;真实模型、桌面界面和 PTC 完整链路尚未验收。**不支持重启后恢复任务。**
|
|
10
10
|
|
|
@@ -102,7 +102,7 @@ flowchart TD
|
|
|
102
102
|
2. 在你选定的隔离 DSH 配置依赖目录安装固定版本,不要在 DSH 程序安装目录执行:
|
|
103
103
|
|
|
104
104
|
```powershell
|
|
105
|
-
npm install --ignore-scripts @feng0531/dsh-execution-bus@0.2.
|
|
105
|
+
npm install --ignore-scripts @feng0531/dsh-execution-bus@0.2.8
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
这是 npm 目录示例。若目标配置使用 pnpm,应沿用其包管理器,不混用锁文件。遇到宿主 peer 版本冲突就停止,不用强制安装绕过。
|
|
@@ -231,7 +231,7 @@ npm run test:install # 临时目录安装,不操作日常 DSH
|
|
|
231
231
|
|
|
232
232
|
- [协议和投递语义](<docs/protocol.md>):字段、状态、重复处理与取消规则。
|
|
233
233
|
- [宿主兼容性与源码调用链](<docs/host-compatibility.md>):为什么可以等待,为什么不能跨重启恢复。
|
|
234
|
-
- [验证记录](<docs/validation.md>)、[0.2.
|
|
234
|
+
- [验证记录](<docs/validation.md>)、[0.2.8 发布说明](<docs/releases/0.2.8.md>):已验证与未验证范围。
|
|
235
235
|
- [维护者发布流程](<docs/RELEASING.md>):标签 CI、安装包校验与正式发布门禁。
|
|
236
236
|
|
|
237
237
|
## 许可
|
package/dist/bus.js
CHANGED
|
@@ -68,6 +68,22 @@ export class ExecutionBus {
|
|
|
68
68
|
retentionMs: 3600000,
|
|
69
69
|
}) {
|
|
70
70
|
this.options = options;
|
|
71
|
+
const keys = [
|
|
72
|
+
"concurrency",
|
|
73
|
+
"queueLimit",
|
|
74
|
+
"recordLimit",
|
|
75
|
+
"resultBytes",
|
|
76
|
+
"retentionMs",
|
|
77
|
+
];
|
|
78
|
+
if (!options ||
|
|
79
|
+
typeof options !== "object" ||
|
|
80
|
+
Array.isArray(options) ||
|
|
81
|
+
Reflect.ownKeys(options).length !== keys.length ||
|
|
82
|
+
keys.some((key) => {
|
|
83
|
+
const descriptor = Object.getOwnPropertyDescriptor(options, key);
|
|
84
|
+
return (!descriptor || !("value" in descriptor) || !descriptor.enumerable);
|
|
85
|
+
}))
|
|
86
|
+
throw Error("INVALID_OPTIONS");
|
|
71
87
|
this.options = Object.freeze({ ...options });
|
|
72
88
|
for (const v of Object.values(this.options))
|
|
73
89
|
if (!Number.isSafeInteger(v) || v < 1)
|
|
@@ -194,10 +210,12 @@ export class ExecutionBus {
|
|
|
194
210
|
return attached;
|
|
195
211
|
}
|
|
196
212
|
attachment(e, onEvent, id) {
|
|
197
|
-
|
|
213
|
+
// Each attachment owns its registration, even when callers reuse one function.
|
|
214
|
+
const listener = onEvent ? (event) => onEvent(event) : undefined;
|
|
215
|
+
if (listener && !terminal(e.view.state)) {
|
|
198
216
|
if (e.listeners.size >= 32)
|
|
199
217
|
throw Error("WAITER_LIMIT");
|
|
200
|
-
e.listeners.add(
|
|
218
|
+
e.listeners.add(listener);
|
|
201
219
|
}
|
|
202
220
|
const accepted = {
|
|
203
221
|
protocolVersion: 1,
|
|
@@ -213,8 +231,8 @@ export class ExecutionBus {
|
|
|
213
231
|
done: e.done,
|
|
214
232
|
cancel: () => this.cancel(e),
|
|
215
233
|
detach: () => {
|
|
216
|
-
if (
|
|
217
|
-
e.listeners.delete(
|
|
234
|
+
if (listener)
|
|
235
|
+
e.listeners.delete(listener);
|
|
218
236
|
},
|
|
219
237
|
returned: () => {
|
|
220
238
|
e.view.delivery = "returned";
|
package/dist/plugin.js
CHANGED
|
@@ -69,6 +69,18 @@ export function apply(ctx) {
|
|
|
69
69
|
throw Error("HOST_READ_FAILED");
|
|
70
70
|
return result.value;
|
|
71
71
|
});
|
|
72
|
+
// Terminal reuse is a read of an existing result, not admission of new work.
|
|
73
|
+
if (attached.accepted.payload.state !== "queued" &&
|
|
74
|
+
attached.accepted.payload.state !== "running") {
|
|
75
|
+
try {
|
|
76
|
+
const value = await attached.done;
|
|
77
|
+
attached.returned();
|
|
78
|
+
return value;
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
attached.detach();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
72
84
|
const abort = () => attached.cancel();
|
|
73
85
|
const jobKey = JSON.stringify([owner.sessionId, m.requestId]);
|
|
74
86
|
let settled = sharedJobs.get(jobKey);
|
package/docs/protocol.md
CHANGED
|
@@ -16,7 +16,7 @@ type 为 request 时 payload 为 {handler,input};type 为 status / result / ca
|
|
|
16
16
|
|
|
17
17
|
核心 submit 返回 accepted 事件和 done Promise。受理只意味着已进入内存记录和队列,durable:false;不是成功。事件包含 protocolVersion、messageId、requestId、correlationId(首次请求 messageId)、sequence、type、payload。每请求 sequence 单调递增,accepted 是当前序号的快照,不占新增序号。
|
|
18
18
|
|
|
19
|
-
事件类型:accepted、started、progress、cancel_requested、succeeded、failed、cancelled、unknown。进度只接受 Handler 正整数序号递增的百分比,重复、乱序、终态后进度丢弃。进程内投递,无外部消息接收端,也不支持任意远端终态注入;终态只由总线持有的执行 Promise 结算。事件及其 payload
|
|
19
|
+
事件类型:accepted、started、progress、cancel_requested、succeeded、failed、cancelled、unknown。进度只接受 Handler 正整数序号递增的百分比,重复、乱序、终态后进度丢弃。进程内投递,无外部消息接收端,也不支持任意远端终态注入;终态只由总线持有的执行 Promise 结算。事件及其 payload 在投递前深度冻结,观察者不得修改请求关联、序号、类型或进度内容。每个附着拥有独立观察者注册和名额,即使复用同一回调;detach 幂等且只移除自己的通知,不影响其他附着或执行结果。观察者是最佳努力通知:同步抛错及异步 Promise 拒绝均被隔离,不记录异常原文;不等待观察者完成,不保证关闭前异步通知已经完成,观察者须自行管理资源。
|
|
20
20
|
|
|
21
21
|
工具的 request 保持 pending,最终返回 RecordView(requestId,state,sequence,cancelRequested,delivery,result?,error?,progress?);status/result/cancel 返回同一种当前快照。工具不会提前返回 accepted 或 taskId,也不会用聊天进度消息唤醒模型。Job 的 UI progress 只含状态/百分比。
|
|
22
22
|
|
|
@@ -31,7 +31,7 @@ queued → cancelled。终态不可变;取消终态任务只返回原状态。
|
|
|
31
31
|
|
|
32
32
|
## 容量和清理
|
|
33
33
|
|
|
34
|
-
默认并发 2,待分发队列 32,记录 256,单结果 JSON 64 KiB;所有请求先经上限检查,满则 BACKPRESSURE,不自动重试。Job 仍受宿主自己的每 owner 容量限制。队列不提供公平性 SLA,单会话可占满实例。core 构造时复制并冻结容量配置,之后修改调用方原对象不改变总线限制;没有动态配置更新接口。重复附着只有成功取得观察者名额后才提交新消息记账,WAITER_LIMIT 拒绝不占用消息 ID 或额度。
|
|
34
|
+
默认并发 2,待分发队列 32,记录 256,单结果 JSON 64 KiB;所有请求先经上限检查,满则 BACKPRESSURE,不自动重试。Job 仍受宿主自己的每 owner 容量限制。队列不提供公平性 SLA,单会话可占满实例。core 不传配置时使用默认值;传入配置必须完整包含五项正安全整数,不接受部分配置、额外字段或访问器,缺项立即 INVALID_OPTIONS。core 构造时复制并冻结容量配置,之后修改调用方原对象不改变总线限制;没有动态配置更新接口。重复附着只有成功取得观察者名额后才提交新消息记账,WAITER_LIMIT 拒绝不占用消息 ID 或额度。
|
|
35
35
|
|
|
36
36
|
终态自完成后保存一小时;新受理及控制消息查询时惰性清理,可通过 core.sweep 主动清理。无定时器常驻、无磁盘结果存储、无日志输出。插件关闭先停止受理,取消队列与运行任务,等待合作 Handler,清理内存;不合作的 Handler 会阻碍关闭,插件无法安全硬杀同进程代码。
|
|
37
37
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# 萧何 / Xiao He 0.2.7
|
|
2
|
+
|
|
3
|
+
## BUG 修复
|
|
4
|
+
|
|
5
|
+
- core 构造器补齐完整配置校验:不传参数仍使用默认值;显式配置须包含 concurrency、queueLimit、recordLimit、resultBytes、retentionMs 五项正安全整数。缺项、额外字段、非对象及访问器立即 INVALID_OPTIONS,避免受理后因缺少并发配置而不执行。不扩展部分配置契约。
|
|
6
|
+
- 每个附着使用独立监听注册,复用同一回调时,解除一个附着不再移除其他附着的进度和终态通知。每个活跃监听附着独立占用名额;detach 可重复执行。
|
|
7
|
+
|
|
8
|
+
## 验证与限制
|
|
9
|
+
|
|
10
|
+
新增三项回归:不完整和异常配置拒绝、默认及完整配置正常调度、共享回调独立解除与名额上限。两个缺陷用例修复前失败,修复后全量与正式发布门禁验证。
|
|
11
|
+
|
|
12
|
+
不改变工具/预设标识。真实模型、桌面 GUI 和 PTC 完整链路未验收,不支持跨重启恢复。DSH 0.2.0-rc.2,非商业源码公开许可,发布不自动安装或重启 DSH。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 萧何 / Xiao He 0.2.8
|
|
2
|
+
|
|
3
|
+
## BUG 修复
|
|
4
|
+
|
|
5
|
+
已终态且仍在保存期的重复请求直接返回保存结果,不再申请新的宿主 Job,修复其他任务占满 Job 容量时,相同请求重发错误返回 HOST_JOB_UNAVAILABLE 的问题。
|
|
6
|
+
|
|
7
|
+
请求冲突检测、会话归属、保存期限及消息额度继续由总线校验;新任务仍正常受 Job 容量背压。正在执行的重复请求继续共用原 Job,不重复执行 Handler。
|
|
8
|
+
|
|
9
|
+
## 验证
|
|
10
|
+
|
|
11
|
+
新增真实 Cordis/ToolRuntime/LocalJobs 隔离回归:Job 上限为 1 时,成功及失败终态请求均可在槽位满时复用结果,不新增 Job;不同输入冲突仍拒绝、新任务仍因容量拒绝。该用例修复前失败,修复后与全量回归、标签四矩阵和安装包门禁一并验证。
|
|
12
|
+
|
|
13
|
+
## 边界
|
|
14
|
+
|
|
15
|
+
DSH 0.2.0-rc.2,非商业源码公开许可。当前桌面/真实模型/PTC 完整链路未验收,不支持跨重启恢复。发布不自动安装或重启 DSH。
|
package/docs/validation.md
CHANGED
|
@@ -54,7 +54,7 @@ npm test:**21/21 通过**。本地 tgz 已在 artifacts/package-check 独立
|
|
|
54
54
|
|
|
55
55
|
## 已知限制
|
|
56
56
|
|
|
57
|
-
- 并发重复附着现在共享一个宿主 Job 和程序等待者;回归测试断言只新增一个 Job。Job admission
|
|
57
|
+
- 并发重复附着现在共享一个宿主 Job 和程序等待者;回归测试断言只新增一个 Job。Job admission 首次失败会取消尚未执行的受理请求。从 0.2.8 起,保存期内已终态请求的重复提交直接复用保存结果,不再新建短暂 Job,也不受新的 Job 容量准入影响;新任务仍受宿主容量限制。
|
|
58
58
|
- 同一逻辑请求的任一等待工具被取消,会请求取消共享执行;这是本版明确的请求级取消规则,不是独立等待者取消。
|
|
59
59
|
- returned 不证明宿主已经持久化或模型已经消费,取消/后置策略仍可能改变最终宿主结果。
|
|
60
60
|
- 核心不是独立安全边界;可信插件可以注册 Handler,恶意同进程插件不在威胁模型内。
|