@migor/agentia 0.8.2 → 0.8.3

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 (48) hide show
  1. package/CHANGELOG.md +77 -1
  2. package/README.md +1 -1
  3. package/dist/AGENTS.md +17 -1
  4. package/dist/core/limits.d.ts +198 -0
  5. package/dist/core/limits.js +186 -0
  6. package/dist/core/limits.js.map +1 -0
  7. package/dist/core/trace.d.ts +66 -2
  8. package/dist/core/trace.js +37 -2
  9. package/dist/core/trace.js.map +1 -1
  10. package/dist/engine/forwarded.d.ts +84 -0
  11. package/dist/engine/forwarded.js +39 -0
  12. package/dist/engine/forwarded.js.map +1 -0
  13. package/dist/engine/spec.d.ts +26 -1
  14. package/dist/engine/spec.js.map +1 -1
  15. package/dist/engine/tracer.d.ts +62 -1
  16. package/dist/engine/tracer.js +130 -14
  17. package/dist/engine/tracer.js.map +1 -1
  18. package/dist/index.d.ts +3 -2
  19. package/dist/index.js +1 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/integrations/adapter-options.d.ts +0 -7
  22. package/dist/integrations/adapter-options.js +2 -1
  23. package/dist/integrations/adapter-options.js.map +1 -1
  24. package/dist/runtime/run.d.ts +13 -1
  25. package/dist/runtime/run.js +14 -3
  26. package/dist/runtime/run.js.map +1 -1
  27. package/dist/toolkit/module.d.ts +22 -1
  28. package/dist/toolkit/module.js +12 -0
  29. package/dist/toolkit/module.js.map +1 -1
  30. package/dist/toolkit/skill.js +4 -13
  31. package/dist/toolkit/skill.js.map +1 -1
  32. package/dist/toolkit/subagent.js +6 -17
  33. package/dist/toolkit/subagent.js.map +1 -1
  34. package/dist/transport/async.d.ts +67 -0
  35. package/dist/transport/async.js +96 -2
  36. package/dist/transport/async.js.map +1 -1
  37. package/dist/transport/http-route.d.ts +6 -1
  38. package/dist/transport/http-route.js +9 -1
  39. package/dist/transport/http-route.js.map +1 -1
  40. package/dist/transport/http.js +93 -1
  41. package/dist/transport/http.js.map +1 -1
  42. package/dist/transport/sse.d.ts +6 -2
  43. package/dist/transport/sse.js +3 -2
  44. package/dist/transport/sse.js.map +1 -1
  45. package/dist/transport/task-events.d.ts +83 -0
  46. package/dist/transport/task-events.js +141 -0
  47. package/dist/transport/task-events.js.map +1 -0
  48. package/package.json +3 -2
@@ -89,8 +89,12 @@ export declare function wireSpanId(id: string): string;
89
89
  /**
90
90
  * 生成 W3C `traceparent`(`parseTraceparent` 的镜像:一个解析、一个生成)。
91
91
  *
92
- * flags 位恒为 `00`:本框架**不采样**(每次 run 全量记账),故没有「已采样」可声明 ——
93
- * 编一个 `01` 是替下游做决定。入站侧 `parseTraceparent` 也从不读 flags。
92
+ * flags 位恒为 `00`。**理由不是「本框架不采样」**(采样早就是明确推荐的宿主配法 ——
93
+ * `docs/observability.md` 2.3),而是**运行期不可知**:记录/导出决策发生在 run **收尾之后**
94
+ * (采样闸门要看完好整棵 trace 才判得出来),而出站调用发生在**运行期** ——
95
+ * 那时「这条 trace 会不会被采样掉」还没有答案。所以恒 `00` 是唯一不撒谎的选择
96
+ * (`00` = 不声明「已采样」);编一个 `01` 是替下游做决定。⚠️ 别下一轮「顺手」改成跟随采样
97
+ * (见 `docs/spec.md` §10 2026-09-21 ⑦)。入站侧 `parseTraceparent` 也从不读 flags。
94
98
  *
95
99
  * 调用方保证给的是内部 id 或线缆 id(本函数只做投影,不做合法性判定)。
96
100
  */
@@ -170,3 +174,63 @@ export declare function capabilityKindOf(span: Span): string;
170
174
  export interface TraceSink {
171
175
  export(trace: Trace): void | Promise<void>;
172
176
  }
177
+ /**
178
+ * **记账事件**(增量出口,`docs/plans/2026-09-21-incremental-trace-export-and-sampling.md`)——
179
+ * run **进行中**就能拿到的明细。它与 `TraceSink` 是**两条缝**,不是替代关系:
180
+ *
181
+ * - `TraceSink`:run 收尾拿到**完整** trace(成功的 sink 该走这条);
182
+ * - 记账事件:**等不了收尾**的消费者 —— 终端面板、SSE 前端、异步任务进度流。
183
+ *
184
+ * 载荷一律是**增量 + 此刻的拷贝**(交付后框架不再变异它):`span.begin` 只给初始形状
185
+ * (`attributes` / `events` 为空),之后的属性 / 事件 / 链路各走自己的事件类型。
186
+ *
187
+ * **折叠规则**(`tests/engine/trace-events.test.ts` 钉着):按 `seq` 升序把同一次 run 的
188
+ * 全部事件应用到 `span.begin` 建出的 span 上,结果必须**逐字等于** `snapshot(status)`。
189
+ * ⇒ 这条不变量一次钉住四件事:不丢、不重、顺序正确、增量与终态同源。要改记账点而不派发事件,
190
+ * 那个用例会红。
191
+ *
192
+ * `seq`:recorder 内**每次记账动作都自增**(与当时有没有订阅者无关)—— 于是「订阅早」与
193
+ * 「订阅晚」看到的同一个事件序号一致。SSE 的 `Last-Event-ID` 重放、去重、跨段对齐都靠它。
194
+ *
195
+ * 投放纪律与 sink 同款:**同步派发、不 await**、订阅者抛错被吞(观测失败不击穿业务)。
196
+ * ⚠️ 但它**不保证送达**(宿主自己的流断了就断了,没有 sink 那层兜底/重试语义)。
197
+ */
198
+ export type TraceRecordEventPayload = {
199
+ type: 'span.begin';
200
+ span: Span;
201
+ } | {
202
+ type: 'span.end';
203
+ spanId: SpanId;
204
+ endedAt: number;
205
+ status: SpanStatus;
206
+ error?: SpanError;
207
+ usage?: Usage;
208
+ } | {
209
+ type: 'span.event';
210
+ spanId: SpanId;
211
+ event: SpanEvent;
212
+ } | {
213
+ type: 'span.attribute';
214
+ spanId: SpanId;
215
+ key: string;
216
+ value: string | number | boolean;
217
+ } | {
218
+ type: 'span.link';
219
+ spanId: SpanId;
220
+ link: SpanLink;
221
+ };
222
+ export type TraceRecordEvent = TraceRecordEventPayload & {
223
+ seq: number;
224
+ };
225
+ /**
226
+ * 把两个增量记账回调**合成一个**订阅者(前者在前)。
227
+ *
228
+ * 为什么要合成而不是 `??` 覆盖:`onTraceEvent` 是**观察者注册**(同 `TraceSink`:
229
+ * 应用级与全局默认一起收),不是值覆盖 —— 覆盖会让「某次 run / 某个宿主顺手传了自己的
230
+ * 回调」把另一条静默顶掉。两个消费者都要它的场景是真实存在的:宿主自己配了一条应用级
231
+ * 面板回调,`AsyncRunner` 还要为 `GET /tasks/:id/stream` 再挂一条按任务分的缓冲。
232
+ *
233
+ * 为什么内部各自 try/catch:合成后它们在 recorder 眼里是**一个**订阅者,而 recorder 只在
234
+ * 这一层兜错 —— 不隔离的话前一个抛错会吞掉后一个(与「一条订阅者炸了不影响另一条」互为镜像)。
235
+ */
236
+ export declare function composeTraceEvents(first: ((e: TraceRecordEvent) => void) | undefined, second: ((e: TraceRecordEvent) => void) | undefined): ((e: TraceRecordEvent) => void) | undefined;
@@ -49,8 +49,12 @@ export function wireSpanId(id) {
49
49
  /**
50
50
  * 生成 W3C `traceparent`(`parseTraceparent` 的镜像:一个解析、一个生成)。
51
51
  *
52
- * flags 位恒为 `00`:本框架**不采样**(每次 run 全量记账),故没有「已采样」可声明 ——
53
- * 编一个 `01` 是替下游做决定。入站侧 `parseTraceparent` 也从不读 flags。
52
+ * flags 位恒为 `00`。**理由不是「本框架不采样」**(采样早就是明确推荐的宿主配法 ——
53
+ * `docs/observability.md` 2.3),而是**运行期不可知**:记录/导出决策发生在 run **收尾之后**
54
+ * (采样闸门要看完好整棵 trace 才判得出来),而出站调用发生在**运行期** ——
55
+ * 那时「这条 trace 会不会被采样掉」还没有答案。所以恒 `00` 是唯一不撒谎的选择
56
+ * (`00` = 不声明「已采样」);编一个 `01` 是替下游做决定。⚠️ 别下一轮「顺手」改成跟随采样
57
+ * (见 `docs/spec.md` §10 2026-09-21 ⑦)。入站侧 `parseTraceparent` 也从不读 flags。
54
58
  *
55
59
  * 调用方保证给的是内部 id 或线缆 id(本函数只做投影,不做合法性判定)。
56
60
  */
@@ -85,4 +89,35 @@ export function capabilityKindOf(span) {
85
89
  return 'subagent';
86
90
  return 'capability';
87
91
  }
92
+ /**
93
+ * 把两个增量记账回调**合成一个**订阅者(前者在前)。
94
+ *
95
+ * 为什么要合成而不是 `??` 覆盖:`onTraceEvent` 是**观察者注册**(同 `TraceSink`:
96
+ * 应用级与全局默认一起收),不是值覆盖 —— 覆盖会让「某次 run / 某个宿主顺手传了自己的
97
+ * 回调」把另一条静默顶掉。两个消费者都要它的场景是真实存在的:宿主自己配了一条应用级
98
+ * 面板回调,`AsyncRunner` 还要为 `GET /tasks/:id/stream` 再挂一条按任务分的缓冲。
99
+ *
100
+ * 为什么内部各自 try/catch:合成后它们在 recorder 眼里是**一个**订阅者,而 recorder 只在
101
+ * 这一层兜错 —— 不隔离的话前一个抛错会吞掉后一个(与「一条订阅者炸了不影响另一条」互为镜像)。
102
+ */
103
+ export function composeTraceEvents(first, second) {
104
+ if (!first)
105
+ return second;
106
+ if (!second)
107
+ return first;
108
+ return (e) => {
109
+ try {
110
+ first(e);
111
+ }
112
+ catch {
113
+ /* 观测不击穿业务(与 flushSinks 同款) */
114
+ }
115
+ try {
116
+ second(e);
117
+ }
118
+ catch {
119
+ /* 同上 */
120
+ }
121
+ };
122
+ }
88
123
  //# sourceMappingURL=trace.js.map
@@ -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;;;;;;;GAOG;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"}
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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * 「嵌套能力(@SubAgent / @Skill)必须原样交下去的旋钮」—— **穷尽转发的单一真源**。
3
+ *
4
+ * 为什么要有这个文件(`docs/guards.md` §2 的「手写转发列表不得漏字段」):
5
+ *
6
+ * 主循环把一批旋钮经 `ToolRunContext` 交给工具,子 agent / skill 拉起自己的 llm 循环时
7
+ * **必须**再把它们交下去。这份清单此前手写在**两个**调用点(`toolkit/subagent.ts` 与
8
+ * `toolkit/skill.ts`),每处七八行 `ctx.X,` —— 而 TS 的结构类型对「少写一个键」**不报错**
9
+ * (键都是可选的),`exactOptionalPropertyTypes` 也只堵住「显式传 undefined」那一半。
10
+ * 于是漏字段是**静默**的:历史事故就是 `runAgentScoped` 漏 `toolTimeoutMs`,跨 engine →
11
+ * toolkit → ctx 三层没人发现,后果还是**反的** —— 子循环 `withTimeout(p, 0)` 永不超时,
12
+ * 而 MCP 桥又另起自己的 60s 兜底计时器(双计时器、双账本)。
13
+ *
14
+ * 本文件的机制有两半,缺一不可:
15
+ *
16
+ * 1. **取值收一处**:`forwardToolContext(ctx)` 是唯一的取值点,映射类型写成
17
+ * `{ [K in Key]-?: … }` —— 七个键**全必填**(值可以是 `undefined`)。少写一行 = 编译错误,
18
+ * 而不是静默漏。调用点播 `...forwardToolContext(ctx)` 即可,**没有**可漏的地方。
19
+ * 2. **归类要穷尽**:`ToolRunContext` 的每个键必须在「转发」或「引擎自装配」里各就各位。
20
+ * 新增一个可选字段而两边都没归类 ⇒ `UnclassifiedToolContextKey` 不再是 `never`
21
+ * ⇒ `tests/types/forwarding.types.ts` 的断言编译失败(`typecheck:types` 是 verify-all 第 3 步)。
22
+ *
23
+ * ⚠️ 唯一需要**覆盖**而不是直取的是 `signal`:两个调用点交下去的是
24
+ * `combineSignals(ctx.signal, ctx.abandoned)`(子循环还要能被「放弃等待」打断),
25
+ * 所以那里写成 `{ ...forwardToolContext(ctx), signal: combined }` —— 覆盖是显式的,
26
+ * 其余六个键仍然不可能漏。
27
+ *
28
+ * ⚠️ 本模块不是公共 API(不进 `src/index.ts`):它是内部纪律的落点。
29
+ */
30
+ import type { ToolRunContext } from '../core/tool.js';
31
+ /**
32
+ * 从 `ToolRunContext` 转进子循环的键。顺序即文档顺序。
33
+ *
34
+ * 加/删这里**必须**同时改 `forwardToolContext` 的返回对象 —— 映射类型要求每个键都出现。
35
+ */
36
+ export declare const FORWARDED_TOOL_CONTEXT_KEYS: readonly [
37
+ /** 中断信号(调用点通常再 combine 上 「放弃等待」) */
38
+ 'signal',
39
+ /** 宿主价格表(漏了 ⇒ 子循环里自定义定价模型退化成「未定价」,`maxCostUsd` 静默失效) */
40
+ 'priceOverrides',
41
+ /** 未定价告警回调(漏了 ⇒ 子循环里算不出成本却没人知道) */
42
+ 'onUnpricedModel',
43
+ /** 正文截断口径(漏了 ⇒ 同一棵树上主/子 agent 的可见性不一致) */
44
+ 'maxEventChars',
45
+ /** 成本护栏(漏了 ⇒ 护栏在子循环期间离线) */
46
+ 'maxTotalTokens', 'maxCostUsd',
47
+ /** 超时裁判权(漏了 ⇒ 永不超时 + 桥另起计时器,见文件头) */
48
+ 'toolTimeoutMs'];
49
+ export type ForwardedToolContextKey = (typeof FORWARDED_TOOL_CONTEXT_KEYS)[number];
50
+ /**
51
+ * 交给子循环的那一组值:**七个键全必填**(值可以是 `undefined` —— 那表示「本 run 没设」,
52
+ * 与「忘了转发」是两件事,后者在类型上写不出来)。
53
+ */
54
+ export type ForwardedToolContext = {
55
+ [K in ForwardedToolContextKey]-?: ToolRunContext[K];
56
+ };
57
+ /**
58
+ * 引擎自己装配、**刻意不**转发的键。每一个都要写清理由 —— 不写的代价是下一个人
59
+ * 不知道该不该转发,于是又手写一遍清单。
60
+ */
61
+ export type ToolContextNotForwardedKey =
62
+ /** 模型客户端:子循环用**它自己**的一份(capability 的 client 由调用点从别处拿) */
63
+ 'client'
64
+ /** 记账器:子循环写**同一条** trace,但由引擎显式传 `recorder`,不走这组旋钮 */
65
+ | 'recorder'
66
+ /** 父 span:子循环的父是 capability span,由调用点显式给 */
67
+ | 'parentSpanId'
68
+ /** 「放弃等待」信号:折进 `signal`(见文件头的 combine),子循环的工具会拿到**它自己**的 */
69
+ | 'abandoned'
70
+ /** 审批决定:属于**本次工具调用**(外层那个工具被批没批),不该灌进子循环的每一次调用 */
71
+ | 'approval';
72
+ /**
73
+ * 未归类的键。全部归类时是 `never`;一旦 `ToolRunContext` 新增字段而上面两组都没收,
74
+ * 它就变成那个字段名 —— 于是 `tests/types/forwarding.types.ts` 里那句赋 `true` 编译失败。
75
+ */
76
+ export type UnclassifiedToolContextKey = Exclude<keyof ToolRunContext, ForwardedToolContextKey | ToolContextNotForwardedKey>;
77
+ /**
78
+ * 取值:把 `ctx` 上该转发的七个键原样取出(**不判空** —— `undefined` 是有信息的值,
79
+ * 表示「本 run 没设这个旋钮」,子循环该用它自己的缺省;判空会把它吃成「没转发」)。
80
+ *
81
+ * ⚠️ 不做真值判定:`maxEventChars: false`(不截断)与 `maxTotalTokens: 0` 都是有意义的值,
82
+ * 真值判定会把它们变成「没设」。这与 `engine/tool-context.ts` 的三档判定口径一致。
83
+ */
84
+ export declare function forwardToolContext(ctx: ToolRunContext): ForwardedToolContext;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * 从 `ToolRunContext` 转进子循环的键。顺序即文档顺序。
3
+ *
4
+ * 加/删这里**必须**同时改 `forwardToolContext` 的返回对象 —— 映射类型要求每个键都出现。
5
+ */
6
+ export const FORWARDED_TOOL_CONTEXT_KEYS = [
7
+ /** 中断信号(调用点通常再 combine 上 「放弃等待」) */
8
+ 'signal',
9
+ /** 宿主价格表(漏了 ⇒ 子循环里自定义定价模型退化成「未定价」,`maxCostUsd` 静默失效) */
10
+ 'priceOverrides',
11
+ /** 未定价告警回调(漏了 ⇒ 子循环里算不出成本却没人知道) */
12
+ 'onUnpricedModel',
13
+ /** 正文截断口径(漏了 ⇒ 同一棵树上主/子 agent 的可见性不一致) */
14
+ 'maxEventChars',
15
+ /** 成本护栏(漏了 ⇒ 护栏在子循环期间离线) */
16
+ 'maxTotalTokens',
17
+ 'maxCostUsd',
18
+ /** 超时裁判权(漏了 ⇒ 永不超时 + 桥另起计时器,见文件头) */
19
+ 'toolTimeoutMs',
20
+ ];
21
+ /**
22
+ * 取值:把 `ctx` 上该转发的七个键原样取出(**不判空** —— `undefined` 是有信息的值,
23
+ * 表示「本 run 没设这个旋钮」,子循环该用它自己的缺省;判空会把它吃成「没转发」)。
24
+ *
25
+ * ⚠️ 不做真值判定:`maxEventChars: false`(不截断)与 `maxTotalTokens: 0` 都是有意义的值,
26
+ * 真值判定会把它们变成「没设」。这与 `engine/tool-context.ts` 的三档判定口径一致。
27
+ */
28
+ export function forwardToolContext(ctx) {
29
+ return {
30
+ signal: ctx.signal,
31
+ priceOverrides: ctx.priceOverrides,
32
+ onUnpricedModel: ctx.onUnpricedModel,
33
+ maxEventChars: ctx.maxEventChars,
34
+ maxTotalTokens: ctx.maxTotalTokens,
35
+ maxCostUsd: ctx.maxCostUsd,
36
+ toolTimeoutMs: ctx.toolTimeoutMs,
37
+ };
38
+ }
39
+ //# sourceMappingURL=forwarded.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forwarded.js","sourceRoot":"","sources":["../../src/engine/forwarded.ts"],"names":[],"mappings":"AA+BA;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,oCAAoC;IACpC,QAAQ;IACR,wDAAwD;IACxD,gBAAgB;IAChB,mCAAmC;IACnC,iBAAiB;IACjB,0CAA0C;IAC1C,eAAe;IACf,4BAA4B;IAC5B,gBAAgB;IAChB,YAAY;IACZ,qCAAqC;IACrC,eAAe;CACP,CAAC;AAqCX;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAmB;IACpD,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,cAAc,EAAE,GAAG,CAAC,cAAc;QAClC,eAAe,EAAE,GAAG,CAAC,eAAe;QACpC,aAAa,EAAE,GAAG,CAAC,aAAa;QAChC,cAAc,EAAE,GAAG,CAAC,cAAc;QAClC,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,aAAa,EAAE,GAAG,CAAC,aAAa;KACjC,CAAC;AACJ,CAAC"}
@@ -1,9 +1,10 @@
1
1
  import type { MessageParam } from '../core/message.js';
2
2
  import type { AgentTool, ApprovalDecision, ModelClient, ModelPricing } from '../core/tool.js';
3
3
  import type { BlackboardSeed } from '../core/blackboard.js';
4
- import type { TraceContext } from '../core/trace.js';
4
+ import type { TraceContext, TraceRecordEvent } from '../core/trace.js';
5
5
  import type { ContextPolicy } from './types.js';
6
6
  import type { RetryOptions } from './retry.js';
7
+ import type { TraceLimits } from './tracer.js';
7
8
  /**
8
9
  * Agentia —— run 调用契约(spec §6.3 三类触发共用同一份入参形态)。
9
10
  * transport 层(同步 RPC / 异步任务 / 定时)只谈 RunInput / RunSpec,
@@ -30,6 +31,30 @@ export interface RunInvocationOptions {
30
31
  retry?: RetryOptions | false;
31
32
  /** 幂等键:异步宿主的 at-least-once 去重依据 */
32
33
  idempotencyKey?: string;
34
+ /**
35
+ * **记账的数量上限**(spec §9.4 的答案里「让少记了数据可数」那一半):整条 trace 的
36
+ * 事件总数上限,超限即停止记账并在交付时于 run 根写一笔 `trace.truncated`
37
+ * (`{ droppedEvents, limit }`)—— 缺口位置可预测(尾巴)、且有计数 ⇒ 可解释。
38
+ *
39
+ * 与 `maxEventChars`(单个事件**正文长度**)正交:一个管「多长」、一个管「多少」,
40
+ * 各有各的家,两个都「不设 = 不限」。缺省**不设** —— 全量记账是本框架的承诺,
41
+ * 上限是给「长跑 + 大出参」的宿主一个显式的闸。坏值(NaN / 负数 / 小数)在 run 入口
42
+ * 抛 `TypeError`,不静默失效。见 `TraceLimits`。
43
+ */
44
+ traceLimits?: TraceLimits;
45
+ /**
46
+ * **增量记账出口**(`docs/plans/2026-09-21-incremental-trace-export-and-sampling.md`):
47
+ * run **进行中**逐笔回调(span 开/合、事件、属性、链路),给「等不了收尾」的消费者 ——
48
+ * 终端面板、SSE 前端、异步任务进度流。
49
+ *
50
+ * 与 `TraceSink` 是**两条缝**(不是替代):sink 在 run 收尾拿**完整** trace,本回调在运行期逐笔给。
51
+ * 纪律与 sink 同款:**同步调用、不 await**、抛错被吞(观测失败不击穿业务)。
52
+ * ⚠️ 但它**不保证送达**(宿主自己的流断了就断了),也**不是** sink 的替代。
53
+ *
54
+ * 应用级缺省见 `AppOptions.onTraceEvent`;两者**叠加**(应用级在前),不是覆盖 ——
55
+ * 观察者注册不该互相顶掉(per-run 传了面板回调就让应用级那条失聪,是静默回退)。
56
+ */
57
+ onTraceEvent?: (e: TraceRecordEvent) => void;
33
58
  /**
34
59
  * 入站链路上下文(spec §9.2 跨进程关联):触发本次 run 的上游 span 记成 run 根的一条
35
60
  * `links`。宿主侧两种给法 —— HTTP 头 `traceparent`(W3C,`createHttpHandler` 自动解析)
@@ -1 +1 @@
1
- {"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/engine/spec.ts"],"names":[],"mappings":"AAmGA;;;;;;;;GAQG;AACH,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,wCAAwC;AACxC,MAAM,UAAU,iBAAiB,CAAC,KAAyB;IACzD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,mDAAmD;QACnD,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,cAAc,CAAC,kBAAkB,CAAC,CAAC;QACzD,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,cAAc,CAAC,kBAAkB,CAAC,CAAC;QACrE,OAAO,KAAuB,CAAC;IACjC,CAAC;IACD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,KAAiE,CAAC;QAC5E,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM,IAAI,cAAc,CAAC,kBAAkB,CAAC,CAAC;YAC1E,OAAO,CAAC,CAAC,QAA0B,CAAC;QACtC,CAAC;QACD,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM;YAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3F,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI;YAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACvF,CAAC;IACD,MAAM,IAAI,cAAc,CAAC,cAAc,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;AACjF,CAAC"}
1
+ {"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/engine/spec.ts"],"names":[],"mappings":"AA4HA;;;;;;;;GAQG;AACH,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,wCAAwC;AACxC,MAAM,UAAU,iBAAiB,CAAC,KAAyB;IACzD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,mDAAmD;QACnD,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,cAAc,CAAC,kBAAkB,CAAC,CAAC;QACzD,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,cAAc,CAAC,kBAAkB,CAAC,CAAC;QACrE,OAAO,KAAuB,CAAC;IACjC,CAAC;IACD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,KAAiE,CAAC;QAC5E,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM,IAAI,cAAc,CAAC,kBAAkB,CAAC,CAAC;YAC1E,OAAO,CAAC,CAAC,QAA0B,CAAC;QACtC,CAAC;QACD,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM;YAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3F,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI;YAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACvF,CAAC;IACD,MAAM,IAAI,cAAc,CAAC,cAAc,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;AACjF,CAAC"}
@@ -1,4 +1,34 @@
1
- import type { SpanError, SpanId, SpanKind, SpanLink, SpanStatus, Trace, TraceId, Usage } from '../core/trace.js';
1
+ import type { SpanError, SpanId, SpanKind, SpanLink, SpanStatus, Trace, TraceId, TraceRecordEvent, Usage } from '../core/trace.js';
2
+ /**
3
+ * 记账的**数量上限**(spec §9.4 的答案里「让少记了数据可数」那一半)。
4
+ *
5
+ * 只有 `maxEvents` 一个旋钮,而且它管的是**整条 trace 的事件总数**
6
+ * (`tool.input` / `tool.output` / `score` / … 都算)—— 因为成本就是整条 trace 的量。
7
+ * 与 `maxEventChars`(**单个事件正文长度**)是两个正交的旋钮,各有各的家:
8
+ * 一个管「多长」,一个管「多少」;两个都「不设 = 不限」。
9
+ *
10
+ * 超限后的行为是**停止记账 + 记一笔 `trace.truncated`**(交付时写在 run 根上:
11
+ * `{ droppedEvents, limit }`)—— 缺口位置可预测(尾巴),且有计数 ⇒ 可解释。
12
+ * 刻意**不做**环形缓冲(丢最旧、留最近):那会让 trace 中间出现空洞,
13
+ * 而空洞比「尾巴截断」难解释得多(「这一回合怎么没有工具事件」)。
14
+ */
15
+ export interface TraceLimits {
16
+ /** 整条 trace 的事件总数上限;`0` = 一条都不记(有意义的值,仍有计数);不设 = 不限 */
17
+ maxEvents?: number;
18
+ }
19
+ /**
20
+ * 解析并校验 `traceLimits.maxEvents` —— **构造期**(run 入口)响亮失败。
21
+ *
22
+ * 坏值不静默的理由与 `integrations/adapter-options.ts` 的 `resolveMaxRetries` 同款:
23
+ * `NaN` / 负数 / 小数会让「记多少条」变成猜的(`>=` 对 NaN 恒假 ⇒ 上限**根本不生效**,
24
+ * 而使用者以为自己设了闸),这类「设了但没生效」正是本仓在收的债。
25
+ */
26
+ export declare function resolveTraceLimits(raw: unknown, owner: string): TraceLimits | undefined;
27
+ /** TraceRecorder 的构造选项(`maxEvents` 来自 `TraceLimits`) */
28
+ export interface TraceRecorderOptions {
29
+ /** 事件总数上限;不设 = 不限。见 `TraceLimits` */
30
+ maxEvents?: number;
31
+ }
2
32
  /**
3
33
  * 内存 TraceRecorder —— v1 实现(spec §9.3)。
4
34
  * 显式传 parentSpanId 而非内部栈,保证并行工具调用时父子关系准确。
@@ -11,6 +41,37 @@ export declare class TraceRecorder {
11
41
  /** parentSpanId → 直接子 span(增量维护,供 capability 结束时就地聚合子孙 usage,O(子孙) 而非每次重建) */
12
42
  private readonly children;
13
43
  private rootSpanId;
44
+ /** 事件总量闸(`traceLimits.maxEvents`);undefined = 不限 */
45
+ private readonly maxEvents;
46
+ /** 已入 trace 的事件数(受 `maxEvents` 约束的那个计数) */
47
+ private recordedEvents;
48
+ /** 因超限被丢弃的事件数(交付时写进 run 根的 `trace.truncated`) */
49
+ private droppedEvents;
50
+ /** 记账事件订阅者(增量出口,见 `core/trace.ts` 的 `TraceRecordEvent`) */
51
+ private readonly listeners;
52
+ /**
53
+ * 记账事件序号。**每次记账动作都自增,与当时有没有订阅者无关** —— 这样「订阅早」与
54
+ * 「订阅晚」看到的同一个事件拿到同一个 `seq`(SSE 的 `Last-Event-ID` 重放靠它)。
55
+ * 只增一个数字,不算成本。
56
+ */
57
+ private seq;
58
+ constructor(opts?: TraceRecorderOptions);
59
+ /**
60
+ * 订阅记账事件(增量出口);返回退订函数。
61
+ *
62
+ * 与 `TraceSink` 是**两条缝**:sink 收尾拿整棵,这里 run 进行中就逐笔拿。
63
+ * 纪律:**同步派发**(不 await —— 订阅者是观察者,不该把 run 变成它的调度)、
64
+ * 订阅者抛错**被吞**(观测失败不击穿业务,与 `flushSinks` 同款)、
65
+ * 无订阅者时**不做任何载荷构造**(「不订阅不付钱」)。
66
+ */
67
+ subscribe(listener: (e: TraceRecordEvent) => void): () => void;
68
+ /**
69
+ * 派发一条记账事件。
70
+ *
71
+ * ⚠️ 顺序要紧:**先自增 `seq` 再判有没有订阅者** —— 若在无订阅者时不计数,
72
+ * 「订阅晚的人」看到的序号就会与「一直订阅的人」不一致(重放与去重都会错位)。
73
+ */
74
+ private emit;
14
75
  begin(kind: SpanKind, name: string, parentSpanId: SpanId | null): SpanId;
15
76
  get rootStarted(): boolean;
16
77
  /**
@@ -1,4 +1,27 @@
1
1
  import { randomUUID } from 'node:crypto';
2
+ import { zeroClauseOf } from '../core/limits.js';
3
+ /**
4
+ * 解析并校验 `traceLimits.maxEvents` —— **构造期**(run 入口)响亮失败。
5
+ *
6
+ * 坏值不静默的理由与 `integrations/adapter-options.ts` 的 `resolveMaxRetries` 同款:
7
+ * `NaN` / 负数 / 小数会让「记多少条」变成猜的(`>=` 对 NaN 恒假 ⇒ 上限**根本不生效**,
8
+ * 而使用者以为自己设了闸),这类「设了但没生效」正是本仓在收的债。
9
+ */
10
+ export function resolveTraceLimits(raw, owner) {
11
+ if (raw === undefined)
12
+ return undefined;
13
+ if (typeof raw !== 'object' || raw === null) {
14
+ throw new TypeError(`${owner}:traceLimits 必须是对象(如 { maxEvents: 500 }),收到 ${String(raw)}`);
15
+ }
16
+ const maxEvents = raw.maxEvents;
17
+ if (maxEvents === undefined)
18
+ return {};
19
+ if (typeof maxEvents !== 'number' || !Number.isSafeInteger(maxEvents) || maxEvents < 0) {
20
+ throw new TypeError(`${owner}:traceLimits.maxEvents 必须是非负安全整数(${zeroClauseOf('traceLimits.maxEvents')}),收到 ${String(maxEvents)} —— ` +
21
+ 'NaN / Infinity / 负数 / 小数都会让「记多少条」变成猜的');
22
+ }
23
+ return { maxEvents };
24
+ }
2
25
  /**
3
26
  * 内存 TraceRecorder —— v1 实现(spec §9.3)。
4
27
  * 显式传 parentSpanId 而非内部栈,保证并行工具调用时父子关系准确。
@@ -11,6 +34,60 @@ export class TraceRecorder {
11
34
  /** parentSpanId → 直接子 span(增量维护,供 capability 结束时就地聚合子孙 usage,O(子孙) 而非每次重建) */
12
35
  children = new Map();
13
36
  rootSpanId = null;
37
+ /** 事件总量闸(`traceLimits.maxEvents`);undefined = 不限 */
38
+ maxEvents;
39
+ /** 已入 trace 的事件数(受 `maxEvents` 约束的那个计数) */
40
+ recordedEvents = 0;
41
+ /** 因超限被丢弃的事件数(交付时写进 run 根的 `trace.truncated`) */
42
+ droppedEvents = 0;
43
+ /** 记账事件订阅者(增量出口,见 `core/trace.ts` 的 `TraceRecordEvent`) */
44
+ listeners = [];
45
+ /**
46
+ * 记账事件序号。**每次记账动作都自增,与当时有没有订阅者无关** —— 这样「订阅早」与
47
+ * 「订阅晚」看到的同一个事件拿到同一个 `seq`(SSE 的 `Last-Event-ID` 重放靠它)。
48
+ * 只增一个数字,不算成本。
49
+ */
50
+ seq = 0;
51
+ constructor(opts = {}) {
52
+ this.maxEvents = opts.maxEvents;
53
+ }
54
+ /**
55
+ * 订阅记账事件(增量出口);返回退订函数。
56
+ *
57
+ * 与 `TraceSink` 是**两条缝**:sink 收尾拿整棵,这里 run 进行中就逐笔拿。
58
+ * 纪律:**同步派发**(不 await —— 订阅者是观察者,不该把 run 变成它的调度)、
59
+ * 订阅者抛错**被吞**(观测失败不击穿业务,与 `flushSinks` 同款)、
60
+ * 无订阅者时**不做任何载荷构造**(「不订阅不付钱」)。
61
+ */
62
+ subscribe(listener) {
63
+ this.listeners.push(listener);
64
+ return () => {
65
+ const i = this.listeners.indexOf(listener);
66
+ if (i >= 0)
67
+ this.listeners.splice(i, 1);
68
+ };
69
+ }
70
+ /**
71
+ * 派发一条记账事件。
72
+ *
73
+ * ⚠️ 顺序要紧:**先自增 `seq` 再判有没有订阅者** —— 若在无订阅者时不计数,
74
+ * 「订阅晚的人」看到的序号就会与「一直订阅的人」不一致(重放与去重都会错位)。
75
+ */
76
+ emit(payload) {
77
+ const seq = ++this.seq;
78
+ if (this.listeners.length === 0)
79
+ return;
80
+ const event = { ...payload, seq };
81
+ // 先拷一份订阅者列表:允许订阅者在回调里退订/新增(否则会漏发或边遍历边改)
82
+ for (const l of [...this.listeners]) {
83
+ try {
84
+ l(event);
85
+ }
86
+ catch {
87
+ /* 观测不击穿业务(与 flushSinks 同款) */
88
+ }
89
+ }
90
+ }
14
91
  begin(kind, name, parentSpanId) {
15
92
  if (kind === 'run') {
16
93
  if (this.rootSpanId)
@@ -36,6 +113,9 @@ export class TraceRecorder {
36
113
  siblings.push(span);
37
114
  else
38
115
  this.children.set(parentSpanId, [span]);
116
+ // 此刻的拷贝(空 attributes/events)—— 之后的属性/事件各走自己的事件类型,
117
+ // 订阅者拿到的对象此后不再变异(与 snapshot 同纪律)
118
+ this.emit({ type: 'span.begin', span: { ...span, attributes: {}, events: [] } });
39
119
  return id;
40
120
  }
41
121
  get rootStarted() {
@@ -69,6 +149,16 @@ export class TraceRecorder {
69
149
  if (aggregated)
70
150
  span.usage = aggregated;
71
151
  }
152
+ // 增量出口:收尾字段以**增量**形态派出(不带 attributes/events —— 那些各走自己的事件),
153
+ // 且取的是**聚合之后**的最终值(capability 的 usage 在此刻才算得出来)
154
+ this.emit({
155
+ type: 'span.end',
156
+ spanId: id,
157
+ endedAt: span.endedAt,
158
+ status: span.status,
159
+ ...(span.error ? { error: span.error } : {}),
160
+ ...(span.usage ? { usage: span.usage } : {}),
161
+ });
72
162
  }
73
163
  /** 子孙里所有 `llm.turn` 的 usage 之和(不含自身);无任何计量时返回 undefined */
74
164
  aggregateDescendantUsage(id) {
@@ -107,12 +197,26 @@ export class TraceRecorder {
107
197
  return total;
108
198
  }
109
199
  event(id, name, body) {
110
- this.index.get(id)?.events.push({ time: Date.now(), name, body });
200
+ const span = this.index.get(id);
201
+ if (!span)
202
+ return; // 未知 span 静默忽略(见类注释的容错策略)—— 增量出口同样不派发
203
+ // 数量闸(traceLimits.maxEvents):超限即**停止记账**,并只记一个计数 ——
204
+ // 计数在 snapshot() 交付时写成 run 根的 `trace.truncated`(见 TraceLimits 的注释)。
205
+ if (this.maxEvents !== undefined && this.recordedEvents >= this.maxEvents) {
206
+ this.droppedEvents += 1;
207
+ return;
208
+ }
209
+ this.recordedEvents += 1;
210
+ const event = { time: Date.now(), name, body };
211
+ span.events.push(event);
212
+ this.emit({ type: 'span.event', spanId: id, event: { ...event } });
111
213
  }
112
214
  setAttribute(id, key, value) {
113
215
  const span = this.index.get(id);
114
- if (span)
115
- span.attributes[key] = value;
216
+ if (!span)
217
+ return;
218
+ span.attributes[key] = value;
219
+ this.emit({ type: 'span.attribute', spanId: id, key, value });
116
220
  }
117
221
  /**
118
222
  * 给 span 记一条跨 trace 的链路引用(入站触发来源,见 `core/trace.ts` 的 `TraceContext`)。
@@ -125,6 +229,7 @@ export class TraceRecorder {
125
229
  if (!span.links)
126
230
  span.links = [];
127
231
  span.links.push(link);
232
+ this.emit({ type: 'span.link', spanId: id, link: { ...link } });
128
233
  }
129
234
  /**
130
235
  * 整条 run 的累计 usage(**只算 `llm.turn` 的自身计量**,子 agent 的往返也在内)。
@@ -167,20 +272,31 @@ export class TraceRecorder {
167
272
  snapshot(status) {
168
273
  if (!this.rootSpanId)
169
274
  throw new Error('run root not started');
275
+ const spans = this.spans.map((s) => ({
276
+ ...s,
277
+ attributes: { ...s.attributes },
278
+ events: [...s.events],
279
+ ...(s.links ? { links: [...s.links] } : {}),
280
+ }));
281
+ // 截断摘要:**交付时**写在 run 根上(与 totalUsage 同族 —— 都是「跑完才算得出的结论」,
282
+ // 不是记账动作)。所以它**不在**增量事件流里:折叠不变量管的是「记账动作不丢不重」,
283
+ // 而这是一个派生结论,增量消费者靠 `droppedEvents > 0` 自己判(见 TraceLimits)。
284
+ if (this.droppedEvents > 0) {
285
+ const root = spans.find((s) => s.spanId === this.rootSpanId);
286
+ root?.events.push({
287
+ time: Date.now(),
288
+ name: 'trace.truncated',
289
+ body: { droppedEvents: this.droppedEvents, limit: this.maxEvents },
290
+ });
291
+ }
170
292
  return {
171
293
  traceId: this.traceId,
172
294
  rootSpanId: this.rootSpanId,
173
- // span 浅拷 + attributes/events/links 拷一层:快照交付后仍在记账的残尾(如超时工具的
174
- // 后台事件)会继续 push 进 recorder 持有的数组 —— 不拷贝就会事后变异已交付的 trace。
175
- // (不递归深拷:事件 body 与 link 记账后不再被框架改写)
176
- // links 用「有才拷」:没有 link 的 span 交付后不该多出 `links: undefined` 这个键
177
- // (见 core/trace.ts 的注释 —— 缺席与空数组是同一件事,别制造第三种形态)。
178
- spans: this.spans.map((s) => ({
179
- ...s,
180
- attributes: { ...s.attributes },
181
- events: [...s.events],
182
- ...(s.links ? { links: [...s.links] } : {}),
183
- })),
295
+ // (spans 的浅拷 + attributes/events/links 拷一层见函数开头:快照交付后仍在记账的
296
+ // 残尾会继续 push 进 recorder 持有的数组,不拷贝就会事后变异已交付的 trace。
297
+ // 不递归深拷:事件 body 与 link 记账后不再被框架改写。links 用「有才拷」——
298
+ // 见 core/trace.ts 的注释:缺席与空数组是同一件事,别制造第三种形态。)
299
+ spans,
184
300
  status,
185
301
  totalUsage: this.usage(),
186
302
  };
@@ -1 +1 @@
1
- {"version":3,"file":"tracer.js","sourceRoot":"","sources":["../../src/engine/tracer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tracer.js","sourceRoot":"","sources":["../../src/engine/tracer.ts"],"names":[],"mappings":"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"}