agent-inspect 1.9.0 → 2.0.0

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 (98) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +13 -9
  3. package/docs/ADAPTER-CONFORMANCE.md +1 -1
  4. package/docs/API.md +30 -29
  5. package/docs/CLI.md +41 -11
  6. package/docs/EXPORTS.md +1 -1
  7. package/docs/GETTING-STARTED.md +2 -1
  8. package/docs/KNOWN-ISSUES.md +8 -3
  9. package/docs/LIMITATIONS.md +6 -6
  10. package/docs/MIGRATION.md +8 -8
  11. package/docs/SCHEMA.md +29 -12
  12. package/package.json +1 -1
  13. package/packages/cli/dist/index.cjs +7135 -7481
  14. package/packages/cli/dist/index.cjs.map +1 -1
  15. package/packages/cli/dist/index.mjs +7135 -7481
  16. package/packages/cli/dist/index.mjs.map +1 -1
  17. package/packages/core/dist/advanced.cjs +2047 -26
  18. package/packages/core/dist/advanced.cjs.map +1 -1
  19. package/packages/core/dist/advanced.d.cts +346 -196
  20. package/packages/core/dist/advanced.d.ts +346 -196
  21. package/packages/core/dist/advanced.mjs +628 -5
  22. package/packages/core/dist/advanced.mjs.map +1 -1
  23. package/packages/core/dist/checks.d.cts +1 -1
  24. package/packages/core/dist/checks.d.ts +1 -1
  25. package/packages/core/dist/chunk-2ZXEMWGK.mjs +549 -0
  26. package/packages/core/dist/chunk-2ZXEMWGK.mjs.map +1 -0
  27. package/packages/core/dist/{chunk-57S5D6HR.mjs → chunk-4JVGFNQH.mjs} +50 -6
  28. package/packages/core/dist/chunk-4JVGFNQH.mjs.map +1 -0
  29. package/packages/core/dist/{chunk-6QSLZCBJ.mjs → chunk-A4V2H3YU.mjs} +329 -163
  30. package/packages/core/dist/chunk-A4V2H3YU.mjs.map +1 -0
  31. package/packages/core/dist/{chunk-74XZ6N7Q.mjs → chunk-IZBJAZGF.mjs} +12 -4
  32. package/packages/core/dist/chunk-IZBJAZGF.mjs.map +1 -0
  33. package/packages/core/dist/{chunk-VTIB5MDK.mjs → chunk-NQZPZ2FN.mjs} +15 -10
  34. package/packages/core/dist/chunk-NQZPZ2FN.mjs.map +1 -0
  35. package/packages/core/dist/{chunk-TZISEVLQ.mjs → chunk-XUNJMAPD.mjs} +3 -3
  36. package/packages/core/dist/{chunk-TZISEVLQ.mjs.map → chunk-XUNJMAPD.mjs.map} +1 -1
  37. package/packages/core/dist/context-CSKnzpXR.d.cts +177 -0
  38. package/packages/core/dist/context-yv2VSDQF.d.ts +177 -0
  39. package/packages/core/dist/diff.d.cts +2 -2
  40. package/packages/core/dist/diff.d.ts +2 -2
  41. package/packages/core/dist/diff.mjs +473 -3
  42. package/packages/core/dist/diff.mjs.map +1 -1
  43. package/packages/core/dist/exporters.cjs +691 -0
  44. package/packages/core/dist/exporters.cjs.map +1 -1
  45. package/packages/core/dist/exporters.d.cts +24 -3
  46. package/packages/core/dist/exporters.d.ts +24 -3
  47. package/packages/core/dist/exporters.mjs +1113 -3
  48. package/packages/core/dist/exporters.mjs.map +1 -1
  49. package/packages/core/dist/index.cjs +1385 -8168
  50. package/packages/core/dist/index.cjs.map +1 -1
  51. package/packages/core/dist/index.d.cts +8 -350
  52. package/packages/core/dist/index.d.ts +8 -350
  53. package/packages/core/dist/index.mjs +18 -1478
  54. package/packages/core/dist/index.mjs.map +1 -1
  55. package/packages/core/dist/{log-config-DanPV3P9.d.cts → log-config-8aE5Kxtr.d.cts} +1 -1
  56. package/packages/core/dist/{log-config-BPHS4Sds.d.ts → log-config-DVimQJho.d.ts} +1 -1
  57. package/packages/core/dist/logs.d.cts +2 -2
  58. package/packages/core/dist/logs.d.ts +2 -2
  59. package/packages/core/dist/logs.mjs +785 -2
  60. package/packages/core/dist/logs.mjs.map +1 -1
  61. package/packages/core/dist/{persisted-inspect-event-Cw7TeYGr.d.ts → persisted-inspect-event-D-WpXeZX.d.ts} +14 -5
  62. package/packages/core/dist/{persisted-inspect-event-DHPfzUd8.d.cts → persisted-inspect-event-DHcHPUKv.d.cts} +14 -5
  63. package/packages/core/dist/persisted.cjs +11 -1
  64. package/packages/core/dist/persisted.cjs.map +1 -1
  65. package/packages/core/dist/persisted.d.cts +4 -4
  66. package/packages/core/dist/persisted.d.ts +4 -4
  67. package/packages/core/dist/persisted.mjs +150 -3
  68. package/packages/core/dist/persisted.mjs.map +1 -1
  69. package/packages/core/dist/readers.cjs +27 -10
  70. package/packages/core/dist/readers.cjs.map +1 -1
  71. package/packages/core/dist/readers.d.cts +1 -1
  72. package/packages/core/dist/readers.d.ts +1 -1
  73. package/packages/core/dist/readers.mjs +1580 -4
  74. package/packages/core/dist/readers.mjs.map +1 -1
  75. package/packages/core/dist/{types-Ap9uMdx_.d.ts → types-D-Y1kOU-.d.ts} +2 -2
  76. package/packages/core/dist/{types-B2-BU5CS.d.cts → types-DgMN3qow.d.cts} +2 -2
  77. package/packages/core/dist/writers.cjs +49 -3
  78. package/packages/core/dist/writers.cjs.map +1 -1
  79. package/packages/core/dist/writers.d.cts +1 -1
  80. package/packages/core/dist/writers.d.ts +1 -1
  81. package/packages/core/dist/writers.mjs +341 -4
  82. package/packages/core/dist/writers.mjs.map +1 -1
  83. package/packages/core/dist/chunk-57S5D6HR.mjs.map +0 -1
  84. package/packages/core/dist/chunk-6QSLZCBJ.mjs.map +0 -1
  85. package/packages/core/dist/chunk-6SZPTECC.mjs +0 -342
  86. package/packages/core/dist/chunk-6SZPTECC.mjs.map +0 -1
  87. package/packages/core/dist/chunk-74XZ6N7Q.mjs.map +0 -1
  88. package/packages/core/dist/chunk-HR7G62IE.mjs +0 -785
  89. package/packages/core/dist/chunk-HR7G62IE.mjs.map +0 -1
  90. package/packages/core/dist/chunk-TFLPUZ56.mjs +0 -1571
  91. package/packages/core/dist/chunk-TFLPUZ56.mjs.map +0 -1
  92. package/packages/core/dist/chunk-U2BGPESY.mjs +0 -150
  93. package/packages/core/dist/chunk-U2BGPESY.mjs.map +0 -1
  94. package/packages/core/dist/chunk-VTIB5MDK.mjs.map +0 -1
  95. package/packages/core/dist/chunk-Y56BPA3B.mjs +0 -990
  96. package/packages/core/dist/chunk-Y56BPA3B.mjs.map +0 -1
  97. package/packages/core/dist/chunk-YWAOOXLR.mjs +0 -475
  98. package/packages/core/dist/chunk-YWAOOXLR.mjs.map +0 -1
@@ -1,11 +1,634 @@
1
- export { MAX_TERMINAL_DEPTH, MAX_TERMINAL_NAME_LENGTH, TERMINAL_INDENT, createInspector, createInspectorRuntime, formatTerminalName, getCurrentContext, getCurrentCorrelationMetadata, getCurrentDepth, getCurrentRunId, getCurrentRunName, getCurrentStepId, getIndent, getParentStepId, getTraceDirFromContext, getTraceSafetyFromContext, hasActiveContext, isSilentContext, printError, printFailedAt, printRunComplete, printRunStart, printStepComplete, printStepStart, renderErrorLine, renderRunSummary, renderStepLine, runWithContext, runWithStepContext } from './chunk-6QSLZCBJ.mjs';
1
+ export { MAX_TERMINAL_DEPTH, MAX_TERMINAL_NAME_LENGTH, TERMINAL_INDENT, TraceDirectory, createInspector, createInspectorRuntime, formatTerminalName, getCurrentContext, getCurrentCorrelationMetadata, getCurrentDepth, getCurrentRunId, getCurrentRunName, getCurrentStepId, getIndent, getParentStepId, getTraceDirFromContext, getTraceSafetyFromContext, hasActiveContext, isAgentInspectEnabled, isSilentContext, maybeInspectRun, printError, printFailedAt, printRunComplete, printRunStart, printStepComplete, printStepStart, renderErrorLine, renderRunSummary, renderStepLine, resolveTraceDir, runWithContext, runWithStepContext } from './chunk-A4V2H3YU.mjs';
2
+ import { buildRunSummary, extractMetadata } from './chunk-2ZXEMWGK.mjs';
3
+ export { buildRunSummary, buildRunTimeline, buildRunWhatSummary, extractMetadata, renderRunWhat, renderTimeline } from './chunk-2ZXEMWGK.mjs';
2
4
  import './chunk-BT7CATSD.mjs';
3
- export { DEFAULT_MAX_EVENT_BYTES, DEFAULT_MAX_METADATA_VALUE_LENGTH, DEFAULT_MAX_PREVIEW_LENGTH, prepareMetadataForDisk, prepareTraceEventForDisk, resolveTraceSafetyOptions } from './chunk-57S5D6HR.mjs';
5
+ import { readTraceEventsFromFile } from './chunk-4JVGFNQH.mjs';
6
+ export { DEFAULT_MAX_EVENT_BYTES, DEFAULT_MAX_METADATA_VALUE_LENGTH, DEFAULT_MAX_PREVIEW_LENGTH, getRunIdFromTraceFileName, initializeTraceFile, listTraceFiles, prepareMetadataForDisk, prepareTraceEventForDisk, readTraceEvents, readTraceFile, resolveTraceSafetyOptions, serializeEvent, validateEvent, writeTraceEvent } from './chunk-4JVGFNQH.mjs';
7
+ import { resolveRedactionProfile } from './chunk-EDTQHZPM.mjs';
4
8
  export { resolveRedactionProfile } from './chunk-EDTQHZPM.mjs';
5
- import './chunk-VU6O5QAH.mjs';
9
+ import { Redactor } from './chunk-VU6O5QAH.mjs';
6
10
  import './chunk-S4YWKV4G.mjs';
7
- export { DEFAULT_TRACE_DIR_NAME, FALLBACK_TRACE_DIR, MAX_NAME_LENGTH, RUNS_DIR_NAME, createRunId, createStepId, ensureTraceDir, formatDuration, formatError, formatTimestamp, getDefaultTraceDir, getTraceFilePath, truncateName, warn } from './chunk-VTIB5MDK.mjs';
8
- import './chunk-74XZ6N7Q.mjs';
11
+ import { parseDuration, formatDuration, isTraceEvent } from './chunk-NQZPZ2FN.mjs';
12
+ export { DEFAULT_TRACE_DIR_NAME, FALLBACK_TRACE_DIR, MAX_NAME_LENGTH, RUNS_DIR_NAME, createRunId, createStepId, ensureTraceDir, formatDuration, formatError, formatTimestamp, getDefaultTraceDir, getTraceFilePath, isStepStatus, isStepType, isTraceEvent, parseDuration, parseTraceJsonl, truncateName, unknownTraceFormatMessage, warn } from './chunk-NQZPZ2FN.mjs';
13
+ import './chunk-IZBJAZGF.mjs';
9
14
  import './chunk-7TGZLWEE.mjs';
15
+ import { createReadStream } from 'fs';
16
+ import { createInterface } from 'readline';
17
+
18
+ // packages/core/src/trace-filter.ts
19
+ function toLower(s) {
20
+ return typeof s === "string" ? s.toLowerCase() : "";
21
+ }
22
+ function filterTraces(traces, options) {
23
+ const input = [...traces];
24
+ let out = input.filter((t) => {
25
+ if (options.status && t.status !== options.status) return false;
26
+ if (options.name) {
27
+ const q = options.name.toLowerCase();
28
+ const hay = `${toLower(t.name)} ${toLower(t.runId)}`;
29
+ if (!hay.includes(q)) return false;
30
+ }
31
+ if (options.since) {
32
+ const windowMs = parseDuration(options.since);
33
+ const cutoff = Date.now() - windowMs;
34
+ const started = typeof t.startedAt === "number" ? t.startedAt : void 0;
35
+ const basis = started ?? t.createdAt.getTime();
36
+ if (!Number.isFinite(basis) || basis < cutoff) return false;
37
+ }
38
+ return true;
39
+ });
40
+ out.sort((a, b) => {
41
+ const aTime = (typeof a.startedAt === "number" ? a.startedAt : void 0) ?? a.createdAt.getTime();
42
+ const bTime = (typeof b.startedAt === "number" ? b.startedAt : void 0) ?? b.createdAt.getTime();
43
+ return bTime - aTime;
44
+ });
45
+ if (typeof options.limit === "number" && Number.isFinite(options.limit)) {
46
+ const n = Math.max(0, Math.floor(options.limit));
47
+ out = out.slice(0, n);
48
+ }
49
+ return out;
50
+ }
51
+
52
+ // packages/core/src/explain.ts
53
+ function flatten(nodes, out = []) {
54
+ for (const node of nodes) {
55
+ out.push({ node, index: out.length + 1 });
56
+ flatten(node.children, out);
57
+ }
58
+ return out;
59
+ }
60
+ function redactValue(redactor, key, value) {
61
+ return redactor.redactValue(key, value);
62
+ }
63
+ function fact(id, label, value, redactor) {
64
+ return {
65
+ id,
66
+ label,
67
+ value: redactValue(redactor, id.split(".").at(-1) ?? id, value),
68
+ source: "trace",
69
+ confidence: "observed"
70
+ };
71
+ }
72
+ function topKinds(run) {
73
+ return Object.entries(run.metadata.kinds).filter(([, count]) => count > 0).sort((a, b) => {
74
+ if (b[1] !== a[1]) return b[1] - a[1];
75
+ return a[0].localeCompare(b[0]);
76
+ }).slice(0, 5).map(([kind, count]) => `${kind}:${count}`);
77
+ }
78
+ function countErrorNodes(nodes) {
79
+ return nodes.filter((entry) => entry.node.event.status === "error").length;
80
+ }
81
+ function slowestNode(nodes) {
82
+ return nodes.filter((entry) => entry.node.event.durationMs !== void 0).sort((a, b) => {
83
+ const delta = (b.node.event.durationMs ?? 0) - (a.node.event.durationMs ?? 0);
84
+ return delta !== 0 ? delta : a.index - b.index;
85
+ })[0];
86
+ }
87
+ function attributeFacts(nodes, redactor) {
88
+ const facts = [];
89
+ for (const entry of nodes) {
90
+ const attrs = entry.node.event.attributes;
91
+ if (attrs === void 0) continue;
92
+ for (const key of Object.keys(attrs).sort()) {
93
+ facts.push({
94
+ id: `node.${entry.index}.attributes.${key}`,
95
+ label: `${entry.node.event.name} attribute ${key}`,
96
+ value: redactValue(redactor, key, attrs[key]),
97
+ source: "trace",
98
+ confidence: "observed"
99
+ });
100
+ if (facts.length >= 8) return facts;
101
+ }
102
+ }
103
+ return facts;
104
+ }
105
+ function buildFacts(run, redactor) {
106
+ const nodes = flatten(run.children);
107
+ const facts = [
108
+ fact("run.id", "Run id", run.runId, redactor),
109
+ fact("run.name", "Run name", run.name ?? run.runId, redactor),
110
+ fact("run.status", "Run status", run.status ?? "unknown", redactor),
111
+ fact("run.totalEvents", "Total events", run.metadata.totalEvents, redactor),
112
+ fact("run.stepCount", "Top-level step count", run.children.length, redactor),
113
+ fact("run.nodeCount", "Total node count", nodes.length, redactor),
114
+ fact("run.errorNodeCount", "Error node count", countErrorNodes(nodes), redactor),
115
+ fact("run.kinds", "Observed kind mix", topKinds(run), redactor)
116
+ ];
117
+ if (run.durationMs !== void 0) {
118
+ facts.push(fact("run.durationMs", "Run duration milliseconds", run.durationMs, redactor));
119
+ }
120
+ const slowest = slowestNode(nodes);
121
+ if (slowest !== void 0) {
122
+ facts.push(
123
+ fact("run.slowestNode", "Slowest observed node", {
124
+ name: slowest.node.event.name,
125
+ kind: slowest.node.event.kind,
126
+ durationMs: slowest.node.event.durationMs
127
+ }, redactor)
128
+ );
129
+ }
130
+ facts.push(...attributeFacts(nodes, redactor));
131
+ return facts;
132
+ }
133
+ function buildInferences(run, facts) {
134
+ const inferences = [];
135
+ const errorFact = facts.find((item) => item.id === "run.errorNodeCount");
136
+ const kindFact = facts.find((item) => item.id === "run.kinds");
137
+ const durationFact = facts.find((item) => item.id === "run.durationMs");
138
+ const errorNodeCount = typeof errorFact?.value === "number" ? errorFact.value : 0;
139
+ if (run.status === "error" || errorNodeCount > 0) {
140
+ inferences.push({
141
+ id: "outcome.error",
142
+ label: "Outcome",
143
+ text: "The run recorded an error status or at least one error node.",
144
+ evidence: ["run.status", "run.errorNodeCount"],
145
+ confidence: "deterministic"
146
+ });
147
+ } else if (run.status === "ok") {
148
+ inferences.push({
149
+ id: "outcome.success",
150
+ label: "Outcome",
151
+ text: "The run completed without observed error nodes.",
152
+ evidence: ["run.status", "run.errorNodeCount"],
153
+ confidence: "deterministic"
154
+ });
155
+ }
156
+ if (kindFact !== void 0) {
157
+ inferences.push({
158
+ id: "shape.kind-mix",
159
+ label: "Trace shape",
160
+ text: "The explanation is based on the observed event kind mix, not generated content.",
161
+ evidence: [kindFact.id],
162
+ confidence: "deterministic"
163
+ });
164
+ }
165
+ if (durationFact !== void 0) {
166
+ inferences.push({
167
+ id: "timing.duration",
168
+ label: "Timing",
169
+ text: "Timing claims are limited to persisted duration fields in the trace.",
170
+ evidence: [durationFact.id],
171
+ confidence: "deterministic"
172
+ });
173
+ }
174
+ return inferences;
175
+ }
176
+ function buildLocalExplanation(run, options = {}) {
177
+ const redactionProfile = options.redactionProfile ?? "local";
178
+ const resolved = resolveRedactionProfile(redactionProfile);
179
+ const redactor = new Redactor({ extraKeys: resolved.extraKeys });
180
+ const mode = options.mode ?? "local";
181
+ const facts = buildFacts(run, redactor);
182
+ return {
183
+ mode,
184
+ runId: String(redactValue(redactor, "runId", run.runId)),
185
+ ...run.name !== void 0 ? { name: String(redactValue(redactor, "name", run.name)) } : {},
186
+ ...run.status !== void 0 ? { status: run.status } : {},
187
+ redactionProfile,
188
+ facts,
189
+ inferences: mode === "dry-run" ? [] : buildInferences(run, facts),
190
+ notes: [
191
+ "Generated locally without provider or network calls.",
192
+ "Facts are observed from normalized trace data; inferences are deterministic labels."
193
+ ]
194
+ };
195
+ }
196
+
197
+ // packages/core/src/stats.ts
198
+ function percentile(sorted, p) {
199
+ if (sorted.length === 0) return void 0;
200
+ const idx = Math.min(
201
+ sorted.length - 1,
202
+ Math.max(0, Math.ceil(p / 100 * sorted.length) - 1)
203
+ );
204
+ return sorted[idx];
205
+ }
206
+ async function readRunStartedMetadata(filePath) {
207
+ try {
208
+ const events = await readTraceEventsFromFile(filePath);
209
+ for (const event of events) {
210
+ if (event.event !== "run_started") continue;
211
+ const rs = event;
212
+ if (rs.metadata && typeof rs.metadata === "object") {
213
+ return rs.metadata;
214
+ }
215
+ return void 0;
216
+ }
217
+ } catch {
218
+ }
219
+ return void 0;
220
+ }
221
+ function metaMatchesCorrelation(metadata, correlationId, groupId) {
222
+ if (correlationId) {
223
+ const v = metadata?.correlationId;
224
+ if (typeof v !== "string" || v !== correlationId) return false;
225
+ }
226
+ if (groupId) {
227
+ const v = metadata?.groupId;
228
+ if (typeof v !== "string" || v !== groupId) return false;
229
+ }
230
+ return true;
231
+ }
232
+ async function buildTraceStats(metas, options) {
233
+ let filtered = filterTraces(metas, { since: options.since });
234
+ if (options.correlationId || options.groupId) {
235
+ const next = [];
236
+ for (const m of filtered) {
237
+ const md = await readRunStartedMetadata(m.filePath);
238
+ if (metaMatchesCorrelation(md, options.correlationId, options.groupId)) {
239
+ next.push(m);
240
+ }
241
+ }
242
+ filtered = next;
243
+ }
244
+ let successCount = 0;
245
+ let errorCount = 0;
246
+ let runningCount = 0;
247
+ let unknownCount = 0;
248
+ const durations = [];
249
+ let totalSteps = 0;
250
+ let totalLlmSteps = 0;
251
+ let totalToolSteps = 0;
252
+ let totalErrorSteps = 0;
253
+ const slowestRuns = [];
254
+ const slowestSteps = [];
255
+ for (const m of filtered) {
256
+ if (m.status === "success") successCount += 1;
257
+ else if (m.status === "error") errorCount += 1;
258
+ else if (m.status === "running") runningCount += 1;
259
+ else unknownCount += 1;
260
+ if (typeof m.durationMs === "number" && Number.isFinite(m.durationMs) && m.durationMs >= 0) {
261
+ durations.push(m.durationMs);
262
+ slowestRuns.push({
263
+ runId: m.runId,
264
+ name: m.name,
265
+ durationMs: m.durationMs,
266
+ status: m.status
267
+ });
268
+ }
269
+ try {
270
+ const events = await readTraceEventsFromFile(m.filePath);
271
+ if (events.length === 0) continue;
272
+ const summary = buildRunSummary(events);
273
+ totalSteps += summary.totalSteps;
274
+ totalLlmSteps += summary.llmSteps;
275
+ totalToolSteps += summary.toolSteps;
276
+ totalErrorSteps += summary.errorSteps;
277
+ const steps = collectCompletedSteps(events, m.runId);
278
+ for (const s of steps) {
279
+ slowestSteps.push(s);
280
+ }
281
+ } catch {
282
+ }
283
+ }
284
+ slowestRuns.sort((a, b) => (b.durationMs ?? 0) - (a.durationMs ?? 0));
285
+ slowestSteps.sort((a, b) => b.durationMs - a.durationMs);
286
+ const runLimit = options.slowRunLimit ?? 5;
287
+ const stepLimit = options.slowStepLimit ?? 5;
288
+ const sortedDur = [...durations].sort((a, b) => a - b);
289
+ const totalRuns = filtered.length;
290
+ const errorRate = totalRuns > 0 ? errorCount / totalRuns : 0;
291
+ const sumDur = durations.reduce((a, b) => a + b, 0);
292
+ return {
293
+ traceDir: options.traceDir,
294
+ ...options.since ? { since: options.since } : {},
295
+ ...options.correlationId ? { correlationId: options.correlationId } : {},
296
+ ...options.groupId ? { groupId: options.groupId } : {},
297
+ totalRuns,
298
+ successCount,
299
+ errorCount,
300
+ runningCount,
301
+ unknownCount,
302
+ errorRate,
303
+ duration: {
304
+ ...sortedDur.length > 0 ? {
305
+ minMs: sortedDur[0],
306
+ maxMs: sortedDur[sortedDur.length - 1],
307
+ avgMs: sumDur / sortedDur.length,
308
+ p50Ms: percentile(sortedDur, 50),
309
+ p95Ms: percentile(sortedDur, 95)
310
+ } : {}
311
+ },
312
+ totalSteps,
313
+ avgStepsPerRun: totalRuns > 0 ? totalSteps / totalRuns : 0,
314
+ totalLlmSteps,
315
+ totalToolSteps,
316
+ totalErrorSteps,
317
+ slowestRuns: slowestRuns.slice(0, runLimit),
318
+ slowestSteps: slowestSteps.slice(0, stepLimit)
319
+ };
320
+ }
321
+ function collectCompletedSteps(events, runId) {
322
+ const started = /* @__PURE__ */ new Map();
323
+ const out = [];
324
+ for (const e of events) {
325
+ if (e.event === "step_started") {
326
+ const s = e;
327
+ started.set(s.stepId, { name: s.name, type: s.type });
328
+ }
329
+ if (e.event === "step_completed") {
330
+ const c = e;
331
+ if (c.status !== "success" && c.status !== "error") continue;
332
+ if (typeof c.durationMs !== "number" || !Number.isFinite(c.durationMs)) {
333
+ continue;
334
+ }
335
+ const meta = started.get(c.stepId);
336
+ out.push({
337
+ runId,
338
+ stepName: meta?.name ?? c.stepId,
339
+ stepType: meta?.type ?? "logic",
340
+ durationMs: c.durationMs
341
+ });
342
+ }
343
+ }
344
+ return out;
345
+ }
346
+ function renderTraceStats(stats) {
347
+ const lines = [];
348
+ lines.push("Trace stats (local)");
349
+ lines.push(`Directory: ${stats.traceDir}`);
350
+ if (stats.since) lines.push(`Since: ${stats.since}`);
351
+ if (stats.correlationId) lines.push(`Correlation ID: ${stats.correlationId}`);
352
+ if (stats.groupId) lines.push(`Group ID: ${stats.groupId}`);
353
+ lines.push("");
354
+ lines.push(`Runs: ${stats.totalRuns}`);
355
+ lines.push(
356
+ ` success: ${stats.successCount} error: ${stats.errorCount} running: ${stats.runningCount} unknown: ${stats.unknownCount}`
357
+ );
358
+ lines.push(`Error rate: ${(stats.errorRate * 100).toFixed(1)}%`);
359
+ if (stats.duration.avgMs !== void 0) {
360
+ lines.push(
361
+ `Duration: min ${formatDuration(stats.duration.minMs ?? 0)} | avg ${formatDuration(stats.duration.avgMs)} | p50 ${formatDuration(stats.duration.p50Ms ?? 0)} | p95 ${formatDuration(stats.duration.p95Ms ?? 0)} | max ${formatDuration(stats.duration.maxMs ?? 0)}`
362
+ );
363
+ }
364
+ lines.push("");
365
+ lines.push(`Steps: ${stats.totalSteps} (avg ${stats.avgStepsPerRun.toFixed(1)} per run)`);
366
+ lines.push(
367
+ ` LLM: ${stats.totalLlmSteps} tool: ${stats.totalToolSteps} errors: ${stats.totalErrorSteps}`
368
+ );
369
+ if (stats.slowestRuns.length > 0) {
370
+ lines.push("");
371
+ lines.push("Slowest runs:");
372
+ for (const r of stats.slowestRuns) {
373
+ lines.push(
374
+ ` ${r.runId} | ${r.name ?? "-"} | ${formatDuration(r.durationMs ?? 0)} | ${r.status}`
375
+ );
376
+ }
377
+ }
378
+ if (stats.slowestSteps.length > 0) {
379
+ lines.push("");
380
+ lines.push("Slowest steps:");
381
+ for (const s of stats.slowestSteps) {
382
+ lines.push(
383
+ ` ${s.runId} | ${s.stepType}:${s.stepName} | ${formatDuration(s.durationMs)}`
384
+ );
385
+ }
386
+ }
387
+ return lines.join("\n");
388
+ }
389
+
390
+ // packages/core/src/search.ts
391
+ function parseDurationFilter(expr) {
392
+ const raw = expr.trim();
393
+ const m = raw.match(/^(>=|<=|>|<)\s*(.+)$/);
394
+ if (!m) {
395
+ throw new Error(
396
+ `Invalid --duration "${expr}". Use forms like >5s, >=500ms, <2m.`
397
+ );
398
+ }
399
+ const op = m[1];
400
+ const ms = parseDuration(m[2].trim());
401
+ return { op, ms };
402
+ }
403
+ function durationMatches(valueMs, filter) {
404
+ if (valueMs === void 0 || !Number.isFinite(valueMs)) return false;
405
+ switch (filter.op) {
406
+ case ">":
407
+ return valueMs > filter.ms;
408
+ case ">=":
409
+ return valueMs >= filter.ms;
410
+ case "<":
411
+ return valueMs < filter.ms;
412
+ case "<=":
413
+ return valueMs <= filter.ms;
414
+ default:
415
+ return false;
416
+ }
417
+ }
418
+ function normalizeStepTypeFilter(kind, type) {
419
+ const v = (kind ?? type)?.trim().toLowerCase();
420
+ return v && v !== "" ? v : void 0;
421
+ }
422
+ function nameMatches(hay, needle) {
423
+ return hay.toLowerCase().includes(needle.toLowerCase());
424
+ }
425
+ async function searchTraces(metas, options) {
426
+ let filtered = filterTraces(metas, { since: options.since });
427
+ const stepTypeFilter = normalizeStepTypeFilter(options.kind, options.type);
428
+ const nameQuery = options.name?.trim();
429
+ const toolQuery = options.tool?.trim();
430
+ let durationFilter;
431
+ if (options.duration) {
432
+ durationFilter = parseDurationFilter(options.duration);
433
+ }
434
+ const limit = options.limit ?? 50;
435
+ const hasContentFilter = Boolean(
436
+ options.status || stepTypeFilter || nameQuery || toolQuery || durationFilter
437
+ );
438
+ const results = [];
439
+ if (!hasContentFilter) {
440
+ for (const m of filtered) {
441
+ results.push({
442
+ runId: m.runId,
443
+ runName: m.name,
444
+ runStatus: m.status,
445
+ timestamp: m.startedAt,
446
+ durationMs: m.durationMs,
447
+ matchReason: "trace in directory",
448
+ matchedFields: ["run"],
449
+ filePath: m.filePath
450
+ });
451
+ }
452
+ return results.slice(0, limit);
453
+ }
454
+ for (const m of filtered) {
455
+ if (options.status && m.status !== options.status) continue;
456
+ let events = [];
457
+ try {
458
+ events = await readTraceEventsFromFile(m.filePath);
459
+ } catch {
460
+ continue;
461
+ }
462
+ if (events.length === 0) continue;
463
+ const runMatches = matchRunLevel(m, {
464
+ stepTypeFilter,
465
+ nameQuery,
466
+ toolQuery,
467
+ durationFilter,
468
+ statusFilter: options.status
469
+ });
470
+ results.push(...runMatches);
471
+ const stepMatches = matchStepLevel(m, events, {
472
+ stepTypeFilter,
473
+ nameQuery,
474
+ toolQuery,
475
+ durationFilter,
476
+ statusFilter: options.status
477
+ });
478
+ results.push(...stepMatches);
479
+ }
480
+ results.sort((a, b) => {
481
+ const ta = a.timestamp ?? 0;
482
+ const tb = b.timestamp ?? 0;
483
+ if (ta !== tb) return ta - tb;
484
+ const runCmp = a.runId.localeCompare(b.runId);
485
+ if (runCmp !== 0) return runCmp;
486
+ return (a.stepName ?? "").localeCompare(b.stepName ?? "");
487
+ });
488
+ return results.slice(0, limit);
489
+ }
490
+ function matchRunLevel(m, opts) {
491
+ if (opts.stepTypeFilter || opts.toolQuery) return [];
492
+ const out = [];
493
+ const fields = [];
494
+ if (opts.statusFilter && m.status === opts.statusFilter) {
495
+ fields.push("run.status");
496
+ }
497
+ if (opts.nameQuery && nameMatches(m.name ?? m.runId, opts.nameQuery)) {
498
+ fields.push("run.name");
499
+ }
500
+ if (opts.durationFilter && durationMatches(m.durationMs, opts.durationFilter)) {
501
+ fields.push("run.durationMs");
502
+ }
503
+ if (fields.length === 0) return out;
504
+ out.push({
505
+ runId: m.runId,
506
+ runName: m.name,
507
+ runStatus: m.status,
508
+ timestamp: m.startedAt,
509
+ durationMs: m.durationMs,
510
+ matchReason: `run match: ${fields.join(", ")}`,
511
+ matchedFields: fields,
512
+ filePath: m.filePath
513
+ });
514
+ return out;
515
+ }
516
+ function matchStepLevel(m, events, opts) {
517
+ const out = [];
518
+ const started = /* @__PURE__ */ new Map();
519
+ for (const e of events) {
520
+ if (e.event === "step_started") {
521
+ started.set(e.stepId, e);
522
+ }
523
+ }
524
+ for (const e of events) {
525
+ if (e.event !== "step_completed") continue;
526
+ const c = e;
527
+ const s = started.get(c.stepId);
528
+ if (!s) continue;
529
+ const fields = [];
530
+ const stepType = s.type;
531
+ if (opts.stepTypeFilter && stepType !== opts.stepTypeFilter) {
532
+ continue;
533
+ }
534
+ const hasStepFilters = opts.stepTypeFilter || opts.nameQuery || opts.toolQuery || opts.durationFilter || opts.statusFilter === "error" || opts.statusFilter === "success";
535
+ if (!hasStepFilters) continue;
536
+ if (opts.statusFilter === "error" && c.status === "error") {
537
+ fields.push("step.status");
538
+ } else if (opts.statusFilter === "success" && c.status === "success") {
539
+ fields.push("step.status");
540
+ } else if (opts.statusFilter === "error" || opts.statusFilter === "success") {
541
+ continue;
542
+ }
543
+ if (opts.nameQuery) {
544
+ if (!nameMatches(s.name, opts.nameQuery)) continue;
545
+ fields.push("step.name");
546
+ }
547
+ if (opts.toolQuery) {
548
+ const toolName = typeof s.metadata?.toolName === "string" ? s.metadata.toolName : s.name;
549
+ if (!nameMatches(toolName, opts.toolQuery)) continue;
550
+ fields.push("step.tool");
551
+ }
552
+ if (opts.durationFilter) {
553
+ if (!durationMatches(c.durationMs, opts.durationFilter)) continue;
554
+ fields.push("step.durationMs");
555
+ }
556
+ if (opts.stepTypeFilter) {
557
+ fields.push("step.type");
558
+ }
559
+ if (fields.length === 0) continue;
560
+ out.push({
561
+ runId: m.runId,
562
+ runName: m.name,
563
+ runStatus: m.status,
564
+ stepId: c.stepId,
565
+ stepName: s.name,
566
+ stepType,
567
+ timestamp: s.startTime ?? s.timestamp,
568
+ durationMs: c.durationMs,
569
+ matchReason: `step match: ${fields.join(", ")}`,
570
+ matchedFields: fields,
571
+ filePath: m.filePath
572
+ });
573
+ }
574
+ return out;
575
+ }
576
+ async function loadTraceMetadataList(_traceDir, fileNames, getPath) {
577
+ const metas = [];
578
+ for (const fileName of fileNames) {
579
+ try {
580
+ const filePath = getPath(fileName);
581
+ const meta = await extractMetadata(filePath);
582
+ metas.push(meta);
583
+ } catch {
584
+ }
585
+ }
586
+ return metas;
587
+ }
588
+ var KNOWN_EVENTS = /* @__PURE__ */ new Set([
589
+ "run_started",
590
+ "run_completed",
591
+ "step_started",
592
+ "step_completed"
593
+ ]);
594
+ function isRecord(value) {
595
+ return typeof value === "object" && value !== null && !Array.isArray(value);
596
+ }
597
+ function safeParse(line) {
598
+ try {
599
+ return JSON.parse(line);
600
+ } catch {
601
+ return void 0;
602
+ }
603
+ }
604
+ async function isAgentInspectTrace(filePath) {
605
+ try {
606
+ const rl = createInterface({
607
+ input: createReadStream(filePath, { encoding: "utf8" }),
608
+ crlfDelay: Infinity
609
+ });
610
+ let checked = 0;
611
+ for await (const line of rl) {
612
+ const trimmed = line.trim();
613
+ if (trimmed === "") continue;
614
+ const parsed = safeParse(trimmed);
615
+ if (!parsed) continue;
616
+ if (!isRecord(parsed)) continue;
617
+ checked += 1;
618
+ if (isTraceEvent(parsed)) return true;
619
+ const ev = parsed.event;
620
+ const runId = parsed.runId;
621
+ if (typeof ev === "string" && KNOWN_EVENTS.has(ev) && typeof runId === "string") {
622
+ return true;
623
+ }
624
+ if (checked >= 20) break;
625
+ }
626
+ return false;
627
+ } catch {
628
+ return false;
629
+ }
630
+ }
631
+
632
+ export { buildLocalExplanation, buildTraceStats, filterTraces, isAgentInspectTrace, loadTraceMetadataList, parseDurationFilter, renderTraceStats, searchTraces };
10
633
  //# sourceMappingURL=advanced.mjs.map
11
634
  //# sourceMappingURL=advanced.mjs.map