@migor/agentia 0.7.1 → 0.7.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 (38) hide show
  1. package/CHANGELOG.md +63 -1
  2. package/README.md +1 -1
  3. package/dist/AGENTS.md +1 -0
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/integrations/anthropic.d.ts +5 -0
  7. package/dist/integrations/anthropic.js +29 -2
  8. package/dist/integrations/anthropic.js.map +1 -1
  9. package/dist/integrations/mcp-http.d.ts +43 -0
  10. package/dist/integrations/mcp-http.js +250 -0
  11. package/dist/integrations/mcp-http.js.map +1 -0
  12. package/dist/integrations/mcp-stdio.d.ts +46 -0
  13. package/dist/integrations/mcp-stdio.js +230 -0
  14. package/dist/integrations/mcp-stdio.js.map +1 -0
  15. package/dist/integrations/mcp.d.ts +37 -72
  16. package/dist/integrations/mcp.js +9 -468
  17. package/dist/integrations/mcp.js.map +1 -1
  18. package/dist/integrations/metrics-otlp.d.ts +42 -0
  19. package/dist/integrations/metrics-otlp.js +178 -0
  20. package/dist/integrations/metrics-otlp.js.map +1 -0
  21. package/dist/integrations/metrics-render.d.ts +2 -0
  22. package/dist/integrations/metrics-render.js +145 -0
  23. package/dist/integrations/metrics-render.js.map +1 -0
  24. package/dist/integrations/metrics-state.d.ts +191 -0
  25. package/dist/integrations/metrics-state.js +363 -0
  26. package/dist/integrations/metrics-state.js.map +1 -0
  27. package/dist/integrations/metrics.d.ts +3 -86
  28. package/dist/integrations/metrics.js +28 -648
  29. package/dist/integrations/metrics.js.map +1 -1
  30. package/dist/integrations/openai.js +4 -3
  31. package/dist/integrations/openai.js.map +1 -1
  32. package/dist/store/fsStore.d.ts +1 -1
  33. package/dist/store/fsStore.js +5 -2
  34. package/dist/store/fsStore.js.map +1 -1
  35. package/dist/transport/async.d.ts +13 -1
  36. package/dist/transport/async.js +109 -12
  37. package/dist/transport/async.js.map +1 -1
  38. package/package.json +2 -2
@@ -0,0 +1,363 @@
1
+ import { capabilityKindOf } from '../core/trace.js';
2
+ import { percentile } from '../core/stats.js';
3
+ /** 超过基数上限后新键的兜底标签(能力 / 模型 / 评分三个维度共用) */
4
+ const OTHER_LABEL = '__other__';
5
+ /**
6
+ * 折叠计数最多记这么多个**不同**键(每个维度各一本)。计数只用于报警「基数爆了」,
7
+ * 不值得为它留一本无界的账 —— 那等于把上限又拆掉一角。正常上限(50~200)下这个数
8
+ * 远够用:真要记满,说明键空间已经失控,此时「≥1024」和精确值一样能说明问题。
9
+ */
10
+ const MAX_DROPPED_TRACKING = 1024;
11
+ /**
12
+ * 标签基数配额:三个维度共用的「有界键空间」。
13
+ *
14
+ * 键第一次出现且在额度内 → 分到自己的标签(**永远认自己**,不会时而被折叠时而不折叠);
15
+ * 超限 → 归入 `OTHER_LABEL`。
16
+ *
17
+ * 被折叠的键记进 `over`,只为回答「多少个**不同**的键被折叠了」;这本账自身也有界
18
+ * (`MAX_DROPPED_TRACKING`),满了以后 `dropped` 是下界。
19
+ */
20
+ export class KeyBudget {
21
+ max;
22
+ assigned = new Set();
23
+ over = new Set();
24
+ constructor(max) {
25
+ this.max = max;
26
+ }
27
+ /** 取键的标签:额度内原样返回,超限返回 `OTHER_LABEL` */
28
+ take(key) {
29
+ if (this.assigned.has(key))
30
+ return key;
31
+ if (this.assigned.size < this.max) {
32
+ this.assigned.add(key);
33
+ return key;
34
+ }
35
+ if (this.over.size < MAX_DROPPED_TRACKING)
36
+ this.over.add(key);
37
+ return OTHER_LABEL;
38
+ }
39
+ /** 被折叠的**不同**键数(记满 `MAX_DROPPED_TRACKING` 后为下界) */
40
+ get dropped() {
41
+ return this.over.size;
42
+ }
43
+ /** 清空配额(`reset()` 用)—— 与 `capabilities` / `models` / `scores` 三张表同步清 */
44
+ reset() {
45
+ this.assigned.clear();
46
+ this.over.clear();
47
+ }
48
+ }
49
+ /**
50
+ * 时长统计:环形窗口(算窗口内精确分位)+ 累积直方图(算可聚合的 bucket)。
51
+ * run / 能力 / 模型共用同一个实现,保证三种粒度的口径与取整完全一致。
52
+ */
53
+ export class DurationStat {
54
+ windowSize;
55
+ bounds;
56
+ ring = [];
57
+ cursor = 0;
58
+ /** 每桶非累积计数:counts[i] 对应 le = bounds[i];末位是 +Inf 桶 */
59
+ counts;
60
+ total = 0;
61
+ sum = 0;
62
+ constructor(windowSize, bounds) {
63
+ this.windowSize = windowSize;
64
+ this.bounds = bounds;
65
+ this.counts = new Array(bounds.length + 1).fill(0);
66
+ }
67
+ add(ms) {
68
+ this.total++;
69
+ this.sum += ms;
70
+ if (this.ring.length < this.windowSize)
71
+ this.ring.push(ms);
72
+ else {
73
+ this.ring[this.cursor] = ms;
74
+ this.cursor = (this.cursor + 1) % this.windowSize;
75
+ }
76
+ let i = 0;
77
+ while (i < this.bounds.length && ms > this.bounds[i])
78
+ i++;
79
+ this.counts[i]++;
80
+ }
81
+ get count() {
82
+ return this.total;
83
+ }
84
+ get sumMs() {
85
+ return this.sum;
86
+ }
87
+ get windowSamples() {
88
+ return this.ring.length;
89
+ }
90
+ /**
91
+ * 窗口内精确分位(Prometheus 的 quantile 语义:取第 ceil(q·n) 个样本)。
92
+ * 算法单源在 `core/stats.ts` —— 与 `report.ts` 的时长 p50/p95 必须同口径,
93
+ * 否则同一条 trace 在看板与报告里会有两个 p95。
94
+ */
95
+ percentile(q) {
96
+ if (this.ring.length === 0)
97
+ return 0;
98
+ const sorted = [...this.ring].sort((a, b) => a - b);
99
+ return percentile(sorted, q);
100
+ }
101
+ /** 累积 bucket 计数(长度 = bounds+1,末位为 +Inf = count)—— Prometheus 文本语义 */
102
+ cumulative() {
103
+ const out = [];
104
+ let running = 0;
105
+ for (const c of this.counts) {
106
+ running += c;
107
+ out.push(running);
108
+ }
109
+ return out;
110
+ }
111
+ /** 每桶**非累积**计数 —— OTLP histogram 的 bucketCounts 语义(与 cumulative() 千万别混用) */
112
+ perBucket() {
113
+ return [...this.counts];
114
+ }
115
+ get boundsList() {
116
+ return this.bounds;
117
+ }
118
+ reset() {
119
+ this.ring.length = 0;
120
+ this.cursor = 0;
121
+ this.counts.fill(0);
122
+ this.total = 0;
123
+ this.sum = 0;
124
+ }
125
+ }
126
+ /** run 时长:取根 span(`trace.rootSpanId`)的起止;根没收尾(如 sink 在失败路径拿到半截)时返回 undefined */
127
+ function runDurationMs(trace) {
128
+ const root = trace.spans.find((s) => s.spanId === trace.rootSpanId);
129
+ if (!root || root.endedAt === undefined)
130
+ return undefined;
131
+ return root.endedAt - root.startedAt;
132
+ }
133
+ function num(v) {
134
+ return typeof v === 'number' && Number.isFinite(v) ? v : 0;
135
+ }
136
+ /**
137
+ * 评分键 → 指标标签。键有两种形态:**折叠桶**(`__other__`,整个键就是标签,不含 `\t`)
138
+ * 与正常的 `name\tsource`(source 缺省为 '')。两个出口(Prometheus 文本 / OTLP)共用一处
139
+ * 解码 —— 各切各的必然有一处把折叠桶切成乱码。
140
+ */
141
+ export function scoreLabels(key) {
142
+ if (key === OTHER_LABEL)
143
+ return { name: OTHER_LABEL, source: '' };
144
+ const tab = key.indexOf('\t');
145
+ return { name: key.slice(0, tab), source: key.slice(tab + 1) };
146
+ }
147
+ /**
148
+ * 进程内累加器:`metricsSink` 的全部可变状态(run / 能力 / 模型 / 评分四个维度 +
149
+ * 三个基数配额)。渲染(`metrics-render.ts`)与 OTLP 导出(`metrics-otlp.ts`)只读它。
150
+ */
151
+ export class MetricsState {
152
+ opts;
153
+ runs = 0;
154
+ failed = 0;
155
+ costUsd = 0;
156
+ tokens = { input: 0, output: 0, cacheRead: 0, cacheCreation: 0 };
157
+ runStat;
158
+ capabilities = new Map();
159
+ models = new Map();
160
+ /** 评分累加器:key = `${name}\t${source}`(source 缺省 '';\t 不会出现在正常评分名里,做天然分隔符) */
161
+ scores = new Map();
162
+ // 三个维度的键空间都封在这些配额里 —— 没有它们,三张 Map 与各自的时长窗口都是无界的
163
+ capBudget;
164
+ modelBudget;
165
+ scoreBudget;
166
+ constructor(opts) {
167
+ this.opts = opts;
168
+ this.runStat = new DurationStat(opts.windowSize, opts.buckets);
169
+ this.capBudget = new KeyBudget(opts.maxCapabilities);
170
+ this.modelBudget = new KeyBudget(opts.maxModels);
171
+ this.scoreBudget = new KeyBudget(opts.maxScores);
172
+ }
173
+ newCapability() {
174
+ return {
175
+ calls: 0,
176
+ errors: 0,
177
+ stat: new DurationStat(this.opts.windowSize, this.opts.buckets),
178
+ tokens: null,
179
+ costUsd: null,
180
+ };
181
+ }
182
+ /** 能力标签分配:labelMode 决定粒度,capBudget 决定基数上限 */
183
+ labelFor(kind, name) {
184
+ if (this.opts.labelMode === 'none')
185
+ return null;
186
+ if (this.opts.labelMode === 'kind')
187
+ return kind;
188
+ return this.capBudget.take(`${kind}:${name}`);
189
+ }
190
+ accumulate(trace) {
191
+ this.runs++;
192
+ if (trace.status === 'error')
193
+ this.failed++;
194
+ const u = trace.totalUsage;
195
+ this.tokens.input += u.inputTokens;
196
+ this.tokens.output += u.outputTokens;
197
+ this.tokens.cacheRead += u.cacheReadTokens;
198
+ this.tokens.cacheCreation += u.cacheCreationTokens;
199
+ if (u.costEstimate != null)
200
+ this.costUsd += u.costEstimate;
201
+ const d = runDurationMs(trace);
202
+ if (d !== undefined)
203
+ this.runStat.add(d);
204
+ // —— 评分(R7):只认根 span 的 score 事件(attachScore 的写入位置);
205
+ // body 宽容读取 —— name 不是 string / value 不是有限 number 就跳过,观测不击穿业务
206
+ const rootSpan = trace.spans.find((s) => s.spanId === trace.rootSpanId);
207
+ if (rootSpan) {
208
+ for (const e of rootSpan.events) {
209
+ if (e.name !== 'score')
210
+ continue;
211
+ const body = e.body;
212
+ if (!body || typeof body !== 'object')
213
+ continue;
214
+ if (typeof body.name !== 'string')
215
+ continue;
216
+ if (typeof body.value !== 'number' || !Number.isFinite(body.value))
217
+ continue;
218
+ const source = typeof body.source === 'string' ? body.source : '';
219
+ const key = this.scoreBudget.take(`${body.name}\t${source}`);
220
+ const acc = this.scores.get(key) ?? { value: 0, count: 0, sum: 0 };
221
+ acc.value = body.value; // gauge 语义:覆盖为最近一次
222
+ acc.count++;
223
+ acc.sum += body.value;
224
+ this.scores.set(key, acc);
225
+ }
226
+ }
227
+ for (const span of trace.spans) {
228
+ if (span.kind === 'capability') {
229
+ const label = this.labelFor(capabilityKindOf(span), span.name);
230
+ // 时长与错误无论哪种 labelMode 都要累计;labelMode:'none' 时整块跳过
231
+ if (label !== null) {
232
+ const acc = this.capabilities.get(label) ?? this.newCapability();
233
+ acc.calls++;
234
+ if (span.status === 'error')
235
+ acc.errors++;
236
+ if (span.endedAt !== undefined)
237
+ acc.stat.add(Math.max(0, span.endedAt - span.startedAt));
238
+ // capability.usage = 子孙 llm.turn 聚合(tracer 写入);工具没有这个语义
239
+ if (span.usage) {
240
+ const sum = span.usage.inputTokens +
241
+ span.usage.outputTokens +
242
+ span.usage.cacheReadTokens +
243
+ span.usage.cacheCreationTokens;
244
+ acc.tokens = (acc.tokens ?? 0) + sum;
245
+ if (span.usage.costEstimate != null)
246
+ acc.costUsd = (acc.costUsd ?? 0) + span.usage.costEstimate;
247
+ }
248
+ this.capabilities.set(label, acc);
249
+ }
250
+ continue;
251
+ }
252
+ if (span.kind === 'llm.turn') {
253
+ const model = this.modelBudget.take(span.name);
254
+ const acc = this.models.get(model) ?? {
255
+ turns: 0,
256
+ tokens: 0,
257
+ costUsd: 0,
258
+ unpricedTurns: 0,
259
+ stat: new DurationStat(this.opts.windowSize, this.opts.buckets),
260
+ };
261
+ acc.turns++;
262
+ if (span.usage) {
263
+ acc.tokens +=
264
+ span.usage.inputTokens +
265
+ span.usage.outputTokens +
266
+ span.usage.cacheReadTokens +
267
+ span.usage.cacheCreationTokens;
268
+ if (span.usage.costEstimate != null)
269
+ acc.costUsd += span.usage.costEstimate;
270
+ else
271
+ acc.unpricedTurns++; // 有计量却算不出成本 = 模型不在价格表内
272
+ }
273
+ if (span.endedAt !== undefined)
274
+ acc.stat.add(Math.max(0, span.endedAt - span.startedAt));
275
+ this.models.set(model, acc);
276
+ // 普通工具的耗时/成败在 turn 的 tool.output 事件上(E1)—— 能力指标的另一路数据源
277
+ for (const e of span.events) {
278
+ if (e.name !== 'tool.output')
279
+ continue;
280
+ const body = e.body;
281
+ if (!body || typeof body !== 'object' || typeof body.tool !== 'string')
282
+ continue;
283
+ const label = this.labelFor('tool', body.tool);
284
+ if (label === null)
285
+ continue;
286
+ const tacc = this.capabilities.get(label) ?? this.newCapability();
287
+ tacc.calls++;
288
+ if (body.ok === false)
289
+ tacc.errors++;
290
+ tacc.stat.add(Math.max(0, num(body.durationMs)));
291
+ this.capabilities.set(label, tacc);
292
+ }
293
+ }
294
+ }
295
+ }
296
+ snapshot() {
297
+ const capabilityOut = {};
298
+ if (this.opts.labelMode !== 'none') {
299
+ for (const [label, acc] of this.capabilities) {
300
+ capabilityOut[label] = {
301
+ calls: acc.calls,
302
+ errors: acc.errors,
303
+ latencyP50: acc.stat.percentile(0.5),
304
+ latencyP95: acc.stat.percentile(0.95),
305
+ tokens: acc.tokens,
306
+ costUsd: acc.costUsd,
307
+ };
308
+ }
309
+ }
310
+ const modelOut = {};
311
+ for (const [model, acc] of this.models) {
312
+ modelOut[model] = {
313
+ turns: acc.turns,
314
+ tokens: acc.tokens,
315
+ costUsd: acc.costUsd,
316
+ unpricedTurns: acc.unpricedTurns,
317
+ latencyP50: acc.stat.percentile(0.5),
318
+ latencyP95: acc.stat.percentile(0.95),
319
+ };
320
+ }
321
+ const scoreOut = {};
322
+ for (const [key, acc] of this.scores) {
323
+ // 折叠桶没有 `name@source` 可黏(也不该有),原样以 `__other__` 出
324
+ if (key === OTHER_LABEL) {
325
+ scoreOut[OTHER_LABEL] = { ...acc };
326
+ continue;
327
+ }
328
+ const { name, source } = scoreLabels(key);
329
+ scoreOut[source === '' ? name : `${name}@${source}`] = { ...acc };
330
+ }
331
+ return {
332
+ runs: this.runs,
333
+ failed: this.failed,
334
+ latencyP50: this.runStat.percentile(0.5),
335
+ latencyP95: this.runStat.percentile(0.95),
336
+ tokens: this.tokens.input + this.tokens.output + this.tokens.cacheRead + this.tokens.cacheCreation,
337
+ costUsd: this.costUsd,
338
+ capabilities: capabilityOut,
339
+ models: modelOut,
340
+ scores: scoreOut,
341
+ droppedCapabilities: this.capBudget.dropped,
342
+ droppedModels: this.modelBudget.dropped,
343
+ droppedScores: this.scoreBudget.dropped,
344
+ };
345
+ }
346
+ reset() {
347
+ this.runs = 0;
348
+ this.failed = 0;
349
+ this.costUsd = 0;
350
+ this.tokens.input = 0;
351
+ this.tokens.output = 0;
352
+ this.tokens.cacheRead = 0;
353
+ this.tokens.cacheCreation = 0;
354
+ this.runStat.reset();
355
+ this.capabilities.clear();
356
+ this.models.clear();
357
+ this.scores.clear();
358
+ this.capBudget.reset();
359
+ this.modelBudget.reset();
360
+ this.scoreBudget.reset();
361
+ }
362
+ }
363
+ //# sourceMappingURL=metrics-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-state.js","sourceRoot":"","sources":["../../src/integrations/metrics-state.ts"],"names":[],"mappings":"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"}
@@ -1,19 +1,7 @@
1
1
  import type { TraceSink } from '../core/trace.js';
2
- /**
3
- * OTLP metrics 导出失败(带数值 `status`)。
4
- *
5
- * 为什么不能抛裸 `Error`:`engine/errors.ts` 的分类是鸭子类型,只看数据属性。
6
- * 裸 Error 会被判 `unknown` + `retryable:false` —— 宿主在 `onExportError` 里拿不到
7
- * status,也就没法区分「collector 拒收(4xx,改配置)」与「collector 挂了(5xx,等它回来)」。
8
- * 形状与 `otlp.ts` 的 `OtlpExportError` 一致(同层两处导出器不该有两种错误形状)。
9
- *
10
- * 注:本处抛错由 `onExportError` 接住并按「观测失败不得击穿业务」吞掉 —— 带 status 是为了
11
- * **可判断**,不是为了让谁重试。
12
- */
13
- export declare class MetricsExportError extends Error {
14
- readonly status: number;
15
- constructor(status: number, message: string);
16
- }
2
+ import type { MetricsSnapshot } from './metrics-state.js';
3
+ export type { CapabilityMetrics, ModelMetrics, ScoreMetrics, MetricsSnapshot, } from './metrics-state.js';
4
+ export { MetricsExportError } from './metrics-otlp.js';
17
5
  /**
18
6
  * Agentia —— 指标(D3 → 可观测下沉 E2/E3/E4/E5)。
19
7
  *
@@ -36,77 +24,6 @@ export declare class MetricsExportError extends Error {
36
24
  *
37
25
  * 零依赖:Prometheus 文本与 OTLP/JSON 都手写(纯文本 / JSON,不值得为此引客户端库)。
38
26
  */
39
- /** 能力维度指标(`snapshot().capabilities[label]`) */
40
- export interface CapabilityMetrics {
41
- /** 该能力的调用次数 */
42
- calls: number;
43
- /** 其中失败次数(工具 `ok:false`;skill/subagent 的 capability span `status:'error'`) */
44
- errors: number;
45
- /** 单次调用耗时(毫秒)的窗口内精确分位;无样本时 0 */
46
- latencyP50: number;
47
- latencyP95: number;
48
- /** 仅 skill/subagent:子孙 llm.turn 的 token 聚合(四类之和);工具为 null */
49
- tokens: number | null;
50
- /** 仅 skill/subagent:估算成本(美元);未定价或工具为 null */
51
- costUsd: number | null;
52
- }
53
- /** 模型维度指标(`snapshot().models[model]`) */
54
- export interface ModelMetrics {
55
- /** 该模型的 llm.turn 次数 */
56
- turns: number;
57
- /** 四类 token 之和 */
58
- tokens: number;
59
- /** 已定价部分的成本(美元);全未定价时为 0 */
60
- costUsd: number;
61
- /** 成本估不出来的 turn 数(模型不在价格表内,且未用 priceOverrides 覆盖)*/
62
- unpricedTurns: number;
63
- latencyP50: number;
64
- latencyP95: number;
65
- }
66
- /** 评分维度指标(`snapshot().scores[key]`,key 为 `name@source`,source 缺省时裸 name) */
67
- export interface ScoreMetrics {
68
- /** 最近一次评分值(gauge 语义 —— 分数不是累加量) */
69
- value: number;
70
- /** 评分条数 */
71
- count: number;
72
- /** 评分值合计(平均 = sum / count) */
73
- sum: number;
74
- }
75
- /** 进程内累计快照(`snapshot()` 返回) */
76
- export interface MetricsSnapshot {
77
- /** 投递过 trace 的 run 总数(= `export` 被调用次数) */
78
- runs: number;
79
- /** 其中 `trace.status === 'error'` 的条数(含 budget_exceeded / aborted / error) */
80
- failed: number;
81
- /** run 时长(根 span `endedAt - startedAt`)分位,毫秒;窗口内无样本时 0 */
82
- latencyP50: number;
83
- latencyP95: number;
84
- /**
85
- * 累计 token —— 口径 = **四类之和**(input + output + cacheRead + cacheCreation),
86
- * 与 `BudgetGuard` 的 token 口径一致。分项在 `render()` 里以 label 给出,不会丢。
87
- */
88
- tokens: number;
89
- /** 累计成本估算(美元);模型不在价格表内时该 run 不计入(见 usage.ts) */
90
- costUsd: number;
91
- /**
92
- * 能力维度(`labelMode:'none'` 时为空对象)。超 `maxCapabilities` 的键折叠在
93
- * `'__other__'` —— 该桶照常累加,所以这里的**总量**不受上限影响。
94
- */
95
- capabilities: Record<string, CapabilityMetrics>;
96
- /** 模型维度;超 `maxModels` 的键折叠在 `'__other__'`(同上:总量不丢) */
97
- models: Record<string, ModelMetrics>;
98
- /**
99
- * 评分维度(key 为 `name@source`,source 缺省时裸 name;无评分时为空对象);
100
- * 超 `maxScores` 的键折叠在 `'__other__'`。
101
- */
102
- scores: Record<string, ScoreMetrics>;
103
- /** 因 `maxCapabilities` 上限被归入 `__other__` 的不同能力数 */
104
- droppedCapabilities: number;
105
- /** 因 `maxModels` 上限被归入 `__other__` 的不同模型数 */
106
- droppedModels: number;
107
- /** 因 `maxScores` 上限被归入 `__other__` 的不同评分维度数 */
108
- droppedScores: number;
109
- }
110
27
  export interface MetricsSinkOptions {
111
28
  /**
112
29
  * 输出形态: