@xgjktech/xg_cwork_im 1.17.53 → 1.17.55

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.
Files changed (32) hide show
  1. package/dist/index.d.ts.map +1 -1
  2. package/dist/index.js +25 -3
  3. package/dist/index.js.map +1 -1
  4. package/dist/src/active-round-registry.d.ts +4 -0
  5. package/dist/src/active-round-registry.d.ts.map +1 -1
  6. package/dist/src/active-round-registry.js +20 -0
  7. package/dist/src/active-round-registry.js.map +1 -1
  8. package/dist/src/dispatch-mentioned-reply.d.ts.map +1 -1
  9. package/dist/src/dispatch-mentioned-reply.js +88 -40
  10. package/dist/src/dispatch-mentioned-reply.js.map +1 -1
  11. package/dist/src/plugin-dispose.d.ts.map +1 -1
  12. package/dist/src/plugin-dispose.js +4 -0
  13. package/dist/src/plugin-dispose.js.map +1 -1
  14. package/dist/src/subagent-monitor.d.ts +11 -0
  15. package/dist/src/subagent-monitor.d.ts.map +1 -1
  16. package/dist/src/subagent-monitor.js +45 -12
  17. package/dist/src/subagent-monitor.js.map +1 -1
  18. package/dist/src/subagent-monitor.test.js +37 -0
  19. package/dist/src/subagent-monitor.test.js.map +1 -1
  20. package/dist/src/turn-agent-event-subscription.d.ts +25 -0
  21. package/dist/src/turn-agent-event-subscription.d.ts.map +1 -0
  22. package/dist/src/turn-agent-event-subscription.js +172 -0
  23. package/dist/src/turn-agent-event-subscription.js.map +1 -0
  24. package/dist/src/turn-end-controller.d.ts +62 -0
  25. package/dist/src/turn-end-controller.d.ts.map +1 -0
  26. package/dist/src/turn-end-controller.js +240 -0
  27. package/dist/src/turn-end-controller.js.map +1 -0
  28. package/dist/src/turn-end-controller.test.d.ts +2 -0
  29. package/dist/src/turn-end-controller.test.d.ts.map +1 -0
  30. package/dist/src/turn-end-controller.test.js +91 -0
  31. package/dist/src/turn-end-controller.test.js.map +1 -0
  32. package/package.json +2 -2
@@ -0,0 +1,240 @@
1
+ /**
2
+ * 整轮(user-turn)结束仲裁。
3
+ *
4
+ * OpenClaw 7.1+ / 8.x(lifecycle 语义一致;245 实测为 2026.7.1-2):父会话(主会话)
5
+ * 自己的 finish 就是它某段 run 的 lifecycle `end/error` 终态且 `yielded !== true`
6
+ * (`yielded:true` 只出现在该段挂起了子任务、会话被挂起等待 resume 时——核心据此把
7
+ * requester 保留为可唤醒)。因此:
8
+ * - 「yield 段终态」≠ 整轮结束(主会话还会 resume 继续派发/产出最终答复);
9
+ * - 「非 yield 段终态」= 主会话 finish:该段不会再挂起子任务、不会再被唤醒。
10
+ *
11
+ * 收尾条件(防御性补强,主判据仍是主会话的非 yield finish):
12
+ * dispatch 已返回 ∧ 无段在跑(segmentActive=false,避免拿旧段终态收尾)
13
+ * ∧ 无运行中子任务(兜非标准边界:异常/乱序下非 yield 终态先于子任务结束到达)
14
+ * ∧ 已出现非 yield 段终态。
15
+ *
16
+ * 本模块只维护进程级共享的每轮状态与「可收尾」信号,不持有任何 WS/HTTP 副作用:
17
+ * - wrapper finally、subagent spawn/end、lifecycle start/end、以及组内活动心跳都来喂状态;
18
+ * - dispatch-mentioned-reply 在 wrapper 里 await 本模块的可收尾信号后再发 RUN_USAGE/FINISHED;
19
+ * - 子任务完成但主会话无法被唤醒(announce/handoff 投递,不再产生 resume 终态)、
20
+ * 或 lifecycle 事件完全不可达(订阅不可用等环境)时,靠静默兜底定时器收尾,保证不悬挂。
21
+ */
22
+ import { getSharedMap } from "./process-shared-store.js";
23
+ /** 非 yield 终态到达后、置可收尾前的防抖(吞掉与 resume 的竞态)。 */
24
+ let NON_YIELD_DEBOUNCE_MS = 1_500;
25
+ /** 子任务全完成但父会话暂未 resume/无 lifecycle 时的静默兜底窗口。 */
26
+ let RESUME_WAIT_FALLBACK_MS = 20_000;
27
+ /** 完全没有 lifecycle 事件(订阅不可用)时的兜底窗口。 */
28
+ let NO_LIFECYCLE_FALLBACK_MS = 30_000;
29
+ const states = getSharedMap("turn-end-states");
30
+ const DIAG = "[xg_cwork_im] [turn-diag]";
31
+ function stateOf(roundKey, gen) {
32
+ const s = states.get(roundKey);
33
+ if (!s || s.gen !== gen)
34
+ return undefined;
35
+ return s;
36
+ }
37
+ function clearTimer(s) {
38
+ if (s.timer !== undefined) {
39
+ clearTimeout(s.timer);
40
+ s.timer = undefined;
41
+ }
42
+ }
43
+ function isQuiescent(s) {
44
+ return s.dispatchReturned && !s.segmentActive && s.activeChildren <= 0;
45
+ }
46
+ /** 防抖置位:静默窗口内无新事件才真正 eligible(避免与 resume 的毫秒级竞态)。 */
47
+ function setEligible(roundKey, gen, s, reason) {
48
+ clearTimer(s);
49
+ s.timer = setTimeout(() => {
50
+ s.timer = undefined;
51
+ const cur = stateOf(roundKey, gen);
52
+ if (!cur)
53
+ return;
54
+ if (isQuiescent(cur) && !cur.eligible) {
55
+ cur.eligible = true;
56
+ console.log(`${DIAG} eligible round=${roundKey}#${gen} reason=${reason} ` +
57
+ `children=${cur.activeChildren} segActive=${cur.segmentActive} ` +
58
+ `lifecycleSeen=${cur.lifecycleSeen}`);
59
+ }
60
+ }, NON_YIELD_DEBOUNCE_MS);
61
+ s.timer.unref?.();
62
+ }
63
+ function armTimer(roundKey, s, delayMs, reason) {
64
+ if (s.timer !== undefined)
65
+ return;
66
+ console.log(`${DIAG} fallback arm round=${roundKey}#${s.gen} reason=${reason} delayMs=${delayMs} ` +
67
+ `children=${s.activeChildren} segActive=${s.segmentActive}`);
68
+ s.timer = setTimeout(() => {
69
+ s.timer = undefined;
70
+ const cur = stateOf(roundKey, s.gen);
71
+ if (!cur)
72
+ return;
73
+ if (isQuiescent(cur) && !cur.eligible) {
74
+ cur.eligible = true;
75
+ console.log(`${DIAG} eligible round=${roundKey}#${s.gen} reason=fallback:${reason} ` +
76
+ `children=${cur.activeChildren} segActive=${cur.segmentActive}`);
77
+ }
78
+ }, delayMs);
79
+ s.timer.unref?.();
80
+ }
81
+ /** 任一事件后统一评估:满足「已非段中、无子任务、dispatch 已返回」时决定防抖收尾或等待。 */
82
+ function reevaluate(roundKey, s) {
83
+ if (!s.dispatchReturned)
84
+ return;
85
+ if (!isQuiescent(s)) {
86
+ // 还有段在跑 / 还有子任务:绝不收尾,也不保留旧的可收尾状态。
87
+ s.eligible = false;
88
+ return;
89
+ }
90
+ if (s.lifecycleSeen && s.lastEnd && s.lastEnd.yielded !== true) {
91
+ // 主会话 finish:最新一段父 run 是非 yield 终态 → 不会再 resume → 防抖后收尾。
92
+ setEligible(roundKey, s.gen, s, "non-yield-end");
93
+ }
94
+ else if (s.lifecycleSeen && s.lastEnd) {
95
+ // 最新一段以 yield 结束 → 主会话仍可能被 resume;等 runStart/新活动取消,
96
+ // 否则静默窗口后收尾(覆盖子任务完成但主会话无法被唤醒的 handoff 路径)。
97
+ armTimer(roundKey, s, RESUME_WAIT_FALLBACK_MS, "yield-end-wait-resume");
98
+ }
99
+ else {
100
+ // 完全没见到 lifecycle(订阅不可用等):纯兜底窗口收尾。
101
+ armTimer(roundKey, s, NO_LIFECYCLE_FALLBACK_MS, "no-lifecycle-seen");
102
+ }
103
+ }
104
+ export function turnOnDispatchReturned(roundKey, gen) {
105
+ const s = stateOf(roundKey, gen);
106
+ if (!s)
107
+ return;
108
+ s.dispatchReturned = true;
109
+ console.log(`${DIAG} dispatchReturned round=${roundKey}#${gen} children=${s.activeChildren} segActive=${s.segmentActive}`);
110
+ reevaluate(roundKey, s);
111
+ }
112
+ /** index.ts `subagent_spawned`:记录本轮见过子任务并 +1 活跃数。 */
113
+ export function turnOnSubagentSpawn(roundKey, gen) {
114
+ const s = stateOf(roundKey, gen);
115
+ if (!s)
116
+ return;
117
+ s.sawSubagent = true;
118
+ s.activeChildren += 1;
119
+ clearTimer(s);
120
+ s.eligible = false;
121
+ console.log(`${DIAG} spawn round=${roundKey}#${gen} activeChildren=${s.activeChildren} sawSubagent=${s.sawSubagent}`);
122
+ }
123
+ /** index.ts `subagent_ended` / monitor settle:活跃子任务数 -1 并重新评估。 */
124
+ export function turnOnSubagentEnded(roundKey, gen) {
125
+ const s = stateOf(roundKey, gen);
126
+ if (!s)
127
+ return;
128
+ if (s.activeChildren > 0)
129
+ s.activeChildren -= 1;
130
+ console.log(`${DIAG} childEnded round=${roundKey}#${gen} activeChildren=${s.activeChildren}`);
131
+ reevaluate(roundKey, s);
132
+ }
133
+ /**
134
+ * 监控层对账:本轮全部已知子任务完成(settle 触发)。与 subagent_ended 事件互补,
135
+ * 覆盖个别 ended 事件丢失导致计数器不为 0、从而永远等不到收尾信号的情况。
136
+ */
137
+ export function turnOnAllChildrenDone(roundKey, gen) {
138
+ const s = stateOf(roundKey, gen);
139
+ if (!s)
140
+ return;
141
+ s.activeChildren = 0;
142
+ console.log(`${DIAG} allChildrenDone round=${roundKey}#${gen} (settle reconcile)`);
143
+ reevaluate(roundKey, s);
144
+ }
145
+ /** lifecycle start(父会话新段开始):清掉旧终态,等待该段终态。 */
146
+ export function turnOnSegmentStart(roundKey, gen) {
147
+ const s = stateOf(roundKey, gen);
148
+ if (!s)
149
+ return;
150
+ s.lifecycleSeen = true;
151
+ s.segmentActive = true;
152
+ s.lastEnd = undefined;
153
+ s.eligible = false;
154
+ clearTimer(s);
155
+ console.log(`${DIAG} segmentStart round=${roundKey}#${gen} (resume/new segment begins)`);
156
+ }
157
+ /** lifecycle end/error(父会话某段结束):记录是否 yield 后评估。 */
158
+ export function turnOnSegmentEnd(roundKey, gen, info) {
159
+ const s = stateOf(roundKey, gen);
160
+ if (!s)
161
+ return;
162
+ s.lifecycleSeen = true;
163
+ s.segmentActive = false;
164
+ s.lastEnd = { ...info, at: Date.now() };
165
+ console.log(`${DIAG} segmentEnd round=${roundKey}#${gen} phase=${info.phase} ` +
166
+ `yielded=${info.yielded === true} stopReason=${info.stopReason ?? "(none)"} ` +
167
+ `children=${s.activeChildren}`);
168
+ reevaluate(roundKey, s);
169
+ }
170
+ /**
171
+ * 组内活动心跳(before_tool_call / thinking / assistant 等属于本轮的其它事件):
172
+ * 说明父会话仍在工作,取消静默收尾计时,但不算“段已结束”。
173
+ */
174
+ export function turnOnActivity(roundKey, gen) {
175
+ const s = stateOf(roundKey, gen);
176
+ if (!s)
177
+ return;
178
+ if (s.timer !== undefined) {
179
+ console.debug(`${DIAG} activity cancels fallback round=${roundKey}#${gen} (timer cleared)`);
180
+ }
181
+ clearTimer(s);
182
+ s.eligible = false;
183
+ }
184
+ /** wrapper 侧首次建轮后登记状态;sawSubagent 由后续 spawn 事件置位。 */
185
+ export function turnEnsureRound(roundKey, gen) {
186
+ const existing = states.get(roundKey);
187
+ if (existing && existing.gen === gen)
188
+ return;
189
+ if (existing) {
190
+ // 同一 group 的新一代轮次:清掉旧代计时与状态,避免旧代事件/定时器干扰新轮。
191
+ clearTimer(existing);
192
+ console.log(`${DIAG} ensure new generation round=${roundKey}#${gen} (was #${existing.gen})`);
193
+ }
194
+ states.set(roundKey, {
195
+ gen,
196
+ sawSubagent: false,
197
+ activeChildren: 0,
198
+ dispatchReturned: false,
199
+ lifecycleSeen: false,
200
+ segmentActive: false,
201
+ eligible: false,
202
+ });
203
+ }
204
+ export function turnIsSawSubagent(roundKey, gen) {
205
+ return stateOf(roundKey, gen)?.sawSubagent === true;
206
+ }
207
+ export function turnIsEligible(roundKey, gen) {
208
+ return stateOf(roundKey, gen)?.eligible === true;
209
+ }
210
+ /** 收尾完成 / 中断 / 插件卸载后清理。 */
211
+ export function turnForget(roundKey, gen) {
212
+ const s = stateOf(roundKey, gen);
213
+ if (!s)
214
+ return;
215
+ console.log(`${DIAG} forget round=${roundKey}#${gen} (round finished/cleaned)`);
216
+ clearTimer(s);
217
+ states.delete(roundKey);
218
+ }
219
+ /** 插件卸载时清理全部轮次状态。 */
220
+ export function disposeTurnEndController() {
221
+ for (const s of states.values()) {
222
+ if (s.timer !== undefined)
223
+ clearTimeout(s.timer);
224
+ }
225
+ states.clear();
226
+ }
227
+ /** 单测辅助。 */
228
+ export function __resetTurnEndControllerForTests() {
229
+ disposeTurnEndController();
230
+ }
231
+ /** 单测辅助:缩短各计时窗口,避免真实等待。 */
232
+ export function __configureTurnEndForTests(overrides) {
233
+ if (overrides.nonYieldDebounceMs !== undefined)
234
+ NON_YIELD_DEBOUNCE_MS = overrides.nonYieldDebounceMs;
235
+ if (overrides.resumeWaitFallbackMs !== undefined)
236
+ RESUME_WAIT_FALLBACK_MS = overrides.resumeWaitFallbackMs;
237
+ if (overrides.noLifecycleFallbackMs !== undefined)
238
+ NO_LIFECYCLE_FALLBACK_MS = overrides.noLifecycleFallbackMs;
239
+ }
240
+ //# sourceMappingURL=turn-end-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turn-end-controller.js","sourceRoot":"","sources":["../../src/turn-end-controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=turn-end-controller.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turn-end-controller.test.d.ts","sourceRoot":"","sources":["../../src/turn-end-controller.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,91 @@
1
+ import { test, describe, beforeEach } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { turnEnsureRound, turnOnDispatchReturned, turnOnSubagentSpawn, turnOnSubagentEnded, turnOnSegmentStart, turnOnSegmentEnd, turnOnActivity, turnIsEligible, turnIsSawSubagent, turnForget, __resetTurnEndControllerForTests, __configureTurnEndForTests, } from "./turn-end-controller.js";
4
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
5
+ describe("turn-end-controller(OpenClaw 7.1+/8.x 子任务整轮收尾)", () => {
6
+ beforeEach(() => {
7
+ __resetTurnEndControllerForTests();
8
+ __configureTurnEndForTests({
9
+ nonYieldDebounceMs: 20,
10
+ resumeWaitFallbackMs: 40,
11
+ noLifecycleFallbackMs: 40,
12
+ });
13
+ });
14
+ test("顺序多子任务:仅首个/各段子任务完成不触发收尾,父会话非 yield 终态后才 eligible", async () => {
15
+ const rk = "acc:g1";
16
+ const gen = 1;
17
+ turnEnsureRound(rk, gen);
18
+ turnOnDispatchReturned(rk, gen);
19
+ // 第 1 段:start → spawn(child1) → yield end
20
+ turnOnSegmentStart(rk, gen);
21
+ turnOnSubagentSpawn(rk, gen);
22
+ turnOnSegmentEnd(rk, gen, { phase: "end", yielded: true, stopReason: "end_turn" });
23
+ assert.equal(turnIsEligible(rk, gen), false, "段以 yield 结束 → 不收尾");
24
+ // child1 完成
25
+ turnOnSubagentEnded(rk, gen);
26
+ assert.equal(turnIsEligible(rk, gen), false, "子任务完成但父会话可能 resume → 不立即收尾");
27
+ // 父会话 resume(新段)→ 派发 child2 → yield end
28
+ turnOnSegmentStart(rk, gen);
29
+ turnOnSubagentSpawn(rk, gen);
30
+ turnOnSegmentEnd(rk, gen, { phase: "end", yielded: true, stopReason: "end_turn" });
31
+ turnOnSubagentEnded(rk, gen);
32
+ assert.equal(turnIsEligible(rk, gen), false);
33
+ // 父会话最后一次 resume,产出最终答复后以非 yield 终态结束
34
+ turnOnSegmentStart(rk, gen);
35
+ turnOnSegmentEnd(rk, gen, { phase: "end", yielded: false, stopReason: "end_turn" });
36
+ await sleep(60);
37
+ assert.equal(turnIsEligible(rk, gen), true, "非 yield 终态 → 防抖后收尾");
38
+ });
39
+ test("子任务完成但父会话无法被唤醒(handoff)→ 静默兜底后收尾", async () => {
40
+ const rk = "acc:g2";
41
+ const gen = 1;
42
+ turnEnsureRound(rk, gen);
43
+ turnOnDispatchReturned(rk, gen);
44
+ turnOnSegmentStart(rk, gen);
45
+ turnOnSubagentSpawn(rk, gen);
46
+ turnOnSegmentEnd(rk, gen, { phase: "end", yielded: true });
47
+ turnOnSubagentEnded(rk, gen);
48
+ assert.equal(turnIsEligible(rk, gen), false);
49
+ await sleep(80);
50
+ assert.equal(turnIsEligible(rk, gen), true, "resume 未到来 → 兜底窗口后收尾");
51
+ });
52
+ test("组内活动心跳可延续等待(父会话还在工作时不误收尾)", async () => {
53
+ const rk = "acc:g3";
54
+ const gen = 1;
55
+ turnEnsureRound(rk, gen);
56
+ turnOnDispatchReturned(rk, gen);
57
+ turnOnSegmentStart(rk, gen);
58
+ turnOnSubagentSpawn(rk, gen);
59
+ turnOnSegmentEnd(rk, gen, { phase: "end", yielded: true });
60
+ turnOnSubagentEnded(rk, gen);
61
+ // 兜底窗口内出现组内工具活动 → 取消收尾计时
62
+ turnOnActivity(rk, gen);
63
+ await sleep(80);
64
+ assert.equal(turnIsEligible(rk, gen), false, "心跳延续等待,不能提前收尾");
65
+ turnOnSegmentStart(rk, gen);
66
+ turnOnSegmentEnd(rk, gen, { phase: "end", yielded: false });
67
+ await sleep(60);
68
+ assert.equal(turnIsEligible(rk, gen), true);
69
+ });
70
+ test("lifecycle 完全不可见(订阅不可用)→ 兜底收尾且不悬挂", async () => {
71
+ const rk = "acc:g4";
72
+ const gen = 1;
73
+ turnEnsureRound(rk, gen);
74
+ turnOnDispatchReturned(rk, gen);
75
+ turnOnSubagentSpawn(rk, gen);
76
+ turnOnSubagentEnded(rk, gen);
77
+ await sleep(80);
78
+ assert.equal(turnIsEligible(rk, gen), true);
79
+ });
80
+ test("sawSubagent 标记来自 spawn 事件;turnForget 清理状态", () => {
81
+ const rk = "acc:g5";
82
+ const gen = 1;
83
+ turnEnsureRound(rk, gen);
84
+ assert.equal(turnIsSawSubagent(rk, gen), false);
85
+ turnOnSubagentSpawn(rk, gen);
86
+ assert.equal(turnIsSawSubagent(rk, gen), true);
87
+ turnForget(rk, gen);
88
+ assert.equal(turnIsSawSubagent(rk, gen), false);
89
+ });
90
+ });
91
+ //# sourceMappingURL=turn-end-controller.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turn-end-controller.test.js","sourceRoot":"","sources":["../../src/turn-end-controller.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xgjktech/xg_cwork_im",
3
- "version": "1.17.53",
3
+ "version": "1.17.55",
4
4
  "description": "XG CWork IM channel plugin for OpenClaw",
5
5
  "keywords": [
6
6
  "bot",
@@ -25,7 +25,7 @@
25
25
  "build": "tsc -p tsconfig.json",
26
26
  "type-check": "tsc -p tsconfig.json --noEmit",
27
27
  "lint": "tsc -p tsconfig.json --noEmit",
28
- "test": "npm run build && node --test dist/src/account-reconciler.test.js dist/src/inbound-terminal-state.test.js dist/src/user-facing-errors.test.js dist/src/deliver-text.test.js dist/src/agent-context-types.test.js dist/src/build-project-prompt.test.js dist/src/nas-volumes.test.js dist/src/workspace-event.test.js dist/src/workspace-event-scheduler.test.js dist/src/connection-workspace-event.test.js dist/src/block-streaming-config.test.js dist/src/channel-disabled-account.test.js dist/src/per-message-fallback-notice.test.js dist/src/thinking-ws-progress.test.js dist/src/resource-file.test.js dist/src/turn-deliver-buffer.test.js dist/src/run-usage.test.js dist/src/ws-run-event-unmapped.test.js dist/src/item-event-guard.test.js dist/src/inbound-model.test.js dist/src/auto-model-router.test.js dist/src/channel-config.test.js dist/src/send-service.test.js dist/src/send-file-tool.test.js dist/src/plan-tool-result.test.js dist/src/plan-blocked-notice.test.js dist/src/plan-store-access.test.js dist/src/plan-tool-middleware.test.js dist/src/plan-event-subscription.test.js dist/src/plan-ws-registry.test.js dist/src/plan-stat-event.test.js dist/src/active-round-registry.test.js dist/src/interrupt-round.test.js dist/src/subagent-monitor.test.js dist/src/session-env-store.test.js dist/src/register-exec-env-hook.test.js dist/src/cron-appkey-binding-store.test.js dist/src/ws-inbound-schema.test.js",
28
+ "test": "npm run build && node --test dist/src/account-reconciler.test.js dist/src/inbound-terminal-state.test.js dist/src/user-facing-errors.test.js dist/src/deliver-text.test.js dist/src/agent-context-types.test.js dist/src/build-project-prompt.test.js dist/src/nas-volumes.test.js dist/src/workspace-event.test.js dist/src/workspace-event-scheduler.test.js dist/src/connection-workspace-event.test.js dist/src/block-streaming-config.test.js dist/src/channel-disabled-account.test.js dist/src/per-message-fallback-notice.test.js dist/src/thinking-ws-progress.test.js dist/src/resource-file.test.js dist/src/turn-deliver-buffer.test.js dist/src/run-usage.test.js dist/src/ws-run-event-unmapped.test.js dist/src/item-event-guard.test.js dist/src/inbound-model.test.js dist/src/auto-model-router.test.js dist/src/channel-config.test.js dist/src/send-service.test.js dist/src/send-file-tool.test.js dist/src/plan-tool-result.test.js dist/src/plan-blocked-notice.test.js dist/src/plan-store-access.test.js dist/src/plan-tool-middleware.test.js dist/src/plan-event-subscription.test.js dist/src/plan-ws-registry.test.js dist/src/plan-stat-event.test.js dist/src/active-round-registry.test.js dist/src/interrupt-round.test.js dist/src/subagent-monitor.test.js dist/src/turn-end-controller.test.js dist/src/session-env-store.test.js dist/src/register-exec-env-hook.test.js dist/src/cron-appkey-binding-store.test.js dist/src/ws-inbound-schema.test.js",
29
29
  "install:prod": "npm install --omit=dev",
30
30
  "prepublishOnly": "npm run build"
31
31
  },