@migor/agentia 0.10.4 → 0.10.6

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 (162) hide show
  1. package/CHANGELOG.md +281 -1
  2. package/README.en.md +1 -1
  3. package/README.md +2 -2
  4. package/dist/AGENTS.md +93 -11
  5. package/dist/container/container.js +3 -0
  6. package/dist/container/container.js.map +1 -1
  7. package/dist/core/abort.js +6 -1
  8. package/dist/core/abort.js.map +1 -1
  9. package/dist/core/json.js +4 -0
  10. package/dist/core/json.js.map +1 -1
  11. package/dist/core/limits.d.ts +13 -5
  12. package/dist/core/limits.js +14 -5
  13. package/dist/core/limits.js.map +1 -1
  14. package/dist/core/sse.d.ts +0 -13
  15. package/dist/core/sse.js +28 -2
  16. package/dist/core/sse.js.map +1 -1
  17. package/dist/core/timeout.d.ts +8 -0
  18. package/dist/core/timeout.js +19 -1
  19. package/dist/core/timeout.js.map +1 -1
  20. package/dist/core/tool.d.ts +18 -0
  21. package/dist/core/trace.d.ts +9 -0
  22. package/dist/core/trace.js +21 -0
  23. package/dist/core/trace.js.map +1 -1
  24. package/dist/engine/forwarded.d.ts +3 -1
  25. package/dist/engine/forwarded.js +5 -0
  26. package/dist/engine/forwarded.js.map +1 -1
  27. package/dist/engine/loop.d.ts +5 -1
  28. package/dist/engine/loop.js +45 -12
  29. package/dist/engine/loop.js.map +1 -1
  30. package/dist/engine/mcp-server.d.ts +17 -1
  31. package/dist/engine/mcp-server.js +36 -2
  32. package/dist/engine/mcp-server.js.map +1 -1
  33. package/dist/engine/policy.js +5 -1
  34. package/dist/engine/policy.js.map +1 -1
  35. package/dist/engine/replay.js +63 -1
  36. package/dist/engine/replay.js.map +1 -1
  37. package/dist/engine/run-config.d.ts +6 -0
  38. package/dist/engine/run-config.js +18 -6
  39. package/dist/engine/run-config.js.map +1 -1
  40. package/dist/engine/spec.d.ts +11 -1
  41. package/dist/engine/spec.js.map +1 -1
  42. package/dist/engine/stop-reason.js +19 -1
  43. package/dist/engine/stop-reason.js.map +1 -1
  44. package/dist/engine/tool-context.d.ts +3 -1
  45. package/dist/engine/tool-context.js +3 -1
  46. package/dist/engine/tool-context.js.map +1 -1
  47. package/dist/engine/tool-events.d.ts +7 -2
  48. package/dist/engine/tool-events.js +24 -3
  49. package/dist/engine/tool-events.js.map +1 -1
  50. package/dist/engine/tracer.js +10 -3
  51. package/dist/engine/tracer.js.map +1 -1
  52. package/dist/engine/turn.d.ts +9 -13
  53. package/dist/engine/turn.js +96 -10
  54. package/dist/engine/turn.js.map +1 -1
  55. package/dist/engine/types.d.ts +19 -2
  56. package/dist/engine/types.js +1 -0
  57. package/dist/engine/types.js.map +1 -1
  58. package/dist/engine/usage.js +12 -4
  59. package/dist/engine/usage.js.map +1 -1
  60. package/dist/index.d.ts +11 -3
  61. package/dist/index.js +7 -1
  62. package/dist/index.js.map +1 -1
  63. package/dist/integrations/anthropic.d.ts +9 -1
  64. package/dist/integrations/anthropic.js +42 -7
  65. package/dist/integrations/anthropic.js.map +1 -1
  66. package/dist/integrations/file-sink.d.ts +1 -0
  67. package/dist/integrations/file-sink.js +35 -32
  68. package/dist/integrations/file-sink.js.map +1 -1
  69. package/dist/integrations/mcp-http.js +33 -9
  70. package/dist/integrations/mcp-http.js.map +1 -1
  71. package/dist/integrations/mcp-protocol.js +33 -16
  72. package/dist/integrations/mcp-protocol.js.map +1 -1
  73. package/dist/integrations/metrics-otlp.js +4 -0
  74. package/dist/integrations/metrics-otlp.js.map +1 -1
  75. package/dist/integrations/metrics.js +17 -2
  76. package/dist/integrations/metrics.js.map +1 -1
  77. package/dist/integrations/openai.d.ts +6 -1
  78. package/dist/integrations/openai.js +45 -8
  79. package/dist/integrations/openai.js.map +1 -1
  80. package/dist/integrations/otlp.js +6 -0
  81. package/dist/integrations/otlp.js.map +1 -1
  82. package/dist/runtime/memory.d.ts +0 -8
  83. package/dist/runtime/memory.js +24 -2
  84. package/dist/runtime/memory.js.map +1 -1
  85. package/dist/runtime/run.js +34 -9
  86. package/dist/runtime/run.js.map +1 -1
  87. package/dist/store/fsStore.d.ts +2 -0
  88. package/dist/store/fsStore.js +38 -5
  89. package/dist/store/fsStore.js.map +1 -1
  90. package/dist/store/record.d.ts +40 -0
  91. package/dist/store/record.js +72 -0
  92. package/dist/store/record.js.map +1 -1
  93. package/dist/store/redisStore.js +15 -4
  94. package/dist/store/redisStore.js.map +1 -1
  95. package/dist/store/sqliteStore.js +39 -14
  96. package/dist/store/sqliteStore.js.map +1 -1
  97. package/dist/store/store.d.ts +6 -1
  98. package/dist/store/store.js +10 -4
  99. package/dist/store/store.js.map +1 -1
  100. package/dist/toolkit/capability-loop.d.ts +92 -0
  101. package/dist/toolkit/capability-loop.js +81 -0
  102. package/dist/toolkit/capability-loop.js.map +1 -0
  103. package/dist/toolkit/manifest.d.ts +21 -0
  104. package/dist/toolkit/manifest.js +38 -0
  105. package/dist/toolkit/manifest.js.map +1 -0
  106. package/dist/toolkit/module.d.ts +5 -0
  107. package/dist/toolkit/module.js +9 -0
  108. package/dist/toolkit/module.js.map +1 -1
  109. package/dist/toolkit/prompt.d.ts +3 -1
  110. package/dist/toolkit/prompt.js +22 -3
  111. package/dist/toolkit/prompt.js.map +1 -1
  112. package/dist/toolkit/skill.d.ts +3 -1
  113. package/dist/toolkit/skill.js +2 -0
  114. package/dist/toolkit/skill.js.map +1 -1
  115. package/dist/toolkit/subagent.d.ts +3 -1
  116. package/dist/toolkit/subagent.js +2 -0
  117. package/dist/toolkit/subagent.js.map +1 -1
  118. package/dist/toolkit/tool.d.ts +3 -1
  119. package/dist/toolkit/tool.js +2 -0
  120. package/dist/toolkit/tool.js.map +1 -1
  121. package/dist/transport/approval-policy.d.ts +1 -1
  122. package/dist/transport/approval-policy.js +18 -3
  123. package/dist/transport/approval-policy.js.map +1 -1
  124. package/dist/transport/approval-supervisor.d.ts +15 -3
  125. package/dist/transport/approval-supervisor.js +37 -11
  126. package/dist/transport/approval-supervisor.js.map +1 -1
  127. package/dist/transport/async.d.ts +3 -4
  128. package/dist/transport/async.js +157 -30
  129. package/dist/transport/async.js.map +1 -1
  130. package/dist/transport/drain-gate.js +13 -1
  131. package/dist/transport/drain-gate.js.map +1 -1
  132. package/dist/transport/http-endpoints.d.ts +13 -0
  133. package/dist/transport/http-endpoints.js +108 -28
  134. package/dist/transport/http-endpoints.js.map +1 -1
  135. package/dist/transport/http-shapes.d.ts +26 -3
  136. package/dist/transport/http-shapes.js +12 -2
  137. package/dist/transport/http-shapes.js.map +1 -1
  138. package/dist/transport/http.d.ts +46 -2
  139. package/dist/transport/http.js +43 -18
  140. package/dist/transport/http.js.map +1 -1
  141. package/dist/transport/resume-scanner.d.ts +3 -0
  142. package/dist/transport/resume-scanner.js +10 -1
  143. package/dist/transport/resume-scanner.js.map +1 -1
  144. package/dist/transport/run-call-options.js +46 -1
  145. package/dist/transport/run-call-options.js.map +1 -1
  146. package/dist/transport/run-options.d.ts +98 -0
  147. package/dist/transport/run-options.js +121 -0
  148. package/dist/transport/run-options.js.map +1 -0
  149. package/dist/transport/run-outcome.js +21 -1
  150. package/dist/transport/run-outcome.js.map +1 -1
  151. package/dist/transport/serve.js +10 -0
  152. package/dist/transport/serve.js.map +1 -1
  153. package/dist/transport/signal-supervisor.d.ts +3 -0
  154. package/dist/transport/signal-supervisor.js +5 -1
  155. package/dist/transport/signal-supervisor.js.map +1 -1
  156. package/dist/transport/stream-janitor.d.ts +45 -0
  157. package/dist/transport/stream-janitor.js +137 -0
  158. package/dist/transport/stream-janitor.js.map +1 -0
  159. package/dist/transport/task-wake-gate.d.ts +40 -0
  160. package/dist/transport/task-wake-gate.js +69 -0
  161. package/dist/transport/task-wake-gate.js.map +1 -0
  162. package/package.json +2 -2
@@ -20,6 +20,7 @@
20
20
  import { approvalExpired, approvalsComplete, fillTimeoutDenials } from './approval-policy.js';
21
21
  import { summarizeSuspended } from './wake-policy.js';
22
22
  import { isThenable } from '../store/store.js';
23
+ import { TaskWakeGate } from './task-wake-gate.js';
23
24
  /**
24
25
  * `approve` 的失败:带 HTTP 语义的状态码(404 = 任务不存在,409 = 任务当前不在
25
26
  * `suspended` 状态),HTTP 宿主据此回对应响应。
@@ -56,8 +57,11 @@ export class ApprovalSupervisor {
56
57
  * `approve` 与超时恢复都会「填决定 + 落库 + 派发」,不互斥就是同一任务跑两遍。 */
57
58
  #inflight = new Map();
58
59
  #deps;
60
+ /** 共享闸;单测可省略(省略时本件自建一把,跨路径互斥只在 AsyncRunner 注入时生效) */
61
+ #wakeGate;
59
62
  constructor(deps) {
60
63
  this.#deps = deps;
64
+ this.#wakeGate = deps.wakeGate ?? new TaskWakeGate();
61
65
  }
62
66
  /** 挂起读数:按原因分组的条数 + 最早的目标时刻(无时间挂起时为 `null`) */
63
67
  get summary() {
@@ -87,12 +91,18 @@ export class ApprovalSupervisor {
87
91
  }
88
92
  }
89
93
  /**
90
- * 惰性审批超时:`approvalExpired` 为真 ⇒ 进在飞闸 + 自动全拒 + 落库 + 派发。返回是否命中。
94
+ * 惰性审批超时:`approvalExpired` 为真 ⇒ 进在飞闸 + 自动全拒 + 落库 + 派发。
95
+ *
96
+ * **返回是否真的起了这次恢复**(2026-11-09 深评 P2):「命中超时判定」不等于「已经恢复」
97
+ * —— cancel 在飞、同任务已有别的唤醒路径占着互斥闸时,这里只是**跳过本轮**。此前它在
98
+ * 两条跳过路径上都返回 true,`resumePending` 据此 `expired++` 会说「处理了 N 条」而实际
99
+ * 一条没动;更糟的是宿主若只在启动时调一次 `resumePending`,这次跳过就等于该任务的
100
+ * 审批超时兜底丢了(下一个重判机会只来自 `poll`)。
91
101
  *
92
102
  * 与原 `#lazyGates` / `#redispatch` 里那两句 `if (approvalExpired(...)) #expireAndResume(...)`
93
- * **逐字等价** —— `approvalExpired` 内部已判 `status === 'suspended'` 与
103
+ * 的**判定**逐字等价 —— `approvalExpired` 内部已判 `status === 'suspended'` 与
94
104
  * `reason === 'approval'`(见 approval-policy.ts),所以 `#redispatch` 原写法里那句额外的
95
- * `rec.status !== 'suspended'` 短路是冗余的,合并到本方法不改变任何可观测行为。
105
+ * `rec.status !== 'suspended'` 短路是冗余的。
96
106
  */
97
107
  expireIfExpired(rec, now) {
98
108
  if (!approvalExpired(rec, now, this.#deps.approvalTimeoutMs))
@@ -101,8 +111,7 @@ export class ApprovalSupervisor {
101
111
  // 就是「取消后照常执行」那条竞态。惰性路径不丢事:下一轮读还会再判(若取消没成)。
102
112
  if (this.#deps.cancelInflight?.(rec.taskId))
103
113
  return false;
104
- this.#expireAndResume(rec, now);
105
- return true;
114
+ return this.#expireAndResume(rec, now);
106
115
  }
107
116
  /**
108
117
  * 审批一个处于 `suspended` 的任务(HITL)。
@@ -134,7 +143,9 @@ export class ApprovalSupervisor {
134
143
  const inflight = this.#inflight.get(taskId);
135
144
  if (inflight)
136
145
  return inflight;
137
- const run = this.#approveInner(taskId, decisions, opts).finally(() => {
146
+ const run = this.#wakeGate
147
+ .run(taskId, () => this.#approveInner(taskId, decisions, opts))
148
+ .finally(() => {
138
149
  this.#inflight.delete(taskId);
139
150
  });
140
151
  this.#inflight.set(taskId, run);
@@ -173,8 +184,15 @@ export class ApprovalSupervisor {
173
184
  }
174
185
  rec.approvals ??= {};
175
186
  for (const [id, d] of Object.entries(decisions)) {
176
- if (rec.approvals[id])
177
- continue; // 逐 id 幂等:第一次决定赢
187
+ const existing = rec.approvals[id];
188
+ // 逐 id 幂等,但**旧挂起的决定**允许被本次覆盖(2026-11-07 深评):
189
+ // OpenAI 兼容端点会复用 `call_1`,旧决定若不换新,新一次等待无法批准。
190
+ const stale = existing !== undefined &&
191
+ rec.suspendedSince !== undefined &&
192
+ existing.requestedAt !== undefined &&
193
+ existing.requestedAt !== rec.suspendedSince;
194
+ if (existing !== undefined && !stale)
195
+ continue;
178
196
  rec.approvals[id] = {
179
197
  approved: d.approved,
180
198
  ...(d.reason !== undefined ? { reason: d.reason } : {}),
@@ -186,7 +204,7 @@ export class ApprovalSupervisor {
186
204
  // 惰性审批超时:人的决定先并入(先到先赢),仍空着的待决项由超时兜底成 deny
187
205
  if (approvalExpired(rec, now, this.#deps.approvalTimeoutMs))
188
206
  fillTimeoutDenials(rec, now);
189
- const complete = approvalsComplete(rec);
207
+ const complete = approvalsComplete(rec, rec.suspendedSince);
190
208
  if (complete) {
191
209
  rec.status = 'running'; // 由 #executeInner 接管(acquireSlot → 恢复执行)
192
210
  rec.ownerId = this.#deps.ownerId;
@@ -218,13 +236,21 @@ export class ApprovalSupervisor {
218
236
  */
219
237
  #expireAndResume(rec, now) {
220
238
  if (this.#inflight.has(rec.taskId))
221
- return;
222
- const run = this.#expireAndResumeInner(rec, now).finally(() => {
239
+ return false;
240
+ // 跨路径互斥(2026-11-07 深评 P1):其它唤醒路径在飞 ⇒ 跳过本轮。
241
+ // 惰性路径不丢事:下一次 poll / resumePending 还会再判。返回 false 让调用方知道
242
+ // 「这一轮什么都没做」(2026-11-09 深评 P2:此前无条件返回 true,计数与事实不符)。
243
+ if (this.#wakeGate.busy(rec.taskId))
244
+ return false;
245
+ const run = this.#wakeGate
246
+ .run(rec.taskId, () => this.#expireAndResumeInner(rec, now))
247
+ .finally(() => {
223
248
  this.#inflight.delete(rec.taskId);
224
249
  });
225
250
  this.#inflight.set(rec.taskId, run);
226
251
  // poll / resumePending 路径没有调用方接 reject —— 订阅掉,不得逃逸成 unhandled rejection
227
252
  run.catch(() => undefined);
253
+ return true;
228
254
  }
229
255
  async #expireAndResumeInner(rec, now) {
230
256
  // 进闸后**重读一遍**再判:闸只互斥「进入」,挡不住「进闸前已取到的旧副本」——
@@ -1 +1 @@
1
- {"version":3,"file":"approval-supervisor.js","sourceRoot":"","sources":["../../src/transport/approval-supervisor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"approval-supervisor.js","sourceRoot":"","sources":["../../src/transport/approval-supervisor.ts"],"names":[],"mappings":"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"}
@@ -283,10 +283,8 @@ export declare class AsyncRunner {
283
283
  * (恢复段不把 session 交给 run 层,见 #executeInner 的 callOpts 注释)。
284
284
  * 只在首个挂起段快照;任务达终态时清掉(#execute 的出口)。
285
285
  *
286
- * **刻意只放内存**:进程崩在「挂起 → 重启 → approve」之间会丢这一次会话回写 ——
287
- * 会话少一轮,但绝写不进坏历史(孤立 tool_use / 历史翻倍),审批决定本身已落库、
288
- * 不受影响。快照若落库就要动 TaskRecord 的序列化 schema(sqlite / redis),
289
- * 而它相对审批决定只是锦上添花 —— 这个取舍是有意的。
286
+ * 这张 Map 只是本进程快路;同一份快照也由 applySuspendedOutcome 写进
287
+ * TaskRecord.sessionInput,挂起期间重启后仍能补写。终态两条路径一起清。
290
288
  */
291
289
  private readonly sessionInputs;
292
290
  constructor(app: AppCallable, opts?: AsyncRunnerOptions);
@@ -322,6 +320,7 @@ export declare class AsyncRunner {
322
320
  */
323
321
  streamTask(taskId: string, listener: (frame: TaskStreamFrame) => void, opts?: {
324
322
  from?: number;
323
+ pollMs?: number;
325
324
  }): Promise<() => void>;
326
325
  byIdempotency(key: string): MaybePromise<TaskRecord | undefined>;
327
326
  list(): MaybePromise<TaskRecord[]>;
@@ -8,11 +8,13 @@ import { combineSignals, releaseCombinedSignal } from '../core/abort.js';
8
8
  import { abortedError } from '../engine/turn.js';
9
9
  import { assertTimerDelay, TimeoutError } from '../core/timeout.js';
10
10
  import { zeroClauseOf } from '../core/limits.js';
11
- import { composeTraceEvents } from '../core/trace.js';
11
+ import { addUsage, composeTraceEvents } from '../core/trace.js';
12
12
  import { SlotPool } from './slot-pool.js';
13
13
  import { ApprovalSupervisor } from './approval-supervisor.js';
14
14
  import { SignalSupervisor } from './signal-supervisor.js';
15
15
  import { ResumeScanner } from './resume-scanner.js';
16
+ import { TaskWakeGate } from './task-wake-gate.js';
17
+ import { createStreamJanitorGroup } from './stream-janitor.js';
16
18
  import { timerDue } from './wake-policy.js';
17
19
  import { DrainGate } from './drain-gate.js';
18
20
  import { formatOwnerId } from './owner-id.js';
@@ -96,6 +98,12 @@ export class TaskQueueFullError extends Error {
96
98
  * 如实抛 409(见 `#awaitCancelled`),不假装取消成功。
97
99
  */
98
100
  const CANCEL_GRACE_MS = 2_000;
101
+ /**
102
+ * 跨进程流的兜底轮询间隔(2026-11-07 深评 F5):本进程的 `markDone` 只覆盖本进程写终态,
103
+ * 后续段在别的进程完成时只能靠读 store 收口。5s 是「连接不挂死」与「store 读放大」的折中;
104
+ * 0 可关闭(内部/测试用)。
105
+ */
106
+ const STREAM_CROSS_PROCESS_POLL_MS = 5_000;
99
107
  export class AsyncRunner {
100
108
  app;
101
109
  store;
@@ -157,6 +165,12 @@ export class AsyncRunner {
157
165
  }
158
166
  runTimeoutMs;
159
167
  approvalTimeoutMs;
168
+ /**
169
+ * 跨唤醒路径的 per-task 互斥闸(2026-11-07 深评 P1):approve / signalTask / 审批超时 /
170
+ * 到期唤醒共用同一张表。缺了它,`approve × signalTask`(或 `wakeDue × signalTask`)
171
+ * 会各自凭同一份 suspended 快照派发一次 ⇒ 同一任务跑两遍、后写覆盖前写。
172
+ */
173
+ #wakeGate = new TaskWakeGate();
160
174
  /**
161
175
  * 审批监督簇(挂起登记 + 在飞闸 + `approve` + 超时恢复)—— 实现见 approval-supervisor.ts。
162
176
  * 依赖(store / ownerId / approvalTimeoutMs / dispatch 回调)在构造函数末尾注入。
@@ -200,6 +214,13 @@ export class AsyncRunner {
200
214
  * 纯记账件,独立于 store / 槽位 —— 所以在 855 行的类里单独抽一个文件。
201
215
  */
202
216
  #streams;
217
+ /**
218
+ * 跨进程流兜底的**单例扫描器**(2026-11-09 深评 P2-1):此前 `streamTask` 给每个订阅
219
+ * 各建一个 5s 定时器去 `store.get`,N 个并发连接就是 N 个定时器 + N/5 QPS,无合并无上限 ——
220
+ * 而跨进程收口是低频事件,不值得按连接付这份成本。现在一拍里每个**任务**只读一次 store,
221
+ * 再把结论分发到该任务的各个订阅(见 stream-janitor.ts)。
222
+ */
223
+ #streamJanitors;
203
224
  /**
204
225
  * **同进程内的幂等键认领表**(idempotencyKey → 在飞记录)。
205
226
  *
@@ -219,10 +240,8 @@ export class AsyncRunner {
219
240
  * (恢复段不把 session 交给 run 层,见 #executeInner 的 callOpts 注释)。
220
241
  * 只在首个挂起段快照;任务达终态时清掉(#execute 的出口)。
221
242
  *
222
- * **刻意只放内存**:进程崩在「挂起 → 重启 → approve」之间会丢这一次会话回写 ——
223
- * 会话少一轮,但绝写不进坏历史(孤立 tool_use / 历史翻倍),审批决定本身已落库、
224
- * 不受影响。快照若落库就要动 TaskRecord 的序列化 schema(sqlite / redis),
225
- * 而它相对审批决定只是锦上添花 —— 这个取舍是有意的。
243
+ * 这张 Map 只是本进程快路;同一份快照也由 applySuspendedOutcome 写进
244
+ * TaskRecord.sessionInput,挂起期间重启后仍能补写。终态两条路径一起清。
226
245
  */
227
246
  sessionInputs = new Map();
228
247
  constructor(app, opts = {}) {
@@ -269,6 +288,15 @@ export class AsyncRunner {
269
288
  throw new Error(`approvalTimeoutMs 必须为 ≥ 0 的有限数(${zeroClauseOf('AsyncRunner.approvalTimeoutMs')}),收到 ${opts.approvalTimeoutMs}`);
270
289
  }
271
290
  this.ownerId = formatOwnerId(process.pid, this.#host, randomUUID().slice(0, 8));
291
+ // 跨进程流兜底(2026-11-09 深评 P2-1):runner 级一个扫描器,一拍里每个任务只读一次 store。
292
+ // 用 `this.poll`(而不是裸 `store.get`)是为了保留惰性挂起闸 —— 审批超时 / 到期唤醒的
293
+ // 重判入口本来就搭在这条轮询上,换成裸 get 会让那两条兜底少一个触发点。
294
+ // 定时器**有订阅才存在**(见 stream-janitor.ts),空闲时零成本。
295
+ this.#streamJanitors = createStreamJanitorGroup({
296
+ poll: (taskId) => Promise.resolve(this.poll(taskId)),
297
+ ownerId: this.ownerId,
298
+ pollMs: STREAM_CROSS_PROCESS_POLL_MS,
299
+ });
272
300
  // 审批监督簇在 ownerId 就位后构造(它要用 store 与 ownerId)。`dispatch` 用**回调**
273
301
  // 注入而不是 import:派发入口 `#dispatch` 仍归本类(停机闸 + 唯一派发点 + 一次性告警),
274
302
  // 依赖保持单向(审批 → 派发),也避免两个模块互相 import。
@@ -276,6 +304,7 @@ export class AsyncRunner {
276
304
  store: this.store,
277
305
  ownerId: this.ownerId,
278
306
  approvalTimeoutMs: this.approvalTimeoutMs,
307
+ wakeGate: this.#wakeGate,
279
308
  dispatch: (rec) => this.#dispatch(rec),
280
309
  cancelInflight: (taskId) => this.#cancelInflight.get(taskId),
281
310
  });
@@ -286,6 +315,7 @@ export class AsyncRunner {
286
315
  store: this.store,
287
316
  ownerId: this.ownerId,
288
317
  approvals: this.#approvals,
318
+ wakeGate: this.#wakeGate,
289
319
  dispatch: (rec) => this.#dispatch(rec),
290
320
  cancelInflight: (taskId) => this.#cancelInflight.get(taskId),
291
321
  });
@@ -294,6 +324,7 @@ export class AsyncRunner {
294
324
  ownerId: this.ownerId,
295
325
  host: this.#host,
296
326
  approvals: this.#approvals,
327
+ wakeGate: this.#wakeGate,
297
328
  dispatch: (rec) => this.#dispatch(rec),
298
329
  isDraining: () => this.#drain.isDraining,
299
330
  cancelInflight: (taskId) => this.#cancelInflight.get(taskId),
@@ -429,17 +460,54 @@ export class AsyncRunner {
429
460
  const rec = await this.poll(taskId);
430
461
  if (rec)
431
462
  listener({ type: 'end', record: rec });
463
+ // 终态但记录被清(TTL / 外部删除)也不能静默:客户端需要一个收口帧。
464
+ else
465
+ listener({ type: 'closed', reason: 'not-in-this-process' });
432
466
  return noop;
433
467
  }
434
468
  // 实时订阅:`onDone` 里补发 `end` 帧 —— 终态是流的一部分
435
469
  //(没有它,这条 SSE 会在任务跑完之后一直挂着,客户端以为它还在跑)
436
- return this.#streams.subscribe(taskId, (item) => listener({ type: 'trace', index: item.index, event: item.event }), () => {
437
- // poll 可能是异步 store ⇒ 用 then 补发(此刻任务已终态、记录已落库)
470
+ const off = this.#streams.subscribe(taskId, (item) => listener({ type: 'trace', index: item.index, event: item.event }), () => {
471
+ // poll 可能是异步 store ⇒ 用 then 补发(此刻任务已终态、记录已落库)。
472
+ // ⚠️ 必须有 rejection 处理(2026-11-07 深评):`poll` 在 Redis 抖动时 reject,
473
+ // 没有第二个参数的 `.then` 会产生 unhandledRejection ⇒ Node ≥15 终止宿主进程。
438
474
  void Promise.resolve(this.poll(taskId)).then((rec) => {
439
- if (rec)
440
- listener({ type: 'end', record: rec });
475
+ try {
476
+ if (rec)
477
+ listener({ type: 'end', record: rec });
478
+ // 记录被清(TTL / 外部删除)时也不能一帧都不发:`end` 是唯一会
479
+ // closeStream 的帧,不发就是永远只有心跳。
480
+ else
481
+ listener({ type: 'closed', reason: 'not-in-this-process' });
482
+ }
483
+ catch {
484
+ /* listener 自己的错由宿主记账,不得再变成 unhandled */
485
+ }
486
+ }, () => {
487
+ try {
488
+ listener({ type: 'closed', reason: 'not-in-this-process' });
489
+ }
490
+ catch {
491
+ /* 同上 */
492
+ }
441
493
  });
442
494
  });
495
+ // 跨进程收口(2026-11-07 深评 F5;2026-11-09 P2-1 提到 runner 级):登记到单例扫描器,
496
+ // 本流关闭时注销。`pollMs <= 0` = 这条流不参与兜底(真正的时间间隔只有一个来源,
497
+ // 即 runner 上那个扫描器 —— 单连接不再各建定时器)。
498
+ let janitorCleanup = noop;
499
+ const cleanup = () => {
500
+ off();
501
+ janitorCleanup();
502
+ };
503
+ if ((opts.pollMs ?? STREAM_CROSS_PROCESS_POLL_MS) > 0) {
504
+ janitorCleanup = this.#streamJanitors.add(taskId, {
505
+ isTerminal: (rec) => isTerminalTask(rec),
506
+ onTerminal: () => this.#streams.markDone(taskId),
507
+ onClosed: () => listener({ type: 'closed', reason: 'not-in-this-process' }),
508
+ });
509
+ }
510
+ return cleanup;
443
511
  }
444
512
  const rec = await this.poll(taskId);
445
513
  if (!rec)
@@ -516,11 +584,13 @@ export class AsyncRunner {
516
584
  if (advance !== undefined || isThenable(found)) {
517
585
  // 异步路径:先入闸(后续推进路径会看到它并等待/跳过),等在飞推进收口后**重读**再判
518
586
  const run = (async () => {
519
- if (advance !== undefined)
520
- await advance.catch(() => undefined);
521
587
  // 意图先立(等闸窗口里就要可见):等槽位那趟 #executeInner 可能正好放行 ——
522
- // 意图在场它才不会起跑(见 #executeInner 的取消意图闸)
588
+ // 意图在场它才不会起跑(见 #executeInner 的取消意图闸)。
589
+ // ⚠️ 必须在 `await advance` **之前**登记:此前写在等待之后,与注释相反,
590
+ // 让「等 approve 收口」的窗口里新起的 #execute 看不到意图(2026-11-07 深评)。
523
591
  this.#cancels.add(taskId);
592
+ if (advance !== undefined)
593
+ await advance.catch(() => undefined);
524
594
  try {
525
595
  const rec = advance !== undefined ? await this.store.get(taskId) : await found;
526
596
  return await this.#cancel(rec, taskId);
@@ -541,7 +611,10 @@ export class AsyncRunner {
541
611
  }
542
612
  /** 三条推进路径(审批 / 事件投递 / 到期唤醒)在该任务上的在飞 Promise(无则 undefined) */
543
613
  #advanceInflight(taskId) {
544
- return (this.#approvals.inflightFor(taskId) ??
614
+ // 跨路径闸的 tail 覆盖**全部**已登记的唤醒(含排队中的);先取它,再退回各监督件的
615
+ // 单件读数 —— tail 是 2026-11-07 深评 P1 的修法,单件读数只作防御性兜底。
616
+ return (this.#wakeGate.tail(taskId) ??
617
+ this.#approvals.inflightFor(taskId) ??
545
618
  this.#signals.inflightFor(taskId) ??
546
619
  this.#scanner.inflightWakeFor(taskId));
547
620
  }
@@ -604,7 +677,10 @@ export class AsyncRunner {
604
677
  this.#reportPersistError(rec, error, 'outcome');
605
678
  saved = undefined;
606
679
  }
607
- if (wasQueued)
680
+ // 只有「确实有一趟活着的 #execute 会消费这个标记」才登记;`queued` 但本进程没有
681
+ // 对应执行趟(resumePending 认领后被停机拒派 / 上一进程崩溃留下的记录)时登记
682
+ // 会永远没人摘(2026-11-07 深评 F8)。
683
+ if (wasQueued && this.#executions.has(taskId))
608
684
  this.#cancelSettled.add(taskId);
609
685
  const finish = () => {
610
686
  // 取消意图的终点(2026-10-13 ref-run-root-close):还有活着的 #execute 时留给它消费 —— 它靠这个意图
@@ -820,11 +896,18 @@ export class AsyncRunner {
820
896
  /** 等到任务终态;超时抛错。`suspended` 不是终态 —— 继续等(人在路上 / 时刻未到)。 */
821
897
  async awaitTask(taskId, opts = {}) {
822
898
  const timeoutMs = opts.timeoutMs ?? 30_000;
899
+ // 坏值防线(2026-11-07 深评 F6):`timeoutMs: NaN` 会让 `deadline` 变 NaN、
900
+ // `left <= 0` 恒假 ⇒ 永不超时;`Math.min(intervalMs, left)` 再把 NaN 交给
901
+ // setTimeout(Node 钳到 1ms)⇒ 每毫秒读一次 store。本仓其它定时旋钮全都挡了,这条漏了。
902
+ assertTimerDelay(timeoutMs, 'AsyncRunner.awaitTask 的 timeoutMs');
823
903
  // intervalMs 现在只是**兜底轮询**间隔,不是主路径:本进程把任务写到终态会主动唤醒
824
904
  // (见 task-waiters.ts 的 notify)。默认从 5ms 放宽到 250ms —— 旧实现每 5ms 读一次 store,
825
905
  // 等 30s 就是约 6000 次读(SQLite/Redis 下是 6000 次往返)。用异步 store 且终态由
826
906
  // **他进程**写入时唤不醒,才靠这个间隔兜底。
827
907
  const intervalMs = opts.intervalMs ?? 250;
908
+ if (!Number.isFinite(intervalMs) || intervalMs <= 0) {
909
+ throw new TypeError(`AsyncRunner.awaitTask 的 intervalMs 必须是正的有限数(毫秒),收到 ${String(opts.intervalMs)}`);
910
+ }
828
911
  const deadline = Date.now() + timeoutMs;
829
912
  for (;;) {
830
913
  // 走 poll 而不是裸 store.get:惰性审批超时的判定挂在那里(HITL)
@@ -1049,22 +1132,58 @@ export class AsyncRunner {
1049
1132
  const out = await this.#raceTimeout(this.app.run(rec.spec.messages, callOpts), rec.taskId, () => runAc.abort());
1050
1133
  rec.runId = out.run.runId;
1051
1134
  rec.result = out.result;
1135
+ // 每段一棵 trace,但任务预算是一笔总账:先把本段落进累计,再供下一次恢复作 offset。
1136
+ // 自定义 AppCallable 若没交 trace(历史测试/薄宿主),跳过累计而不是把业务任务判失败。
1137
+ const segmentUsage = out.result.trace?.totalUsage;
1138
+ if (segmentUsage)
1139
+ rec.usageTotal = addUsage(rec.usageTotal, segmentUsage);
1052
1140
  rec.error = out.result.error;
1053
1141
  if (out.result.stopReason === 'suspended' && out.result.suspendedMessages) {
1054
- // HITL 挂起:记录怎么改、事件簿记按 `eventsDelivered` 分档、以及「用户输入快照
1055
- // 必须在 `rec.spec` 被覆盖**之前**取」那条顺序事实 —— 全在 `run-outcome.ts`。
1056
- // 槽位照常释放(finally)、onFinished 不触发(#execute 的出口判断)、
1057
- // finishedAt 不置(下面 finally 里按状态跳过):它不是终态。
1058
- const snapshot = applySuspendedOutcome(rec, out.result, out.result.suspendedMessages, {
1059
- isResume,
1060
- hasSessionStore: this.sessionStore !== undefined,
1061
- now: Date.now(),
1062
- });
1063
- // 顺序承重:快照先落地,`markSuspended` 再登记(后者读 status / suspendedReason /
1064
- // wakeAt —— 三样都刚被上一行写好;挂起读数纪律①:与落库同一个分支登记)
1065
- if (snapshot !== undefined)
1066
- this.sessionInputs.set(rec.taskId, snapshot);
1067
- this.#approvals.markSuspended(rec);
1142
+ // 取消意图优先于挂起(2026-11-07 深评 P1-1):引擎侧的 abort 守卫已覆盖
1143
+ // 「signal 已中止」的出口;这里再兜住「结果已返回、cancel 在随后一拍到达」的
1144
+ // 窗口 —— 否则记录会落成 suspended,cancel 等不到终态而 409。
1145
+ if (this.#cancels.has(rec.taskId)) {
1146
+ rec.status = 'cancelled';
1147
+ rec.error ??= abortedError();
1148
+ rec.pendingApprovals = undefined;
1149
+ rec.suspendedSince = undefined;
1150
+ rec.suspendedReason = undefined;
1151
+ rec.wakeAt = undefined;
1152
+ rec.pendingEvents = undefined;
1153
+ this.#approvals.unmarkSuspended(rec.taskId);
1154
+ }
1155
+ else {
1156
+ // HITL 挂起:记录怎么改、事件簿记按 `eventsDelivered` 分档、以及「用户输入快照
1157
+ // 必须在 `rec.spec` 被覆盖**之前**取」那条顺序事实 —— 全在 `run-outcome.ts`。
1158
+ // 槽位照常释放(finally)、onFinished 不触发(#execute 的出口判断)、
1159
+ // finishedAt 不置(下面 finally 里按状态跳过):它不是终态。
1160
+ const snapshot = applySuspendedOutcome(rec, out.result, out.result.suspendedMessages, {
1161
+ isResume,
1162
+ hasSessionStore: this.sessionStore !== undefined,
1163
+ now: Date.now(),
1164
+ });
1165
+ // 顺序承重:快照先落地,`markSuspended` 再登记(后者读 status / suspendedReason /
1166
+ // wakeAt —— 三样都刚被上一行写好;挂起读数纪律①:与落库同一个分支登记)
1167
+ if (snapshot !== undefined)
1168
+ this.sessionInputs.set(rec.taskId, snapshot);
1169
+ this.#approvals.markSuspended(rec);
1170
+ }
1171
+ }
1172
+ else if (out.result.stopReason === 'suspended') {
1173
+ // 自定义 AppCallable 返回 suspended 却没给 suspendedMessages:内建引擎不会
1174
+ // 产生这种形状,但薄宿主/JS 宿主可达。按终态 failed 收口,别落成
1175
+ // 「suspended 但挂起痕迹全清」的僵尸记录(approve / resume 两条闸都判不到)。
1176
+ rec.status = 'failed';
1177
+ rec.error = {
1178
+ type: 'agent_error',
1179
+ message: 'AppCallable 返回了 stopReason=suspended,但没有 suspendedMessages —— 无法恢复,按失败收口',
1180
+ retryable: false,
1181
+ };
1182
+ rec.pendingApprovals = undefined;
1183
+ rec.suspendedSince = undefined;
1184
+ rec.suspendedReason = undefined;
1185
+ rec.wakeAt = undefined;
1186
+ this.#approvals.unmarkSuspended(rec.taskId);
1068
1187
  }
1069
1188
  else {
1070
1189
  // 取消:机制与 `runTimeoutMs` 一字不差(同一条 abort signal),**意图**不同 ——
@@ -1109,6 +1228,9 @@ export class AsyncRunner {
1109
1228
  }
1110
1229
  }
1111
1230
  finally {
1231
+ // 所有终态出口都清补写快照(含异常/取消);挂起则必须留下。
1232
+ if (isTerminalTask(rec))
1233
+ rec.sessionInput = undefined;
1112
1234
  // HITL:挂起不是「完成」—— finishedAt 不置(等待中的任务没有结束时刻)
1113
1235
  if (rec.status !== 'suspended')
1114
1236
  rec.finishedAt = Date.now();
@@ -1122,6 +1244,10 @@ export class AsyncRunner {
1122
1244
  }
1123
1245
  }
1124
1246
  catch (e) {
1247
+ // 认领处的 #runAborts 登记在 save('running') **之前**,而 save 可能同步抛 /
1248
+ // 异步 reject —— 那条路径跳过了内层 finally 的 delete ⇒ 句柄永久滞留。
1249
+ // 这里兜底摘除(幂等),避免失败次数把 Map 撑成无界(2026-11-07 深评 F7)。
1250
+ this.#runAborts.delete(rec.taskId);
1125
1251
  rec.status = 'failed';
1126
1252
  rec.error = classifyError(e);
1127
1253
  rec.finishedAt = Date.now();
@@ -1200,11 +1326,12 @@ export class AsyncRunner {
1200
1326
  * 只写「本轮用户输入 + 最终回复」(run 内部 tool 往返不进历史)、历史以 assistant
1201
1327
  * 结尾(无文本补占位)。回写失败吞掉 —— 辅助动作不得击穿任务(同 memory 回写防护)。
1202
1328
  *
1203
- * 无快照(进程在挂起期间重启过)时**跳过**:宁可少一轮历史,也不凭猜测写。
1329
+ * 本进程优先读内存快路;重启后读 TaskRecord.sessionInput。只有旧版本留下的挂起记录
1330
+ * 才可能两边都没有,那时跳过,不凭猜测写。
1204
1331
  */
1205
1332
  async #appendResumedSession(rec, finalText) {
1206
1333
  const sessionId = rec.spec.options?.sessionId;
1207
- const input = this.sessionInputs.get(rec.taskId);
1334
+ const input = this.sessionInputs.get(rec.taskId) ?? rec.sessionInput;
1208
1335
  if (sessionId === undefined || this.sessionStore === undefined || input === undefined)
1209
1336
  return;
1210
1337
  try {