@migor/agentia 0.2.0 → 0.2.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.
- package/LICENSE +21 -0
- package/README.en.md +144 -0
- package/README.md +202 -76
- package/dist/AGENTS.md +811 -0
- package/dist/container/container.d.ts +10 -2
- package/dist/container/container.js +27 -3
- package/dist/container/container.js.map +1 -1
- package/dist/core/abort.d.ts +10 -0
- package/dist/core/abort.js +28 -0
- package/dist/core/abort.js.map +1 -0
- package/dist/core/blackboard.d.ts +37 -0
- package/dist/core/blackboard.js +2 -0
- package/dist/core/blackboard.js.map +1 -0
- package/dist/core/json.d.ts +2 -0
- package/dist/core/json.js +4 -0
- package/dist/core/json.js.map +1 -1
- package/dist/core/run.d.ts +18 -0
- package/dist/core/run.js +2 -0
- package/dist/core/run.js.map +1 -0
- package/dist/core/schema.js +2 -2
- package/dist/core/schema.js.map +1 -1
- package/dist/core/tool.d.ts +62 -7
- package/dist/core/trace.d.ts +20 -4
- package/dist/engine/budget.d.ts +49 -0
- package/dist/engine/budget.js +30 -0
- package/dist/engine/budget.js.map +1 -0
- package/dist/engine/concurrency.d.ts +43 -0
- package/dist/engine/concurrency.js +95 -0
- package/dist/engine/concurrency.js.map +1 -0
- package/dist/engine/errors.d.ts +2 -0
- package/dist/engine/errors.js +7 -0
- package/dist/engine/errors.js.map +1 -1
- package/dist/engine/loop.d.ts +35 -10
- package/dist/engine/loop.js +336 -66
- package/dist/engine/loop.js.map +1 -1
- package/dist/engine/policy.d.ts +9 -1
- package/dist/engine/policy.js +8 -5
- package/dist/engine/policy.js.map +1 -1
- package/dist/engine/replay.d.ts +10 -4
- package/dist/engine/replay.js +57 -27
- package/dist/engine/replay.js.map +1 -1
- package/dist/engine/retry.d.ts +47 -0
- package/dist/engine/retry.js +51 -0
- package/dist/engine/retry.js.map +1 -0
- package/dist/engine/spec.d.ts +61 -0
- package/dist/{run → engine}/spec.js +4 -1
- package/dist/engine/spec.js.map +1 -0
- package/dist/engine/tracer.d.ts +9 -0
- package/dist/engine/tracer.js +57 -1
- package/dist/engine/tracer.js.map +1 -1
- package/dist/engine/{context.d.ts → trimming.d.ts} +19 -20
- package/dist/engine/trimming.js +238 -0
- package/dist/engine/trimming.js.map +1 -0
- package/dist/engine/types.d.ts +109 -13
- package/dist/engine/types.js +9 -1
- package/dist/engine/types.js.map +1 -1
- package/dist/engine/usage.d.ts +28 -2
- package/dist/engine/usage.js +39 -6
- package/dist/engine/usage.js.map +1 -1
- package/dist/eval/defineEval.d.ts +73 -0
- package/dist/eval/defineEval.js +44 -0
- package/dist/eval/defineEval.js.map +1 -0
- package/dist/eval/scripted.d.ts +26 -0
- package/dist/eval/scripted.js +43 -0
- package/dist/eval/scripted.js.map +1 -0
- package/dist/index.d.ts +60 -35
- package/dist/index.js +38 -20
- package/dist/index.js.map +1 -1
- package/dist/integrations/anthropic.d.ts +53 -0
- package/dist/integrations/anthropic.js +24 -0
- package/dist/integrations/anthropic.js.map +1 -0
- package/dist/integrations/mcp.d.ts +79 -0
- package/dist/integrations/mcp.js +108 -0
- package/dist/integrations/mcp.js.map +1 -0
- package/dist/integrations/metrics.d.ts +131 -0
- package/dist/integrations/metrics.js +488 -0
- package/dist/integrations/metrics.js.map +1 -0
- package/dist/{run → integrations}/openai.d.ts +12 -5
- package/dist/integrations/openai.js +386 -0
- package/dist/integrations/openai.js.map +1 -0
- package/dist/integrations/otlp.js.map +1 -0
- package/dist/integrations/report.d.ts +78 -0
- package/dist/integrations/report.js +257 -0
- package/dist/integrations/report.js.map +1 -0
- package/dist/runtime/context.d.ts +25 -0
- package/dist/{run → runtime}/context.js +8 -1
- package/dist/runtime/context.js.map +1 -0
- package/dist/{run → runtime}/memory.d.ts +1 -1
- package/dist/{run → runtime}/memory.js +3 -1
- package/dist/runtime/memory.js.map +1 -0
- package/dist/{run → runtime}/run.d.ts +22 -5
- package/dist/runtime/run.js +218 -0
- package/dist/runtime/run.js.map +1 -0
- package/dist/runtime/session.d.ts +27 -0
- package/dist/runtime/session.js +16 -0
- package/dist/runtime/session.js.map +1 -0
- package/dist/{run → runtime}/spec.d.ts +16 -2
- package/dist/runtime/spec.js +28 -0
- package/dist/runtime/spec.js.map +1 -0
- package/dist/{run → runtime}/systemPrompt.d.ts +12 -0
- package/dist/{run → runtime}/systemPrompt.js +16 -3
- package/dist/runtime/systemPrompt.js.map +1 -0
- package/dist/{run → runtime}/types.js.map +1 -1
- package/dist/{run → store}/fsStore.d.ts +15 -0
- package/dist/{run → store}/fsStore.js +43 -1
- package/dist/store/fsStore.js.map +1 -0
- package/dist/{run → store}/redisStore.d.ts +23 -1
- package/dist/{run → store}/redisStore.js +33 -6
- package/dist/store/redisStore.js.map +1 -0
- package/dist/{run → store}/sqliteStore.js +22 -1
- package/dist/store/sqliteStore.js.map +1 -0
- package/dist/{run → store}/store.d.ts +25 -3
- package/dist/store/store.js +63 -0
- package/dist/store/store.js.map +1 -0
- package/dist/toolkit/asset.d.ts +7 -6
- package/dist/toolkit/asset.js +7 -6
- package/dist/toolkit/asset.js.map +1 -1
- package/dist/toolkit/collect.d.ts +20 -7
- package/dist/toolkit/collect.js +21 -7
- package/dist/toolkit/collect.js.map +1 -1
- package/dist/toolkit/discover.d.ts +21 -1
- package/dist/toolkit/discover.js +59 -12
- package/dist/toolkit/discover.js.map +1 -1
- package/dist/toolkit/middleware.d.ts +10 -10
- package/dist/toolkit/middleware.js +17 -4
- package/dist/toolkit/middleware.js.map +1 -1
- package/dist/toolkit/module.d.ts +100 -34
- package/dist/toolkit/module.js +112 -36
- package/dist/toolkit/module.js.map +1 -1
- package/dist/toolkit/prompt.d.ts +4 -6
- package/dist/toolkit/prompt.js +11 -10
- package/dist/toolkit/prompt.js.map +1 -1
- package/dist/toolkit/skill.d.ts +14 -16
- package/dist/toolkit/skill.js +32 -25
- package/dist/toolkit/skill.js.map +1 -1
- package/dist/toolkit/subagent.d.ts +10 -12
- package/dist/toolkit/subagent.js +23 -21
- package/dist/toolkit/subagent.js.map +1 -1
- package/dist/toolkit/tool.d.ts +19 -11
- package/dist/toolkit/tool.js +11 -8
- package/dist/toolkit/tool.js.map +1 -1
- package/dist/toolkit/zod.d.ts +4 -3
- package/dist/toolkit/zod.js +2 -1
- package/dist/toolkit/zod.js.map +1 -1
- package/dist/transport/async.d.ts +133 -0
- package/dist/transport/async.js +415 -0
- package/dist/transport/async.js.map +1 -0
- package/dist/transport/http.d.ts +146 -0
- package/dist/transport/http.js +387 -0
- package/dist/transport/http.js.map +1 -0
- package/dist/{run → transport}/scheduler.d.ts +9 -1
- package/dist/transport/scheduler.js +133 -0
- package/dist/transport/scheduler.js.map +1 -0
- package/dist/transport/sse.d.ts +43 -0
- package/dist/transport/sse.js +51 -0
- package/dist/transport/sse.js.map +1 -0
- package/dist/{run → transport}/transport.d.ts +1 -1
- package/dist/{run → transport}/transport.js +1 -1
- package/dist/transport/transport.js.map +1 -0
- package/package.json +24 -9
- package/dist/engine/context.js +0 -146
- package/dist/engine/context.js.map +0 -1
- package/dist/run/async.d.ts +0 -59
- package/dist/run/async.js +0 -185
- package/dist/run/async.js.map +0 -1
- package/dist/run/context.d.ts +0 -16
- package/dist/run/context.js.map +0 -1
- package/dist/run/fsStore.js.map +0 -1
- package/dist/run/http.d.ts +0 -47
- package/dist/run/http.js +0 -119
- package/dist/run/http.js.map +0 -1
- package/dist/run/memory.js.map +0 -1
- package/dist/run/openai.js +0 -181
- package/dist/run/openai.js.map +0 -1
- package/dist/run/otlp.js.map +0 -1
- package/dist/run/redisStore.js.map +0 -1
- package/dist/run/run.js +0 -129
- package/dist/run/run.js.map +0 -1
- package/dist/run/scheduler.js +0 -85
- package/dist/run/scheduler.js.map +0 -1
- package/dist/run/spec.js.map +0 -1
- package/dist/run/sqliteStore.js.map +0 -1
- package/dist/run/store.js +0 -28
- package/dist/run/store.js.map +0 -1
- package/dist/run/systemPrompt.js.map +0 -1
- package/dist/run/transport.js.map +0 -1
- /package/dist/{run → integrations}/otlp.d.ts +0 -0
- /package/dist/{run → integrations}/otlp.js +0 -0
- /package/dist/{run → runtime}/types.d.ts +0 -0
- /package/dist/{run → runtime}/types.js +0 -0
- /package/dist/{run → store}/sqliteStore.d.ts +0 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/** 空 usage 副本(避免多处各写一遍字面量) */
|
|
2
|
+
function emptyUsage() {
|
|
3
|
+
return { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheCreationTokens: 0 };
|
|
4
|
+
}
|
|
5
|
+
function usageTotal(u) {
|
|
6
|
+
return u.inputTokens + u.outputTokens + u.cacheReadTokens + u.cacheCreationTokens;
|
|
7
|
+
}
|
|
8
|
+
/** Prometheus 式「最近 rank」分位,与 metricsSink 同口径 */
|
|
9
|
+
function percentile(sorted, q) {
|
|
10
|
+
if (sorted.length === 0)
|
|
11
|
+
return 0;
|
|
12
|
+
const rank = Math.ceil(q * sorted.length);
|
|
13
|
+
return sorted[Math.min(Math.max(rank, 1), sorted.length) - 1];
|
|
14
|
+
}
|
|
15
|
+
function durationReport(samples) {
|
|
16
|
+
if (samples.length === 0)
|
|
17
|
+
return { total: 0, max: 0, p50: 0, p95: 0 };
|
|
18
|
+
const sorted = [...samples].sort((a, b) => a - b);
|
|
19
|
+
return {
|
|
20
|
+
total: samples.reduce((a, b) => a + b, 0),
|
|
21
|
+
max: sorted[sorted.length - 1],
|
|
22
|
+
p50: percentile(sorted, 0.5),
|
|
23
|
+
p95: percentile(sorted, 0.95),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function addUsage(into, add) {
|
|
27
|
+
into.inputTokens += add.inputTokens;
|
|
28
|
+
into.outputTokens += add.outputTokens;
|
|
29
|
+
into.cacheReadTokens += add.cacheReadTokens;
|
|
30
|
+
into.cacheCreationTokens += add.cacheCreationTokens;
|
|
31
|
+
if (add.costEstimate != null)
|
|
32
|
+
into.costEstimate = (into.costEstimate ?? 0) + add.costEstimate;
|
|
33
|
+
}
|
|
34
|
+
function capabilityKindOf(span) {
|
|
35
|
+
if (span.attributes.skill !== undefined)
|
|
36
|
+
return 'skill';
|
|
37
|
+
if (span.attributes.subagent !== undefined)
|
|
38
|
+
return 'subagent';
|
|
39
|
+
return 'capability';
|
|
40
|
+
}
|
|
41
|
+
/** 从一条 Trace 生成报告(纯函数) */
|
|
42
|
+
export function buildRunReport(trace) {
|
|
43
|
+
const capabilities = new Map();
|
|
44
|
+
const acc = (capability) => {
|
|
45
|
+
let a = capabilities.get(capability);
|
|
46
|
+
if (!a) {
|
|
47
|
+
a = { calls: 0, errors: 0, durations: [], tokens: null, costUsd: null };
|
|
48
|
+
capabilities.set(capability, a);
|
|
49
|
+
}
|
|
50
|
+
return a;
|
|
51
|
+
};
|
|
52
|
+
const models = new Map();
|
|
53
|
+
const unpriced = new Set();
|
|
54
|
+
for (const span of trace.spans) {
|
|
55
|
+
if (span.kind === 'capability') {
|
|
56
|
+
const a = acc(`${capabilityKindOf(span)}:${span.name}`);
|
|
57
|
+
a.calls++;
|
|
58
|
+
if (span.status === 'error')
|
|
59
|
+
a.errors++;
|
|
60
|
+
if (span.endedAt !== undefined)
|
|
61
|
+
a.durations.push(Math.max(0, span.endedAt - span.startedAt));
|
|
62
|
+
if (span.usage) {
|
|
63
|
+
a.tokens = a.tokens ? { ...a.tokens } : emptyUsage();
|
|
64
|
+
addUsage(a.tokens, span.usage);
|
|
65
|
+
if (span.usage.costEstimate != null)
|
|
66
|
+
a.costUsd = (a.costUsd ?? 0) + span.usage.costEstimate;
|
|
67
|
+
}
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (span.kind !== 'llm.turn')
|
|
71
|
+
continue;
|
|
72
|
+
const model = span.name;
|
|
73
|
+
let m = models.get(model);
|
|
74
|
+
if (!m) {
|
|
75
|
+
m = {
|
|
76
|
+
model,
|
|
77
|
+
turns: 0,
|
|
78
|
+
tokens: emptyUsage(),
|
|
79
|
+
tokensTotal: 0,
|
|
80
|
+
costUsd: null,
|
|
81
|
+
unpricedTurns: 0,
|
|
82
|
+
durationMs: { total: 0, max: 0, p50: 0, p95: 0 },
|
|
83
|
+
durations: [],
|
|
84
|
+
};
|
|
85
|
+
models.set(model, m);
|
|
86
|
+
}
|
|
87
|
+
m.turns++;
|
|
88
|
+
if (span.usage) {
|
|
89
|
+
addUsage(m.tokens, span.usage);
|
|
90
|
+
if (span.usage.costEstimate != null)
|
|
91
|
+
m.costUsd = (m.costUsd ?? 0) + span.usage.costEstimate;
|
|
92
|
+
else {
|
|
93
|
+
m.unpricedTurns++;
|
|
94
|
+
unpriced.add(model);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (span.endedAt !== undefined)
|
|
98
|
+
m.durations.push(Math.max(0, span.endedAt - span.startedAt));
|
|
99
|
+
// 普通工具的耗时/成败在 turn 的 tool.output 事件上(E1)
|
|
100
|
+
for (const e of span.events) {
|
|
101
|
+
if (e.name !== 'tool.output')
|
|
102
|
+
continue;
|
|
103
|
+
const body = e.body;
|
|
104
|
+
if (!body || typeof body !== 'object' || typeof body.tool !== 'string')
|
|
105
|
+
continue;
|
|
106
|
+
const a = acc(`tool:${body.tool}`);
|
|
107
|
+
a.calls++;
|
|
108
|
+
if (body.ok === false)
|
|
109
|
+
a.errors++;
|
|
110
|
+
const d = body.durationMs;
|
|
111
|
+
a.durations.push(typeof d === 'number' && Number.isFinite(d) ? Math.max(0, d) : 0);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const capabilityReports = [...capabilities.entries()].map(([capability, a]) => ({
|
|
115
|
+
capability,
|
|
116
|
+
calls: a.calls,
|
|
117
|
+
errors: a.errors,
|
|
118
|
+
durationMs: durationReport(a.durations),
|
|
119
|
+
tokens: a.tokens,
|
|
120
|
+
tokensTotal: a.tokens ? usageTotal(a.tokens) : null,
|
|
121
|
+
costUsd: a.costUsd,
|
|
122
|
+
durations: [...a.durations],
|
|
123
|
+
}));
|
|
124
|
+
// 按总耗时降序 —— 排在最前的是「最该看的那个」
|
|
125
|
+
capabilityReports.sort((x, y) => y.durationMs.total - x.durationMs.total || y.calls - x.calls);
|
|
126
|
+
const modelReports = [...models.values()].map((m) => ({
|
|
127
|
+
...m,
|
|
128
|
+
tokensTotal: usageTotal(m.tokens),
|
|
129
|
+
durationMs: durationReport(m.durations),
|
|
130
|
+
}));
|
|
131
|
+
const root = trace.spans.find((s) => s.spanId === trace.rootSpanId);
|
|
132
|
+
return {
|
|
133
|
+
traceId: trace.traceId,
|
|
134
|
+
status: trace.status,
|
|
135
|
+
durationMs: root && root.endedAt !== undefined ? Math.max(0, root.endedAt - root.startedAt) : 0,
|
|
136
|
+
totalUsage: { ...trace.totalUsage },
|
|
137
|
+
models: modelReports,
|
|
138
|
+
capabilities: capabilityReports,
|
|
139
|
+
unpricedModels: [...unpriced].sort(),
|
|
140
|
+
runs: 1,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/** 汇总多条报告(跨 run 的能力排行才有统计意义)。空数组 → 空报告。 */
|
|
144
|
+
export function mergeRunReports(reports) {
|
|
145
|
+
const total = {
|
|
146
|
+
traceId: `merged(${reports.length} runs)`,
|
|
147
|
+
status: reports.some((r) => r.status === 'error') ? 'error' : 'ok',
|
|
148
|
+
durationMs: 0,
|
|
149
|
+
totalUsage: emptyUsage(),
|
|
150
|
+
models: [],
|
|
151
|
+
capabilities: [],
|
|
152
|
+
unpricedModels: [],
|
|
153
|
+
runs: reports.length,
|
|
154
|
+
};
|
|
155
|
+
const capabilities = new Map();
|
|
156
|
+
const models = new Map();
|
|
157
|
+
const unpriced = new Set();
|
|
158
|
+
for (const r of reports) {
|
|
159
|
+
total.durationMs += r.durationMs;
|
|
160
|
+
addUsage(total.totalUsage, r.totalUsage);
|
|
161
|
+
for (const m of r.models) {
|
|
162
|
+
let acc = models.get(m.model);
|
|
163
|
+
if (!acc) {
|
|
164
|
+
acc = {
|
|
165
|
+
model: m.model,
|
|
166
|
+
turns: 0,
|
|
167
|
+
tokens: emptyUsage(),
|
|
168
|
+
tokensTotal: 0,
|
|
169
|
+
costUsd: null,
|
|
170
|
+
unpricedTurns: 0,
|
|
171
|
+
durationMs: { total: 0, max: 0, p50: 0, p95: 0 },
|
|
172
|
+
durations: [],
|
|
173
|
+
};
|
|
174
|
+
models.set(m.model, acc);
|
|
175
|
+
}
|
|
176
|
+
acc.turns += m.turns;
|
|
177
|
+
addUsage(acc.tokens, m.tokens);
|
|
178
|
+
if (m.costUsd != null)
|
|
179
|
+
acc.costUsd = (acc.costUsd ?? 0) + m.costUsd;
|
|
180
|
+
acc.unpricedTurns += m.unpricedTurns;
|
|
181
|
+
acc.durations.push(...m.durations);
|
|
182
|
+
}
|
|
183
|
+
for (const u of r.capabilities) {
|
|
184
|
+
let acc = capabilities.get(u.capability);
|
|
185
|
+
if (!acc) {
|
|
186
|
+
acc = { calls: 0, errors: 0, durations: [], tokens: null, costUsd: null };
|
|
187
|
+
capabilities.set(u.capability, acc);
|
|
188
|
+
}
|
|
189
|
+
acc.calls += u.calls;
|
|
190
|
+
acc.errors += u.errors;
|
|
191
|
+
acc.durations.push(...u.durations);
|
|
192
|
+
if (u.tokens) {
|
|
193
|
+
acc.tokens = acc.tokens ?? emptyUsage();
|
|
194
|
+
addUsage(acc.tokens, u.tokens);
|
|
195
|
+
}
|
|
196
|
+
if (u.costUsd != null)
|
|
197
|
+
acc.costUsd = (acc.costUsd ?? 0) + u.costUsd;
|
|
198
|
+
}
|
|
199
|
+
for (const m of r.unpricedModels)
|
|
200
|
+
unpriced.add(m);
|
|
201
|
+
}
|
|
202
|
+
total.capabilities = [...capabilities.entries()].map(([capability, a]) => ({
|
|
203
|
+
capability,
|
|
204
|
+
calls: a.calls,
|
|
205
|
+
errors: a.errors,
|
|
206
|
+
durationMs: durationReport(a.durations),
|
|
207
|
+
tokens: a.tokens,
|
|
208
|
+
tokensTotal: a.tokens ? usageTotal(a.tokens) : null,
|
|
209
|
+
costUsd: a.costUsd,
|
|
210
|
+
durations: [...a.durations],
|
|
211
|
+
}));
|
|
212
|
+
total.capabilities.sort((x, y) => y.durationMs.total - x.durationMs.total || y.calls - x.calls);
|
|
213
|
+
total.models = [...models.values()].map((m) => ({
|
|
214
|
+
...m,
|
|
215
|
+
tokensTotal: usageTotal(m.tokens),
|
|
216
|
+
durationMs: durationReport(m.durations),
|
|
217
|
+
}));
|
|
218
|
+
total.unpricedModels = [...unpriced].sort();
|
|
219
|
+
return total;
|
|
220
|
+
}
|
|
221
|
+
/** 人类可读的纯文本报告(CLI `agentia report` 与日志用;零依赖手写) */
|
|
222
|
+
export function renderRunReport(report) {
|
|
223
|
+
const lines = [];
|
|
224
|
+
const u = report.totalUsage;
|
|
225
|
+
lines.push(`run ${report.traceId} [${report.status}]`);
|
|
226
|
+
lines.push(`total ${report.durationMs}ms · tokens ${usageTotal(u)} (in ${u.inputTokens} / out ${u.outputTokens} / cacheR ${u.cacheReadTokens} / cacheW ${u.cacheCreationTokens})` +
|
|
227
|
+
(u.costEstimate != null ? ` · ~$${u.costEstimate}` : ' · 成本:未定价'));
|
|
228
|
+
if (report.unpricedModels.length > 0) {
|
|
229
|
+
lines.push(`⚠️ 未定价模型:${report.unpricedModels.join(', ')} —— 这些模型的成本按 0 计,maxCostUsd 对它们不生效`);
|
|
230
|
+
}
|
|
231
|
+
const pad = (s, n) => (s.length >= n ? s : s + ' '.repeat(n - s.length));
|
|
232
|
+
if (report.models.length > 0) {
|
|
233
|
+
lines.push('');
|
|
234
|
+
lines.push(`${pad('model', 24)} ${pad('turns', 6)} ${pad('tokens', 10)} ${pad('cost', 10)} ${pad('avg ms', 8)}`);
|
|
235
|
+
for (const m of report.models) {
|
|
236
|
+
const avg = m.turns > 0 ? Math.round(m.durationMs.total / m.turns) : 0;
|
|
237
|
+
lines.push(`${pad(m.model, 24)} ${pad(String(m.turns), 6)} ${pad(String(m.tokensTotal), 10)} ` +
|
|
238
|
+
`${pad(m.costUsd != null ? m.costUsd.toFixed(6) : '未定价', 10)} ${pad(String(avg), 8)}`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (report.capabilities.length > 0) {
|
|
242
|
+
lines.push('');
|
|
243
|
+
lines.push(`${pad('capability', 32)} ${pad('calls', 6)} ${pad('err', 5)} ${pad('total ms', 9)} ${pad('max ms', 8)} ${pad('tokens', 8)} ${pad('cost', 10)}`);
|
|
244
|
+
for (const x of report.capabilities) {
|
|
245
|
+
lines.push(`${pad(x.capability, 32)} ${pad(String(x.calls), 6)} ${pad(String(x.errors), 5)} ` +
|
|
246
|
+
`${pad(String(x.durationMs.total), 9)} ${pad(String(x.durationMs.max), 8)} ` +
|
|
247
|
+
`${pad(x.tokensTotal != null ? String(x.tokensTotal) : '-', 8)} ` +
|
|
248
|
+
`${pad(x.costUsd != null ? x.costUsd.toFixed(6) : '-', 10)}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (report.capabilities.length === 0 && report.models.length === 0) {
|
|
252
|
+
lines.push('');
|
|
253
|
+
lines.push('(没有可归因的能力/模型:trace 里没有 capability span、llm.turn span 或 tool.output 事件)');
|
|
254
|
+
}
|
|
255
|
+
return lines.join('\n') + '\n';
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/integrations/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Run } from './run.js';
|
|
2
|
+
import type { BlackboardKey, BlackboardValue } from '../core/blackboard.js';
|
|
3
|
+
/** 在指定 ctx 下执行(executeRun 内部使用);当前上下文对外以 current() 读取。
|
|
4
|
+
* 返回类型随 fn 而定:async fn → Promise<T>,同步 fn → T(不再是恒 Promise 的假类型)。 */
|
|
5
|
+
export declare function withRunContext<T>(ctx: RunContext, fn: () => Promise<T>): Promise<T>;
|
|
6
|
+
export declare function withRunContext<T>(ctx: RunContext, fn: () => T): T;
|
|
7
|
+
export declare class RunContext {
|
|
8
|
+
readonly run: Run;
|
|
9
|
+
private readonly blackboard;
|
|
10
|
+
constructor(run: Run);
|
|
11
|
+
/** 当前 run 的上下文。不在 run 内调用时返回 undefined。 */
|
|
12
|
+
static current(): RunContext | undefined;
|
|
13
|
+
get runId(): string;
|
|
14
|
+
/**
|
|
15
|
+
* 读黑板。键经 `Blackboard` 声明后:字面量键 → 对应值类型;未知键 → 编译期报错。
|
|
16
|
+
* 未声明 `Blackboard` 时键为 `string`、值为 `unknown`(旧行为)。
|
|
17
|
+
*/
|
|
18
|
+
get<K extends BlackboardKey>(key: K): BlackboardValue<K> | undefined;
|
|
19
|
+
/** 写黑板。值类型与 `Blackboard` 声明的键对齐(未声明时不校验)。 */
|
|
20
|
+
set<K extends BlackboardKey>(key: K, value: BlackboardValue<K>): this;
|
|
21
|
+
has(key: BlackboardKey): boolean;
|
|
22
|
+
delete(key: BlackboardKey): boolean;
|
|
23
|
+
/** 当前黑板上的全部键(扩展过 `Blackboard` 时为键联合数组,字面量有补全) */
|
|
24
|
+
keys(): BlackboardKey[];
|
|
25
|
+
}
|
|
@@ -8,9 +8,10 @@ import { AsyncLocalStorage } from 'node:async_hooks';
|
|
|
8
8
|
* `RunContext.current()` 拿到当前 run —— 无需把 ctx 作为参数层层下传。
|
|
9
9
|
*
|
|
10
10
|
* blackboard:单次 run 内累积的项目事实/产物,随 run 释放(spec §2)。
|
|
11
|
+
* 其**类型**(Blackboard/BlackboardKey/BlackboardSeed)定义在 `core/blackboard.js`
|
|
12
|
+
* —— core 是纯数据层,store 也要读这些类型;机制(ALS 传播 + 读写方法)留在这里。
|
|
11
13
|
*/
|
|
12
14
|
const store = new AsyncLocalStorage();
|
|
13
|
-
/** 在指定 ctx 下执行(executeRun 内部使用);当前上下文对外以 current() 读取 */
|
|
14
15
|
export function withRunContext(ctx, fn) {
|
|
15
16
|
return store.run(ctx, fn);
|
|
16
17
|
}
|
|
@@ -27,9 +28,14 @@ export class RunContext {
|
|
|
27
28
|
get runId() {
|
|
28
29
|
return this.run.runId;
|
|
29
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* 读黑板。键经 `Blackboard` 声明后:字面量键 → 对应值类型;未知键 → 编译期报错。
|
|
33
|
+
* 未声明 `Blackboard` 时键为 `string`、值为 `unknown`(旧行为)。
|
|
34
|
+
*/
|
|
30
35
|
get(key) {
|
|
31
36
|
return this.blackboard.get(key);
|
|
32
37
|
}
|
|
38
|
+
/** 写黑板。值类型与 `Blackboard` 声明的键对齐(未声明时不校验)。 */
|
|
33
39
|
set(key, value) {
|
|
34
40
|
this.blackboard.set(key, value);
|
|
35
41
|
return this;
|
|
@@ -40,6 +46,7 @@ export class RunContext {
|
|
|
40
46
|
delete(key) {
|
|
41
47
|
return this.blackboard.delete(key);
|
|
42
48
|
}
|
|
49
|
+
/** 当前黑板上的全部键(扩展过 `Blackboard` 时为键联合数组,字面量有补全) */
|
|
43
50
|
keys() {
|
|
44
51
|
return [...this.blackboard.keys()];
|
|
45
52
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/runtime/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAIrD;;;;;;;;;;;GAWG;AACH,MAAM,KAAK,GAAG,IAAI,iBAAiB,EAAc,CAAC;AAMlD,MAAM,UAAU,cAAc,CAAI,GAAe,EAAE,EAAwB;IACzE,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,OAAO,UAAU;IAGA,GAAG;IAFP,UAAU,GAAG,IAAI,GAAG,EAAmB,CAAC;IAEzD,YAAqB,GAAQ;mBAAR,GAAG;IAAQ,CAAC;IAEjC,2CAA2C;IAC3C,MAAM,CAAC,OAAO;QACZ,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;IACxB,CAAC;IAED;;;OAGG;IACH,GAAG,CAA0B,GAAM;QACjC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAmC,CAAC;IACpE,CAAC;IACD,6CAA6C;IAC7C,GAAG,CAA0B,GAAM,EAAE,KAAyB;QAC5D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,GAAG,CAAC,GAAkB;QACpB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IACD,MAAM,CAAC,GAAkB;QACvB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IACD,iDAAiD;IACjD,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAoB,CAAC;IACxD,CAAC;CACF"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* blackboard(RunContext)随单次 run 释放;MemoryStore 在 run 边界做
|
|
5
5
|
* 水合/回写:run 开始时把 load(keys) 注入 blackboard,run 结束时把
|
|
6
6
|
* 这些 key 的当前值 save 回 store —— 同一份 store 跨多次 executeRun
|
|
7
|
-
* 复用即得跨 run 记忆。接线见
|
|
7
|
+
* 复用即得跨 run 记忆。接线见 runtime/run.ts 的 ExecuteRunOptions.memory。
|
|
8
8
|
*/
|
|
9
9
|
export interface MemoryStore {
|
|
10
10
|
load(keys: string[]): Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
export class InMemoryMemoryStore {
|
|
3
3
|
data = new Map();
|
|
4
4
|
load(keys) {
|
|
5
|
-
|
|
5
|
+
// 无原型对象:`out['__proto__'] = v` 在 {} 上会走原型 setter(改原型而非建属性),
|
|
6
|
+
// 该 key 会静默丢失 —— 与 run.ts 的 flushMemory 保持对称。
|
|
7
|
+
const out = Object.create(null);
|
|
6
8
|
for (const key of keys) {
|
|
7
9
|
if (this.data.has(key))
|
|
8
10
|
out[key] = this.data.get(key);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/runtime/memory.ts"],"names":[],"mappings":"AAaA,gCAAgC;AAChC,MAAM,OAAO,mBAAmB;IACb,IAAI,GAAG,IAAI,GAAG,EAAmB,CAAC;IAEnD,IAAI,CAAC,IAAc;QACjB,4DAA4D;QAC5D,8CAA8C;QAC9C,MAAM,GAAG,GAA4B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,IAAI,CAAC,OAAgC;QACnC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;CACF"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { AgentRunResult, RunAgentOptions } from '../engine/types.js';
|
|
2
|
+
import type { JsonSchema, SchemaType } from '../core/tool.js';
|
|
3
|
+
import type { TraceSink } from '../core/trace.js';
|
|
2
4
|
import { TraceRecorder } from '../engine/tracer.js';
|
|
3
|
-
import type { RunMeta, RunStatus } from '
|
|
5
|
+
import type { RunMeta, RunStatus } from '../core/run.js';
|
|
4
6
|
import { RunContext } from './context.js';
|
|
5
7
|
import type { MemoryStore } from './memory.js';
|
|
8
|
+
import type { SessionStore } from './session.js';
|
|
6
9
|
/**
|
|
7
10
|
* Run —— 一次运行的生命周期容器(spec §2/§6.1)。
|
|
8
11
|
* runId == recorder.traceId == traceId(1:1)。
|
|
@@ -28,7 +31,7 @@ export declare class Run {
|
|
|
28
31
|
finish(result: AgentRunResult): void;
|
|
29
32
|
fail(error: unknown): void;
|
|
30
33
|
}
|
|
31
|
-
export interface ExecuteRunOptions extends RunAgentOptions {
|
|
34
|
+
export interface ExecuteRunOptions<S extends JsonSchema = JsonSchema> extends RunAgentOptions<S> {
|
|
32
35
|
idempotencyKey?: string;
|
|
33
36
|
/** 在 runAgent 前对本次 RunContext 做预置(blackboard 种子等) */
|
|
34
37
|
contextInit?: (ctx: RunContext) => void;
|
|
@@ -41,20 +44,34 @@ export interface ExecuteRunOptions extends RunAgentOptions {
|
|
|
41
44
|
store: MemoryStore;
|
|
42
45
|
keys: string[];
|
|
43
46
|
};
|
|
47
|
+
/**
|
|
48
|
+
* 会话持久化(C4):run 开始把 `store.load(id)` 拼在**传入 messages 之前**,
|
|
49
|
+
* 收尾把「本轮消息 + 回复」`append` 回去。与 `memory`(键值黑板)正交 —— 见 SessionStore。
|
|
50
|
+
*
|
|
51
|
+
* 只记**对话轮次**:本轮传入的 messages + 最终回复(`finalText`)。
|
|
52
|
+
* run 内部的 tool_use / tool_result 往返**不进会话历史**(它们属于这次 run 的内部过程;
|
|
53
|
+
* 要重建完整过程用 trace 重放 `traceToMessages`)—— 这样历史保持干净、可长期累积。
|
|
54
|
+
*/
|
|
55
|
+
session?: {
|
|
56
|
+
store: SessionStore;
|
|
57
|
+
id: string;
|
|
58
|
+
};
|
|
44
59
|
/**
|
|
45
60
|
* 硬失败(请求/API 层异常)是否抛出。缺省 true;
|
|
46
61
|
* 异步宿主(AsyncRunner)置 false:失败也以 {run(status=failed), result.error} 返回,
|
|
47
62
|
* 便于把失败 run 落库而非冒泡。
|
|
48
63
|
*/
|
|
49
64
|
rethrow?: boolean;
|
|
65
|
+
/** trace 出口(观测):run 收尾后逐个投递;sink 抛错被吞,不影响 run */
|
|
66
|
+
sinks?: TraceSink[];
|
|
50
67
|
}
|
|
51
68
|
/**
|
|
52
69
|
* 高层入口:建 Run → start → 注入 recorder 跑 engine → finish。
|
|
53
70
|
* run 层持有 recorder,返回后 run.recorder 里的 trace 即本次完整调用树。
|
|
54
71
|
* RunContext 在整个执行期间经 AsyncLocalStorage 可被 `RunContext.current()` 读到,
|
|
55
|
-
*
|
|
72
|
+
* 工具/能力执行体无需把 ctx 作为参数层层下传。
|
|
56
73
|
*/
|
|
57
|
-
export declare function executeRun(options: ExecuteRunOptions): Promise<{
|
|
74
|
+
export declare function executeRun<S extends JsonSchema = JsonSchema>(options: ExecuteRunOptions<S>): Promise<{
|
|
58
75
|
run: Run;
|
|
59
|
-
result: AgentRunResult
|
|
76
|
+
result: AgentRunResult<SchemaType<S>>;
|
|
60
77
|
}>;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { isSuccessStopReason } from '../engine/types.js';
|
|
2
|
+
import { runAgent } from '../engine/loop.js';
|
|
3
|
+
import { TraceRecorder } from '../engine/tracer.js';
|
|
4
|
+
import { classifyError } from '../engine/errors.js';
|
|
5
|
+
import { RunContext, withRunContext } from './context.js';
|
|
6
|
+
/**
|
|
7
|
+
* Run —— 一次运行的生命周期容器(spec §2/§6.1)。
|
|
8
|
+
* runId == recorder.traceId == traceId(1:1)。
|
|
9
|
+
* recorder 由 engine 的 runAgent 写入(run 根 span 归 engine 开)。
|
|
10
|
+
*/
|
|
11
|
+
export class Run {
|
|
12
|
+
recorder;
|
|
13
|
+
runId;
|
|
14
|
+
idempotencyKey;
|
|
15
|
+
createdAt = Date.now();
|
|
16
|
+
_status = 'queued';
|
|
17
|
+
startedAt;
|
|
18
|
+
finishedAt;
|
|
19
|
+
_result;
|
|
20
|
+
constructor(opts = {}) {
|
|
21
|
+
this.recorder = new TraceRecorder();
|
|
22
|
+
this.runId = this.recorder.traceId;
|
|
23
|
+
this.idempotencyKey = opts.idempotencyKey;
|
|
24
|
+
}
|
|
25
|
+
get status() {
|
|
26
|
+
return this._status;
|
|
27
|
+
}
|
|
28
|
+
get result() {
|
|
29
|
+
return this._result;
|
|
30
|
+
}
|
|
31
|
+
/** meta(供运行记录/持久化使用) */
|
|
32
|
+
toMeta() {
|
|
33
|
+
return {
|
|
34
|
+
runId: this.runId,
|
|
35
|
+
status: this._status,
|
|
36
|
+
idempotencyKey: this.idempotencyKey,
|
|
37
|
+
createdAt: this.createdAt,
|
|
38
|
+
startedAt: this.startedAt,
|
|
39
|
+
finishedAt: this.finishedAt,
|
|
40
|
+
error: this._result?.error,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
start() {
|
|
44
|
+
if (this._status !== 'queued')
|
|
45
|
+
throw new Error(`cannot start a run in status ${this._status}`);
|
|
46
|
+
this._status = 'running';
|
|
47
|
+
this.startedAt = Date.now();
|
|
48
|
+
}
|
|
49
|
+
finish(result) {
|
|
50
|
+
this._result = result;
|
|
51
|
+
this.finishedAt = Date.now();
|
|
52
|
+
this._status = isSuccessStopReason(result.stopReason) ? 'succeeded' : 'failed';
|
|
53
|
+
}
|
|
54
|
+
fail(error) {
|
|
55
|
+
this._status = 'failed';
|
|
56
|
+
this.finishedAt = Date.now();
|
|
57
|
+
if (!this._result) {
|
|
58
|
+
// run 根可能尚未开(如 contextInit 抛错):补一个 error 根再 snapshot,
|
|
59
|
+
// 避免 snapshot 的 "run root not started" 掩盖原始错误。
|
|
60
|
+
if (!this.recorder.rootStarted) {
|
|
61
|
+
const rootId = this.recorder.begin('run', 'agent.run', null);
|
|
62
|
+
this.recorder.end(rootId, { status: 'error', error: classifyError(error) });
|
|
63
|
+
}
|
|
64
|
+
this._result = {
|
|
65
|
+
trace: this.recorder.snapshot('error'),
|
|
66
|
+
stopReason: 'error',
|
|
67
|
+
finalText: '',
|
|
68
|
+
iterations: 0,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
this._result.error = classifyError(error);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 高层入口:建 Run → start → 注入 recorder 跑 engine → finish。
|
|
76
|
+
* run 层持有 recorder,返回后 run.recorder 里的 trace 即本次完整调用树。
|
|
77
|
+
* RunContext 在整个执行期间经 AsyncLocalStorage 可被 `RunContext.current()` 读到,
|
|
78
|
+
* 工具/能力执行体无需把 ctx 作为参数层层下传。
|
|
79
|
+
*/
|
|
80
|
+
export async function executeRun(options) {
|
|
81
|
+
const run = new Run({ idempotencyKey: options.idempotencyKey });
|
|
82
|
+
run.start();
|
|
83
|
+
const ctx = new RunContext(run);
|
|
84
|
+
const memory = options.memory;
|
|
85
|
+
const session = options.session;
|
|
86
|
+
return withRunContext(ctx, async () => {
|
|
87
|
+
try {
|
|
88
|
+
options.contextInit?.(ctx);
|
|
89
|
+
if (memory) {
|
|
90
|
+
// 水合是辅助动作:store 故障(Redis 挂掉等)不得杀死本次 run ——
|
|
91
|
+
// 与下面 flushMemory 对称(那里已有同款防护)。失败即当「无记忆」继续跑。
|
|
92
|
+
try {
|
|
93
|
+
await hydrateMemory(memory, ctx);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
/* ignore:辅助动作失败不影响 run */
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const result = await runAgent({
|
|
100
|
+
...options,
|
|
101
|
+
// 会话历史拼在传入 messages **之前**;读不出来就当无历史(同上:辅助动作不击穿 run)
|
|
102
|
+
messages: await loadSession(session, options.messages),
|
|
103
|
+
recorder: run.recorder,
|
|
104
|
+
});
|
|
105
|
+
run.finish(result);
|
|
106
|
+
if (memory) {
|
|
107
|
+
// 回写是辅助动作:失败不得把已成功的 run 翻成 failed(会丢结果与 trace),
|
|
108
|
+
// 与下面失败路径的 flushMemory 同款防护。
|
|
109
|
+
try {
|
|
110
|
+
await flushMemory(memory, ctx);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
/* ignore */
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// 只在**跑成功**的轮次回写会话(见 appendSession 的不变量 1)。
|
|
117
|
+
// 注意判据是 run 的终态而非「有没有抛异常」—— stopReason 为 error / max_tokens /
|
|
118
|
+
// budget_exceeded / aborted 的 run 同样是「没跑完」,不该进对话历史。
|
|
119
|
+
if (session && run.status === 'succeeded') {
|
|
120
|
+
await appendSession(session, options.messages, result.finalText);
|
|
121
|
+
}
|
|
122
|
+
await flushSinks(options.sinks, result.trace);
|
|
123
|
+
return { run, result };
|
|
124
|
+
}
|
|
125
|
+
catch (e) {
|
|
126
|
+
run.fail(e);
|
|
127
|
+
if (memory) {
|
|
128
|
+
// 失败路径也回写;save 自身出错不掩盖原始错误
|
|
129
|
+
try {
|
|
130
|
+
await flushMemory(memory, ctx);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
/* ignore */
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
await flushSinks(options.sinks, run.result.trace);
|
|
137
|
+
// 失败路径:run.fail() 造的结果没有 typed(恒为 undefined),断言只为对齐返回类型
|
|
138
|
+
if (options.rethrow === false)
|
|
139
|
+
return { run, result: run.result };
|
|
140
|
+
throw e;
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
/** 没有文本输出时写进会话的占位(保住「历史以 assistant 结尾」这个不变量,见 appendSession) */
|
|
145
|
+
const EMPTY_REPLY_MARK = '(本次无文本输出)';
|
|
146
|
+
/**
|
|
147
|
+
* 读会话历史,拼在传入 messages 之前。失败当「无历史」继续 ——
|
|
148
|
+
* 与 memory 水合同款防护:辅助动作失败不得击穿 run。
|
|
149
|
+
*/
|
|
150
|
+
async function loadSession(session, incoming) {
|
|
151
|
+
if (!session)
|
|
152
|
+
return incoming;
|
|
153
|
+
try {
|
|
154
|
+
const history = await session.store.load(session.id);
|
|
155
|
+
return history.length > 0 ? [...history, ...incoming] : incoming;
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return incoming;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* 把本轮消息 + 回复追加回会话(**只在成功路径调用**)。失败吞掉(同 memory 回写防护)。
|
|
163
|
+
*
|
|
164
|
+
* 三条不变量(都是为了下一轮还能把这个历史发出去):
|
|
165
|
+
* 1. **只有成功路径回写** —— 失败时若只存下用户的提问,历史就会以 user 结尾,
|
|
166
|
+
* 下一轮再传入 user 消息即变成「连续两条 user」,撞 API 的角色交替校验;
|
|
167
|
+
* 2. 历史**以 assistant 结尾**:没有文本输出时补一条占位(`end_turn` 下极罕见);
|
|
168
|
+
* 3. 只存**对话轮次**(用户输入 + 最终回复),run 内部的 tool 往返不进历史
|
|
169
|
+
* —— 要完整过程请用 trace 重放 `traceToMessages`。
|
|
170
|
+
*/
|
|
171
|
+
async function appendSession(session, incoming, finalText) {
|
|
172
|
+
if (!session)
|
|
173
|
+
return;
|
|
174
|
+
try {
|
|
175
|
+
await session.store.append(session.id, [
|
|
176
|
+
...incoming,
|
|
177
|
+
{ role: 'assistant', content: finalText || EMPTY_REPLY_MARK },
|
|
178
|
+
]);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
/* ignore */
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/** 投递 trace 给所有 sink:观测失败(sink 抛错)不得影响 run 结果(同 memory 回写防护) */
|
|
185
|
+
async function flushSinks(sinks, trace) {
|
|
186
|
+
if (!sinks || sinks.length === 0)
|
|
187
|
+
return;
|
|
188
|
+
for (const sink of sinks) {
|
|
189
|
+
try {
|
|
190
|
+
await sink.export(trace);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
/* 观测失败不得影响 run */
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/** 水合:store 值注入 blackboard;contextInit 已写的同名 key 不覆盖(用户种子优先) */
|
|
198
|
+
async function hydrateMemory(memory, ctx) {
|
|
199
|
+
const loaded = await memory.store.load(memory.keys);
|
|
200
|
+
for (const key of memory.keys) {
|
|
201
|
+
// Object.hasOwn 而非 `in`:`in` 会命中 Object.prototype 的继承属性 ——
|
|
202
|
+
// key='toString'/'constructor' 之类会把原型上的函数当成记忆值水合进黑板
|
|
203
|
+
if (Object.hasOwn(loaded, key) && !ctx.has(key))
|
|
204
|
+
ctx.set(key, loaded[key]);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/** 回写:blackboard 里这些 key 的当前值存回 store */
|
|
208
|
+
async function flushMemory(memory, ctx) {
|
|
209
|
+
// 无原型对象:`entries['__proto__'] = v` 在 {} 上会走 Object.prototype 的 setter
|
|
210
|
+
// (改掉原型而非建属性),该 key 的回写值会静默丢失
|
|
211
|
+
const entries = Object.create(null);
|
|
212
|
+
for (const key of memory.keys) {
|
|
213
|
+
if (ctx.has(key))
|
|
214
|
+
entries[key] = ctx.get(key);
|
|
215
|
+
}
|
|
216
|
+
await memory.store.save(entries);
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=run.js.map
|