@migor/agentia 0.9.4 → 0.10.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.
Files changed (211) hide show
  1. package/CHANGELOG.md +1280 -4
  2. package/README.en.md +61 -3
  3. package/README.md +66 -4
  4. package/dist/AGENTS.md +330 -45
  5. package/dist/container/container.js +21 -0
  6. package/dist/container/container.js.map +1 -1
  7. package/dist/core/limits.d.ts +101 -14
  8. package/dist/core/limits.js +103 -13
  9. package/dist/core/limits.js.map +1 -1
  10. package/dist/core/line-framing.d.ts +36 -0
  11. package/dist/core/line-framing.js +39 -0
  12. package/dist/core/line-framing.js.map +1 -0
  13. package/dist/core/message.d.ts +11 -0
  14. package/dist/core/run.d.ts +68 -4
  15. package/dist/core/run.js +27 -1
  16. package/dist/core/run.js.map +1 -1
  17. package/dist/core/schema.js +59 -8
  18. package/dist/core/schema.js.map +1 -1
  19. package/dist/core/timeout.d.ts +43 -1
  20. package/dist/core/timeout.js +76 -3
  21. package/dist/core/timeout.js.map +1 -1
  22. package/dist/core/tool.d.ts +25 -1
  23. package/dist/core/trace.d.ts +40 -1
  24. package/dist/core/trace.js +26 -0
  25. package/dist/core/trace.js.map +1 -1
  26. package/dist/engine/budget.js +14 -0
  27. package/dist/engine/budget.js.map +1 -1
  28. package/dist/engine/defer.d.ts +49 -0
  29. package/dist/engine/defer.js +72 -0
  30. package/dist/engine/defer.js.map +1 -0
  31. package/dist/engine/errors.d.ts +23 -1
  32. package/dist/engine/errors.js +24 -0
  33. package/dist/engine/errors.js.map +1 -1
  34. package/dist/engine/forwarded.d.ts +14 -5
  35. package/dist/engine/forwarded.js +4 -1
  36. package/dist/engine/forwarded.js.map +1 -1
  37. package/dist/engine/loop-result.d.ts +65 -7
  38. package/dist/engine/loop-result.js +24 -5
  39. package/dist/engine/loop-result.js.map +1 -1
  40. package/dist/engine/loop.d.ts +2 -0
  41. package/dist/engine/loop.js +157 -17
  42. package/dist/engine/loop.js.map +1 -1
  43. package/dist/engine/mcp-server-http.d.ts +2 -0
  44. package/dist/engine/mcp-server-http.js +215 -0
  45. package/dist/engine/mcp-server-http.js.map +1 -0
  46. package/dist/engine/mcp-server-stdio.d.ts +15 -0
  47. package/dist/engine/mcp-server-stdio.js +106 -0
  48. package/dist/engine/mcp-server-stdio.js.map +1 -0
  49. package/dist/engine/mcp-server.d.ts +134 -0
  50. package/dist/engine/mcp-server.js +232 -0
  51. package/dist/engine/mcp-server.js.map +1 -0
  52. package/dist/engine/menu-drift.d.ts +34 -0
  53. package/dist/engine/menu-drift.js +81 -0
  54. package/dist/engine/menu-drift.js.map +1 -0
  55. package/dist/engine/policy.d.ts +2 -1
  56. package/dist/engine/policy.js +7 -1
  57. package/dist/engine/policy.js.map +1 -1
  58. package/dist/engine/replay.d.ts +2 -1
  59. package/dist/engine/replay.js +3 -2
  60. package/dist/engine/replay.js.map +1 -1
  61. package/dist/engine/resume-input.d.ts +10 -0
  62. package/dist/engine/resume-input.js +11 -0
  63. package/dist/engine/resume-input.js.map +1 -1
  64. package/dist/engine/run-config.d.ts +26 -2
  65. package/dist/engine/run-config.js +60 -0
  66. package/dist/engine/run-config.js.map +1 -1
  67. package/dist/engine/spec.d.ts +33 -4
  68. package/dist/engine/spec.js.map +1 -1
  69. package/dist/engine/tool-context.d.ts +10 -5
  70. package/dist/engine/tool-context.js +5 -1
  71. package/dist/engine/tool-context.js.map +1 -1
  72. package/dist/engine/tracer.d.ts +43 -5
  73. package/dist/engine/tracer.js +73 -10
  74. package/dist/engine/tracer.js.map +1 -1
  75. package/dist/engine/trimming.js +28 -2
  76. package/dist/engine/trimming.js.map +1 -1
  77. package/dist/engine/turn.d.ts +60 -3
  78. package/dist/engine/turn.js +180 -71
  79. package/dist/engine/turn.js.map +1 -1
  80. package/dist/engine/types.d.ts +89 -3
  81. package/dist/engine/types.js +38 -2
  82. package/dist/engine/types.js.map +1 -1
  83. package/dist/eval/export.d.ts +48 -0
  84. package/dist/eval/export.js +146 -0
  85. package/dist/eval/export.js.map +1 -0
  86. package/dist/eval/harvest.js +7 -2
  87. package/dist/eval/harvest.js.map +1 -1
  88. package/dist/index.d.ts +8 -5
  89. package/dist/index.js +6 -1
  90. package/dist/index.js.map +1 -1
  91. package/dist/integrations/adapter-options.d.ts +22 -0
  92. package/dist/integrations/adapter-options.js +51 -0
  93. package/dist/integrations/adapter-options.js.map +1 -1
  94. package/dist/integrations/anthropic.d.ts +4 -2
  95. package/dist/integrations/anthropic.js +27 -27
  96. package/dist/integrations/anthropic.js.map +1 -1
  97. package/dist/integrations/file-sink.d.ts +20 -0
  98. package/dist/integrations/file-sink.js +27 -0
  99. package/dist/integrations/file-sink.js.map +1 -0
  100. package/dist/integrations/mcp-http.d.ts +3 -3
  101. package/dist/integrations/mcp-http.js +1 -1
  102. package/dist/integrations/mcp-http.js.map +1 -1
  103. package/dist/integrations/mcp-protocol.d.ts +115 -0
  104. package/dist/integrations/mcp-protocol.js +69 -0
  105. package/dist/integrations/mcp-protocol.js.map +1 -0
  106. package/dist/integrations/mcp-stdio.d.ts +3 -3
  107. package/dist/integrations/mcp-stdio.js +17 -3
  108. package/dist/integrations/mcp-stdio.js.map +1 -1
  109. package/dist/integrations/mcp.d.ts +6 -95
  110. package/dist/integrations/mcp.js +24 -66
  111. package/dist/integrations/mcp.js.map +1 -1
  112. package/dist/integrations/metrics-otlp.js +52 -7
  113. package/dist/integrations/metrics-otlp.js.map +1 -1
  114. package/dist/integrations/metrics-render.d.ts +15 -0
  115. package/dist/integrations/metrics-render.js +79 -2
  116. package/dist/integrations/metrics-render.js.map +1 -1
  117. package/dist/integrations/metrics-state.d.ts +99 -1
  118. package/dist/integrations/metrics-state.js +128 -4
  119. package/dist/integrations/metrics-state.js.map +1 -1
  120. package/dist/integrations/metrics.d.ts +62 -6
  121. package/dist/integrations/metrics.js +49 -8
  122. package/dist/integrations/metrics.js.map +1 -1
  123. package/dist/integrations/openai.js +9 -31
  124. package/dist/integrations/openai.js.map +1 -1
  125. package/dist/integrations/otlp.d.ts +3 -3
  126. package/dist/integrations/report.d.ts +7 -0
  127. package/dist/integrations/report.js +20 -1
  128. package/dist/integrations/report.js.map +1 -1
  129. package/dist/runtime/memory.d.ts +61 -1
  130. package/dist/runtime/memory.js +47 -7
  131. package/dist/runtime/memory.js.map +1 -1
  132. package/dist/runtime/run.d.ts +12 -2
  133. package/dist/runtime/run.js +126 -17
  134. package/dist/runtime/run.js.map +1 -1
  135. package/dist/store/fsStore.js +10 -4
  136. package/dist/store/fsStore.js.map +1 -1
  137. package/dist/store/record.d.ts +41 -0
  138. package/dist/store/record.js +54 -0
  139. package/dist/store/record.js.map +1 -0
  140. package/dist/store/redisStore.d.ts +24 -1
  141. package/dist/store/redisStore.js +42 -7
  142. package/dist/store/redisStore.js.map +1 -1
  143. package/dist/store/sqliteStore.d.ts +23 -0
  144. package/dist/store/sqliteStore.js +103 -8
  145. package/dist/store/sqliteStore.js.map +1 -1
  146. package/dist/store/store.d.ts +65 -2
  147. package/dist/store/store.js +5 -2
  148. package/dist/store/store.js.map +1 -1
  149. package/dist/toolkit/capability-cycles.d.ts +50 -0
  150. package/dist/toolkit/capability-cycles.js +88 -0
  151. package/dist/toolkit/capability-cycles.js.map +1 -0
  152. package/dist/toolkit/capability-slice.d.ts +86 -0
  153. package/dist/toolkit/capability-slice.js +98 -0
  154. package/dist/toolkit/capability-slice.js.map +1 -0
  155. package/dist/toolkit/module.d.ts +7 -1
  156. package/dist/toolkit/module.js +65 -32
  157. package/dist/toolkit/module.js.map +1 -1
  158. package/dist/transport/approval-policy.d.ts +1 -1
  159. package/dist/transport/approval-policy.js +8 -4
  160. package/dist/transport/approval-policy.js.map +1 -1
  161. package/dist/transport/approval-supervisor.d.ts +73 -0
  162. package/dist/transport/approval-supervisor.js +252 -0
  163. package/dist/transport/approval-supervisor.js.map +1 -0
  164. package/dist/transport/async.d.ts +159 -56
  165. package/dist/transport/async.js +627 -269
  166. package/dist/transport/async.js.map +1 -1
  167. package/dist/transport/drain-gate.d.ts +6 -2
  168. package/dist/transport/drain-gate.js +14 -2
  169. package/dist/transport/drain-gate.js.map +1 -1
  170. package/dist/transport/http-endpoints.d.ts +151 -0
  171. package/dist/transport/http-endpoints.js +480 -0
  172. package/dist/transport/http-endpoints.js.map +1 -0
  173. package/dist/transport/http-io.d.ts +66 -0
  174. package/dist/transport/http-io.js +145 -0
  175. package/dist/transport/http-io.js.map +1 -0
  176. package/dist/transport/http-route.d.ts +10 -3
  177. package/dist/transport/http-route.js +18 -3
  178. package/dist/transport/http-route.js.map +1 -1
  179. package/dist/transport/http-shapes.d.ts +11 -0
  180. package/dist/transport/http-shapes.js +31 -1
  181. package/dist/transport/http-shapes.js.map +1 -1
  182. package/dist/transport/http.d.ts +22 -35
  183. package/dist/transport/http.js +98 -476
  184. package/dist/transport/http.js.map +1 -1
  185. package/dist/transport/owner-id.d.ts +29 -0
  186. package/dist/transport/owner-id.js +46 -0
  187. package/dist/transport/owner-id.js.map +1 -0
  188. package/dist/transport/owner-liveness.d.ts +8 -0
  189. package/dist/transport/owner-liveness.js +56 -0
  190. package/dist/transport/owner-liveness.js.map +1 -0
  191. package/dist/transport/resume-policy.d.ts +48 -10
  192. package/dist/transport/resume-policy.js +25 -10
  193. package/dist/transport/resume-policy.js.map +1 -1
  194. package/dist/transport/resume-scanner.d.ts +55 -0
  195. package/dist/transport/resume-scanner.js +219 -0
  196. package/dist/transport/resume-scanner.js.map +1 -0
  197. package/dist/transport/scheduler.js +9 -23
  198. package/dist/transport/scheduler.js.map +1 -1
  199. package/dist/transport/signal-supervisor.d.ts +80 -0
  200. package/dist/transport/signal-supervisor.js +129 -0
  201. package/dist/transport/signal-supervisor.js.map +1 -0
  202. package/dist/transport/slot-pool.d.ts +9 -1
  203. package/dist/transport/slot-pool.js +9 -1
  204. package/dist/transport/slot-pool.js.map +1 -1
  205. package/dist/transport/task-events.d.ts +34 -3
  206. package/dist/transport/task-events.js +93 -5
  207. package/dist/transport/task-events.js.map +1 -1
  208. package/dist/transport/wake-policy.d.ts +50 -0
  209. package/dist/transport/wake-policy.js +43 -0
  210. package/dist/transport/wake-policy.js.map +1 -0
  211. package/package.json +14 -4
@@ -6,11 +6,65 @@ import type { SpanError } from './trace.js';
6
6
  * store / transport / runtime 都要读它,下沉 core 后三者都不必再向上引 runtime
7
7
  * (此前 `store → runtime` 是未声明的兄弟层依赖,见 AGENTS.md 分层约定)。
8
8
  *
9
- * `awaiting_approval`(HITL):run 在等人审批 —— **非终态**(awaitTask 继续轮询)、
10
- * 不占并发槽(执行段落已收尾释放)、`resumePending` 不捡走(它不是孤儿,崩溃续跑语义
11
- * 不适用于「在等人」);消息历史(含未决 tool_use)与待决清单随 TaskRecord 落库。
9
+ * `suspended`:run **挂起了** —— **非终态**(awaitTask 继续轮询)、不占并发槽(执行段落已
10
+ * 收尾释放)、`resumePending` 不捡走(它不是孤儿,崩溃续跑语义不适用于「在等」);
11
+ * 消息历史(含未决 tool_use)与待决清单随 TaskRecord 落库。
12
+ *
13
+ * 「挂起」是**一个状态 + 一个原因**(2026-09-28 ①:从前 `awaiting_approval` 一个状态兼职
14
+ * 两件事):状态只说「它在等」,等什么由 `SuspendedReason` 说 —— 判据(审批超时 / 能否
15
+ * 审批)落在**原因**上,于是「时间挂起被审批超时提前叫醒」这类误伤在类型上就写不出来。
16
+ */
17
+ export type RunStatus = 'queued' | 'running' | 'suspended' | 'succeeded' | 'failed'
18
+ /**
19
+ * 被**取消**(宿主调 `runner.cancel`)—— 终态,但与 `failed` **分开**:
20
+ * 取消不是失败(引擎侧 `abortedResult` 的注释早就这么写),运维读数不该把
21
+ * 「人按的」与「跑挂的」混成一类(`GROUP BY status` 是第一读者)。
22
+ * 机制上是 `abort signal`(与 `runTimeoutMs` 同一条),差别在**意图** ——
23
+ * 状态按意图落:超时仍是 `failed`。
24
+ *
25
+ * ⚠️ **可达性如实(外部深评 K3)**:这个成员**由宿主落**(`TaskRecord.status`),
26
+ * 进程内 `Run` **到不了它** —— 引擎侧的取消表现为 `stopReason: 'aborted'`,
27
+ * `Run.finish()` 按 `isSuccessStopReason` 判 ⇒ 记 `failed`(带结构化
28
+ * `error.type: 'aborted'`)。同一份联合类型有**两个消费者、可达集不同**,这是有意的:
29
+ * `TaskRecord` 是运维读数(「人按的」与「跑挂的」必须分得开,`GROUP BY status` 是第一读者),
30
+ * 而 `Run` 是进程内状态机(只关心跑没跑完)。要加状态时**先想清是给谁的**。
31
+ */
32
+ | 'cancelled';
33
+ /**
34
+ * 挂起原因 —— 「等人工审批」与「等一个时刻」是两种挂起,判据必须分开:
35
+ * approval —— 等人工决定(HITL):`approve()` 能叫醒它,`approvalTimeoutMs` 管它;
36
+ * timer —— 等一个时刻(durable timer):只有到点能叫醒它。
37
+ * ⚠️ 拿 timer 挂起去撞 `approvalTimeoutMs` = **提前叫醒一条在睡的 run** ——
38
+ * 那两条闸(`approvalExpired` / `approve` 的 409)因此都 gate 在原因上,不 gate 在状态上。
12
39
  */
13
- export type RunStatus = 'queued' | 'running' | 'awaiting_approval' | 'succeeded' | 'failed';
40
+ export type SuspendedReason = 'approval' | 'timer';
41
+ /** 该状态是否已到终态(不会再变)。判定只此一处 —— 别在调用点重写。 */
42
+ export declare function isTerminalStatus(status: RunStatus): boolean;
43
+ /**
44
+ * run 事件(2026-09-28 ⑥,run 事件投入口):外部系统投给一条**挂起** run 的一条输入
45
+ * (`AsyncRunner.signalTask` / `POST /tasks/:id/events`;审批是它的特例)。
46
+ *
47
+ * 白名单形状(设计稿 B1):**全是字符串** —— 外部永远不能构造消息块,投毒面只到
48
+ * 「内容注入」为止(任意 `MessageParam` 透传 = 把伪造 assistant / tool_use 块的能力
49
+ * 交给外部,那是协议注入,明确不做)。续跑段由引擎把它渲染成**一条 user 文本消息**
50
+ * 注入消息流(见 `engine/resume-input.ts` 的 `renderTaskEvent` 与 `engine/loop.ts`)。
51
+ *
52
+ * 与 `transport/task-events.ts` 的 `TaskStreamEvent` 不是一回事:那个是**记账事件流**
53
+ * 的一帧(出站,`GET /tasks/:id/stream`),这个是**入站**输入。
54
+ */
55
+ export interface TaskEvent {
56
+ /**
57
+ * 幂等键(可选):给了就按它去重 —— 同一任务重复投递同一个 eventId ⇒ 409
58
+ * (与 cancel 的「已终态」同款:说出来,不静默)。去重簿记随 TaskRecord 落库
59
+ * (`deliveredEventIds`,有界 FIFO),跨进程/重启不丢。
60
+ * **不给则没有恰好一次**:重复投递 = 重复进消息历史(如实文档化,不假装)。
61
+ */
62
+ eventId?: string | undefined;
63
+ /** 事件类型(非空字符串,如 `payment.settled`)—— 进渲染文本与 trace 留痕 */
64
+ type: string;
65
+ /** 事件正文(字符串)。HTTP 侧的字节上限与 `maxBodyBytes` 同口径(整个 body 那一道闸) */
66
+ payload: string;
67
+ }
14
68
  /**
15
69
  * run 的运行记录(供持久化 / 读取)。字段**必填但可为 undefined**:它们是框架在 run
16
70
  * 生命周期各阶段**总是写进对象**的状态(`toMeta()` 一次构造全量),「缺省」在这里不是
@@ -26,4 +80,14 @@ export interface RunMeta {
26
80
  startedAt: number | undefined;
27
81
  finishedAt: number | undefined;
28
82
  error: SpanError | undefined;
83
+ /**
84
+ * 挂起原因(仅 `status === 'suspended'` 时非空)—— 「字段在场」约定同 `error`:
85
+ * 它是 run 生命周期里**总会写进对象**的状态位,缺省在这里没有语义。
86
+ */
87
+ suspendedReason: SuspendedReason | undefined;
88
+ /**
89
+ * 时间挂起的目标时刻(epoch ms,仅 `suspendedReason === 'timer'` 时非空;字段在场约定同上)
90
+ * —— 「这条 run 什么时候该醒」是运行记录的一部分,与「在等什么」并列。
91
+ */
92
+ wakeAt: number | undefined;
29
93
  }
package/dist/core/run.js CHANGED
@@ -1,2 +1,28 @@
1
- export {};
1
+ /**
2
+ * `RunStatus` → 「是不是终态」的**唯一真源**(2026-09-28 外部深评 S1)。
3
+ *
4
+ * 为什么要有它:这个判定此前**散在三处各写一遍**,而且写法不同——
5
+ * `transport/async.ts` 的 `isTerminalTask` 是 `status !== 'queued' && …`(负向枚举
6
+ * 非终态),`store/redisStore.ts` 施加 TTL 时压根判都不判(于是**挂起中也照样过期**:
7
+ * 一条在等审批的任务,TTL 一到记录就没了,「批了它」的决定无家可归 —— 与
8
+ * `InMemoryTaskStore.evict` 里那句「suspended 不可淘汰」正好相反)。谁都没错,
9
+ * 合起来是错的:**同一事实的两份读数**。
10
+ *
11
+ * 形状取**穷尽的分类表**而不是负向枚举:往 `RunStatus` 加成员而不在这里表态 ⇒
12
+ * `tsc` 报缺属性(`TS2741`,与 `stop-reason.ts` 的分类表同款)。负向枚举会让新成员
13
+ * **静默变成「终态」**——那正是「挂起中的任务被当成跑完了」那类 bug 的来源。
14
+ */
15
+ const TERMINAL_STATUS = {
16
+ queued: false,
17
+ running: false,
18
+ // 挂起**不是**终态:批了(或睡到点)它会接着跑
19
+ suspended: false,
20
+ succeeded: true,
21
+ failed: true,
22
+ cancelled: true,
23
+ };
24
+ /** 该状态是否已到终态(不会再变)。判定只此一处 —— 别在调用点重写。 */
25
+ export function isTerminalStatus(status) {
26
+ return TERMINAL_STATUS[status];
27
+ }
2
28
  //# sourceMappingURL=run.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/core/run.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/core/run.ts"],"names":[],"mappings":"AAgDA;;;;;;;;;;;;;GAaG;AACH,MAAM,eAAe,GAA+B;IAClD,MAAM,EAAE,KAAK;IACb,OAAO,EAAE,KAAK;IACd,2BAA2B;IAC3B,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,IAAI;IACf,MAAM,EAAE,IAAI;IACZ,SAAS,EAAE,IAAI;CAChB,CAAC;AAEF,yCAAyC;AACzC,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC"}
@@ -1,4 +1,17 @@
1
1
  import { stringifySafe } from './json.js';
2
+ /**
3
+ * `check()` 的**递归深度背板**(2026-09-28 外部深评 C6 收口)。
4
+ *
5
+ * 这道闸只管一件事:**别让递归钻到 V8 的栈溢出**(`RangeError: Maximum call stack size exceeded`
6
+ * 的症状没有辨识度 —— 调用方看到的是「校验不了」,而不是「这个 schema 有问题」)。
7
+ * 环本身由 `assertNoSchemaCycle()`(前置、与值深度无关)具名抓出来;这里只兜「合法但深到失控」
8
+ * 那种形态(要手搓几千层嵌套 schema 才够,属于事故级输入)。
9
+ *
10
+ * 256 的判据:真实 tool schema 的深度是**个位数**,256 是它的两个数量级以上 ⇒ 不误伤;
11
+ * 而 V8 的栈在几千帧量级 ⇒ 256 足够早地拦住。**数量有界不是用户旋钮**,不进 `core/limits.ts`
12
+ * 的 0 语义表(与 `MAX_DELIVERED_EVENT_IDS` / `MAX_PENDING_EVENTS` 同档)。
13
+ */
14
+ const MAX_SCHEMA_DEPTH = 256;
2
15
  /**
3
16
  * Agentia —— 最小 JSON Schema 校验子集(v1 裸 JSON Schema;zod 为可选外挂,
4
17
  * 见 toolkit/zod.ts —— schema 上挂 __zodValidate 时先走它,core 本身不依赖 zod)。
@@ -21,18 +34,56 @@ export function validateJsonSchema(schema, input) {
21
34
  if (err)
22
35
  return `$: ${err}`;
23
36
  }
24
- return check(schema, input, '$');
37
+ assertNoSchemaCycle(schema);
38
+ return check(schema, input, '$', 0);
25
39
  }
26
- function check(schema, value, path) {
40
+ /**
41
+ * **前置环检测**:`properties` / `items` / `additionalProperties` 这几条边里有环 ⇒ 具名报错。
42
+ *
43
+ * 为什么不是「只靠深度闸」:递归深度 = min(schema 深度, 值深度),所以**环 + 浅值**根本不会爆栈
44
+ * (照常校验通过)—— 那是作者的一个合法但可疑的写法,不该被当成「输入非法」。真正要防的是
45
+ * 环**配深值**时钻进栈溢出,而那件事用深度闸只能兜住症状;这里直接点出病根(哪条路径上是环)。
46
+ *
47
+ * 用**祖先集**而不是全局 visited:共享子树(DAG,`{a: s, b: s}` 这种)是合法写法,不能报环。
48
+ */
49
+ function assertNoSchemaCycle(root) {
50
+ const ancestors = new Set();
51
+ const walk = (schema, path) => {
52
+ if (typeof schema !== 'object' || schema === null || Array.isArray(schema))
53
+ return;
54
+ if (ancestors.has(schema)) {
55
+ throw new Error(`schema 里有**环**(循环引用):${path} 又指回了它自己的祖先。` +
56
+ '这会按值深度一路递归下去 —— 深值就是 RangeError: Maximum call stack size exceeded。' +
57
+ '修法:把自引用那段拆成不带环的子 schema,或改成显式的深度上限。');
58
+ }
59
+ ancestors.add(schema);
60
+ const s = schema;
61
+ for (const [key, sub] of Object.entries(s.properties ?? {})) {
62
+ walk(sub, `${path}.properties.${key}`);
63
+ }
64
+ if (s.items !== undefined)
65
+ walk(s.items, `${path}.items`);
66
+ if (typeof s.additionalProperties === 'object') {
67
+ walk(s.additionalProperties, `${path}.additionalProperties`);
68
+ }
69
+ ancestors.delete(schema);
70
+ };
71
+ walk(root, '$');
72
+ }
73
+ function check(schema, value, path, depth = 0) {
74
+ if (depth > MAX_SCHEMA_DEPTH) {
75
+ throw new Error(`schema 递归超过 ${MAX_SCHEMA_DEPTH} 层(路径 ${path})—— 校验在这里中止。` +
76
+ '(环由 assertNoSchemaCycle 前置抓;这里兜的是「合法但深到失控」的形态。)');
77
+ }
27
78
  const en = schema.enum;
28
79
  if (Array.isArray(en) && !en.some((v) => deepEqual(v, value))) {
29
80
  return `${path}: 值不在 enum 允许范围内(得到 ${preview(value)})`;
30
81
  }
31
82
  switch (schema.type) {
32
83
  case 'object':
33
- return checkObject(schema, value, path);
84
+ return checkObject(schema, value, path, depth);
34
85
  case 'array':
35
- return checkArray(schema, value, path);
86
+ return checkArray(schema, value, path, depth);
36
87
  case 'string':
37
88
  return typeof value === 'string' ? null : `${path}: 期望 string,得到 ${typeOf(value)}`;
38
89
  case 'number':
@@ -51,7 +102,7 @@ function check(schema, value, path) {
51
102
  return null; // 未声明/未覆盖的 type 放行
52
103
  }
53
104
  }
54
- function checkObject(schema, value, path) {
105
+ function checkObject(schema, value, path, depth) {
55
106
  if (typeof value !== 'object' || value === null || Array.isArray(value)) {
56
107
  return `${path}: 期望 object,得到 ${typeOf(value)}`;
57
108
  }
@@ -64,7 +115,7 @@ function checkObject(schema, value, path) {
64
115
  const properties = schema.properties ?? {};
65
116
  for (const [key, sub] of Object.entries(properties)) {
66
117
  if (Object.hasOwn(obj, key)) {
67
- const err = check(sub, obj[key], `${path}.${key}`);
118
+ const err = check(sub, obj[key], `${path}.${key}`, depth + 1);
68
119
  if (err)
69
120
  return err;
70
121
  }
@@ -78,13 +129,13 @@ function checkObject(schema, value, path) {
78
129
  }
79
130
  return null;
80
131
  }
81
- function checkArray(schema, value, path) {
132
+ function checkArray(schema, value, path, depth) {
82
133
  if (!Array.isArray(value))
83
134
  return `${path}: 期望 array,得到 ${typeOf(value)}`;
84
135
  const items = schema.items;
85
136
  if (items && typeof items === 'object' && !Array.isArray(items)) {
86
137
  for (let i = 0; i < value.length; i++) {
87
- const err = check(items, value[i], `${path}[${i}]`);
138
+ const err = check(items, value[i], `${path}[${i}]`, depth + 1);
88
139
  if (err)
89
140
  return err;
90
141
  }
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"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"}
@@ -6,10 +6,52 @@
6
6
  * 2026-09-14 的「硬保证」收紧只落进了 `engine/concurrency.ts`,桥那一份继续用竞速判定 ——
7
7
  * 同一个承诺两套实现,于是同一个事件在 trace 里能有两种账(见 `docs/spec.md` §10 2026-09-17 ①)。
8
8
  * `integrations` 只能依赖 core(`tests/architecture/layering.test.ts` 强制),
9
- * 所以单源的落点是 core。core 是叶子:本文件零 import。
9
+ * 所以单源的落点是 core。core 是叶子:本文件只 import `limits.js`(**纯数据表,零 import**)
10
+ * —— 2026-09-28 起它要 `zeroClauseOf`:两处 `assertTimerDelay` 的文案必须与 limits 表同源
11
+ * (外部深评 C3/C4 的「单源断了一头」)。叶子性没变:数据表不引入任何运行期依赖,也不成环。
10
12
  */
11
13
  /** 超时哨兵:区分「超时」与「工具恰好返回了 undefined」 */
12
14
  export declare const TIMED_OUT: unique symbol;
15
+ /**
16
+ * Node 定时器延迟的**物理上限**:`2^31-1` ms(约 **24.86 天**)。
17
+ *
18
+ * 为什么它必须是单源(而不是各调用点各写一份):超过这个值的延迟**不会「等那么久」** ——
19
+ * Node 只会在 stderr 留一行 `TimeoutOverflowWarning`(`Timeout duration was set to 1`),
20
+ * 然后把延迟**钳到 1ms**。于是「30 天后触发」变成「立刻触发」、「退避到限流窗口之后」
21
+ * 变成「热重试打风暴」。实测(Node 22):`delay = 2^31` 在 200ms 内触发并打警告,
22
+ * 而 `delay = 2^31-1`(边界内)如期不触发。
23
+ *
24
+ * 本仓此前的处置是**每个旋钮各自设防**(`transport/scheduler.ts` 的 every/at 各一条,
25
+ * 2026-09-19 复审加的),而「派生出来的等待」没有 —— 那些正是漏网的部分:
26
+ * `withTimeout`(引擎 `toolTimeoutMs`)、`interruptibleSleep`(退避)、
27
+ * `DrainGate.waitForIdle`(drain 预算)、`#raceTimeout`(`runTimeoutMs`)、
28
+ * `composeSignal`(client `timeout`)五处都直喂 `setTimeout` 且只查「非负有限」。
29
+ * 单源收在这里(见 `docs/spec.md` §10 2026-09-28 ⑪)。
30
+ */
31
+ export declare const MAX_TIMER_DELAY_MS = 2147483647;
32
+ /**
33
+ * 校验一个**将要喂给 `setTimeout` 的延迟**:`NaN` 与超过 [MAX_TIMER_DELAY_MS] 一律抛。
34
+ *
35
+ * 「拒绝」而不是「钳制」是刻意的 —— 钳制正是 Node 现在做的事(钳到 1ms),
36
+ * 它把「远期」静默变成「立即」,是本条要消灭的那种失败模式。照 `Scheduler.at`
37
+ * 的既有先例:超上限直接抛,让使用者在配置处就看见(远期等待请拆成多次自检)。
38
+ *
39
+ * ⚠️ **非正数不在此列**:`0` / 负数在调用点各有合法语义(「不设超时」/「一直等」/「不睡」),
40
+ * 各按 `core/limits.ts` 的表读 —— 本函数只挡「物理上兑现不了」的值。
41
+ * ⚠️ `NaN` 单独判并**必须排在调用点的「非正」早返回之前**:`!(NaN > 0)` 与 `NaN <= 0`
42
+ * 都不成立或都成立得不一致,不先挡就会被静默读成另一种语义(见 `withTimeout` 处的注释)。
43
+ */
44
+ export declare function assertTimerDelay(ms: number, where: string): number;
45
+ /**
46
+ * 把**外部数据**得出的延迟夹进可兑现区间(`retry-after` 等)。
47
+ *
48
+ * 与 [assertTimerDelay] 的分工是刻意的、别合并:
49
+ * - 那个「**拒绝**」使用者配出来的坏值 —— 配置错误必须响亮,否则修法会被写歪;
50
+ * - 这个「**夹**」上游回给我们的值 —— `Retry-After: 99999999` 不是使用者的错,
51
+ * 为它抛错会把一次 429 升级成硬失败;但放它直通 `setTimeout` 会钳到 1ms,
52
+ * 把「等限流窗口过去」变成「热重试」,那才是真危害。
53
+ */
54
+ export declare function clampTimerDelay(ms: number): number;
13
55
  /**
14
56
  * 超时错误(`code === 'timeout'`)。
15
57
  *
@@ -6,10 +6,68 @@
6
6
  * 2026-09-14 的「硬保证」收紧只落进了 `engine/concurrency.ts`,桥那一份继续用竞速判定 ——
7
7
  * 同一个承诺两套实现,于是同一个事件在 trace 里能有两种账(见 `docs/spec.md` §10 2026-09-17 ①)。
8
8
  * `integrations` 只能依赖 core(`tests/architecture/layering.test.ts` 强制),
9
- * 所以单源的落点是 core。core 是叶子:本文件零 import。
9
+ * 所以单源的落点是 core。core 是叶子:本文件只 import `limits.js`(**纯数据表,零 import**)
10
+ * —— 2026-09-28 起它要 `zeroClauseOf`:两处 `assertTimerDelay` 的文案必须与 limits 表同源
11
+ * (外部深评 C3/C4 的「单源断了一头」)。叶子性没变:数据表不引入任何运行期依赖,也不成环。
10
12
  */
13
+ import { zeroClauseOf } from './limits.js';
11
14
  /** 超时哨兵:区分「超时」与「工具恰好返回了 undefined」 */
12
15
  export const TIMED_OUT = Symbol('agentia.timed-out');
16
+ /**
17
+ * Node 定时器延迟的**物理上限**:`2^31-1` ms(约 **24.86 天**)。
18
+ *
19
+ * 为什么它必须是单源(而不是各调用点各写一份):超过这个值的延迟**不会「等那么久」** ——
20
+ * Node 只会在 stderr 留一行 `TimeoutOverflowWarning`(`Timeout duration was set to 1`),
21
+ * 然后把延迟**钳到 1ms**。于是「30 天后触发」变成「立刻触发」、「退避到限流窗口之后」
22
+ * 变成「热重试打风暴」。实测(Node 22):`delay = 2^31` 在 200ms 内触发并打警告,
23
+ * 而 `delay = 2^31-1`(边界内)如期不触发。
24
+ *
25
+ * 本仓此前的处置是**每个旋钮各自设防**(`transport/scheduler.ts` 的 every/at 各一条,
26
+ * 2026-09-19 复审加的),而「派生出来的等待」没有 —— 那些正是漏网的部分:
27
+ * `withTimeout`(引擎 `toolTimeoutMs`)、`interruptibleSleep`(退避)、
28
+ * `DrainGate.waitForIdle`(drain 预算)、`#raceTimeout`(`runTimeoutMs`)、
29
+ * `composeSignal`(client `timeout`)五处都直喂 `setTimeout` 且只查「非负有限」。
30
+ * 单源收在这里(见 `docs/spec.md` §10 2026-09-28 ⑪)。
31
+ */
32
+ export const MAX_TIMER_DELAY_MS = 2_147_483_647;
33
+ /**
34
+ * 校验一个**将要喂给 `setTimeout` 的延迟**:`NaN` 与超过 [MAX_TIMER_DELAY_MS] 一律抛。
35
+ *
36
+ * 「拒绝」而不是「钳制」是刻意的 —— 钳制正是 Node 现在做的事(钳到 1ms),
37
+ * 它把「远期」静默变成「立即」,是本条要消灭的那种失败模式。照 `Scheduler.at`
38
+ * 的既有先例:超上限直接抛,让使用者在配置处就看见(远期等待请拆成多次自检)。
39
+ *
40
+ * ⚠️ **非正数不在此列**:`0` / 负数在调用点各有合法语义(「不设超时」/「一直等」/「不睡」),
41
+ * 各按 `core/limits.ts` 的表读 —— 本函数只挡「物理上兑现不了」的值。
42
+ * ⚠️ `NaN` 单独判并**必须排在调用点的「非正」早返回之前**:`!(NaN > 0)` 与 `NaN <= 0`
43
+ * 都不成立或都成立得不一致,不先挡就会被静默读成另一种语义(见 `withTimeout` 处的注释)。
44
+ */
45
+ export function assertTimerDelay(ms, where) {
46
+ if (Number.isNaN(ms)) {
47
+ throw new RangeError(`${where} 不能是 NaN —— 它既不是「不限」也不是任何时长,` +
48
+ `静默接受会把它读成另一件事(各旋钮 0 的含义见 core/limits.ts 的表)`);
49
+ }
50
+ if (ms > MAX_TIMER_DELAY_MS) {
51
+ throw new RangeError(`${where} 超过 Node 定时器延迟上限 ${MAX_TIMER_DELAY_MS}ms(约 24.86 天),收到 ${ms} —— ` +
52
+ `超上限的延迟不会被遵守:Node 只在 stderr 留一行 TimeoutOverflowWarning,` +
53
+ `随后把延迟钳到 1ms(远期变立即)。远期等待请拆成多次自检`);
54
+ }
55
+ return ms;
56
+ }
57
+ /**
58
+ * 把**外部数据**得出的延迟夹进可兑现区间(`retry-after` 等)。
59
+ *
60
+ * 与 [assertTimerDelay] 的分工是刻意的、别合并:
61
+ * - 那个「**拒绝**」使用者配出来的坏值 —— 配置错误必须响亮,否则修法会被写歪;
62
+ * - 这个「**夹**」上游回给我们的值 —— `Retry-After: 99999999` 不是使用者的错,
63
+ * 为它抛错会把一次 429 升级成硬失败;但放它直通 `setTimeout` 会钳到 1ms,
64
+ * 把「等限流窗口过去」变成「热重试」,那才是真危害。
65
+ */
66
+ export function clampTimerDelay(ms) {
67
+ if (!(ms > 0))
68
+ return 0; // 含 NaN / 负数:调用点读 0 即「不睡」(见 limits 表)
69
+ return ms > MAX_TIMER_DELAY_MS ? MAX_TIMER_DELAY_MS : ms;
70
+ }
13
71
  /**
14
72
  * 超时错误(`code === 'timeout'`)。
15
73
  *
@@ -91,6 +149,12 @@ export function isTimeoutError(e) {
91
149
  * SSE 心跳、metrics 刷盘)成立,对**「等待的终点」**不成立:那正是调用方在等的东西。
92
150
  */
93
151
  export async function withTimeout(p, timeoutMs) {
152
+ // 坏值先挡(NaN / 超 2^31-1,见 assertTimerDelay)。⚠️ 必须排在下面那句
153
+ // 「非正 = 不设超时」**之前**:那句的判据是 `!(timeoutMs > 0)`,而 NaN 满足它
154
+ // ⇒ 会被**静默**读成「不设超时」,与使用者「我设了个预算」的预期正好相反
155
+ // (桥还会因此起自己的 60s 兜底 ⇒ 双计时器、双账本,见 limits 表 withTimeout.ms 的 note)。
156
+ // `0` / 负数不在此列 —— 它们是合法的「不设超时」,走下面那句原样透传。
157
+ assertTimerDelay(timeoutMs, `withTimeout 的 timeoutMs(引擎 toolTimeoutMs / 桥兜底超时;${zeroClauseOf('withTimeout.ms')})`);
94
158
  if (!(timeoutMs > 0))
95
159
  return p;
96
160
  // 单调钟(performance.now):硬超时判定看的是**耗时**,墙钟(Date.now)会被
@@ -158,6 +222,11 @@ export async function withTimeout(p, timeoutMs) {
158
222
  * 曾把它当「一致性缺口」改反过一次,被这条用例拦住 —— 保留该用例,别删。
159
223
  */
160
224
  export function interruptibleSleep(ms, signal, abortMessage = '已被取消') {
225
+ // 坏值先挡(NaN / 超 2^31-1):这句**先于**下面的 `ms <= 0`,因为 `NaN <= 0` 是 false
226
+ // —— 它会穿透那句直落 `setTimeout(fn, NaN)`,被 Node 钳成 1ms ⇒「退避」静默变成
227
+ // 「立刻重试」;超上限同理(钳到 1ms)。`0` / 负数仍是合法的「不睡」,
228
+ // 且「先于 aborted 检查」那条次序(被用例钉着)不受影响 —— 见函数头注释。
229
+ assertTimerDelay(ms, `interruptibleSleep 的 ms(重试退避;${zeroClauseOf('interruptibleSleep.ms')})`);
161
230
  if (ms <= 0)
162
231
  return Promise.resolve();
163
232
  return new Promise((resolve, reject) => {
@@ -195,11 +264,15 @@ export function interruptibleSleep(ms, signal, abortMessage = '已被取消') {
195
264
  export function backoffMs(attempt, retryAfter) {
196
265
  if (retryAfter) {
197
266
  const secs = Number(retryAfter);
267
+ // ⚠️ `retry-after` 是**上游数据**,可以大到兑现不了(`Retry-After: 99999999` ⇒ 1e11 ms)。
268
+ // 这里走 clampTimerDelay(夹)而不是 assertTimerDelay(拒):为上游的荒谬值把一次 429
269
+ // 升级成硬失败是错的;而放它直通 setTimeout 会被钳到 1ms,把「等限流窗口过去」
270
+ // 变成「热重试打风暴」—— 那才是真危害。两条分支都要夹(HTTP-date 可以指到几个月后)。
198
271
  if (Number.isFinite(secs))
199
- return Math.max(0, Math.round(secs * 1000));
272
+ return clampTimerDelay(Math.max(0, Math.round(secs * 1000)));
200
273
  const at = Date.parse(retryAfter);
201
274
  if (Number.isFinite(at))
202
- return Math.max(0, at - Date.now());
275
+ return clampTimerDelay(Math.max(0, at - Date.now()));
203
276
  // 解析不了就回落指数退避
204
277
  }
205
278
  const base = Math.min(500 * 2 ** Math.max(0, attempt - 1), 8000);
@@ -1 +1 @@
1
- {"version":3,"file":"timeout.js","sourceRoot":"","sources":["../../src/core/timeout.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"timeout.js","sourceRoot":"","sources":["../../src/core/timeout.ts"],"names":[],"mappings":"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"}
@@ -169,6 +169,14 @@ export interface ToolRunContext {
169
169
  * 不设(undefined)= 子循环用各自缺省(不是"不截断")。
170
170
  */
171
171
  maxEventChars?: number | false;
172
+ /**
173
+ * 本 run 是否记录 assistant 文本进 llm.turn span(`RunAgentOptions.traceContent`,R8-P3a)。
174
+ * 嵌套能力(@SubAgent / @Skill)拉起自己的 llm 循环时必须原样传下去 —— 否则同一棵
175
+ * 调用树上主 agent 的回合有 `output.text`、子 agent 的没有(与 maxEventChars 同理由)。
176
+ *
177
+ * 不设(undefined)= 子循环不记录(缺省行为)。
178
+ */
179
+ traceContent?: 'full';
172
180
  /**
173
181
  * 成本硬管控(C1)透传:整条 run 累计 token 上限(见 `RunAgentOptions.maxTotalTokens`)。
174
182
  * 嵌套能力(@SubAgent / @Skill)拉起自己的 llm 循环时必须原样传下去 —— 预算是
@@ -184,6 +192,22 @@ export interface ToolRunContext {
184
192
  * 批准/拒绝(审计日志、按 decidedBy 分级授权等)。
185
193
  */
186
194
  approval?: ApprovalDecision;
195
+ /**
196
+ * 「现在还不是时候,T 之后再问我」(durable timer,2026-09-28 ① 的 timer 侧)。
197
+ * 工具在执行期调用它 = 请求**本回合到此为止**:引擎丢弃本回合这批工具的结果、
198
+ * 把整批 tool_use 挂起(`stopReason: 'suspended'` + `suspendedReason: 'timer'` +
199
+ * 目标时刻 `wakeAt`),到点后由宿主续跑并**重跑这一批**(与审批续跑的形态一致)。
200
+ * 真实用途:等批处理作业、等限流窗口、等收盘、等外部系统回填。
201
+ *
202
+ * ⚠️ 两条契约(都是「说错就静默出事」的位置,细则见 `engine/defer.ts`):
203
+ * ① **必须传将来的时刻**:T ≤ 现在(或非有限数)**当场抛 TypeError** —— 那次工具调用以
204
+ * is_error 的 tool_result 回给模型、run 照常往前走(不挂起)。否则到期扫描会立刻
205
+ * 唤醒、重跑、工具再请求同一个过去时刻=一条自己打转的 run。
206
+ * ② **整批语义**:挂起是回合级的(协议要求每个 tool_use 都有配对 tool_result),
207
+ * 所以同回合**已经执行完**的其他工具会在醒来后重跑(副作用重复)—— 要精确控制就让
208
+ * 模型单独调它,或把它做成幂等读。本回合多个请求取**最早**的那个时刻。
209
+ */
210
+ deferUntil?: (at: number | Date) => void;
187
211
  /**
188
212
  * 工具执行被引擎**放弃等待**的信号(`toolTimeoutMs` 超时触发)。
189
213
  *
@@ -225,7 +249,7 @@ export interface AgentTool<I = unknown, O = unknown> {
225
249
  strict?: boolean;
226
250
  /**
227
251
  * 人工审批闸(HITL):`'required'` 时模型发起的该工具调用**不直接执行** ——
228
- * 该回合挂起(`stopReason: 'awaiting_approval'`,回合级全有或全无:同一回合的
252
+ * 该回合挂起(`stopReason: 'suspended'`,回合级全有或全无:同一回合的
229
253
  * 其他工具也一并等待,因为协议要求每个 tool_use 都有配对 tool_result),
230
254
  * 等宿主把决定(`ApprovalDecision`,按 tool_use_id)喂回来后恢复:
231
255
  * 批准 → 正常执行(工具体内经 `ToolRunContext.approval` 读到自己的决定);
@@ -25,6 +25,34 @@ export interface SpanError {
25
25
  /** 是否可安全重试(429/5xx/网络 vs 400/400类) */
26
26
  retryable: boolean;
27
27
  }
28
+ /**
29
+ * 工具**入参**事件的 `SpanEvent.name`(`TOOL_OUTPUT_EVENT` 是它的另一半)。
30
+ *
31
+ * 为什么单源在 `core/`(2026-09-28 外部深评 E8):这两个名字跨 **engine → eval →
32
+ * integrations** 三层被手写(12 处取值)—— 改名要改三遍,而漏一处不是「少记一条」,
33
+ * 是**静默归零**:事件在引擎里叫 A、报表按 B 过滤 ⇒ 报表说「没有工具调用」,而 trace 里
34
+ * 明明有(`integrations/report.ts` 与 `metrics-state.ts` 那两处都按名字过滤)。
35
+ *
36
+ * ⚠️ 报告建议的落点(`engine/tool-events.ts`,与载荷构造器同处)**不可行**:
37
+ * `integrations` 只许依赖 `core`(`tests/architecture/layering.test.ts`),拿不到 engine 的
38
+ * 导出 —— 那样 integrations 侧只能再手写一份,等于把「单源」补成「两处」。
39
+ * 所以词汇表落在最底层:**载荷构造器(engine)与名字(core)分开**,谁都能引。
40
+ */
41
+ export declare const TOOL_INPUT_EVENT = "tool.input";
42
+ export declare const TOOL_OUTPUT_EVENT = "tool.output";
43
+ /**
44
+ * 「上游**没回报 usage**」事件名(2026-09-28 外部深评 S2)。
45
+ *
46
+ * 为什么也单源在这里:与上面那两条同一理由 —— 名字是跨层契约。写它的是
47
+ * `engine/turn.ts`,按名字数的是 `integrations/report.ts` 与 `metrics-state.ts`。
48
+ * 手写三遍 ⇒ 一处改名就是**静默归零**(报表说「没有缺失」,而 trace 里明明有)。
49
+ *
50
+ * 语义:该回合的上游响应**没有**带 token 计量,于是 `MessageUsage` 里那几个 `0` 是
51
+ * **替身值**(不是读数)—— 成本估算会把它读成「真的花了 0」,`maxCostUsd` 因此静默失效。
52
+ */
53
+ export declare const USAGE_MISSING_EVENT = "usage.missing";
54
+ /** 工具 I/O 事件名的联合 —— `eval/export.ts` 的工具事件过滤器按它取参数 */
55
+ export type ToolIoEventName = typeof TOOL_INPUT_EVENT | typeof TOOL_OUTPUT_EVENT;
28
56
  /**
29
57
  * 结构化事件(日志)。工具入参/出参**正文默认截断**(入参/成功出参 2000 字符、失败出参 1000),
30
58
  * 完整正文需显式开启:`RunInvocationOptions.maxEventChars: false`(缺省关)。
@@ -32,6 +60,11 @@ export interface SpanError {
32
60
  */
33
61
  export interface SpanEvent {
34
62
  time: number;
63
+ /**
64
+ * 事件名。工具 I/O 的两条走 `TOOL_INPUT_EVENT` / `TOOL_OUTPUT_EVENT` 常量
65
+ * (见上:这个名字是跨层契约,不许在别处再写一遍字面量);
66
+ * 其余(`'compaction'` 等)目前仍是字面量,尚未单源 —— 如实记在这里,别当已成网。
67
+ */
35
68
  name: string;
36
69
  body: unknown;
37
70
  }
@@ -168,7 +201,7 @@ export declare function attachScore(trace: Trace, score: Score): void;
168
201
  export declare function capabilityKindOf(span: Span): string;
169
202
  /**
170
203
  * trace 出口:run 收尾(成功或失败)后,框架把【完整 Trace】交给每个 sink。
171
- * sink 抛错由框架吞掉,绝不影响 run 结果(与 memory 回写同款防护)。
204
+ * sink 抛错由框架吞掉(吞之前落一条 console.warn 告警),绝不影响 run 结果(与 memory 回写同款防护)。
172
205
  * 形状与 OtlpExporter 一致 —— createOtlpExporter() 的返回值天然满足本接口。
173
206
  */
174
207
  export interface TraceSink {
@@ -189,6 +222,12 @@ export interface TraceSink {
189
222
  * ⇒ 这条不变量一次钉住四件事:不丢、不重、顺序正确、增量与终态同源。要改记账点而不派发事件,
190
223
  * 那个用例会红。
191
224
  *
225
+ * ⚠️ **没有例外**(2026-09-28 PR #164 复核 §4 定的口径):截断簿记(`traceLimits.maxEvents`
226
+ * 超限时 run 根上的 `trace.truncated`)也走**普通 `span.event` 帧**,因此同样折得出来。
227
+ * 「只在一条缝上出现的事件」正是让这条规则变成假话的方式 —— 判据是「两处同一份载荷」,
228
+ * 不是「哪条缝更需要它」。折叠侧的类型分派是**编译期穷尽**的(新帧类型会编译失败,
229
+ * 而不是被当成 `span.link` 静默吞掉)。
230
+ *
192
231
  * `seq`:recorder 内**每次记账动作都自增**(与当时有没有订阅者无关)—— 于是「订阅早」与
193
232
  * 「订阅晚」看到的同一个事件序号一致。SSE 的 `Last-Event-ID` 重放、去重、跨段对齐都靠它。
194
233
  *
@@ -2,6 +2,32 @@
2
2
  * Agentia —— Trace / 调用树 类型草稿。
3
3
  * 设计见 docs/spec.md §9。一次 run == 一条 trace(v1 中 traceId == runId)。
4
4
  */
5
+ /**
6
+ * 工具**入参**事件的 `SpanEvent.name`(`TOOL_OUTPUT_EVENT` 是它的另一半)。
7
+ *
8
+ * 为什么单源在 `core/`(2026-09-28 外部深评 E8):这两个名字跨 **engine → eval →
9
+ * integrations** 三层被手写(12 处取值)—— 改名要改三遍,而漏一处不是「少记一条」,
10
+ * 是**静默归零**:事件在引擎里叫 A、报表按 B 过滤 ⇒ 报表说「没有工具调用」,而 trace 里
11
+ * 明明有(`integrations/report.ts` 与 `metrics-state.ts` 那两处都按名字过滤)。
12
+ *
13
+ * ⚠️ 报告建议的落点(`engine/tool-events.ts`,与载荷构造器同处)**不可行**:
14
+ * `integrations` 只许依赖 `core`(`tests/architecture/layering.test.ts`),拿不到 engine 的
15
+ * 导出 —— 那样 integrations 侧只能再手写一份,等于把「单源」补成「两处」。
16
+ * 所以词汇表落在最底层:**载荷构造器(engine)与名字(core)分开**,谁都能引。
17
+ */
18
+ export const TOOL_INPUT_EVENT = 'tool.input';
19
+ export const TOOL_OUTPUT_EVENT = 'tool.output';
20
+ /**
21
+ * 「上游**没回报 usage**」事件名(2026-09-28 外部深评 S2)。
22
+ *
23
+ * 为什么也单源在这里:与上面那两条同一理由 —— 名字是跨层契约。写它的是
24
+ * `engine/turn.ts`,按名字数的是 `integrations/report.ts` 与 `metrics-state.ts`。
25
+ * 手写三遍 ⇒ 一处改名就是**静默归零**(报表说「没有缺失」,而 trace 里明明有)。
26
+ *
27
+ * 语义:该回合的上游响应**没有**带 token 计量,于是 `MessageUsage` 里那几个 `0` 是
28
+ * **替身值**(不是读数)—— 成本估算会把它读成「真的花了 0」,`maxCostUsd` 因此静默失效。
29
+ */
30
+ export const USAGE_MISSING_EVENT = 'usage.missing';
5
31
  /** W3C traceparent:`<2位版本>-<32位trace>-<16位span>-<2位flags>`,全小写 hex */
6
32
  const TRACEPARENT_RE = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;
7
33
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"trace.js","sourceRoot":"","sources":["../../src/core/trace.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAqEH,sEAAsE;AACtE,MAAM,cAAc,GAAG,6DAA6D,CAAC;AAErF;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAgC;IAC/D,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,MAAM,CAAC,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IAC1D,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACvC,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAClE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC7B,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAAC,EAAU;IACpC,OAAO,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,OAAO,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,MAAc;IAC/D,OAAO,MAAM,WAAW,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;AAC/D,CAAC;AAqDD;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,KAAY,EAAE,KAAY;IACpD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,UAAU,CAAC,CAAC;IACpE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACtE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAU;IACzC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IACxD,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,KAAK,SAAS;QAAE,OAAO,UAAU,CAAC;IAC9D,OAAO,YAAY,CAAC;AACtB,CAAC;AAgDD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAkD,EAClD,MAAmD;IAEnD,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC;IAC1B,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,OAAO,CAAC,CAAC,EAAE,EAAE;QACX,IAAI,CAAC;YACH,KAAK,CAAC,CAAC,CAAC,CAAC;QACX,CAAC;QAAC,MAAM,CAAC;YACP,8BAA8B;QAChC,CAAC;QACD,IAAI,CAAC;YACH,MAAM,CAAC,CAAC,CAAC,CAAC;QACZ,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ;QACV,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"trace.js","sourceRoot":"","sources":["../../src/core/trace.ts"],"names":[],"mappings":"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"}