@xgjktech/xg_cwork_im 1.16.45 → 1.17.1

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 (81) hide show
  1. package/README.md +433 -433
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +25 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/src/connection.d.ts +1 -1
  6. package/dist/src/connection.d.ts.map +1 -1
  7. package/dist/src/connection.js +2 -2
  8. package/dist/src/connection.js.map +1 -1
  9. package/dist/src/deliver-text.test.js +22 -22
  10. package/dist/src/dispatch-mentioned-reply.d.ts.map +1 -1
  11. package/dist/src/dispatch-mentioned-reply.js +2 -0
  12. package/dist/src/dispatch-mentioned-reply.js.map +1 -1
  13. package/dist/src/plan-blocked-notice.d.ts +14 -0
  14. package/dist/src/plan-blocked-notice.d.ts.map +1 -0
  15. package/dist/src/plan-blocked-notice.js +41 -0
  16. package/dist/src/plan-blocked-notice.js.map +1 -0
  17. package/dist/src/plan-blocked-notice.test.d.ts +2 -0
  18. package/dist/src/plan-blocked-notice.test.d.ts.map +1 -0
  19. package/dist/src/plan-blocked-notice.test.js +96 -0
  20. package/dist/src/plan-blocked-notice.test.js.map +1 -0
  21. package/dist/src/plan-event-subscription.d.ts +36 -0
  22. package/dist/src/plan-event-subscription.d.ts.map +1 -0
  23. package/dist/src/plan-event-subscription.js +57 -0
  24. package/dist/src/plan-event-subscription.js.map +1 -0
  25. package/dist/src/plan-event-subscription.test.d.ts +2 -0
  26. package/dist/src/plan-event-subscription.test.d.ts.map +1 -0
  27. package/dist/src/plan-event-subscription.test.js +167 -0
  28. package/dist/src/plan-event-subscription.test.js.map +1 -0
  29. package/dist/src/plan-session-registry.d.ts +24 -0
  30. package/dist/src/plan-session-registry.d.ts.map +1 -0
  31. package/dist/src/plan-session-registry.js +84 -0
  32. package/dist/src/plan-session-registry.js.map +1 -0
  33. package/dist/src/plan-session-registry.test.d.ts +2 -0
  34. package/dist/src/plan-session-registry.test.d.ts.map +1 -0
  35. package/dist/src/plan-session-registry.test.js +109 -0
  36. package/dist/src/plan-session-registry.test.js.map +1 -0
  37. package/dist/src/plan-stat-event.d.ts +28 -0
  38. package/dist/src/plan-stat-event.d.ts.map +1 -0
  39. package/dist/src/plan-stat-event.js +68 -0
  40. package/dist/src/plan-stat-event.js.map +1 -0
  41. package/dist/src/plan-stat-event.test.d.ts +2 -0
  42. package/dist/src/plan-stat-event.test.d.ts.map +1 -0
  43. package/dist/src/plan-stat-event.test.js +167 -0
  44. package/dist/src/plan-stat-event.test.js.map +1 -0
  45. package/dist/src/plan-store-access.d.ts +23 -0
  46. package/dist/src/plan-store-access.d.ts.map +1 -0
  47. package/dist/src/plan-store-access.js +96 -0
  48. package/dist/src/plan-store-access.js.map +1 -0
  49. package/dist/src/plan-store-access.test.d.ts +2 -0
  50. package/dist/src/plan-store-access.test.d.ts.map +1 -0
  51. package/dist/src/plan-store-access.test.js +207 -0
  52. package/dist/src/plan-store-access.test.js.map +1 -0
  53. package/dist/src/plan-tool-middleware.d.ts +22 -0
  54. package/dist/src/plan-tool-middleware.d.ts.map +1 -0
  55. package/dist/src/plan-tool-middleware.js +85 -0
  56. package/dist/src/plan-tool-middleware.js.map +1 -0
  57. package/dist/src/plan-tool-middleware.test.d.ts +2 -0
  58. package/dist/src/plan-tool-middleware.test.d.ts.map +1 -0
  59. package/dist/src/plan-tool-middleware.test.js +488 -0
  60. package/dist/src/plan-tool-middleware.test.js.map +1 -0
  61. package/dist/src/plan-tool-result.d.ts +20 -0
  62. package/dist/src/plan-tool-result.d.ts.map +1 -0
  63. package/dist/src/plan-tool-result.js +78 -0
  64. package/dist/src/plan-tool-result.js.map +1 -0
  65. package/dist/src/plan-tool-result.test.d.ts +2 -0
  66. package/dist/src/plan-tool-result.test.d.ts.map +1 -0
  67. package/dist/src/plan-tool-result.test.js +107 -0
  68. package/dist/src/plan-tool-result.test.js.map +1 -0
  69. package/dist/src/plan-ws-registry.d.ts +11 -0
  70. package/dist/src/plan-ws-registry.d.ts.map +1 -0
  71. package/dist/src/plan-ws-registry.js +27 -0
  72. package/dist/src/plan-ws-registry.js.map +1 -0
  73. package/dist/src/plan-ws-registry.test.d.ts +2 -0
  74. package/dist/src/plan-ws-registry.test.d.ts.map +1 -0
  75. package/dist/src/plan-ws-registry.test.js +43 -0
  76. package/dist/src/plan-ws-registry.test.js.map +1 -0
  77. package/dist/src/subagent-monitor.js +11 -17
  78. package/dist/src/subagent-monitor.js.map +1 -1
  79. package/dist/src/turn-deliver-buffer.test.js +25 -25
  80. package/openclaw.plugin.json +27 -26
  81. package/package.json +76 -72
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-tool-middleware.js","sourceRoot":"","sources":["../../src/plan-tool-middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=plan-tool-middleware.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-tool-middleware.test.d.ts","sourceRoot":"","sources":["../../src/plan-tool-middleware.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,488 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { createPlanToolResultMiddleware } from "./plan-tool-middleware.js";
4
+ const FAKE_CTX = { runtime: "openclaw" };
5
+ function makePlan(overrides = {}) {
6
+ return {
7
+ planId: "plan-1",
8
+ goal: "迁移配置到新版本",
9
+ createdAt: "2026-07-27T00:00:00.000Z",
10
+ updatedAt: "2026-07-27T00:00:00.000Z",
11
+ tasks: [],
12
+ ...overrides,
13
+ };
14
+ }
15
+ function makeEvent(overrides) {
16
+ const content = overrides.text !== undefined
17
+ ? [{ type: "text", text: overrides.text }]
18
+ : [];
19
+ return {
20
+ toolCallId: overrides.toolCallId ?? "call-1",
21
+ toolName: overrides.toolName ?? "xg_plan_write",
22
+ args: {},
23
+ result: {
24
+ details: overrides.details,
25
+ content,
26
+ },
27
+ };
28
+ }
29
+ function makeSuccessPayload(plan, withEvent = false) {
30
+ return {
31
+ ok: true,
32
+ planId: plan.planId,
33
+ plan,
34
+ ...(withEvent ? { event: { emitted: false, reason: "no runId" } } : {}),
35
+ };
36
+ }
37
+ class RecordingDeps {
38
+ planById = new Map();
39
+ planStatCalls = [];
40
+ sendPlanStatImpl = (params) => {
41
+ this.planStatCalls.push(params);
42
+ };
43
+ getPlanById = (planId) => {
44
+ return this.planById.get(planId);
45
+ };
46
+ sendPlanStat = (params) => {
47
+ this.sendPlanStatImpl(params);
48
+ };
49
+ }
50
+ /** 临时替换 console.warn 统计 [plan-telemetry] 行数,测试结束务必还原。 */
51
+ function captureTelemetryLines(fn) {
52
+ const original = console.warn;
53
+ const lines = [];
54
+ console.warn = (...args) => {
55
+ const line = args.map(String).join(" ");
56
+ if (line.includes("[plan-telemetry]")) {
57
+ lines.push(line);
58
+ }
59
+ };
60
+ try {
61
+ fn();
62
+ }
63
+ finally {
64
+ console.warn = original;
65
+ }
66
+ return lines;
67
+ }
68
+ describe("createPlanToolResultMiddleware: 非 plan 工具直接放行", () => {
69
+ it("does not touch getPlanById or emit telemetry for unrelated tools", () => {
70
+ const deps = new RecordingDeps();
71
+ let getPlanByIdCalled = false;
72
+ deps.getPlanById = (planId) => {
73
+ getPlanByIdCalled = true;
74
+ return deps.planById.get(planId);
75
+ };
76
+ const handler = createPlanToolResultMiddleware(deps);
77
+ const event = makeEvent({
78
+ toolName: "some_other_tool",
79
+ details: { ok: true, data: 123 },
80
+ });
81
+ const lines = captureTelemetryLines(() => {
82
+ const result = handler(event, FAKE_CTX);
83
+ assert.equal(result, undefined);
84
+ });
85
+ assert.equal(getPlanByIdCalled, false);
86
+ assert.equal(lines.length, 0);
87
+ });
88
+ it("does not emit telemetry even when a non-plan tool's details is a structurally valid plan payload (pins the name filter)", () => {
89
+ const deps = new RecordingDeps();
90
+ const handler = createPlanToolResultMiddleware(deps);
91
+ const plan = makePlan({ tasks: [{ title: "备份旧配置", status: "blocked", note: "缺少权限" }] });
92
+ const event = makeEvent({
93
+ toolCallId: "call-evil",
94
+ toolName: "some_evil_tool",
95
+ details: makeSuccessPayload(plan),
96
+ });
97
+ const lines = captureTelemetryLines(() => {
98
+ const result = handler(event, FAKE_CTX);
99
+ assert.equal(result, undefined);
100
+ });
101
+ assert.equal(lines.length, 0);
102
+ });
103
+ });
104
+ describe("createPlanToolResultMiddleware: details 路径", () => {
105
+ it("emits a telemetry line when details carries a valid plan with a blocked task", () => {
106
+ const deps = new RecordingDeps();
107
+ const handler = createPlanToolResultMiddleware(deps);
108
+ const plan = makePlan({
109
+ tasks: [{ title: "备份旧配置", status: "blocked", note: "缺少权限" }],
110
+ });
111
+ const event = makeEvent({
112
+ toolCallId: "call-1",
113
+ toolName: "xg_plan_write",
114
+ details: makeSuccessPayload(plan),
115
+ });
116
+ const lines = captureTelemetryLines(() => {
117
+ const result = handler(event, FAKE_CTX);
118
+ assert.equal(result, undefined);
119
+ });
120
+ assert.equal(lines.length, 1);
121
+ assert.ok(lines[0].includes("备份旧配置"));
122
+ assert.ok(lines[0].includes("缺少权限"));
123
+ });
124
+ });
125
+ describe("createPlanToolResultMiddleware: text 回退路径", () => {
126
+ it("falls back to content[0].text when details is undefined", () => {
127
+ const deps = new RecordingDeps();
128
+ const handler = createPlanToolResultMiddleware(deps);
129
+ const plan = makePlan({
130
+ planId: "plan-2",
131
+ tasks: [{ title: "校验数据", status: "blocked", note: "依赖未就绪" }],
132
+ });
133
+ const rawBody = JSON.stringify(makeSuccessPayload(plan, true), null, 2);
134
+ const event = makeEvent({
135
+ toolCallId: "call-2",
136
+ toolName: "xg_plan_execute",
137
+ details: undefined,
138
+ text: rawBody,
139
+ });
140
+ const lines = captureTelemetryLines(() => {
141
+ const result = handler(event, FAKE_CTX);
142
+ assert.equal(result, undefined);
143
+ });
144
+ assert.equal(lines.length, 1);
145
+ assert.ok(lines[0].includes("校验数据"));
146
+ });
147
+ it("uses getPlanById authoritative state when details is missing (D5/RULING-1 §3)", () => {
148
+ const deps = new RecordingDeps();
149
+ const handler = createPlanToolResultMiddleware(deps);
150
+ // text 路径拿到的 plan 里没有 blocked task,但权威反查里有
151
+ const textPlan = makePlan({ planId: "plan-3", tasks: [{ title: "t1", status: "pending" }] });
152
+ const authoritativePlan = makePlan({
153
+ planId: "plan-3",
154
+ tasks: [{ title: "t1", status: "blocked", note: "authoritative 才有的阻塞" }],
155
+ });
156
+ deps.planById.set("plan-3", authoritativePlan);
157
+ const rawBody = JSON.stringify(makeSuccessPayload(textPlan), null, 2);
158
+ const event = makeEvent({
159
+ toolCallId: "call-3",
160
+ toolName: "xg_plan_write",
161
+ details: undefined,
162
+ text: rawBody,
163
+ });
164
+ const lines = captureTelemetryLines(() => {
165
+ handler(event, FAKE_CTX);
166
+ });
167
+ assert.equal(lines.length, 1);
168
+ assert.ok(lines[0].includes("authoritative 才有的阻塞"));
169
+ });
170
+ });
171
+ describe("createPlanToolResultMiddleware: 守卫拒绝畸形 payload", () => {
172
+ it("does not emit telemetry for ok:false", () => {
173
+ const deps = new RecordingDeps();
174
+ const handler = createPlanToolResultMiddleware(deps);
175
+ const event = makeEvent({
176
+ toolCallId: "call-4",
177
+ toolName: "xg_plan_write",
178
+ details: { ok: false, error: { code: "PLAN_NOT_FOUND" } },
179
+ });
180
+ const lines = captureTelemetryLines(() => {
181
+ assert.equal(handler(event, FAKE_CTX), undefined);
182
+ });
183
+ assert.equal(lines.length, 0);
184
+ });
185
+ it("does not emit telemetry when planId is missing", () => {
186
+ const deps = new RecordingDeps();
187
+ const handler = createPlanToolResultMiddleware(deps);
188
+ const event = makeEvent({
189
+ toolCallId: "call-5",
190
+ toolName: "xg_plan_write",
191
+ details: { ok: true, plan: makePlan() },
192
+ });
193
+ const lines = captureTelemetryLines(() => {
194
+ assert.equal(handler(event, FAKE_CTX), undefined);
195
+ });
196
+ assert.equal(lines.length, 0);
197
+ });
198
+ it("does not emit telemetry when tasks is not an array", () => {
199
+ const deps = new RecordingDeps();
200
+ const handler = createPlanToolResultMiddleware(deps);
201
+ const event = makeEvent({
202
+ toolCallId: "call-6",
203
+ toolName: "xg_plan_write",
204
+ details: {
205
+ ok: true,
206
+ planId: "plan-6",
207
+ plan: { planId: "plan-6", goal: "g", createdAt: "t", updatedAt: "t", tasks: "not-an-array" },
208
+ },
209
+ });
210
+ const lines = captureTelemetryLines(() => {
211
+ assert.equal(handler(event, FAKE_CTX), undefined);
212
+ });
213
+ assert.equal(lines.length, 0);
214
+ });
215
+ });
216
+ describe("createPlanToolResultMiddleware: handler 内部出错不外抛", () => {
217
+ it("resolves normally even when getPlanById throws", () => {
218
+ const deps = new RecordingDeps();
219
+ deps.getPlanById = () => {
220
+ throw new Error("boom");
221
+ };
222
+ const handler = createPlanToolResultMiddleware(deps);
223
+ const plan = makePlan({ planId: "plan-8", tasks: [{ title: "t1", status: "blocked", note: "n" }] });
224
+ const rawBody = JSON.stringify(makeSuccessPayload(plan), null, 2);
225
+ const event = makeEvent({
226
+ toolCallId: "call-8",
227
+ toolName: "xg_plan_write",
228
+ details: undefined,
229
+ text: rawBody,
230
+ });
231
+ assert.doesNotThrow(() => handler(event, FAKE_CTX));
232
+ });
233
+ });
234
+ describe("createPlanToolResultMiddleware: 恒返回 void(同步性断言)", () => {
235
+ // 本任务 handler 已无异步出口(推群没了)。TASK-2x-4 引入 sendPlanStat 的
236
+ // fire-and-forget 之后,这条要恢复成"even when 内部 promise 永不 resolve 仍立即返回"的真实用例。
237
+ it("handler's return value is undefined and the call itself is synchronous", () => {
238
+ const deps = new RecordingDeps();
239
+ const handler = createPlanToolResultMiddleware(deps);
240
+ const plan = makePlan({ tasks: [{ title: "t1", status: "blocked", note: "n" }] });
241
+ const event = makeEvent({
242
+ toolCallId: "call-9",
243
+ toolName: "xg_plan_write",
244
+ details: makeSuccessPayload(plan),
245
+ });
246
+ const result = handler(event, FAKE_CTX);
247
+ assert.equal(result, undefined);
248
+ });
249
+ });
250
+ describe("createPlanToolResultMiddleware: [plan-telemetry] 遥测行为(D2)", () => {
251
+ it("plan 含 1 个 blocked task → 恰好打 1 行,内容含 planId/taskIndex/taskTitle/note/goal", () => {
252
+ const deps = new RecordingDeps();
253
+ const handler = createPlanToolResultMiddleware(deps);
254
+ const plan = makePlan({
255
+ planId: "plan-telemetry-1",
256
+ goal: "迁移配置到新版本",
257
+ tasks: [{ title: "备份旧配置", status: "blocked", note: "缺少权限" }],
258
+ });
259
+ const event = makeEvent({
260
+ toolCallId: "call-t1",
261
+ toolName: "xg_plan_execute",
262
+ details: makeSuccessPayload(plan),
263
+ });
264
+ const lines = captureTelemetryLines(() => {
265
+ handler(event, FAKE_CTX);
266
+ });
267
+ assert.equal(lines.length, 1);
268
+ const jsonPart = lines[0].slice(lines[0].indexOf("{"));
269
+ const parsed = JSON.parse(jsonPart);
270
+ assert.equal(parsed.planId, "plan-telemetry-1");
271
+ assert.equal(parsed.taskIndex, 0);
272
+ assert.equal(parsed.taskTitle, "备份旧配置");
273
+ assert.equal(parsed.note, "缺少权限");
274
+ assert.equal(parsed.goal, "迁移配置到新版本");
275
+ assert.equal(parsed.toolName, "xg_plan_execute");
276
+ });
277
+ it("plan 含 2 个 blocked task → 打 2 行,顺序与 tasks 下标一致", () => {
278
+ const deps = new RecordingDeps();
279
+ const handler = createPlanToolResultMiddleware(deps);
280
+ const plan = makePlan({
281
+ tasks: [
282
+ { title: "备份旧配置", status: "blocked", note: "缺少权限" },
283
+ { title: "校验数据", status: "pending" },
284
+ { title: "切换流量", status: "blocked", note: "依赖未就绪" },
285
+ ],
286
+ });
287
+ const event = makeEvent({
288
+ toolCallId: "call-t2",
289
+ toolName: "xg_plan_write",
290
+ details: makeSuccessPayload(plan),
291
+ });
292
+ const lines = captureTelemetryLines(() => {
293
+ handler(event, FAKE_CTX);
294
+ });
295
+ assert.equal(lines.length, 2);
296
+ const first = JSON.parse(lines[0].slice(lines[0].indexOf("{")));
297
+ const second = JSON.parse(lines[1].slice(lines[1].indexOf("{")));
298
+ assert.equal(first.taskIndex, 0);
299
+ assert.equal(second.taskIndex, 2);
300
+ });
301
+ it("无 blocked task → 不打任何遥测行", () => {
302
+ const deps = new RecordingDeps();
303
+ const handler = createPlanToolResultMiddleware(deps);
304
+ const plan = makePlan({
305
+ tasks: [{ title: "t1", status: "pending" }, { title: "t2", status: "completed" }],
306
+ });
307
+ const event = makeEvent({
308
+ toolCallId: "call-t3",
309
+ toolName: "xg_plan_write",
310
+ details: makeSuccessPayload(plan),
311
+ });
312
+ const lines = captureTelemetryLines(() => {
313
+ handler(event, FAKE_CTX);
314
+ });
315
+ assert.equal(lines.length, 0);
316
+ });
317
+ it("🔴 同一 plan、同一 blocked、连续两次 middleware 事件 → 打 2 行(钉住不去重)", () => {
318
+ const deps = new RecordingDeps();
319
+ const handler = createPlanToolResultMiddleware(deps);
320
+ const plan = makePlan({
321
+ planId: "plan-no-dedup",
322
+ tasks: [{ title: "备份旧配置", status: "blocked", note: "缺少权限" }],
323
+ });
324
+ const event = makeEvent({
325
+ toolCallId: "call-t4",
326
+ toolName: "xg_plan_write",
327
+ details: makeSuccessPayload(plan),
328
+ });
329
+ const lines = captureTelemetryLines(() => {
330
+ handler(event, FAKE_CTX);
331
+ handler(event, FAKE_CTX);
332
+ });
333
+ assert.equal(lines.length, 2, "不去重:同一 blocked 连续两次事件应各打一行");
334
+ });
335
+ it("plan 带 origin → 日志行含 channel/to/sessionKey", () => {
336
+ const deps = new RecordingDeps();
337
+ const handler = createPlanToolResultMiddleware(deps);
338
+ const plan = makePlan({
339
+ tasks: [{ title: "t1", status: "blocked", note: "n" }],
340
+ origin: { channel: "xg_cwork_im", to: "g-123", sessionKey: "sess-1" },
341
+ });
342
+ const event = makeEvent({
343
+ toolCallId: "call-t5",
344
+ toolName: "xg_plan_write",
345
+ details: makeSuccessPayload(plan),
346
+ });
347
+ const lines = captureTelemetryLines(() => {
348
+ handler(event, FAKE_CTX);
349
+ });
350
+ assert.equal(lines.length, 1);
351
+ const parsed = JSON.parse(lines[0].slice(lines[0].indexOf("{")));
352
+ assert.equal(parsed.channel, "xg_cwork_im");
353
+ assert.equal(parsed.to, "g-123");
354
+ assert.equal(parsed.sessionKey, "sess-1");
355
+ });
356
+ it("🔴 plan 无 origin(旧数据)→ 日志行不含这几个键,且照常打日志、不抛、不跳过", () => {
357
+ const deps = new RecordingDeps();
358
+ const handler = createPlanToolResultMiddleware(deps);
359
+ const plan = makePlan({
360
+ tasks: [{ title: "t1", status: "blocked", note: "n" }],
361
+ });
362
+ const event = makeEvent({
363
+ toolCallId: "call-t6",
364
+ toolName: "xg_plan_write",
365
+ details: makeSuccessPayload(plan),
366
+ });
367
+ const lines = captureTelemetryLines(() => {
368
+ assert.doesNotThrow(() => handler(event, FAKE_CTX));
369
+ });
370
+ assert.equal(lines.length, 1);
371
+ const parsed = JSON.parse(lines[0].slice(lines[0].indexOf("{")));
372
+ assert.equal("channel" in parsed, false);
373
+ assert.equal("to" in parsed, false);
374
+ assert.equal("sessionKey" in parsed, false);
375
+ });
376
+ it("blocked task 的 note 为空/空白 → 该条不产出遥测", () => {
377
+ const deps = new RecordingDeps();
378
+ const handler = createPlanToolResultMiddleware(deps);
379
+ const plan = makePlan({
380
+ tasks: [
381
+ { title: "无 note", status: "blocked" },
382
+ { title: "空白 note", status: "blocked", note: " " },
383
+ ],
384
+ });
385
+ const event = makeEvent({
386
+ toolCallId: "call-t7",
387
+ toolName: "xg_plan_write",
388
+ details: makeSuccessPayload(plan),
389
+ });
390
+ const lines = captureTelemetryLines(() => {
391
+ handler(event, FAKE_CTX);
392
+ });
393
+ assert.equal(lines.length, 0);
394
+ });
395
+ });
396
+ describe("createPlanToolResultMiddleware: PLAN_STAT 增量推送(D3)", () => {
397
+ it("plan_write 成功 → 发 1 条 PLAN_STAT,source === \"tool\"", () => {
398
+ const deps = new RecordingDeps();
399
+ const handler = createPlanToolResultMiddleware(deps);
400
+ const plan = makePlan({ tasks: [{ title: "t1", status: "pending" }] });
401
+ const event = makeEvent({
402
+ toolCallId: "call-ps1",
403
+ toolName: "xg_plan_write",
404
+ details: makeSuccessPayload(plan),
405
+ });
406
+ handler(event, FAKE_CTX);
407
+ assert.equal(deps.planStatCalls.length, 1);
408
+ assert.equal(deps.planStatCalls[0].source, "tool");
409
+ assert.equal(deps.planStatCalls[0].plan.planId, plan.planId);
410
+ });
411
+ it("plan_execute 成功(start_task/block_task/complete_task)→ 各发 1 条", () => {
412
+ const actions = [
413
+ { toolCallId: "call-ps2", plan: makePlan({ tasks: [{ title: "t1", status: "in_progress" }] }) },
414
+ {
415
+ toolCallId: "call-ps3",
416
+ plan: makePlan({ tasks: [{ title: "t1", status: "blocked", note: "缺少权限" }] }),
417
+ },
418
+ { toolCallId: "call-ps4", plan: makePlan({ tasks: [{ title: "t1", status: "completed" }] }) },
419
+ ];
420
+ for (const { toolCallId, plan } of actions) {
421
+ const deps = new RecordingDeps();
422
+ const handler = createPlanToolResultMiddleware(deps);
423
+ const event = makeEvent({
424
+ toolCallId,
425
+ toolName: "xg_plan_execute",
426
+ details: makeSuccessPayload(plan),
427
+ });
428
+ handler(event, FAKE_CTX);
429
+ assert.equal(deps.planStatCalls.length, 1, `action status=${plan.tasks[0].status} 应发 1 条`);
430
+ assert.equal(deps.planStatCalls[0].source, "tool");
431
+ }
432
+ });
433
+ it("🔴 工具返回 ok:false → 不发 PLAN_STAT(失败不发)", () => {
434
+ const deps = new RecordingDeps();
435
+ const handler = createPlanToolResultMiddleware(deps);
436
+ const event = makeEvent({
437
+ toolCallId: "call-ps5",
438
+ toolName: "xg_plan_write",
439
+ details: { ok: false, error: { code: "PLAN_NOT_FOUND" } },
440
+ });
441
+ handler(event, FAKE_CTX);
442
+ assert.equal(deps.planStatCalls.length, 0);
443
+ });
444
+ it("🔴 非 plan 工具 → 不发 PLAN_STAT", () => {
445
+ const deps = new RecordingDeps();
446
+ const handler = createPlanToolResultMiddleware(deps);
447
+ const plan = makePlan({ tasks: [{ title: "t1", status: "pending" }] });
448
+ const event = makeEvent({
449
+ toolCallId: "call-ps6",
450
+ toolName: "some_other_tool",
451
+ details: makeSuccessPayload(plan),
452
+ });
453
+ handler(event, FAKE_CTX);
454
+ assert.equal(deps.planStatCalls.length, 0);
455
+ });
456
+ it("🔴 sendPlanStat 内部抛异常 → handler 不外抛、仍返回 void(红线回归)", () => {
457
+ const deps = new RecordingDeps();
458
+ deps.sendPlanStatImpl = () => {
459
+ throw new Error("boom");
460
+ };
461
+ const handler = createPlanToolResultMiddleware(deps);
462
+ const plan = makePlan({ tasks: [{ title: "t1", status: "pending" }] });
463
+ const event = makeEvent({
464
+ toolCallId: "call-ps7",
465
+ toolName: "xg_plan_write",
466
+ details: makeSuccessPayload(plan),
467
+ });
468
+ assert.doesNotThrow(() => {
469
+ const result = handler(event, FAKE_CTX);
470
+ assert.equal(result, undefined);
471
+ });
472
+ });
473
+ it("🔴 跨调用序列:同一 plan 连续 3 次成功调用 → 发 3 条(全量幂等,不去重)", () => {
474
+ const deps = new RecordingDeps();
475
+ const handler = createPlanToolResultMiddleware(deps);
476
+ const plan = makePlan({ planId: "plan-stat-no-dedup", tasks: [{ title: "t1", status: "pending" }] });
477
+ const event = makeEvent({
478
+ toolCallId: "call-ps8",
479
+ toolName: "xg_plan_write",
480
+ details: makeSuccessPayload(plan),
481
+ });
482
+ handler(event, FAKE_CTX);
483
+ handler(event, FAKE_CTX);
484
+ handler(event, FAKE_CTX);
485
+ assert.equal(deps.planStatCalls.length, 3, "不去重:同一 plan 连续 3 次成功调用应各发一条");
486
+ });
487
+ });
488
+ //# sourceMappingURL=plan-tool-middleware.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-tool-middleware.test.js","sourceRoot":"","sources":["../../src/plan-tool-middleware.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { Plan } from "@xgjktech/xg-openclaw-shared";
2
+ export interface ParsedPlanToolResult {
3
+ planId: string;
4
+ plan: Plan;
5
+ /** plan_execute 的返回带 event 字段,plan_write 没有——用于日志区分,不参与正确性判定 */
6
+ hasEventField: boolean;
7
+ }
8
+ /**
9
+ * 从已解析的值(如 JSON.parse 结果、middleware 的 `event.result.details`)中
10
+ * 结构校验并提取计划工具的成功返回。不是计划工具返回、ok:false 一律返回 undefined。
11
+ * 供 `parsePlanToolResult`(字符串输入)与 middleware(对象输入)共用同一份判定,
12
+ * 避免两份校验漂移。
13
+ */
14
+ export declare function parsePlanToolResultFromValue(value: unknown): ParsedPlanToolResult | undefined;
15
+ /**
16
+ * 从工具返回 JSON 文本中解析计划工具的成功返回。
17
+ * 不是计划工具返回、解析失败、ok:false 一律返回 undefined(绝不抛异常)。
18
+ */
19
+ export declare function parsePlanToolResult(rawBody: string): ParsedPlanToolResult | undefined;
20
+ //# sourceMappingURL=plan-tool-result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-tool-result.d.ts","sourceRoot":"","sources":["../../src/plan-tool-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,8BAA8B,CAAC;AAErE,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,gEAAgE;IAChE,aAAa,EAAE,OAAO,CAAC;CAC1B;AA4CD;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,GAAG,SAAS,CAmB7F;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CASrF"}
@@ -0,0 +1,78 @@
1
+ const TASK_STATUSES = [
2
+ "pending",
3
+ "in_progress",
4
+ "completed",
5
+ "blocked",
6
+ ];
7
+ function isTaskStatus(value) {
8
+ return typeof value === "string" && TASK_STATUSES.includes(value);
9
+ }
10
+ function isPlainObject(value) {
11
+ return typeof value === "object" && value !== null && !Array.isArray(value);
12
+ }
13
+ function isValidPlan(value) {
14
+ if (!isPlainObject(value)) {
15
+ return false;
16
+ }
17
+ if (typeof value.planId !== "string" || value.planId === "") {
18
+ return false;
19
+ }
20
+ if (typeof value.goal !== "string") {
21
+ return false;
22
+ }
23
+ if (!Array.isArray(value.tasks)) {
24
+ return false;
25
+ }
26
+ for (const task of value.tasks) {
27
+ if (!isPlainObject(task)) {
28
+ return false;
29
+ }
30
+ if (typeof task.title !== "string") {
31
+ return false;
32
+ }
33
+ if (!isTaskStatus(task.status)) {
34
+ return false;
35
+ }
36
+ }
37
+ return true;
38
+ }
39
+ /**
40
+ * 从已解析的值(如 JSON.parse 结果、middleware 的 `event.result.details`)中
41
+ * 结构校验并提取计划工具的成功返回。不是计划工具返回、ok:false 一律返回 undefined。
42
+ * 供 `parsePlanToolResult`(字符串输入)与 middleware(对象输入)共用同一份判定,
43
+ * 避免两份校验漂移。
44
+ */
45
+ export function parsePlanToolResultFromValue(value) {
46
+ if (!isPlainObject(value)) {
47
+ return undefined;
48
+ }
49
+ if (value.ok !== true) {
50
+ return undefined;
51
+ }
52
+ if (typeof value.planId !== "string" || value.planId === "") {
53
+ return undefined;
54
+ }
55
+ if (!isValidPlan(value.plan)) {
56
+ return undefined;
57
+ }
58
+ return {
59
+ planId: value.planId,
60
+ plan: value.plan,
61
+ hasEventField: "event" in value,
62
+ };
63
+ }
64
+ /**
65
+ * 从工具返回 JSON 文本中解析计划工具的成功返回。
66
+ * 不是计划工具返回、解析失败、ok:false 一律返回 undefined(绝不抛异常)。
67
+ */
68
+ export function parsePlanToolResult(rawBody) {
69
+ let parsed;
70
+ try {
71
+ parsed = JSON.parse(rawBody);
72
+ }
73
+ catch {
74
+ return undefined;
75
+ }
76
+ return parsePlanToolResultFromValue(parsed);
77
+ }
78
+ //# sourceMappingURL=plan-tool-result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-tool-result.js","sourceRoot":"","sources":["../../src/plan-tool-result.ts"],"names":[],"mappings":"AASA,MAAM,aAAa,GAA0B;IACzC,SAAS;IACT,aAAa;IACb,WAAW;IACX,SAAS;CACZ,CAAC;AAEF,SAAS,YAAY,CAAC,KAAc;IAChC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,aAAmC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC7F,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACjC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IAC/B,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC1D,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACjC,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAAC,KAAc;IACvD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,IAAI,KAAK,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC1D,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,OAAO;QACH,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,aAAa,EAAE,OAAO,IAAI,KAAK;KAClC,CAAC;AACN,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAe;IAC/C,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,OAAO,4BAA4B,CAAC,MAAM,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=plan-tool-result.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-tool-result.test.d.ts","sourceRoot":"","sources":["../../src/plan-tool-result.test.ts"],"names":[],"mappings":""}