@migor/agentia 0.9.4 → 0.9.5
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.
- package/CHANGELOG.md +688 -4
- package/README.md +1 -1
- package/dist/AGENTS.md +313 -33
- package/dist/container/container.js +15 -0
- package/dist/container/container.js.map +1 -1
- package/dist/core/limits.d.ts +93 -13
- package/dist/core/limits.js +103 -13
- package/dist/core/limits.js.map +1 -1
- package/dist/core/line-framing.d.ts +36 -0
- package/dist/core/line-framing.js +39 -0
- package/dist/core/line-framing.js.map +1 -0
- package/dist/core/message.d.ts +11 -0
- package/dist/core/run.d.ts +68 -4
- package/dist/core/run.js +27 -1
- package/dist/core/run.js.map +1 -1
- package/dist/core/schema.js +59 -8
- package/dist/core/schema.js.map +1 -1
- package/dist/core/timeout.d.ts +43 -1
- package/dist/core/timeout.js +76 -3
- package/dist/core/timeout.js.map +1 -1
- package/dist/core/tool.d.ts +25 -1
- package/dist/core/trace.d.ts +40 -1
- package/dist/core/trace.js +26 -0
- package/dist/core/trace.js.map +1 -1
- package/dist/engine/defer.d.ts +49 -0
- package/dist/engine/defer.js +72 -0
- package/dist/engine/defer.js.map +1 -0
- package/dist/engine/forwarded.d.ts +14 -5
- package/dist/engine/forwarded.js +4 -1
- package/dist/engine/forwarded.js.map +1 -1
- package/dist/engine/loop-result.d.ts +65 -7
- package/dist/engine/loop-result.js +24 -5
- package/dist/engine/loop-result.js.map +1 -1
- package/dist/engine/loop.d.ts +2 -0
- package/dist/engine/loop.js +157 -17
- package/dist/engine/loop.js.map +1 -1
- package/dist/engine/mcp-server-http.d.ts +2 -0
- package/dist/engine/mcp-server-http.js +215 -0
- package/dist/engine/mcp-server-http.js.map +1 -0
- package/dist/engine/mcp-server-stdio.d.ts +15 -0
- package/dist/engine/mcp-server-stdio.js +106 -0
- package/dist/engine/mcp-server-stdio.js.map +1 -0
- package/dist/engine/mcp-server.d.ts +134 -0
- package/dist/engine/mcp-server.js +232 -0
- package/dist/engine/mcp-server.js.map +1 -0
- package/dist/engine/menu-drift.d.ts +34 -0
- package/dist/engine/menu-drift.js +81 -0
- package/dist/engine/menu-drift.js.map +1 -0
- package/dist/engine/policy.d.ts +2 -1
- package/dist/engine/policy.js +7 -1
- package/dist/engine/policy.js.map +1 -1
- package/dist/engine/replay.d.ts +2 -1
- package/dist/engine/replay.js +3 -2
- package/dist/engine/replay.js.map +1 -1
- package/dist/engine/resume-input.d.ts +10 -0
- package/dist/engine/resume-input.js +11 -0
- package/dist/engine/resume-input.js.map +1 -1
- package/dist/engine/run-config.d.ts +26 -2
- package/dist/engine/run-config.js +60 -0
- package/dist/engine/run-config.js.map +1 -1
- package/dist/engine/spec.d.ts +33 -4
- package/dist/engine/spec.js.map +1 -1
- package/dist/engine/tool-context.d.ts +10 -5
- package/dist/engine/tool-context.js +5 -1
- package/dist/engine/tool-context.js.map +1 -1
- package/dist/engine/tracer.d.ts +43 -5
- package/dist/engine/tracer.js +73 -10
- package/dist/engine/tracer.js.map +1 -1
- package/dist/engine/trimming.js +28 -2
- package/dist/engine/trimming.js.map +1 -1
- package/dist/engine/turn.d.ts +60 -3
- package/dist/engine/turn.js +180 -71
- package/dist/engine/turn.js.map +1 -1
- package/dist/engine/types.d.ts +89 -3
- package/dist/engine/types.js +38 -2
- package/dist/engine/types.js.map +1 -1
- package/dist/eval/export.d.ts +48 -0
- package/dist/eval/export.js +146 -0
- package/dist/eval/export.js.map +1 -0
- package/dist/eval/harvest.js +7 -2
- package/dist/eval/harvest.js.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/adapter-options.d.ts +22 -0
- package/dist/integrations/adapter-options.js +51 -0
- package/dist/integrations/adapter-options.js.map +1 -1
- package/dist/integrations/anthropic.d.ts +4 -2
- package/dist/integrations/anthropic.js +27 -27
- package/dist/integrations/anthropic.js.map +1 -1
- package/dist/integrations/file-sink.d.ts +20 -0
- package/dist/integrations/file-sink.js +27 -0
- package/dist/integrations/file-sink.js.map +1 -0
- package/dist/integrations/mcp-http.d.ts +3 -3
- package/dist/integrations/mcp-http.js +1 -1
- package/dist/integrations/mcp-http.js.map +1 -1
- package/dist/integrations/mcp-protocol.d.ts +115 -0
- package/dist/integrations/mcp-protocol.js +69 -0
- package/dist/integrations/mcp-protocol.js.map +1 -0
- package/dist/integrations/mcp-stdio.d.ts +3 -3
- package/dist/integrations/mcp-stdio.js +17 -3
- package/dist/integrations/mcp-stdio.js.map +1 -1
- package/dist/integrations/mcp.d.ts +6 -95
- package/dist/integrations/mcp.js +24 -66
- package/dist/integrations/mcp.js.map +1 -1
- package/dist/integrations/metrics-otlp.js +52 -7
- package/dist/integrations/metrics-otlp.js.map +1 -1
- package/dist/integrations/metrics-render.d.ts +15 -0
- package/dist/integrations/metrics-render.js +79 -2
- package/dist/integrations/metrics-render.js.map +1 -1
- package/dist/integrations/metrics-state.d.ts +99 -1
- package/dist/integrations/metrics-state.js +128 -4
- package/dist/integrations/metrics-state.js.map +1 -1
- package/dist/integrations/metrics.d.ts +62 -6
- package/dist/integrations/metrics.js +49 -8
- package/dist/integrations/metrics.js.map +1 -1
- package/dist/integrations/openai.js +9 -31
- package/dist/integrations/openai.js.map +1 -1
- package/dist/integrations/otlp.d.ts +3 -3
- package/dist/integrations/report.d.ts +7 -0
- package/dist/integrations/report.js +20 -1
- package/dist/integrations/report.js.map +1 -1
- package/dist/runtime/memory.d.ts +61 -1
- package/dist/runtime/memory.js +47 -7
- package/dist/runtime/memory.js.map +1 -1
- package/dist/runtime/run.d.ts +12 -2
- package/dist/runtime/run.js +112 -15
- package/dist/runtime/run.js.map +1 -1
- package/dist/store/fsStore.js +10 -4
- package/dist/store/fsStore.js.map +1 -1
- package/dist/store/record.d.ts +41 -0
- package/dist/store/record.js +54 -0
- package/dist/store/record.js.map +1 -0
- package/dist/store/redisStore.d.ts +3 -1
- package/dist/store/redisStore.js +21 -7
- package/dist/store/redisStore.js.map +1 -1
- package/dist/store/sqliteStore.d.ts +23 -0
- package/dist/store/sqliteStore.js +103 -8
- package/dist/store/sqliteStore.js.map +1 -1
- package/dist/store/store.d.ts +65 -2
- package/dist/store/store.js +5 -2
- package/dist/store/store.js.map +1 -1
- package/dist/toolkit/capability-cycles.d.ts +50 -0
- package/dist/toolkit/capability-cycles.js +88 -0
- package/dist/toolkit/capability-cycles.js.map +1 -0
- package/dist/toolkit/capability-slice.d.ts +86 -0
- package/dist/toolkit/capability-slice.js +98 -0
- package/dist/toolkit/capability-slice.js.map +1 -0
- package/dist/toolkit/module.d.ts +7 -1
- package/dist/toolkit/module.js +65 -32
- package/dist/toolkit/module.js.map +1 -1
- package/dist/transport/approval-policy.d.ts +1 -1
- package/dist/transport/approval-policy.js +8 -4
- package/dist/transport/approval-policy.js.map +1 -1
- package/dist/transport/async.d.ts +197 -18
- package/dist/transport/async.js +871 -85
- package/dist/transport/async.js.map +1 -1
- package/dist/transport/drain-gate.d.ts +6 -2
- package/dist/transport/drain-gate.js +14 -2
- package/dist/transport/drain-gate.js.map +1 -1
- package/dist/transport/http-endpoints.d.ts +151 -0
- package/dist/transport/http-endpoints.js +480 -0
- package/dist/transport/http-endpoints.js.map +1 -0
- package/dist/transport/http-io.d.ts +66 -0
- package/dist/transport/http-io.js +145 -0
- package/dist/transport/http-io.js.map +1 -0
- package/dist/transport/http-route.d.ts +10 -3
- package/dist/transport/http-route.js +18 -3
- package/dist/transport/http-route.js.map +1 -1
- package/dist/transport/http-shapes.d.ts +11 -0
- package/dist/transport/http-shapes.js +31 -1
- package/dist/transport/http-shapes.js.map +1 -1
- package/dist/transport/http.d.ts +22 -35
- package/dist/transport/http.js +98 -476
- package/dist/transport/http.js.map +1 -1
- package/dist/transport/owner-id.d.ts +29 -0
- package/dist/transport/owner-id.js +46 -0
- package/dist/transport/owner-id.js.map +1 -0
- package/dist/transport/owner-liveness.d.ts +8 -0
- package/dist/transport/owner-liveness.js +56 -0
- package/dist/transport/owner-liveness.js.map +1 -0
- package/dist/transport/resume-policy.d.ts +48 -10
- package/dist/transport/resume-policy.js +25 -10
- package/dist/transport/resume-policy.js.map +1 -1
- package/dist/transport/scheduler.js +9 -23
- package/dist/transport/scheduler.js.map +1 -1
- package/dist/transport/slot-pool.d.ts +9 -1
- package/dist/transport/slot-pool.js +9 -1
- package/dist/transport/slot-pool.js.map +1 -1
- package/dist/transport/task-events.d.ts +34 -3
- package/dist/transport/task-events.js +86 -5
- package/dist/transport/task-events.js.map +1 -1
- package/dist/transport/wake-policy.d.ts +50 -0
- package/dist/transport/wake-policy.js +43 -0
- package/dist/transport/wake-policy.js.map +1 -0
- package/package.json +6 -4
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { MessageParam } from '../core/message.js';
|
|
2
|
+
import type { Trace } from '../core/trace.js';
|
|
3
|
+
/**
|
|
4
|
+
* Agentia —— trace → 训练数据导出(R8-P3b,质量闭环的另一半)。
|
|
5
|
+
*
|
|
6
|
+
* `exportRun` 把一条完成的 trace 翻成一份**训练数据记录**(`{ messages, meta }`),
|
|
7
|
+
* CLI `agentia export` 在它的外面包文件读写与过滤(--min-score / --ok-only / --out)。
|
|
8
|
+
* 纯函数:不写文件、不联网。
|
|
9
|
+
*
|
|
10
|
+
* ⚠️ module 级 export,刻意不进 src/index.ts 公共面(与 harvestEvalCase 同款纪律,
|
|
11
|
+
* 见 AGENTS.md「内部工具不进公共面」;CLI 侧是去类型移植副本,逐字对拍守护)。
|
|
12
|
+
*
|
|
13
|
+
* 诚实边界(缺席一律进 `meta.incomplete`,不静默):
|
|
14
|
+
* - trace 不记 run 的**原始输入** ⇒ messages 首条 user 是占位,标 `incomplete: ['input']`;
|
|
15
|
+
* - assistant 文本只在 run 开了 `traceContent: 'full'`(R8-P3a)时有真值
|
|
16
|
+
* (llm.turn 的 `output.text` 属性);缺了**不造占位文本**(占位文本进训练数据是
|
|
17
|
+
* 投毒)—— 该回合的 assistant 消息只剩 tool_use 块,并标 `incomplete`;
|
|
18
|
+
* - 只重建**直属 run 根**的主循环回合(子 agent 嵌套回合不进主线 —— 它们的能力出参
|
|
19
|
+
* 已在主线里;数量记在 `meta.nestedTurns`,与 harvest 同口径);
|
|
20
|
+
* - tool_use ↔ tool_result 按 `tool_use_id` 配对;缺输出的补 is_error 占位(协议要求
|
|
21
|
+
* 配对合法),有输出没配对的跳过并计数(`meta.droppedOutputs`)—— 都不静默。
|
|
22
|
+
*/
|
|
23
|
+
export interface ExportRecordMeta {
|
|
24
|
+
traceId: string;
|
|
25
|
+
/** run 根的 model / stop_reason(attributes;没有则 undefined) */
|
|
26
|
+
model: string | undefined;
|
|
27
|
+
stopReason: string | undefined;
|
|
28
|
+
/** trace.status('ok' / 'error') */
|
|
29
|
+
status: string;
|
|
30
|
+
/** run 根的 score 事件(attachScore;可能多条 —— 不同维度各记各的) */
|
|
31
|
+
scores: Array<{
|
|
32
|
+
name: string;
|
|
33
|
+
value: number;
|
|
34
|
+
}>;
|
|
35
|
+
/** 略去的子 agent 嵌套回合数(它们不进主线) */
|
|
36
|
+
nestedTurns: number;
|
|
37
|
+
/** 有 tool.output 事件但没配上本回合 tool_use 的条数(被跳过,见文件头) */
|
|
38
|
+
droppedOutputs: number;
|
|
39
|
+
/** 完整性缺口清单(空数组 = 无已知缺口);值是机器可 grep 的固定词 */
|
|
40
|
+
incomplete: string[];
|
|
41
|
+
}
|
|
42
|
+
export interface ExportRecord {
|
|
43
|
+
/** Anthropic Messages 形状(MessageParam[]):首条 user 是占位(见 incomplete) */
|
|
44
|
+
messages: MessageParam[];
|
|
45
|
+
meta: ExportRecordMeta;
|
|
46
|
+
}
|
|
47
|
+
/** 导出一条 trace 为训练数据记录(形状与纪律见文件头)。 */
|
|
48
|
+
export declare function exportRun(trace: Trace): ExportRecord;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { TOOL_INPUT_EVENT, TOOL_OUTPUT_EVENT } from '../core/trace.js';
|
|
2
|
+
import { stringifySafe } from '../core/json.js';
|
|
3
|
+
/** 原始输入占位(trace 不记 run 的原始输入 —— 与 harvest 的占位同一性质,但词不同便于区分来源) */
|
|
4
|
+
const INPUT_PLACEHOLDER = '[export] 原始输入未入 trace —— 训练前请补写真实用户输入';
|
|
5
|
+
function toolEvents(turn, name) {
|
|
6
|
+
const out = [];
|
|
7
|
+
for (const e of turn.events) {
|
|
8
|
+
if (e.name !== name)
|
|
9
|
+
continue;
|
|
10
|
+
const b = (e.body ?? {});
|
|
11
|
+
// 缺 `tool` 的事件跳过、不回填占位名(伪造的 'unknown' 会变成一个断言必然通过 /
|
|
12
|
+
// 训练必然「学会」的假工具调用 —— 与 harvest 同一条纪律)
|
|
13
|
+
if (typeof b.tool !== 'string')
|
|
14
|
+
continue;
|
|
15
|
+
out.push({
|
|
16
|
+
tool: b.tool,
|
|
17
|
+
toolUseId: typeof b.tool_use_id === 'string' ? b.tool_use_id : undefined,
|
|
18
|
+
input: b.input === undefined ? undefined : stringifySafe(b.input),
|
|
19
|
+
ok: typeof b.ok === 'boolean' ? b.ok : undefined,
|
|
20
|
+
content: b.content === undefined ? undefined : stringifySafe(b.content),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
/** 入参还原:尝试 JSON.parse 回对象,失败(或非 object)包 {_raw}(tool_use.input 必须是 object) */
|
|
26
|
+
function parseToolInput(raw) {
|
|
27
|
+
const s = raw ?? '';
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(s);
|
|
30
|
+
return typeof parsed === 'object' && parsed !== null
|
|
31
|
+
? parsed
|
|
32
|
+
: { _raw: s };
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return { _raw: s };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** 导出一条 trace 为训练数据记录(形状与纪律见文件头)。 */
|
|
39
|
+
export function exportRun(trace) {
|
|
40
|
+
const root = trace.spans.find((s) => s.spanId === trace.rootSpanId);
|
|
41
|
+
const mainTurns = trace.spans
|
|
42
|
+
.filter((s) => s.kind === 'llm.turn' && s.parentSpanId === trace.rootSpanId)
|
|
43
|
+
.sort((a, b) => a.startedAt - b.startedAt);
|
|
44
|
+
const nestedTurns = trace.spans.filter((s) => s.kind === 'llm.turn' && s.parentSpanId !== trace.rootSpanId).length;
|
|
45
|
+
const incomplete = ['input']; // 首条 user 恒为占位(trace 不记原始输入)
|
|
46
|
+
let droppedOutputs = 0;
|
|
47
|
+
let tuSeq = 0;
|
|
48
|
+
// 「本 run 压根没开 traceContent」是 run 根上的 ground truth(loop.ts 写入)。它不能直接
|
|
49
|
+
// 用来标缺口(合成 / 老 trace 可能没有这个属性,却真的有正文),只在**收尾**时与
|
|
50
|
+
// 「整棵 trace 一行正文都没有」合取使用,见下面那段。
|
|
51
|
+
const textRecorded = root?.attributes['config.traceContent'] === 'full';
|
|
52
|
+
let anyTextRecorded = false;
|
|
53
|
+
const messages = [{ role: 'user', content: INPUT_PLACEHOLDER }];
|
|
54
|
+
for (const turn of mainTurns) {
|
|
55
|
+
const content = [];
|
|
56
|
+
// assistant 文本:只记真值(output.text,R8-P3a);缺了不造占位(占位文本进训练数据是投毒)。
|
|
57
|
+
// 缺口判定:纯 tool_use 回合**本来就没文本**(引擎只在文本非空时记 output.text),
|
|
58
|
+
// 不算缺口;没有 tool_use 又没有文本的回合(终端回合)缺文本才是真缺口。
|
|
59
|
+
const inputs = toolEvents(turn, TOOL_INPUT_EVENT);
|
|
60
|
+
// ⚠️ 宽容读取(`?.`):trace 经 JSONL / 手搓对象回来时可能没有 `attributes`
|
|
61
|
+
// 字段(类型上说必填、运行时不是)—— CLI 那份移植副本一直这么读,两侧产物必须一致。
|
|
62
|
+
const text = turn.attributes?.['output.text'];
|
|
63
|
+
if (typeof text === 'string' && text !== '') {
|
|
64
|
+
anyTextRecorded = true;
|
|
65
|
+
content.push({ type: 'text', text });
|
|
66
|
+
}
|
|
67
|
+
else if (inputs.length === 0 && !incomplete.includes('assistant-text')) {
|
|
68
|
+
incomplete.push('assistant-text');
|
|
69
|
+
}
|
|
70
|
+
const usedIds = [];
|
|
71
|
+
for (const e of inputs) {
|
|
72
|
+
const id = e.toolUseId ?? `export_tu_${++tuSeq}`; // 老 trace 无 id 时合成(replay 同款)
|
|
73
|
+
usedIds.push(id);
|
|
74
|
+
content.push({ type: 'tool_use', id, name: e.tool, input: parseToolInput(e.input) });
|
|
75
|
+
}
|
|
76
|
+
if (content.length > 0)
|
|
77
|
+
messages.push({ role: 'assistant', content: content });
|
|
78
|
+
// tool_result 配对:按 tool_use_id 配本回合的 tool.output;缺输出的补 is_error 占位
|
|
79
|
+
// (协议要求每个 tool_use 都有配对 tool_result —— 残缺历史喂训练是静音投毒)
|
|
80
|
+
if (usedIds.length > 0) {
|
|
81
|
+
const outputs = toolEvents(turn, TOOL_OUTPUT_EVENT);
|
|
82
|
+
const byId = new Map(outputs.map((o) => [o.toolUseId, o]));
|
|
83
|
+
const results = [];
|
|
84
|
+
for (const [i, id] of usedIds.entries()) {
|
|
85
|
+
const out = byId.get(id) ?? (outputs[i]?.toolUseId === undefined ? outputs[i] : undefined);
|
|
86
|
+
if (out === undefined) {
|
|
87
|
+
results.push({
|
|
88
|
+
type: 'tool_result',
|
|
89
|
+
tool_use_id: id,
|
|
90
|
+
is_error: true,
|
|
91
|
+
content: '[export] 该 tool_use 的输出未入 trace(失败/截断的 run 段)',
|
|
92
|
+
});
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
results.push({
|
|
96
|
+
type: 'tool_result',
|
|
97
|
+
tool_use_id: id,
|
|
98
|
+
...(out.ok === false ? { is_error: true } : {}),
|
|
99
|
+
content: out.content ?? '',
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
// 有输出却没配上本回合任何 tool_use(id 对不上):跳过并计数,不静默丢
|
|
103
|
+
droppedOutputs += outputs.filter((o) => o.toolUseId !== undefined && !usedIds.includes(o.toolUseId)).length;
|
|
104
|
+
messages.push({ role: 'user', content: results });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// 收尾判定(2026-09-27 ⑪):整棵 trace 一行正文都没有、且本 run 没开 traceContent
|
|
108
|
+
// ⇒ 缺的不只是「终端回合那句话」:**混合回合**(模型先说一句再调工具)的真实正文同样
|
|
109
|
+
// 不在 trace 里,而只看「本回合有没有 tool_use」是判不出来的(那种回合按定义就是
|
|
110
|
+
// 「本来没文本」)。两条合取才成立:有正文就不标(合成 / 老 trace 也照顾到),
|
|
111
|
+
// 开了 traceContent 而没正文也不标(那是模型确实没说话,不是记录缺口)。
|
|
112
|
+
if (!anyTextRecorded && !textRecorded && !incomplete.includes('assistant-text')) {
|
|
113
|
+
incomplete.push('assistant-text');
|
|
114
|
+
}
|
|
115
|
+
// SFT 形状(2026-09-27 ⑫):末条是 user ⇒ 这条样本**没有 loss 目标**(训练器会静默
|
|
116
|
+
// 丢掉它),而它恰恰是「run 没有终答」的形状(半截 run / 只剩工具往返)。标注出来,
|
|
117
|
+
// 别让下游以为每条都能直接用:`--ok-only` 挡不住它 —— status ok ≠ 有终答。
|
|
118
|
+
if (messages[messages.length - 1]?.role === 'user' &&
|
|
119
|
+
!incomplete.includes('no-final-assistant')) {
|
|
120
|
+
incomplete.push('no-final-assistant');
|
|
121
|
+
}
|
|
122
|
+
const scores = [];
|
|
123
|
+
for (const e of root?.events ?? []) {
|
|
124
|
+
if (e.name !== 'score')
|
|
125
|
+
continue;
|
|
126
|
+
const b = (e.body ?? {});
|
|
127
|
+
if (typeof b.name === 'string' && typeof b.value === 'number') {
|
|
128
|
+
scores.push({ name: b.name, value: b.value });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
messages,
|
|
133
|
+
meta: {
|
|
134
|
+
traceId: trace.traceId,
|
|
135
|
+
model: typeof root?.attributes.model === 'string' ? root.attributes.model : undefined,
|
|
136
|
+
stopReason: typeof root?.attributes.stop_reason === 'string' ? root.attributes.stop_reason : undefined,
|
|
137
|
+
// `?? ''` 与 CLI 副本同款:trace 缺 status 时两侧产物必须逐字一致(对拍守着)
|
|
138
|
+
status: trace.status ?? '',
|
|
139
|
+
scores,
|
|
140
|
+
nestedTurns,
|
|
141
|
+
droppedOutputs,
|
|
142
|
+
incomplete,
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/eval/export.ts"],"names":[],"mappings":"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"}
|
package/dist/eval/harvest.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TOOL_INPUT_EVENT } from '../core/trace.js';
|
|
1
2
|
import { stringifySafe } from '../core/json.js';
|
|
2
3
|
/** trace 不记 assistant 文本 —— 脚本 text 块的统一占位(测试与 CLI 都对齐这个词) */
|
|
3
4
|
const ASSISTANT_TEXT_PLACEHOLDER = '[harvest] assistant 文本未入 trace';
|
|
@@ -5,7 +6,7 @@ const ASSISTANT_TEXT_PLACEHOLDER = '[harvest] assistant 文本未入 trace';
|
|
|
5
6
|
function toolInputsOf(turn) {
|
|
6
7
|
const out = [];
|
|
7
8
|
for (const e of turn.events) {
|
|
8
|
-
if (e.name !==
|
|
9
|
+
if (e.name !== TOOL_INPUT_EVENT)
|
|
9
10
|
continue;
|
|
10
11
|
const b = (e.body ?? {});
|
|
11
12
|
// 缺 `tool` 的事件**跳过**,不回填占位名:伪造的 'unknown' 会在生成的脚本里变成一个
|
|
@@ -137,7 +138,11 @@ export function harvestEvalCase(input) {
|
|
|
137
138
|
.join(',\n'));
|
|
138
139
|
body.push(' ]),');
|
|
139
140
|
}
|
|
140
|
-
body.push(' expect: (result, { trace }) => {', ' // 主循环实际调用过的工具名序列(直属 run 根的 llm.turn 上的 tool.input 事件)', ' const tools = trace.spans', " .filter((s) => s.kind === 'llm.turn' && s.parentSpanId === trace.rootSpanId)", ' .sort((a, b) => a.startedAt - b.startedAt)', ' .flatMap((s) =>',
|
|
141
|
+
body.push(' expect: (result, { trace }) => {', ' // 主循环实际调用过的工具名序列(直属 run 根的 llm.turn 上的 tool.input 事件)', ' const tools = trace.spans', " .filter((s) => s.kind === 'llm.turn' && s.parentSpanId === trace.rootSpanId)", ' .sort((a, b) => a.startedAt - b.startedAt)', ' .flatMap((s) =>',
|
|
142
|
+
// ⚠️ 这一行是**生成出去的代码文本**(写进 harvested 用例的源码),不是本仓的取值 ——
|
|
143
|
+
// 所以它保留字面量:生成的脚本不 import 本仓常量,改成 `TOOL_INPUT_EVENT` 会得到一个
|
|
144
|
+
// 引用了不存在标识符的脚本(跑起来才炸)。源码级守卫正是按这个理由给它白名单。
|
|
145
|
+
" s.events.filter((e) => e.name === 'tool.input').map((e) => (e.body || {}).tool),", ' );', ` assert.deepEqual(tools, ${JSON.stringify(toolSeq)});`, ' },', '}');
|
|
141
146
|
return `${head.join('\n')}\n${body.join('\n')}\n`;
|
|
142
147
|
}
|
|
143
148
|
//# sourceMappingURL=harvest.js.map
|
package/dist/eval/harvest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harvest.js","sourceRoot":"","sources":["../../src/eval/harvest.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA+BhD,8DAA8D;AAC9D,MAAM,0BAA0B,GAAG,gCAAgC,CAAC;AASpE,wDAAwD;AACxD,SAAS,YAAY,CAAC,IAAU;IAC9B,MAAM,GAAG,GAAqB,EAAE,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,IAAI,CAAC,CAAC,IAAI,KAAK,
|
|
1
|
+
{"version":3,"file":"harvest.js","sourceRoot":"","sources":["../../src/eval/harvest.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const AGENTIA_VERSION = "0.9.
|
|
1
|
+
export declare const AGENTIA_VERSION = "0.9.5";
|
|
2
2
|
export type { Trace, Span, SpanEvent, SpanError, SpanId, SpanKind, SpanLink, SpanStatus, TraceId, TraceContext, TraceSink, TraceRecordEvent, CapabilityType, Usage, Score, } from './core/trace.js';
|
|
3
3
|
export { attachScore, parseTraceparent } from './core/trace.js';
|
|
4
4
|
export type { AgentTool, ApprovalDecision, JsonSchema, ModelClient, RecorderBackend, SchemaInput, SchemaType, ToolRunContext, TypedSchema, } from './core/tool.js';
|
|
@@ -12,7 +12,7 @@ export type { TraceLimits, TraceRecorderOptions } from './engine/tracer.js';
|
|
|
12
12
|
export { currentTraceparent } from './engine/span-scope.js';
|
|
13
13
|
export { classifyError, isAbortError } from './engine/errors.js';
|
|
14
14
|
export { isSuccessStopReason } from './engine/types.js';
|
|
15
|
-
export type { AgentRunResult, AgentStopReason, ContextPolicy, RunAgentOptions, SystemParam, SystemTextBlock, } from './engine/types.js';
|
|
15
|
+
export type { AgentRunResult, AgentStopReason, ContextPolicy, ModelFallbackLink, RunAgentOptions, SystemParam, SystemTextBlock, } from './engine/types.js';
|
|
16
16
|
export { defaultEstimateTokens, estimateMessages, renderMessages, trimToolPairs, compactMessages, } from './engine/trimming.js';
|
|
17
17
|
export type { CompactOptions, TrimOptions } from './engine/trimming.js';
|
|
18
18
|
export { createBudgetPolicy } from './engine/policy.js';
|
|
@@ -30,7 +30,7 @@ export type { Blackboard, BlackboardKey, BlackboardSeed, BlackboardValue, } from
|
|
|
30
30
|
export { SystemPrompt } from './runtime/systemPrompt.js';
|
|
31
31
|
export type { SystemPromptOptions, SystemSection } from './runtime/systemPrompt.js';
|
|
32
32
|
export type { ExecuteRunOptions } from './runtime/run.js';
|
|
33
|
-
export type { RunMeta, RunStatus } from './core/run.js';
|
|
33
|
+
export type { RunMeta, RunStatus, SuspendedReason, TaskEvent } from './core/run.js';
|
|
34
34
|
export { Container } from './container/container.js';
|
|
35
35
|
export type { Provider, ClassProvider, ValueProvider, FactoryProvider, Token, } from './container/container.js';
|
|
36
36
|
export { asset } from './toolkit/asset.js';
|
|
@@ -66,11 +66,12 @@ export { createHttpHandler, HttpException } from './transport/http.js';
|
|
|
66
66
|
export type { HttpHandlerOptions, HttpHandler, HealthResponse, RunHttpResponse, TaskSubmitBody, } from './transport/http.js';
|
|
67
67
|
export { SqliteTaskStore } from './store/sqliteStore.js';
|
|
68
68
|
export { createOtlpExporter } from './integrations/otlp.js';
|
|
69
|
+
export { jsonlTraceSink } from './integrations/file-sink.js';
|
|
69
70
|
export { createOpenAIClient } from './integrations/openai.js';
|
|
70
71
|
export { createAnthropicClient } from './integrations/anthropic.js';
|
|
71
72
|
export type { AnthropicClientOptions } from './integrations/anthropic.js';
|
|
72
73
|
export { InMemoryMemoryStore } from './runtime/memory.js';
|
|
73
|
-
export type { MemoryStore } from './runtime/memory.js';
|
|
74
|
+
export type { MemorySnapshot, MemoryStore, MemoryWriteResult } from './runtime/memory.js';
|
|
74
75
|
export { InMemorySessionStore } from './runtime/session.js';
|
|
75
76
|
export type { SessionStore } from './runtime/session.js';
|
|
76
77
|
export { RedisTaskStore } from './store/redisStore.js';
|
|
@@ -84,8 +85,10 @@ export { diffTraces } from './engine/trace-diff.js';
|
|
|
84
85
|
export type { DiffEntry, SpanDiff, TraceDiff, TraceDiffOptions } from './engine/trace-diff.js';
|
|
85
86
|
export { mcpTools, MCP_DEFAULT_TIMEOUT_MS, MCP_CLOSE_GRACE_MS, createStdioMcpConnector, createStreamableHttpMcpConnector, } from './integrations/mcp.js';
|
|
86
87
|
export type { McpClientLike, McpConnector, McpToolInfo, McpToolsOptions, StdioMcpConnectorOptions, StreamableHttpMcpConnectorOptions, } from './integrations/mcp.js';
|
|
88
|
+
export { createMcpServer } from './engine/mcp-server.js';
|
|
89
|
+
export type { McpServer, McpServerApp, McpServerOptions } from './engine/mcp-server.js';
|
|
87
90
|
export { metricsSink, DEFAULT_BUCKETS } from './integrations/metrics.js';
|
|
88
|
-
export type { MetricsSink, MetricsSinkOptions, MetricsSnapshot, ModelMetrics, CapabilityMetrics, } from './integrations/metrics.js';
|
|
91
|
+
export type { MetricsSink, MetricsSinkOptions, MetricsSnapshot, ModelMetrics, CapabilityMetrics, RunLabelMetrics, ExemplarSnapshot, } from './integrations/metrics.js';
|
|
89
92
|
export { buildRunReport, mergeRunReports, renderRunReport } from './integrations/report.js';
|
|
90
93
|
export type { DurationReport, ModelReport, RunReport, CapabilityReport, } from './integrations/report.js';
|
|
91
94
|
export { scriptedClient } from './eval/scripted.js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const AGENTIA_VERSION = '0.9.
|
|
1
|
+
export const AGENTIA_VERSION = '0.9.5';
|
|
2
2
|
export { attachScore, parseTraceparent } from './core/trace.js';
|
|
3
3
|
export { validateJsonSchema } from './core/schema.js';
|
|
4
4
|
export { combineSignals } from './core/abort.js';
|
|
@@ -48,6 +48,8 @@ export { runSync, createSyncHandler } from './transport/transport.js';
|
|
|
48
48
|
export { createHttpHandler, HttpException } from './transport/http.js';
|
|
49
49
|
export { SqliteTaskStore } from './store/sqliteStore.js';
|
|
50
50
|
export { createOtlpExporter } from './integrations/otlp.js';
|
|
51
|
+
// JSONL 文件 sink:`agentia report` / `diff` / `harvest` 的输入格式(一行一条裸 Trace)
|
|
52
|
+
export { jsonlTraceSink } from './integrations/file-sink.js';
|
|
51
53
|
export { createOpenAIClient } from './integrations/openai.js';
|
|
52
54
|
export { createAnthropicClient } from './integrations/anthropic.js';
|
|
53
55
|
export { InMemoryMemoryStore } from './runtime/memory.js';
|
|
@@ -59,6 +61,9 @@ export { diffTraces } from './engine/trace-diff.js';
|
|
|
59
61
|
// integrations:MCP 桥(D1)+ 两个内置连接器(stdio / StreamableHTTP)—— 桥是 duck-typed,
|
|
60
62
|
// 连接器只用标准库(`node:child_process` + 全局 `fetch`),**不新增第三方依赖**(spec §10 2026-09-18)
|
|
61
63
|
export { mcpTools, MCP_DEFAULT_TIMEOUT_MS, MCP_CLOSE_GRACE_MS, createStdioMcpConnector, createStreamableHttpMcpConnector, } from './integrations/mcp.js';
|
|
64
|
+
// engine:MCP 反向桥(R8-P5)—— 把 app 的能力菜单暴露成 MCP server(stdio / StreamableHTTP,
|
|
65
|
+
// 只用标准库)。落 engine 层的理由见该文件头注(integrations 只允许依赖 core,装不下它)
|
|
66
|
+
export { createMcpServer } from './engine/mcp-server.js';
|
|
62
67
|
// integrations:指标(D3 → E2/E3/E4/E5)—— 满足 TraceSink 即可接入,能力零新出口
|
|
63
68
|
export { metricsSink, DEFAULT_BUCKETS } from './integrations/metrics.js';
|
|
64
69
|
// integrations:调优报告(G1)—— 纯函数,从 trace 派生「哪个能力慢/贵/爱失败」
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AAoBvC,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAYhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAoBjD,eAAe;AACf,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,sDAAsD;AACtD,qDAAqD;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 流内 error 分片的 type/code → HTTP status。
|
|
3
|
+
*
|
|
4
|
+
* **为什么必须共用一份**(2026-09-28 外部深评 S3):`anthropic.ts` 与 `openai.ts` 是同一
|
|
5
|
+
* 契约(`ModelClient`)的两条实现,同一判定原本**各写一份**,一致性只靠两边注释里
|
|
6
|
+
* 「与那边同口径」互相喊话 —— 而注释不会在被改的那一刻失败(本仓已有前科:同一个 429
|
|
7
|
+
* 两侧尝试次数不同,见 `tests/integrations/adapter-parity.test.ts` 的文件头)。
|
|
8
|
+
* 现在判定只写一处,两条适配器都调它:改口径只能改这里,漂不了。
|
|
9
|
+
*
|
|
10
|
+
* 目的:兼容端点(DeepSeek 等)常把限流 / 内部故障塞进 **HTTP 200** 的流里,不给非 2xx。
|
|
11
|
+
* 不反推成 status,引擎就无法识别这是可重试的限流,重试层照样不生效。
|
|
12
|
+
*
|
|
13
|
+
* 为什么不细分 401/403/404:`engine/errors.ts` 的鸭子分类只看「4xx = 改配置才有救、
|
|
14
|
+
* 别白重试」,401 与 403 在引擎侧是同一处置;细分只会多三个没人读的分支。
|
|
15
|
+
*
|
|
16
|
+
* 值域:**只回 429 / 529 / 400 / 500 四个**(均为「引擎侧已有处置」的档位)——
|
|
17
|
+
* 别在这里返回 4xx 里没人处理的状态码。
|
|
18
|
+
*/
|
|
19
|
+
export declare function statusOfStreamError(err: {
|
|
20
|
+
type?: string | null | undefined;
|
|
21
|
+
code?: string | null | undefined;
|
|
22
|
+
}): number;
|
|
1
23
|
/** 适配器缺省内层重试次数(与 Anthropic SDK 的缺省对齐:2) */
|
|
2
24
|
export declare const DEFAULT_MAX_RETRIES = 2;
|
|
3
25
|
/**
|
|
@@ -6,6 +6,57 @@
|
|
|
6
6
|
* `tests/integrations/adapter-parity.test.ts`)。所以判定只写一次,两条适配器都调它。
|
|
7
7
|
*/
|
|
8
8
|
import { zeroClauseOf } from '../core/limits.js';
|
|
9
|
+
/**
|
|
10
|
+
* 流内 error 分片的 type/code → HTTP status。
|
|
11
|
+
*
|
|
12
|
+
* **为什么必须共用一份**(2026-09-28 外部深评 S3):`anthropic.ts` 与 `openai.ts` 是同一
|
|
13
|
+
* 契约(`ModelClient`)的两条实现,同一判定原本**各写一份**,一致性只靠两边注释里
|
|
14
|
+
* 「与那边同口径」互相喊话 —— 而注释不会在被改的那一刻失败(本仓已有前科:同一个 429
|
|
15
|
+
* 两侧尝试次数不同,见 `tests/integrations/adapter-parity.test.ts` 的文件头)。
|
|
16
|
+
* 现在判定只写一处,两条适配器都调它:改口径只能改这里,漂不了。
|
|
17
|
+
*
|
|
18
|
+
* 目的:兼容端点(DeepSeek 等)常把限流 / 内部故障塞进 **HTTP 200** 的流里,不给非 2xx。
|
|
19
|
+
* 不反推成 status,引擎就无法识别这是可重试的限流,重试层照样不生效。
|
|
20
|
+
*
|
|
21
|
+
* 为什么不细分 401/403/404:`engine/errors.ts` 的鸭子分类只看「4xx = 改配置才有救、
|
|
22
|
+
* 别白重试」,401 与 403 在引擎侧是同一处置;细分只会多三个没人读的分支。
|
|
23
|
+
*
|
|
24
|
+
* 值域:**只回 429 / 529 / 400 / 500 四个**(均为「引擎侧已有处置」的档位)——
|
|
25
|
+
* 别在这里返回 4xx 里没人处理的状态码。
|
|
26
|
+
*/
|
|
27
|
+
export function statusOfStreamError(err) {
|
|
28
|
+
const key = `${err.type ?? ''} ${err.code ?? ''}`.toLowerCase();
|
|
29
|
+
// 限流档:可重试短路
|
|
30
|
+
if (key.includes('rate_limit') ||
|
|
31
|
+
key.includes('insufficient_quota') ||
|
|
32
|
+
key.includes('too_many')) {
|
|
33
|
+
return 429;
|
|
34
|
+
}
|
|
35
|
+
// 过载档(Anthropic 的 overloaded_error = 529,语义就是「稍后重试」);
|
|
36
|
+
// OpenAI 侧的兼容端点也用同一个词,两侧同判 —— 它同样是 5xx 可重试,但保留 529 让
|
|
37
|
+
// trace / 指标能把它与「真故障」分开数
|
|
38
|
+
if (key.includes('overloaded'))
|
|
39
|
+
return 529;
|
|
40
|
+
// 4xx 档:这些是**改配置才有救**的病因(上下文超限 / 模型名错 / 鉴权 / 内容策略),
|
|
41
|
+
// 一律 500 + retryable 会让引擎白重试 3 次(3 次网络请求 + 3 倍等待),
|
|
42
|
+
// 且 trace 记成 `server` 而非 `api` —— 排障方向被带偏。
|
|
43
|
+
//
|
|
44
|
+
// 用 `includes` 而不是枚举:OpenAI 兼容生态的类型/错误码多得多(下面全部来自真实
|
|
45
|
+
// 兼容端点的读数),枚举会把没列到的私下归 500。两侧原本各自枚举得**不完全一致**
|
|
46
|
+
// (anthropic 列 `not_found_error`、openai 列 `model_not_found`/`does_not_exist`),
|
|
47
|
+
// 合并时取**并集**:这是本函数存在的意义 —— 同一病因在两条适配器上必须同一档。
|
|
48
|
+
if (key.includes('invalid_request') ||
|
|
49
|
+
key.includes('context_length') ||
|
|
50
|
+
key.includes('model_not_found') ||
|
|
51
|
+
key.includes('does_not_exist') ||
|
|
52
|
+
key.includes('not_found') ||
|
|
53
|
+
key.includes('content_filter') ||
|
|
54
|
+
key.includes('authentication') ||
|
|
55
|
+
key.includes('permission')) {
|
|
56
|
+
return 400;
|
|
57
|
+
}
|
|
58
|
+
return 500;
|
|
59
|
+
}
|
|
9
60
|
/** 适配器缺省内层重试次数(与 Anthropic SDK 的缺省对齐:2) */
|
|
10
61
|
export const DEFAULT_MAX_RETRIES = 2;
|
|
11
62
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-options.js","sourceRoot":"","sources":["../../src/integrations/adapter-options.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,2CAA2C;AAC3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY,EAAE,KAAa;IAC3D,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,mBAAmB,CAAC;IAClD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,SAAS,CACjB,GAAG,KAAK,yBAAyB,YAAY,CAAC,YAAY,CAAC,QAAQ,MAAM,CAAC,GAAG,CAAC,MAAM;YAClF,gEAAgE;YAChE,kCAAkC,CACrC,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
1
|
+
{"version":3,"file":"adapter-options.js","sourceRoot":"","sources":["../../src/integrations/adapter-options.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAKnC;IACC,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC;IAChE,YAAY;IACZ,IACE,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC1B,GAAG,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAClC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,EACxB,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,sDAAsD;IACtD,qDAAqD;IACrD,yBAAyB;IACzB,IAAI,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAO,GAAG,CAAC;IAC3C,oDAAoD;IACpD,mDAAmD;IACnD,2CAA2C;IAC3C,EAAE;IACF,oDAAoD;IACpD,8CAA8C;IAC9C,+EAA+E;IAC/E,6CAA6C;IAC7C,IACE,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAC/B,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAC9B,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAC/B,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAC9B,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC;QACzB,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAC9B,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAC9B,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,EAC1B,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,2CAA2C;AAC3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY,EAAE,KAAa;IAC3D,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,mBAAmB,CAAC;IAClD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,SAAS,CACjB,GAAG,KAAK,yBAAyB,YAAY,CAAC,YAAY,CAAC,QAAQ,MAAM,CAAC,GAAG,CAAC,MAAM;YAClF,gEAAgE;YAChE,kCAAkC,CACrC,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -33,8 +33,10 @@ export interface AnthropicClientOptions {
|
|
|
33
33
|
* 单次请求超时(毫秒)。缺省不给(中止由引擎的 signal 管,见 `ModelClient` 契约);
|
|
34
34
|
* 给了就用超时信号与 params.signal 合成(任一触发即中止)。超时按连接错误处理(可重试)。
|
|
35
35
|
*
|
|
36
|
-
*
|
|
37
|
-
* NaN / Infinity
|
|
36
|
+
* 必须为**正的有限数、且不超过 Node 定时器上限**(构造期校验,与 AsyncRunner 对
|
|
37
|
+
* `runTimeoutMs` 的校验同款):NaN / Infinity / 超过 `2^31-1`ms 的延迟都会被 `setTimeout`
|
|
38
|
+
* 钳到 1ms(Node 只在 stderr 留一行 `TimeoutOverflowWarning`,没人会看到)——
|
|
39
|
+
* 于是每个请求立即「超时」,看起来像上游全挂。
|
|
38
40
|
* ⚠️ 校验只挡非法配置,**不改超时的既有行为**:client 层超时经合成信号中止请求、
|
|
39
41
|
* 自身不再重试,抛出的 `TimeoutError`(DOMException)由引擎归 `timeout` 一类账。
|
|
40
42
|
*/
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { textOf } from '../core/text.js';
|
|
2
|
-
import { resolveMaxRetries } from './adapter-options.js';
|
|
2
|
+
import { resolveMaxRetries, statusOfStreamError } from './adapter-options.js';
|
|
3
3
|
import { sseLines } from '../core/sse.js';
|
|
4
|
-
import { backoffMs, interruptibleSleep } from '../core/timeout.js';
|
|
4
|
+
import { assertTimerDelay, backoffMs, interruptibleSleep } from '../core/timeout.js';
|
|
5
|
+
import { zeroClauseOf } from '../core/limits.js';
|
|
5
6
|
/**
|
|
6
7
|
* Anthropic API 错误:非 2xx 响应(读响应体截断进 message)或 200 流内嵌 error 事件。
|
|
7
8
|
* 带数值 `status` —— `engine/errors.ts` 的鸭子类型分类靠它(429 → rate_limit、
|
|
@@ -28,8 +29,13 @@ export function createAnthropicClient(options = {}) {
|
|
|
28
29
|
if (timeoutMs !== undefined && (!Number.isFinite(timeoutMs) || timeoutMs <= 0)) {
|
|
29
30
|
// NaN / Infinity 会被 setTimeout 钳到 1ms(每个请求立即「超时」),0 / 负数同理无意义 ——
|
|
30
31
|
// 响亮抛错,不静默生效(与 AsyncRunner 对 runTimeoutMs 的构造期校验同款)。
|
|
31
|
-
throw new Error(`createAnthropicClient:timeout
|
|
32
|
+
throw new Error(`createAnthropicClient:timeout 必须为正的有限毫秒数(${zeroClauseOf('createAnthropicClient.timeout')}),收到 ${String(options.timeout)}`);
|
|
32
33
|
}
|
|
34
|
+
// 上界(2026-09-28):「正的有限数」还不够 —— 超过 2^31-1ms(约 24.86 天)的延迟
|
|
35
|
+
// Node 不会遵守(stderr 一行警告 + 钳到 1ms)⇒「30 天超时」变成「每个请求立即超时」。
|
|
36
|
+
// 上限单源在 core/timeout.ts(composeSignal 直喂 setTimeout 的正是这个值)。
|
|
37
|
+
if (timeoutMs !== undefined)
|
|
38
|
+
assertTimerDelay(timeoutMs, 'createAnthropicClient 的 timeout');
|
|
33
39
|
return {
|
|
34
40
|
messages: {
|
|
35
41
|
stream(params) {
|
|
@@ -58,7 +64,7 @@ export function createAnthropicClient(options = {}) {
|
|
|
58
64
|
// textOf 的 .filter() 抛裸 TypeError → classifyError 判 unknown/不可重试
|
|
59
65
|
// —— 同一事件走流式路径却是带 status 的可重试错误,两本账。
|
|
60
66
|
if (body.error) {
|
|
61
|
-
throw new AnthropicApiError(statusOfStreamError(body.error.type), `Anthropic 非流式响应携带错误(${body.error.type ?? 'unknown'}):` +
|
|
67
|
+
throw new AnthropicApiError(statusOfStreamError({ type: body.error.type }), `Anthropic 非流式响应携带错误(${body.error.type ?? 'unknown'}):` +
|
|
62
68
|
(body.error.message ?? JSON.stringify(body).slice(0, 300)));
|
|
63
69
|
}
|
|
64
70
|
// content 不是数组 = 200 但没给可用补全(网关截断 / 兼容端点 bug):
|
|
@@ -67,7 +73,10 @@ export function createAnthropicClient(options = {}) {
|
|
|
67
73
|
if (!Array.isArray(body.content)) {
|
|
68
74
|
throw new AnthropicApiError(500, 'Anthropic 非流式响应缺 content 数组;响应无可用补全,按上游故障处理');
|
|
69
75
|
}
|
|
70
|
-
|
|
76
|
+
// usage 缺失(端点没回计量)也要如实标出来 —— 别让 0 冒充读数(S2)
|
|
77
|
+
const message = body.usage
|
|
78
|
+
? body
|
|
79
|
+
: { ...body, usage: { input_tokens: 0, output_tokens: 0, unreported: true } };
|
|
71
80
|
// 分隔符 `''`:回落的原文本来就是一整段,拼回去要与流式累积的文本逐字一致
|
|
72
81
|
const full = textOf(message, '');
|
|
73
82
|
if (full)
|
|
@@ -239,6 +248,9 @@ async function readAnthropicStream(body, fallbackModel, textCallbacks) {
|
|
|
239
248
|
let stopReason = null;
|
|
240
249
|
let stopSequence = null;
|
|
241
250
|
let usage = {};
|
|
251
|
+
// 上游**到底报没报** usage:空对象(没报)与「报了全 0」是两回事 ——
|
|
252
|
+
// 前者要如实标 `unreported`,别让 0 冒充读数(2026-09-28 外部深评 S2)
|
|
253
|
+
let sawUsage = false;
|
|
242
254
|
for await (const line of sseLines(body)) {
|
|
243
255
|
if (!line.startsWith('data:'))
|
|
244
256
|
continue; // 忽略 event: / 注释 / 空行
|
|
@@ -257,6 +269,8 @@ async function readAnthropicStream(body, fallbackModel, textCallbacks) {
|
|
|
257
269
|
started = true;
|
|
258
270
|
id = event.message?.id ?? '';
|
|
259
271
|
model = event.message?.model ?? '';
|
|
272
|
+
if (event.message?.usage)
|
|
273
|
+
sawUsage = true;
|
|
260
274
|
usage = { ...event.message?.usage };
|
|
261
275
|
break;
|
|
262
276
|
}
|
|
@@ -325,15 +339,17 @@ async function readAnthropicStream(body, fallbackModel, textCallbacks) {
|
|
|
325
339
|
stopSequence = d.stop_sequence;
|
|
326
340
|
// message_delta 的 usage 是累计口径(output_tokens 为累计值,cache 计量在此回报)。
|
|
327
341
|
// 走 mergeUsage 而非浅合并:显式 null 不得清掉 message_start 已拿到的真实值。
|
|
328
|
-
if (event.usage)
|
|
342
|
+
if (event.usage) {
|
|
343
|
+
sawUsage = true;
|
|
329
344
|
usage = mergeUsage(usage, event.usage);
|
|
345
|
+
}
|
|
330
346
|
break;
|
|
331
347
|
}
|
|
332
348
|
case 'error': {
|
|
333
349
|
// 上游故障以错误事件下发(HTTP 仍是 200)—— 不抛出就会被组装成假成功,
|
|
334
350
|
// run 结论与真实相反(openai.ts 处理过同款形态)
|
|
335
351
|
const err = event.error ?? {};
|
|
336
|
-
throw new AnthropicApiError(statusOfStreamError(err.type), `Anthropic 流内错误(${err.type ?? 'unknown'}):${err.message ?? payload.slice(0, 300)}`);
|
|
352
|
+
throw new AnthropicApiError(statusOfStreamError({ type: err.type }), `Anthropic 流内错误(${err.type ?? 'unknown'}):${err.message ?? payload.slice(0, 300)}`);
|
|
337
353
|
}
|
|
338
354
|
case 'message_stop': {
|
|
339
355
|
sawStop = true;
|
|
@@ -402,29 +418,13 @@ async function readAnthropicStream(body, fallbackModel, textCallbacks) {
|
|
|
402
418
|
output_tokens: usage.output_tokens ?? 0,
|
|
403
419
|
cache_creation_input_tokens: usage.cache_creation_input_tokens ?? 0,
|
|
404
420
|
cache_read_input_tokens: usage.cache_read_input_tokens ?? 0,
|
|
421
|
+
// 上游全程没给 usage ⇒ 上面四个 0 是**替身值**,如实标出来(S2)
|
|
422
|
+
...(sawUsage ? {} : { unreported: true }),
|
|
405
423
|
},
|
|
406
424
|
};
|
|
407
425
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
switch (type) {
|
|
411
|
-
case 'rate_limit_error':
|
|
412
|
-
return 429;
|
|
413
|
-
case 'overloaded_error':
|
|
414
|
-
return 529;
|
|
415
|
-
// 4xx 档(与 openai.ts 的 statusOfStreamError 同口径 —— 那边把
|
|
416
|
-
// invalid_request / authentication / permission / model_not_found 一律归 400,
|
|
417
|
-
// 不细分 401/403/404):这些是**改配置才有救**的病因,归 500 + retryable 会让
|
|
418
|
-
// 引擎白重试三轮,且 trace 记成 server —— 排障方向被带偏。
|
|
419
|
-
case 'invalid_request_error':
|
|
420
|
-
case 'authentication_error':
|
|
421
|
-
case 'permission_error':
|
|
422
|
-
case 'not_found_error':
|
|
423
|
-
return 400;
|
|
424
|
-
default:
|
|
425
|
-
return 500;
|
|
426
|
-
}
|
|
427
|
-
}
|
|
426
|
+
// 「流内 error → HTTP status」的判定在 `adapter-options.ts`(与 openai.ts **共用一份**,
|
|
427
|
+
// 2026-09-28 外部深评 S3:此前两份实现靠注释互相喊话对齐)—— 别在这里再写一份。
|
|
428
428
|
/** tool_use 的 input 是分片拼出的 JSON 字符串;非法时原样交给下游 schema 校验(同 openai.ts) */
|
|
429
429
|
function parseToolInput(raw) {
|
|
430
430
|
if (!raw)
|