@migor/agentia 0.8.0 → 0.8.2

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 (49) hide show
  1. package/CHANGELOG.md +140 -1
  2. package/README.md +1 -1
  3. package/dist/AGENTS.md +57 -7
  4. package/dist/core/timeout.d.ts +9 -0
  5. package/dist/core/timeout.js +13 -3
  6. package/dist/core/timeout.js.map +1 -1
  7. package/dist/core/trace.d.ts +25 -0
  8. package/dist/core/trace.js +31 -0
  9. package/dist/core/trace.js.map +1 -1
  10. package/dist/engine/loop.js +7 -3
  11. package/dist/engine/loop.js.map +1 -1
  12. package/dist/engine/span-scope.d.ts +48 -0
  13. package/dist/engine/span-scope.js +31 -0
  14. package/dist/engine/span-scope.js.map +1 -0
  15. package/dist/engine/turn.d.ts +3 -4
  16. package/dist/engine/turn.js +9 -7
  17. package/dist/engine/turn.js.map +1 -1
  18. package/dist/index.d.ts +2 -1
  19. package/dist/index.js +4 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/integrations/adapter-options.d.ts +22 -0
  22. package/dist/integrations/adapter-options.js +32 -0
  23. package/dist/integrations/adapter-options.js.map +1 -0
  24. package/dist/integrations/anthropic.js +4 -1
  25. package/dist/integrations/anthropic.js.map +1 -1
  26. package/dist/integrations/mcp-stdio.js +11 -7
  27. package/dist/integrations/mcp-stdio.js.map +1 -1
  28. package/dist/integrations/metrics-otlp.js +7 -0
  29. package/dist/integrations/metrics-otlp.js.map +1 -1
  30. package/dist/integrations/metrics-state.d.ts +9 -0
  31. package/dist/integrations/metrics-state.js +13 -0
  32. package/dist/integrations/metrics-state.js.map +1 -1
  33. package/dist/integrations/metrics.js +3 -2
  34. package/dist/integrations/metrics.js.map +1 -1
  35. package/dist/integrations/openai.js +4 -2
  36. package/dist/integrations/openai.js.map +1 -1
  37. package/dist/integrations/otlp-partial.d.ts +27 -0
  38. package/dist/integrations/otlp-partial.js +63 -0
  39. package/dist/integrations/otlp-partial.js.map +1 -0
  40. package/dist/integrations/otlp.d.ts +12 -2
  41. package/dist/integrations/otlp.js +67 -45
  42. package/dist/integrations/otlp.js.map +1 -1
  43. package/dist/toolkit/skill.js +4 -1
  44. package/dist/toolkit/skill.js.map +1 -1
  45. package/dist/toolkit/subagent.js +6 -3
  46. package/dist/toolkit/subagent.js.map +1 -1
  47. package/dist/transport/async.js +33 -0
  48. package/dist/transport/async.js.map +1 -1
  49. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -5,6 +5,143 @@
5
5
  (0.x 阶段:minor 可含破坏性变更,每个破坏性变更都在对应版本的「迁移」小节里写明)。
6
6
  决策的完整证据链在 `docs/spec.md` §10(带时间线的决策日志)。
7
7
 
8
+ ## [0.8.2] - 2026-09-21
9
+
10
+ ### 变更
11
+
12
+ > 本版主题(窗口 `0.8.1 → 0.8.2`,含 #112):**外部双模型复核逐条复现收口** —— 9 条真缺陷
13
+ > (7 条复核成立 + 改的过程中照出的 2 条),全部落在「不报错地不干活」这一类:静默丢观测数据、
14
+ > 静默无限重试、无声永久挂起、生成出来的工程一跑就崩。
15
+ > **框架 API 无破坏性变更**:只新增一个选项(`createOtlpExporter({ onExportError })`),
16
+ > 既有签名与行为在「你没传坏值 / 没按 200 当全部成功」的前提下逐字不变。
17
+ > **一处需要你确认的收紧**:`maxRetries` 的坏值改在**构造期抛错**(见「修复」与「迁移」)。
18
+
19
+ ### 修复(观测出口 —— 三条都属于「看板少数据而框架说一切正常」)
20
+
21
+ - **OTLP 导出的 `status.code` 从名字符串改成整数**(`'STATUS_CODE_OK'` / `'STATUS_CODE_ERROR'`
22
+ → `1` / `2`)。OTLP 规范对此是**明文 MUST**,而且专门点出它与 protobuf 的通用 JSON 映射不同:
23
+
24
+ > *Values of enum fields MUST be encoded as integer values.*
25
+ > *Unlike the standard Protobuf JSON Mapping, which allows values of enum fields to be encoded as
26
+ > either integer values or as enum name strings, only integer enum values are allowed in OTLP JSON
27
+ > Protobuf Encoding; the enum name strings MUST NOT be used.*
28
+ > —— [OTLP 规范 · JSON Protobuf Encoding](https://opentelemetry.io/docs/specs/otlp/)
29
+
30
+ (同期 `kind` 一直是整数 1,只有 `status` 漏了。)**后果取决于你那侧 collector 的宽容度**:
31
+ 照规范校验的实现会判非法并**整批拒收**(也就说这些 span 在采集端**根本没落库**,而框架侧只看得到
32
+ 「HTTP 200」);按通用 protobuf JSON 映射的宽容实现(enum 名与整数都收)能落库。
33
+ 受影响范围:**`v0.2.2` → `v0.8.1`**(`createOtlpExporter` 自 `v0.2.2` 起就带这个错)。
34
+ 动作:升级即可,不需要改代码。**但请顺手去采集端确认一眼**这期间(用严格 collector 的话)
35
+ 的 trace 是否为空 —— 你的实现属于哪一档,看那里比看本文档准;丢掉的**历史数据补不回来**。
36
+ - **HTTP 200 不再等于「全部接收」**:collector 可以回 `200 + partialSuccess` 表示「收了一部分」。
37
+ 此前 `res.ok` 为真就算成功 ⇒ 少了一半数据也没人知道。现在「**真拒收**(键在场且值 > 0)
38
+ **或**非空 `errorMessage`」判为导出失败;`{}` 与 `rejectedSpans: 0` 仍算全部接收
39
+ (有 collector 恒发这种形状,不能反着误报)。
40
+ - **新增 `createOtlpExporter({ onExportError })`**(与 `metricsSink` 的同名选项对称):
41
+ 不给,维持既有行为(抛出 → `flushSinks` 吞掉,观测失败不击穿业务);给了,**所有**导出失败
42
+ (非 2xx / 超时 / **HTTP 200 但部分接收**)都交给它。存在的理由:`TraceSink` 的失败缺省是
43
+ **静默**的,「导出其实少了一半数据」这类消息得有人能收到 —— 否则它和「一切正常」在监控上
44
+ 看不出区别。
45
+ - **`metricsSink` 的 `reset()` 语义明确为「开启新窗口」**:计数清零**且**数据点起点前移。
46
+ 此前 `reset()` 只清计数、而数据点的 `startTimeUnixNano` 取自 sink **创建时刻的常量** ⇒
47
+ 同一 `startTime` 下 counter 从 2 退到 1(CUMULATIVE 指标的契约是「同一区间单调不减」,
48
+ 后端会算出负增量或直接丢样本)。同一毫秒内连按两次 `reset()` 时起点也**严格**前进。
49
+
50
+ ### 修复(其余)
51
+
52
+ - **`maxRetries` 的坏值改在构造期抛 `TypeError`**(`createAnthropicClient` /
53
+ `createOpenAIClient`,两条适配器共用一份判定)。重试判定是 `attempt >= maxRetries`,于是
54
+ 四类坏值此前被**静默接受**、后果各不相同:`NaN` ⇒ 比较恒假 ⇒ **无限重试**;`Infinity` ⇒
55
+ 永不达到 ⇒ **无限重试**;`-1` ⇒ 静默变成「不重试」;`1.5` ⇒ 实际只允许 1 次(读数上看不出来)。
56
+ 使用者以为自己设了上限,实际没有 —— 429 场景下每多一次重试都是真金白银。
57
+ **`0` 与不传仍然合法**(`0` = 不重试,是有意义的值;缺省 2);坏的是「非整数 / 负数 / 非有限」。
58
+ - **已中止的 MCP 调用不再发请求、不再永久挂起**:此前的写法是「把 pending 条目删掉、然后照样
59
+ `write`」⇒ ① 副作用请求**仍然送达** server(取消在传输层是无效的);② 返回的 Promise
60
+ **永远不 settle**(条目已删,没人能 resolve/reject)⇒ 调用方**永久挂起**
61
+ (引擎侧靠 `toolTimeoutMs` 兜底才没炸)。现在判据在 `write()` **之前**,以 `AbortError` 收场
62
+ (取消不是超时,记账仍归 `aborted`)。发送**之后**才中止的,请求已在路上、取消不了 ——
63
+ 那是「不等了」,与 `toolTimeoutMs` 同口径。
64
+ - **异步 store 下同键并发提交不再重复执行**:`submit` 是**同步门面**、无法 await 异步 store 的
65
+ `byIdempotency`,而 `#executeInner` 只采纳已 `succeeded` 的既有记录 ⇒ 「同时提交两个相同
66
+ `idempotencyKey`」在异步 store(Redis / SQLite)下**两次都执行**(文档承诺的同键去重实际只对
67
+ 同步 store 成立)。现在补一张**进程内认领表**:认领在同步前段完成(两次连续 `submit` 之间
68
+ 没有窗口),且**只在终态释放**(挂起还在等人,放了会让同键另起一个任务)。
69
+ **边界(同时写进 `usage-guide` §7)**:修的是「同进程内并发提交」这一档;**跨进程并发**与
70
+ **终态之后重提同键**仍是 at-least-once(store 的 idem 索引 last-wins)。
71
+ - **`@migor/cli`:模板漏写 `scripts/clean.mjs`**。本版首次给脚手架模板加「构建前先清 dist」,
72
+ 并在发布前发现 `create.ts` 忘了把该脚本写出去 —— 生成的新工程 `npm run build` **第一步就
73
+ `MODULE_NOT_FOUND`**。**已发布版本(≤0.8.1)的模板不含这一步,你此前生成的工程不受影响**,
74
+ 也不需要改;本版发布的是修好的形态。仓库自身与模板的构建现在都先清 dist(`tsc` 不会删除
75
+ 它不再产出的文件 —— 目录重构后旧产物会原样进包),并新增「模板目录 ↔ 源码双向引用」守卫
76
+ (模板文件必须被引用、每个 accessor 必须有调用方)与 e2e 的**真删能力再重建**对照。
77
+
78
+ ### 仓库自身(不面向使用者)
79
+
80
+ - e2e-cli 的构建步骤从「测试复刻 `clean → tsc → copy-assets` 三步」改成**字面跑产物自己的
81
+ `npm run typecheck` / `npm run build`** —— 这条改法当场照出上面那条真缺陷(测试复刻命令的
82
+ 版本照不出来)。同时删掉一条会在合法重构时误报的字面量断言。
83
+ - `docs/guards.md` §1 增补五条守卫(OTLP enum + partialSuccess、CUMULATIVE 窗口起点、模板重建
84
+ 清 dist、幂等键进程内认领、模板 ↔ 源码双向引用);`docs/spec.md` §10 ⑤ 记逐条定性、
85
+ 反向验证与「报告自称已证伪」的抽查范围。
86
+ - `tests/docs/usage-guide.test.ts` 把 `OtlpExporterOptions` 登记进成员表校验 —— 新增选项自此
87
+ 被文档守卫钉住(注入假成员验证过会红)。
88
+
89
+ **迁移**:无(框架 API 无破坏性变更,既有代码不需要任何改动)。唯一需要动作的是 `maxRetries`:
90
+ 如果你此前给它传过 `NaN` / `±Infinity` / 负数 / 小数,升级后**构造期会抛 `TypeError`** ——
91
+ 这是有意的(它此前是静默失效),改成非负整数即可;传 `0` 或不传的代码不受影响。
92
+
93
+ ## [0.8.1] - 2026-09-21
94
+
95
+ ### 变更
96
+
97
+ > 本版主题(窗口 `0.8.0 → 0.8.1`,含 #107–#110):**出站链路传播** —— spec §9.2 那条
98
+ > 「出站传播仍开放」的项收口。**无破坏性变更**:只新增一个公开函数;既有 API、trace 形状、
99
+ > OTLP 导出值与 id 生成本身全部逐字不变(id 投影只是从 `integrations/otlp.ts` 的私有函数
100
+ > **上移到** `core/trace.ts` 成为单一真源,取值一字未改)。
101
+
102
+ ### 新增
103
+
104
+ - **`currentTraceparent(): string | undefined`**(出站链路传播):给出**当前调用期** span 的
105
+ W3C `traceparent`(`00-<32位trace>-<16位span>-00`),自己带在出站请求上(`fetch` 头 / gRPC
106
+ metadata)。下游若也是 agentia(或任何认 `traceparent` 的服务),就能把「谁触发了这次调用」
107
+ 关联到**具体 span**,而不是只到 run 粒度:
108
+
109
+ ```ts
110
+ import { currentTraceparent } from '@migor/agentia';
111
+
112
+ const tp = currentTraceparent();
113
+ await fetch(url, { headers: { ...(tp ? { traceparent: tp } : {}) } });
114
+ ```
115
+
116
+ 粒度:普通工具与 `@Prompt` **不建 span**,取到的是发起它们的那次 `llm.turn`;`@Skill` /
117
+ `@SubAgent` 方法体内取到的是自己的 `capability` span(内层覆盖外层)。入站那一半
118
+ (`traceparent` 头 → run 根 `links`)已随 0.6.2 落地,本版把出站补上,跨服务关联从此双向。
119
+
120
+ ### 已知边界(同时写进 `usage-guide` §7)
121
+
122
+ - **只给读取器,不替你做注入** —— 框架不创建出站请求,注入那一行是宿主的(与「webhook 用
123
+ sink + 你自己的 `fetch`」同一条既有决策)。
124
+ - `run` 根 span 由 `runAgent` 打开 ⇒ 更早的 `contextInit` / 记忆水合取到 `undefined` —— 那时
125
+ 确实还没有 span 可指,不编造。
126
+ - flags 位恒 `00`:本框架不采样(每次 run 全量记账),不替下游声明「已采样」。
127
+ - id 宽度:内部 id 是 UUID,出站与 OTLP 共用**同一份**投影(trace 去横线 32-hex、span 截
128
+ 16-hex)⇒ 下游收到的 span id 与 collector 里那个**是同一个数**(各写一份会让同一次调用在
129
+ 两个系统里出现两个 span id)。
130
+
131
+ ### 仓库自身(不面向使用者)
132
+
133
+ - 第七 / 第八轮复审散件沉淀进 `docs/guards.md` 附录 B,并立「多 agent 同仓作业」三条纪律
134
+ (结论钉 commit / 门禁跑隔离导出树 / 不碰别人的未提交改动)。
135
+ - 出处链更正:spec §10 的「132 条直接用例」→ **127**(逐文件计数,独立复核不可复现 132),
136
+ 全仓口径改引「+140 条(`tests/` 增量)」;覆盖率棘轮分支 85→88 / 函数 92→95。
137
+ - 新增两条守卫并入册:id 投影**单源**(OTLP 与出站必须同一个数)、出站**调用期作用域**
138
+ (并行不串 / 内层不外泄),两条都做过承重性反向验证。
139
+ - 发布面清单的 lock 项改为**按包名锚定**:裸 `"version"` 计数会被**恰好同版本号的第三方
140
+ 依赖**撞网(本次真发生:`@grpc/proto-loader` 恰好 @0.8.1 ⇒ 闸门报「4 处应为 0.8.1,实际
141
+ 命中 5 处」,读起来像漏项)。夹具同步加了同版本诱饵,断言它既不被替换、也不进网。
142
+
143
+ **迁移**:无。既有代码不需要任何改动;要开始用出站传播,就在出站请求上加一行 `traceparent`。
144
+
8
145
  ## [0.8.0] - 2026-09-21
9
146
 
10
147
  ### 变更
@@ -727,7 +864,9 @@
727
864
  首个公开发布:`@migor/agentia` + `@migor/cli`(scope `@migor/*`),两包版本同步。
728
865
  框架本体单包;CLI 独立成包(workspaces)。
729
866
 
730
- [Unreleased]: https://github.com/retrychx/agentia/compare/v0.8.0...HEAD
867
+ [Unreleased]: https://github.com/retrychx/agentia/compare/v0.8.2...HEAD
868
+ [0.8.2]: https://github.com/retrychx/agentia/releases/tag/v0.8.2
869
+ [0.8.1]: https://github.com/retrychx/agentia/releases/tag/v0.8.1
731
870
  [0.8.0]: https://github.com/retrychx/agentia/releases/tag/v0.8.0
732
871
  [0.7.2]: https://github.com/retrychx/agentia/releases/tag/v0.7.2
733
872
  [0.7.1]: https://github.com/retrychx/agentia/releases/tag/v0.7.1
package/README.md CHANGED
@@ -34,7 +34,7 @@ npm run dev # = agentia dev:tsx watch + 本地 inspec
34
34
  > 框架**不自动**读 `.env`:脚手架 `src/main.ts` 首行的 `loadEnvFile()` 负责把它读进 `process.env`。
35
35
  > 真实环境变量优先(CI / docker / 命令行永远赢过文件),`loadEnvFile({ override: true })` 才反过来。
36
36
 
37
- > **版本**:`0.8.0`(`@migor/agentia` 与 `@migor/cli` 均已发布到 npm)。`examples/` **刻意**用
37
+ > **版本**:`0.8.2`(`@migor/agentia` 与 `@migor/cli` 均已发布到 npm)。`examples/` **刻意**用
38
38
  > `file:../..` 指向本仓库而不是 npm 版本 —— 跑的是**工作区代码**,理由见
39
39
  > [`examples/README.md`](examples/README.md) 的「依赖说明」。
40
40
 
package/dist/AGENTS.md CHANGED
@@ -461,7 +461,7 @@ npm run client # 另一个终端:把四个 RPC 跑一遍
461
461
  | 端点 | 请求 | 响应 |
462
462
  |---|---|---|
463
463
  | `POST /run` | body 是 `RunInput`(string / messages / `{prompt\|text\|messages}`);带 `Accept: text/event-stream` 则走 SSE | 200 `{ runId, status, stopReason, finalText, typed?, trace, error? }` —— **`status=failed` 也照返 200**(`rethrow:false` 语义:硬失败以 `error` 字段表达,不用 HTTP 错误码) |
464
- | `POST /tasks` | `{ input, idempotencyKey?, options? }` —— `input` 同 `RunInput`;`options` 是 `RunInvocationOptions` | 202 `TaskRecord`(`status: 'queued'`);同 `idempotencyKey` 未失败则去重,直接返回既有记录 |
464
+ | `POST /tasks` | `{ input, idempotencyKey?, options? }` —— `input` 同 `RunInput`;`options` 是 `RunInvocationOptions` | 202 `TaskRecord`(`status: 'queued'`);同 `idempotencyKey` 未失败则去重、直接返回既有记录(**同步 store** 当场判定;**异步 store** 下只保证**同进程内并发提交**不重复执行,跨进程与终态后重提仍是 at-least-once —— 见 §7「同键去重的能力边界」) |
465
465
  | `GET /tasks/:id` | — | 200 `TaskRecord`;不存在 → 404。**停机中仍可轮询**(否则拿不到在飞任务的结果) |
466
466
  | `POST /tasks/:id/approve` | `{ decisions: { <tool_use_id>: { approved, reason? } }, decidedBy? }` | 200 `TaskRecord`(HITL 审批:批准/拒绝挂起任务,见 §6.6「人工审批」);任务不存在 → 404;不在 `awaiting_approval` 状态 → 409;body 非法 → 400。**停机中仍可审批**(与 GET 轮询同理由) |
467
467
  | `GET /healthz` | — | 200 `HealthResponse`;**不鉴权**,停机中也回 200 |
@@ -538,7 +538,7 @@ process.on('SIGTERM', async () => {
538
538
  | `mapWithConcurrency` | 有界并发 map(结果保序);`maxToolConcurrency` 的底座,也可自用 |
539
539
 
540
540
  - **取消**:`app.run(messages, { signal })` 传 `AbortSignal` —— 框架会 abort 在飞请求(内置 Anthropic / OpenAI 适配器都转发 `signal`),run 以 `stopReason='aborted'` 收尾(算失败)。`createHttpHandler` 已内置「客户端断开即中止」;`AsyncRunner.runTimeoutMs` 到点同样是**真中止**(构造期校验:必须 ≥ 0 的**有限**数 —— NaN/Infinity 会被 `setTimeout` 钳到 1ms,等于每个任务立即超时,故直接抛错;要「不限」传 0 或不设)。
541
- - **重试**:缺省自动重试可重试失败(429 / 5xx / 连接失败),指数退避 + 抖动。`retry: false` 关闭,或 `retry: { maxAttempts, baseDelayMs, maxDelayMs, jitter, onRetry }` 调参。**只在本次尝试尚未产出任何文本时重试**(已吐出的字无法撤回)。⚠️ 与底层 client 的**内置重试**叠加 —— **两条内置适配器口径一致**(`createAnthropicClient` / `createOpenAIClient` 都有 `maxRetries`,缺省 2,重试同一状态码集合 408/409/429/5xx)—— 建议二选一调(这里 `maxAttempts: 1`,或 `<适配器>({ maxRetries: 0 })`)。
541
+ - **重试**:缺省自动重试可重试失败(429 / 5xx / 连接失败),指数退避 + 抖动。`retry: false` 关闭,或 `retry: { maxAttempts, baseDelayMs, maxDelayMs, jitter, onRetry }` 调参。**只在本次尝试尚未产出任何文本时重试**(已吐出的字无法撤回)。⚠️ 与底层 client 的**内置重试**叠加 —— **两条内置适配器口径一致**(`createAnthropicClient` / `createOpenAIClient` 都有 `maxRetries`,缺省 2,重试同一状态码集合 408/409/429/5xx)—— 建议二选一调(这里 `maxAttempts: 1`,或 `<适配器>({ maxRetries: 0 })`)。`maxRetries` 在**构造期**校验:只收非负安全整数(`0` = 不重试),NaN / ±Infinity / 负数 / 小数一律抛 `TypeError` —— 判定是 `attempt >= maxRetries`,NaN 恒假、Infinity 永不达到,两者都等于**无限重试**(且静默)。
542
542
  - **流式**:`POST /run` 带 `Accept: text/event-stream` → SSE 逐帧下发(`text.delta` / `run.end` / `error`);不带该头仍回一元 JSON。
543
543
  - **工具超时 / 并发闸门**:`toolTimeoutMs` 超时**不杀 run**(该条 tool_result 记 `is_error`,模型可换路);`maxToolConcurrency` 给同回合的并行工具设上限(默认全并行)。⚠️ 超时 = **放弃等待**:`AgentTool.run` 没有 signal 参数,**副作用可能已发生**;但引擎放弃等待时会 abort `ToolRunContext.abandoned` —— 想真停的工具监听它自行收尾(框架自带的 @SubAgent / @Skill 已这么做:超时即中止子循环,capability span 以 error 收尾)。**超时判定只有一个裁判**:`toolTimeoutMs` 是唯一判据 —— 工具自带的超时(如 MCP 桥的 `timeoutMs`)在设了本项时**不参与**判定;反过来说,工具自判的超时(抛 `code='timeout'` 的错误)与引擎判的记**同一类账**(`errorKind='timeout'`),并同样回 `is_error`。
544
544
 
@@ -628,12 +628,34 @@ trace 出去之后能干什么:指标、调用树面板、调优报告、生
628
628
  | `registerDefaultTraceSink` | 注册全局默认 sink(构造期快照合并) |
629
629
  | `TraceRecorder` | 内存 recorder(一次 run 一个);`addLink(spanId, { traceId, spanId? })` 记一条跨 trace 链路(见 §6「跨进程关联」) |
630
630
  | `parseTraceparent` | 解析 W3C `traceparent` 头 → `{ traceId, spanId? }`;**非法 / 缺头一律返回 `undefined`**(不抛、不打 400)—— 结果直接交给 `traceContext` 选项,见 §6「跨进程关联」 |
631
- | `createOtlpExporter` | OTLP/JSON 导出,零依赖;选项 `OtlpExporterOptions`:`endpoint` / `headers` / `serviceName` / `timeoutMs`(单次导出超时,缺省 10000,非正数 = 不限 —— 裸 fetch 无超时,collector 半开连接会让 run 收尾永久挂起;超时按导出失败处理,不击穿 run) |
631
+ | `createOtlpExporter` | OTLP/JSON 导出,零依赖;选项见下面「`OtlpExporterOptions`」表 |
632
632
  | `metricsSink` | 指标累加器(Prometheus 文本 / OTLP metrics),满足 `TraceSink` 即接入 —— 见 §6「指标」 |
633
633
  | `buildRunReport` | 从一条 trace 生成**调优报告**(能力/模型的耗时、token、成本、错误率排行)—— 见 §6「调优报告」 |
634
634
  | `Score` | 质量评分:`{ name; value; source?; comment? }` —— LLM-judge / 人工标注 / eval 结论挂到 trace 上;约定 `value` 为 0–1(布尔结论用 0/1),`source` 记评分来源(eval 名 / `'human'` / judge 模型 id) |
635
635
  | `attachScore` | `attachScore(trace, score)`:把评分挂到 run 根 span(一条 `score` 事件,body 即 `Score`)。评分通常来自 run **之外**(跑完才评),所以走事件而非 span 字段;trace 找不到根 span 时静默忽略(观测不击穿业务) |
636
636
 
637
+ #### `OtlpExporterOptions`(`createOtlpExporter` 的选项)
638
+
639
+ | 字段 | 说明 |
640
+ |---|---|
641
+ | `endpoint` | collector 基地址(如 `http://localhost:4318`);导出即 POST `${endpoint}/v1/traces` |
642
+ | `headers` | 追加的请求头(鉴权 / 租户标) |
643
+ | `serviceName` | OTLP resource 的 `service.name`,缺省 `agentia` |
644
+ | `timeoutMs` | 单次导出请求超时(毫秒,缺省 10000,非正数 = 不限)——裸 `fetch` 没有超时,collector 半开连接会让 run 收尾**永久挂起**;超时按导出失败处理 |
645
+ | `onExportError` | 导出失败回调:给了它,**所有**失败(非 2xx / 超时 / **HTTP 200 但 collector 报部分接收**)都交给它、不再向 `TraceSink` 调用方抛;不给则维持既有行为(抛出,由 `flushSinks` 吞掉 —— 观测失败不击穿业务)。存在理由:`TraceSink` 的失败缺省是**静默**的,「导出其实少了一半数据」这类消息得有人能收到 |
646
+
647
+ 导出器的两条线缆口径(都有守卫钉着,别按直觉改):
648
+
649
+ - **enum 一律整数编码**:`status.code` = `1`(ok)/ `2`(error)、`kind` = `1`(INTERNAL)。
650
+ OTLP 规范是**明文 MUST**,且专门区别于 protobuf 的通用 JSON 映射:*「Values of enum fields
651
+ MUST be encoded as integer values… only integer enum values are allowed in OTLP JSON Protobuf
652
+ Encoding; the enum name strings MUST NOT be used.」*(曾经发的是 `'STATUS_CODE_OK'` 这种字符串,
653
+ 本地假 collector 只做 `JSON.parse`,所以一直没被发现)。**代价取决于 collector 的宽容度**:
654
+ 照规范校验的会整批拒收(数据没落库、框架只见 HTTP 200),按通用 protobuf JSON 映射的能收下。
655
+ - **HTTP 200 不等于全部接收**:collector 可以回 `200 + partialSuccess`(部分接收 / 拒收若干)。
656
+ 导出器把「**真拒收**(键在场且值 > 0)**或**非空 `errorMessage`」判为失败;`{}` 与
657
+ `rejectedSpans: 0` 属于「全部接收」的另一种写法(有 collector 恒发),不算失败。
658
+
637
659
  **评分链路**:`attachScore` 写 run 根 `score` 事件 → OTLP 导出时译为 `gen_ai.evaluation.result`
638
660
  (`gen_ai.evaluation.name` / `.score.value`,`source` / `comment` 走自有 `agentia.score.*` 键)→
639
661
  `metricsSink` 聚合成 `agentia_score` 指标族(见 §6「指标」)。eval / 在线评估怎么用见 §6「evals」与「在线评估采样」。
@@ -678,8 +700,34 @@ runner.submit(msg.value, {
678
700
  换宿主这条缝不变:gRPC 宿主把 metadata 的 `traceparent` 翻进 `options.traceContext`,
679
701
  见 §6.2「gRPC 宿主」。
680
702
 
681
- > **只做入站**:框架**不生成**出站 `traceparent`(运行中没有「当前 span」这个概念,硬造一个会是假的
682
- > spanId,比不做更糟)。要从 run 往外传,用结果里的 `runId`(== `traceId`)拼你自己的头,见 §7 已知边界。
703
+ **出站(反过来:你调别人)**:在 run 内用 `currentTraceparent()` 取当前 span 的 W3C 头,
704
+ 自己带在出站请求上 —— 下游若也是 agentia(或任何认 `traceparent` 的服务),接到的就是一条指向
705
+ **具体 span**(回合 / 能力调用)的 link,而不是只到 run 粒度:
706
+
707
+ ```ts
708
+ import { currentTraceparent } from '@migor/agentia';
709
+
710
+ @Tool({ description: '把工单交给订单服务' })
711
+ async placeOrder(input: { sku: string }) {
712
+ const tp = currentTraceparent(); // 不在 run 内 → undefined(那时不该编一个)
713
+ const res = await fetch(orderSvc, {
714
+ method: 'POST',
715
+ headers: { 'content-type': 'application/json', ...(tp ? { traceparent: tp } : {}) },
716
+ body: JSON.stringify(input),
717
+ });
718
+ return res.json();
719
+ }
720
+ ```
721
+
722
+ - **粒度**:普通工具与 `@Prompt` **不建 span**,它们的「当前 span」就是发起它们的那次 `llm.turn`;
723
+ `@Skill` / `@SubAgent` 的方法体内则是它自己的 `capability` span。内层覆盖外层。
724
+ - **不自动注入**:框架不创建出站请求,注入那一行是你自己的(同上 `fetch`;gRPC 宿主塞进 metadata)。
725
+ - 与入站同一个格式、同一份 id 投影:`currentTraceparent()` 的输出喂回 `parseTraceparent()` 逐字还原,
726
+ 下游 OTLP 里看到的 span id 与本地 collector 里的是**同一个数**(见 §7 已知边界)。
727
+
728
+ > **出站的边界(如实)**:`run` 根 span 由 `runAgent` 打开,所以比它更早的环节 ——
729
+ > `contextInit`、记忆水合(`MemoryStore.load`)—— `currentTraceparent()` 返回 `undefined`:
730
+ > 那时确实还没有 span 可指。flags 位恒 `00`(本框架**不采样**,不替下游声明「已采样」)。
683
731
 
684
732
  #### 指标(从 trace 派生)
685
733
 
@@ -1206,6 +1254,7 @@ const callable = {
1206
1254
  | `strict` 只是透传 | 框架**不校验** schema 的合规性(是否 `additionalProperties:false` 等) |
1207
1255
  | schema 校验是**子集** | 只覆盖 `type/properties/required/additionalProperties/enum/items`;`format`/`minimum`/`oneOf` 一律放行 |
1208
1256
  | 历史畸形就放弃裁剪 | `trimToolPairs` 遇到非严格交替历史会整体放弃(宁可少裁,也不切出孤立 tool_use 让请求 400) |
1257
+ | 同键去重的能力边界 | `idempotencyKey` 的去重分三档:**同步 store** 下 `submit` 当场返回既有记录;**异步 store**(Redis / SQLite 等)下 `submit` 是同步门面、无法 await,去重靠**进程内认领表**,只覆盖「**同进程内并发提交**」(2026-09-21 修复前这里会两次都执行);**跨进程并发**与**终态之后重提同键**仍是 at-least-once —— store 的 idem 索引是 last-wins(重提即新任务,`redisStore` / `fsStore` / `sqliteStore` 头注释同口径)。要严格一次,请让副作用自身幂等(或在 store 层做唯一约束) |
1209
1258
  | 缺省内存 store 不淘汰 | 长跑宿主请设 `InMemoryTaskStore({ maxRecords })` 或换 `FileTaskStore` / `SqliteTaskStore` |
1210
1259
  | 能力引用两种粒度 | `tools` 写 **provider token** = 整片能力菜单;写 `'<token>/<能力名>'` = 只引单个能力(@Tool/@Skill/@SubAgent/@Prompt 都可点名,装配期校验,名字不存在即抛错并列出可用名单) |
1211
1260
  | 能力名有格式校验 | 装饰器能力名(`name` 或缺省的方法名)必须匹配 `^[A-Za-z0-9_-]{1,64}$`(与 MCP 桥同口径),非法名在 `createApp` **装配期即抛错** —— 含空格/点/中文的名字会让模型 API 400,宁可在启动期拦住 |
@@ -1233,6 +1282,7 @@ const callable = {
1233
1282
  | MCP 只做 tools | `sampling`(server 反向请求模型)/ `resources` / `prompts` 原语不做;出厂连接器同样只做 `tools/list` + `tools/call` |
1234
1283
  | MCP 的协议层错误框架看不见 | `isError: true` 只有连接器能看见 —— 它必须转成抛错,否则模型收到的是一条「成功」的结果(出厂连接器已代你处理) |
1235
1284
  | MCP 超时同样是「不等了」 | 桥的 `timeoutMs` 取消不了 server 侧执行(拿不到取消句柄);它只是**兜底** —— 引擎设了 `toolTimeoutMs` 时**不参与**判定(一次调用只有一个裁判;**显式 `toolTimeoutMs: 0` 也算设了** —— 那是引擎表态「不限」,桥不会再自作主张判 60s),两条路径**同判定、同账**(`errorKind='timeout'`) |
1285
+ | 已中止的 MCP 调用**不发请求** | 信号在**发送前**就已中止 ⇒ 立刻以 `AbortError` 收场,请求不出门(2026-09-21 前是「照样 write、Promise 永不 settle」:副作用真送达、调用方永久挂起)。发送**之后**才中止的,请求已在路上、取消不了 —— 那是「不等了」,与 `toolTimeoutMs` 同口径 |
1236
1286
  | MCP 连接器的超时只管装配期 | 连接器自带的 `timeoutMs` 只作用于**握手 + `tools/list`**(那两步**没有任何别的裁判** —— server 卡住会让 `createApp` 永久挂起);`callTool` 仍是引擎 / 桥那一个裁判 |
1237
1287
  | MCP 连接的 `close()` 保证子进程已终止 | stdio 先 `SIGTERM`、`MCP_CLOSE_GRACE_MS`(2000 ms)后 `SIGKILL`,然后**等真正的 `'exit'`** —— **返回即代表进程已被回收**(此前到点即返回,会留孤儿进程而调用方无从知晓);HTTP 尽力 `DELETE` 会话(server 不认也无所谓) |
1238
1288
  | StreamableHTTP 会话过期**自愈** | 带会话 id 收到 `404` = 会话已终止、**该请求未被 server 执行** ⇒ 丢会话 → 重新握手 → 把**这一次**重试一次(**只一次**,不再循环)。自愈本身是静默的 ⇒ 用 `onSessionExpired` 去计数 / 告警,否则它和「静默失效」在监控上看不出区别。`404` **之外**的失败仍按 `classifyError` 分流抛出,不重试 |
@@ -1240,7 +1290,7 @@ const callable = {
1240
1290
  | MCP 工具不能进 DI 容器 | 它没有 provider token,也不能被别的能力的 `tools` 引用(两种引用粒度都要先有 token) |
1241
1291
  | 指标分位是窗口内精确值 | `*_last{quantile=...}` 只反映最近 `windowSize`(缺省 1024)条样本;要跨实例聚合请用直方图(`*_bucket` / `_sum` / `_count`,累积语义) |
1242
1292
  | 指标是**进程内**累加 | 不做分布式聚合与持久化:多实例各算各的(直方图可相加),重启即清零。要长期保留请把 `render()` 抓走或用 `export:'otlp'` 推给采集端 |
1243
- | OTLP metrics 只推当前累计 | 按 `intervalMs` 周期导出**累积值**(CUMULATIVE),不做增量/背压;导出失败按 `onExportError` 处理(缺省吞掉,不重试、不阻塞 run) |
1293
+ | OTLP metrics 只推当前累计 | 按 `intervalMs` 周期导出**累积值**(CUMULATIVE),不做增量/背压;导出失败按 `onExportError` 处理(缺省吞掉,不重试、不阻塞 run)。`reset()` 语义是**开启新窗口**:计数清零**且**数据点起点前移(同一 `startTime` 下 counter 只能单调不减,只清零会让后端算出负增量或丢样本) |
1244
1294
  | `GET /metrics` 不鉴权 | 与 `/healthz` 同档(拉取端在集群内网)。要保护请放反代之后,或不传 `metrics` 选项自行在外层挂路由 |
1245
1295
  | 工具没有 token/成本指标 | 工具是**你的代码**、本身不消耗 token,所以只产出调用数/失败数/耗时;token 与成本只对 `skill`/`subagent`(有 `capability` span)与模型维度产出 |
1246
1296
  | `@Prompt` 没有能力指标 | 资产类能力不建 span、无独立耗时,故不出现在能力排行里(这是刻意的:硬凑一个假耗时会误导调优) |
@@ -1250,7 +1300,7 @@ const callable = {
1250
1300
  | `agentia harvest` 的产物是轨迹骨架 | trace **不记 assistant 文本**(llm.turn 只记 usage/事件),故 harvest 用例脚本里的 text 块是占位、预填 `expect` 是从原 trace 抄录的实际轨迹 —— 脚手架不是成品,人工核对后再进 CI(见 §6「线上 trace 回流」) |
1251
1301
  | 分叉重放不是续跑 | `forkMessages` 与 `traceToMessages` / harvest **同源有损**:trace 不记 assistant 文本与 run 原始输入(重放里 assistant 是标注占位、首尾 user 是合成),也不记 blackboard(分叉种子经 `RunInvocationOptions.blackboard` 自带);它产出喂回 `app.run` 的 messages、起的是**新 run**,不是接着原 run 的循环位置跑 |
1252
1302
  | 评分来自 run 之外 | `Score` 走 run 根 `score` **事件**而非 span 字段(评分通常在 run 跑完后才产生);`attachScore` 找不到根 span 时静默忽略,多次调用即多条事件(不同维度各记各的) |
1253
- | 链路关联只做**入站** | `traceContext` / `traceparent` 头只把**上游**接进来(run 根的 `links`);框架**不生成**出站 `traceparent` —— 运行中没有「当前 span」可导出,硬造会给出假 spanId。要从 run 往外传,用 `result.trace.traceId`(== `runId`)自行拼头。另:link 只落在 run 根(子 span 不散),且**一进程内**不跨进程自动传播 —— 队列场景要自己把 `traceContext` 传下去(HTTP 头带走,或随 `TaskRecord.spec.options` 落库) |
1303
+ | 链路关联:入站自动、**出站只给读取器** | `traceContext` / `traceparent` 头把**上游**接进来(run 根的 `links`);出站方向给 `currentTraceparent()`(当前 span 的 W3C 串,回合 / 能力调用粒度),但框架**不替你做注入** —— 它不创建出站请求,那一行由宿主的 `fetch` / metadata 自己写。两个边界:① `run` 根 span 由 `runAgent` 打开 ⇒ 更早的 `contextInit` / 记忆水合取到 `undefined`(那时确实没有 span);② flags 恒 `00`(本框架不采样)。id 宽度经**同一份投影**压到 16 位(与 OTLP 导出共用,单一真源)—— 故下游收到的 span id 与 collector 里的是同一个数。另:link 只落在 run 根(子 span 不散),且**一进程内**不跨进程自动传播 —— 队列场景要自己把 `traceContext` 传下去(HTTP 头带走,或随 `TaskRecord.spec.options` 落库) |
1254
1304
  | 配额不是框架子系统 | 只给缝(middleware + TraceSink + BudgetGuard),计数放哪(内存 / Redis / DB)与超限怎么办都是你的策略 |
1255
1305
  | 人工审批两种形态 | 进程内闸门用 `middleware`(`await` 决策再放行);跨进程耐久审批用 `@Tool({ approval: 'required' })` + `POST /tasks/:id/approve`(挂起/恢复,见 §6.6「人工审批」) |
1256
1306
  | 审批超时是**惰性**判定 | `approvalTimeoutMs` 不起定时器:`approve` / `poll` / `resumePending` 读到过期挂起任务时才自动全拒并重派 —— 没人读的任务不会自己超时(要定期扫就调 `resumePending()`) |
@@ -25,6 +25,15 @@ export declare class TimeoutError extends Error {
25
25
  readonly code: 'timeout';
26
26
  constructor(message: string);
27
27
  }
28
+ /**
29
+ * 造一个「已取消」错误:`name === 'AbortError'`(**不是** `TimeoutError` —— 取消不是超时,
30
+ * `engine/errors.ts` 按 `name` 把它归进 aborted,loop 据此以 `aborted` 收尾)。
31
+ *
32
+ * 为什么要导出:这个形状此前**只**活在 `interruptibleSleep` 内部,于是别处需要「以取消收场」
33
+ * 时只能各写各的(写成 `TimeoutError` 或干脆不 settle)。MCP stdio 桥的「已中止就不该发请求」
34
+ * 正是这种场景(2026-09-21 外部复核),两处共用一份形状,免得口径漂开。
35
+ */
36
+ export declare function abortError(message?: string): Error;
28
37
  /**
29
38
  * 是否超时错误。三条判据(任一条成立即算,**全部是鸭子类型** —— 使用者不必 import 本模块):
30
39
  *
@@ -28,6 +28,17 @@ export class TimeoutError extends Error {
28
28
  this.name = 'TimeoutError';
29
29
  }
30
30
  }
31
+ /**
32
+ * 造一个「已取消」错误:`name === 'AbortError'`(**不是** `TimeoutError` —— 取消不是超时,
33
+ * `engine/errors.ts` 按 `name` 把它归进 aborted,loop 据此以 `aborted` 收尾)。
34
+ *
35
+ * 为什么要导出:这个形状此前**只**活在 `interruptibleSleep` 内部,于是别处需要「以取消收场」
36
+ * 时只能各写各的(写成 `TimeoutError` 或干脆不 settle)。MCP stdio 桥的「已中止就不该发请求」
37
+ * 正是这种场景(2026-09-21 外部复核),两处共用一份形状,免得口径漂开。
38
+ */
39
+ export function abortError(message = '已被取消') {
40
+ return Object.assign(new Error(message), { name: 'AbortError' });
41
+ }
31
42
  /**
32
43
  * 是否超时错误。三条判据(任一条成立即算,**全部是鸭子类型** —— 使用者不必 import 本模块):
33
44
  *
@@ -150,15 +161,14 @@ export function interruptibleSleep(ms, signal, abortMessage = '已被取消') {
150
161
  if (ms <= 0)
151
162
  return Promise.resolve();
152
163
  return new Promise((resolve, reject) => {
153
- const abortError = () => Object.assign(new Error(abortMessage), { name: 'AbortError' });
154
164
  // 已中止:立即 reject(此处 timer 尚未创建,绝不能去 clear)
155
165
  if (signal?.aborted) {
156
- reject(abortError());
166
+ reject(abortError(abortMessage));
157
167
  return;
158
168
  }
159
169
  function onAbort() {
160
170
  clearTimeout(timer);
161
- reject(abortError());
171
+ reject(abortError(abortMessage));
162
172
  }
163
173
  const timer = setTimeout(() => {
164
174
  signal?.removeEventListener('abort', onAbort);
@@ -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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"}
@@ -70,6 +70,31 @@ export interface SpanLink {
70
70
  * 版本号非 `00` 时按 W3C「兼容未来」规则接受(只认前四段语义)。
71
71
  */
72
72
  export declare function parseTraceparent(value: string | null | undefined): TraceContext | undefined;
73
+ /**
74
+ * 内部 id → **线缆形态**(W3C `traceparent` 与 OTLP 通用)。
75
+ *
76
+ * 内部 id 一律 UUID(去横线 32-hex),而线上两份契约都要求 trace 16 字节(32-hex)、
77
+ * span **8 字节(16-hex)** —— 宽度不同,不能共用。原样发出去会被判 `invalid span_id`
78
+ * (拒收)或按前 16 位截断。故 trace 侧去横线即可、span 侧必须截到 16 位。
79
+ *
80
+ * ⚠️ **单一真源**:OTLP 导出(`integrations/otlp.ts`)与出站 `formatTraceparent` 必须
81
+ * 走**同一份**投影。各写一份的后果不是「风格不统一」,而是**同一次调用在两个系统里
82
+ * 是两个 span id** —— 跨系统关联最不能出的错。要改这里,先看 `tests/integrations/otlp.test.ts`
83
+ * 的「导出与出站同数」用例。
84
+ *
85
+ * 幂等:已经是 32-hex(trace)/ 16-hex(span)的输入原样通过(上游 span id 被再次转发不变形)。
86
+ */
87
+ export declare function wireTraceId(id: string): string;
88
+ export declare function wireSpanId(id: string): string;
89
+ /**
90
+ * 生成 W3C `traceparent`(`parseTraceparent` 的镜像:一个解析、一个生成)。
91
+ *
92
+ * flags 位恒为 `00`:本框架**不采样**(每次 run 全量记账),故没有「已采样」可声明 ——
93
+ * 编一个 `01` 是替下游做决定。入站侧 `parseTraceparent` 也从不读 flags。
94
+ *
95
+ * 调用方保证给的是内部 id 或线缆 id(本函数只做投影,不做合法性判定)。
96
+ */
97
+ export declare function formatTraceparent(traceId: string, spanId: string): string;
73
98
  export interface Span {
74
99
  spanId: SpanId;
75
100
  traceId: TraceId;
@@ -26,6 +26,37 @@ export function parseTraceparent(value) {
26
26
  return undefined;
27
27
  return { traceId, spanId };
28
28
  }
29
+ /**
30
+ * 内部 id → **线缆形态**(W3C `traceparent` 与 OTLP 通用)。
31
+ *
32
+ * 内部 id 一律 UUID(去横线 32-hex),而线上两份契约都要求 trace 16 字节(32-hex)、
33
+ * span **8 字节(16-hex)** —— 宽度不同,不能共用。原样发出去会被判 `invalid span_id`
34
+ * (拒收)或按前 16 位截断。故 trace 侧去横线即可、span 侧必须截到 16 位。
35
+ *
36
+ * ⚠️ **单一真源**:OTLP 导出(`integrations/otlp.ts`)与出站 `formatTraceparent` 必须
37
+ * 走**同一份**投影。各写一份的后果不是「风格不统一」,而是**同一次调用在两个系统里
38
+ * 是两个 span id** —— 跨系统关联最不能出的错。要改这里,先看 `tests/integrations/otlp.test.ts`
39
+ * 的「导出与出站同数」用例。
40
+ *
41
+ * 幂等:已经是 32-hex(trace)/ 16-hex(span)的输入原样通过(上游 span id 被再次转发不变形)。
42
+ */
43
+ export function wireTraceId(id) {
44
+ return id.replaceAll('-', '');
45
+ }
46
+ export function wireSpanId(id) {
47
+ return id.replaceAll('-', '').slice(0, 16);
48
+ }
49
+ /**
50
+ * 生成 W3C `traceparent`(`parseTraceparent` 的镜像:一个解析、一个生成)。
51
+ *
52
+ * flags 位恒为 `00`:本框架**不采样**(每次 run 全量记账),故没有「已采样」可声明 ——
53
+ * 编一个 `01` 是替下游做决定。入站侧 `parseTraceparent` 也从不读 flags。
54
+ *
55
+ * 调用方保证给的是内部 id 或线缆 id(本函数只做投影,不做合法性判定)。
56
+ */
57
+ export function formatTraceparent(traceId, spanId) {
58
+ return `00-${wireTraceId(traceId)}-${wireSpanId(spanId)}-00`;
59
+ }
29
60
  /**
30
61
  * 把评分挂到 trace 根 span(一条 `score` 事件,body 即 Score)。
31
62
  * trace 找不到根 span 时静默忽略(观测不击穿业务);多次调用即多条事件(不同维度各记各的)。
@@ -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;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;;;;;;;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,9 +1,11 @@
1
1
  import { createAnthropicClient } from '../integrations/anthropic.js';
2
+ import { withCurrentSpan } from './span-scope.js';
2
3
  import { abortedResult, failedResult, finishedResult, suspendedResult } from './loop-result.js';
3
4
  import { tailToolUses, textOfParam } from './resume-input.js';
4
5
  import { DEFAULT_MAX_ITERATIONS, DEFAULT_MAX_TOKENS, resolveDefaultModel, runConfigSnapshot, } from './run-config.js';
5
6
  import { TraceRecorder } from './tracer.js';
6
- import { abortedError, budgetError, buildLoopContext, checkTurnEntry, executeTurnTools, recordTurnUsage, streamTurn, textOf, } from './turn.js';
7
+ import { abortedError, budgetError, buildLoopContext, checkTurnEntry, executeTurnTools, recordTurnUsage, streamTurn, } from './turn.js';
8
+ import { textOf } from './text.js';
7
9
  import { resolveStopReason } from './stop-reason.js';
8
10
  import { isSuccessStopReason } from './types.js';
9
11
  /**
@@ -194,7 +196,9 @@ export async function runAgent(options) {
194
196
  const progress = { iterations: 0 };
195
197
  let result;
196
198
  try {
197
- result = await agentLoop({
199
+ // run 根作用域(spec §9.2 出站传播):循环内任何地方(工具 / 子能力 / 中间件)都读得到
200
+ // 「我正处在哪个 span」—— 更内层的作用域由 turn / skill / subagent 逐层收窄。
201
+ result = await withCurrentSpan({ traceId: recorder.traceId, spanId: rootId }, () => agentLoop({
198
202
  client: options.client ?? createAnthropicClient(),
199
203
  model: resolveDefaultModel(options.model),
200
204
  maxTokens: options.maxTokens ?? DEFAULT_MAX_TOKENS,
@@ -219,7 +223,7 @@ export async function runAgent(options) {
219
223
  priceOverrides: options.priceOverrides,
220
224
  onUnpricedModel: options.onUnpricedModel,
221
225
  approvals: options.approvals,
222
- });
226
+ }));
223
227
  }
224
228
  catch (e) {
225
229
  // 硬写 0 会把「第 3 回合请求失败」报成「一次模型都没调」——按实际进度报
@@ -1 +1 @@
1
- {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/engine/loop.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/engine/loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { type SpanId } from '../core/trace.js';
2
+ /**
3
+ * Agentia —— **调用期**「当前 span」作用域(spec §9.2 出站传播)。
4
+ *
5
+ * 为什么不是 run 级:run 级 ALS 只有一个值,并行工具调用会互相覆盖 ⇒ 父子关系错。
6
+ * spec §9.2 正是因此锁定「span 句柄**不放** `RunContext`」(那里只有 blackboard)。
7
+ * 这里**每次调用一份** —— `withCurrentSpan` 进入的是该次调用的 async 上下文,
8
+ * 并行调用天然互不干扰(`tests/engine/spanScope.test.ts` 钉着这条)。
9
+ *
10
+ * 写入点由粗到细三层,内层覆盖外层:
11
+ * - `run` 根 —— `engine/loop.ts` 包住整轮循环;
12
+ * - `llm.turn` —— `engine/turn.ts` 包住每次工具调用(普通工具与 `@Prompt` **刻意不建 span**,
13
+ * 它们的「当前 span」就是发起它的那个回合,与 `ToolRunContext.parentSpanId` 同一个值);
14
+ * - `capability` —— `toolkit/skill.ts` / `toolkit/subagent.ts` 包住自己的方法体 / 子循环。
15
+ *
16
+ * 边界(如实):`run` 根 span 由 `runAgent` 打开,故 `executeRun` 里更早的 `contextInit` /
17
+ * 记忆水合**没有**作用域 —— 那时确实还没有 span 可指,`currentTraceparent()` 返回 `undefined`。
18
+ */
19
+ /** 作用域内容:一次调用同时知道自己是哪条 trace 的哪个 span(两件都要,才能编出合法头) */
20
+ export interface SpanScope {
21
+ traceId: string;
22
+ spanId: SpanId;
23
+ }
24
+ /**
25
+ * 在指定 span 作用域内执行。返回类型随 fn 而定(async fn → Promise<T>,同步 fn → T)。
26
+ *
27
+ * 传的是**值**而不是「读 ctx」:写入者手上只有 recorder 与 span id,这里不去反向依赖
28
+ * runtime 的 `RunContext`(`engine` 不能引 `runtime`,分层单向)。
29
+ */
30
+ export declare function withCurrentSpan<T>(scope: SpanScope, fn: () => Promise<T>): Promise<T>;
31
+ export declare function withCurrentSpan<T>(scope: SpanScope, fn: () => T): T;
32
+ /** 当前调用期的 span 作用域;不在任何 run / 调用内时 undefined。 */
33
+ export declare function currentSpan(): SpanScope | undefined;
34
+ /**
35
+ * 当前调用期的 W3C `traceparent`(**公共 API**,spec §9.2 出站传播)。
36
+ *
37
+ * 玩法:在自己发起的出站请求里带上它,下游就能把「谁触发了这次调用」记成一条指向
38
+ * **具体 span** 的 link(粒度到 turn / capability,不再是 run 级)。
39
+ *
40
+ * ```ts
41
+ * await fetch(url, { headers: { traceparent: currentTraceparent()! } });
42
+ * ```
43
+ *
44
+ * - 不在 run 内、或在 `run` 根 span 打开之前的环节(`contextInit` / 记忆水合)→ `undefined`;
45
+ * - flags 位恒 `00`:本框架不采样,不替下游声明「已采样」;
46
+ * - 框架**不替你做**出站注入(它不创建出站请求)—— 这一行是你自己的。
47
+ */
48
+ export declare function currentTraceparent(): string | undefined;
@@ -0,0 +1,31 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import { formatTraceparent } from '../core/trace.js';
3
+ const store = new AsyncLocalStorage();
4
+ export function withCurrentSpan(scope, fn) {
5
+ return store.run(scope, fn);
6
+ }
7
+ /** 当前调用期的 span 作用域;不在任何 run / 调用内时 undefined。 */
8
+ export function currentSpan() {
9
+ return store.getStore();
10
+ }
11
+ /**
12
+ * 当前调用期的 W3C `traceparent`(**公共 API**,spec §9.2 出站传播)。
13
+ *
14
+ * 玩法:在自己发起的出站请求里带上它,下游就能把「谁触发了这次调用」记成一条指向
15
+ * **具体 span** 的 link(粒度到 turn / capability,不再是 run 级)。
16
+ *
17
+ * ```ts
18
+ * await fetch(url, { headers: { traceparent: currentTraceparent()! } });
19
+ * ```
20
+ *
21
+ * - 不在 run 内、或在 `run` 根 span 打开之前的环节(`contextInit` / 记忆水合)→ `undefined`;
22
+ * - flags 位恒 `00`:本框架不采样,不替下游声明「已采样」;
23
+ * - 框架**不替你做**出站注入(它不创建出站请求)—— 这一行是你自己的。
24
+ */
25
+ export function currentTraceparent() {
26
+ const scope = store.getStore();
27
+ if (!scope)
28
+ return undefined;
29
+ return formatTraceparent(scope.traceId, scope.spanId);
30
+ }
31
+ //# sourceMappingURL=span-scope.js.map