agent-inspect 4.0.0 → 4.2.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.
@@ -0,0 +1,3487 @@
1
+ import { readdir, stat, readFile } from 'fs/promises';
2
+ import os from 'os';
3
+ import path from 'path';
4
+ import crypto2, { webcrypto } from 'crypto';
5
+ import process2 from 'process';
6
+ import tty from 'tty';
7
+ import { AsyncLocalStorage } from 'async_hooks';
8
+ import { createReadStream } from 'fs';
9
+ import { createInterface } from 'readline';
10
+
11
+ var __create = Object.create;
12
+ var __defProp = Object.defineProperty;
13
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
14
+ var __getOwnPropNames = Object.getOwnPropertyNames;
15
+ var __getProtoOf = Object.getPrototypeOf;
16
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
17
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
18
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
19
+ }) : x)(function(x) {
20
+ if (typeof require !== "undefined") return require.apply(this, arguments);
21
+ throw Error('Dynamic require of "' + x + '" is not supported');
22
+ });
23
+ var __commonJS = (cb, mod) => function __require2() {
24
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
25
+ };
26
+ var __copyProps = (to, from, except, desc) => {
27
+ if (from && typeof from === "object" || typeof from === "function") {
28
+ for (let key of __getOwnPropNames(from))
29
+ if (!__hasOwnProp.call(to, key) && key !== except)
30
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
31
+ }
32
+ return to;
33
+ };
34
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
35
+ // If the importer is in node compatibility mode or this is not an ESM
36
+ // file that has been converted to a CommonJS file using a Babel-
37
+ // compatible transform (i.e. "__esModule" has not been set), then set
38
+ // "default" to the CommonJS "module.exports" for node compatibility.
39
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
40
+ mod
41
+ ));
42
+
43
+ // packages/core/src/types/persisted-inspect-event.ts
44
+ var INSPECT_KINDS = [
45
+ "RUN",
46
+ "AGENT",
47
+ "LLM",
48
+ "TOOL",
49
+ "CHAIN",
50
+ "RETRIEVER",
51
+ "DECISION",
52
+ "RESULT",
53
+ "ERROR",
54
+ "LOGIC",
55
+ "LOG"
56
+ ];
57
+ var ATTRIBUTION_CONFIDENCES = [
58
+ "explicit",
59
+ "correlated",
60
+ "heuristic",
61
+ "unknown"
62
+ ];
63
+ var PERSISTED_EVENT_SOURCE_TYPES = [
64
+ "manual",
65
+ "json-log",
66
+ "log4js",
67
+ "adapter",
68
+ "ai-sdk",
69
+ "otel"
70
+ ];
71
+ var PERSISTED_EVENT_STATUSES = [
72
+ "running",
73
+ "ok",
74
+ "error",
75
+ "unknown"
76
+ ];
77
+ function isRecord(value) {
78
+ return typeof value === "object" && value !== null && !Array.isArray(value);
79
+ }
80
+ function isString(value) {
81
+ return typeof value === "string";
82
+ }
83
+ function isNonEmptyString(value) {
84
+ return typeof value === "string" && value.length > 0;
85
+ }
86
+ function isOptionalString(value) {
87
+ return value === void 0 || isString(value);
88
+ }
89
+ function isNonNegativeNumber(value) {
90
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
91
+ }
92
+ function isOptionalNonNegativeNumber(value) {
93
+ return value === void 0 || isNonNegativeNumber(value);
94
+ }
95
+ function isInspectKind(value) {
96
+ return typeof value === "string" && INSPECT_KINDS.includes(value);
97
+ }
98
+ function isAttributionConfidence(value) {
99
+ return typeof value === "string" && ATTRIBUTION_CONFIDENCES.includes(value);
100
+ }
101
+ function isPersistedEventSourceType(value) {
102
+ return typeof value === "string" && PERSISTED_EVENT_SOURCE_TYPES.includes(value);
103
+ }
104
+ function isPersistedEventStatus(value) {
105
+ return typeof value === "string" && PERSISTED_EVENT_STATUSES.includes(value);
106
+ }
107
+ function isPersistedEventSource(value) {
108
+ if (!isRecord(value)) return false;
109
+ if (!isPersistedEventSourceType(value.type)) return false;
110
+ if (!isOptionalString(value.name)) return false;
111
+ if (!isOptionalString(value.version)) return false;
112
+ return true;
113
+ }
114
+ function isPersistedInspectError(value) {
115
+ if (!isRecord(value)) return false;
116
+ if (!isNonEmptyString(value.message)) return false;
117
+ if (!isOptionalString(value.name)) return false;
118
+ if (!isOptionalString(value.code)) return false;
119
+ return true;
120
+ }
121
+ function isPersistedTokenUsage(value) {
122
+ if (!isRecord(value)) return false;
123
+ if (!isOptionalNonNegativeNumber(value.input)) return false;
124
+ if (!isOptionalNonNegativeNumber(value.output)) return false;
125
+ if (!isOptionalNonNegativeNumber(value.total)) return false;
126
+ if (!isOptionalNonNegativeNumber(value.cached)) return false;
127
+ return true;
128
+ }
129
+ function isPersistedTraceContext(value) {
130
+ if (!isRecord(value)) return false;
131
+ if (!isOptionalString(value.traceId)) return false;
132
+ if (!isOptionalString(value.spanId)) return false;
133
+ if (!isOptionalString(value.parentSpanId)) return false;
134
+ return true;
135
+ }
136
+ function isPersistedInspectEvent(value) {
137
+ if (!isRecord(value)) return false;
138
+ if (value.schemaVersion !== "0.2" && value.schemaVersion !== "1.0") {
139
+ return false;
140
+ }
141
+ if (!isNonEmptyString(value.eventId)) return false;
142
+ if (!isNonEmptyString(value.runId)) return false;
143
+ if (!isInspectKind(value.kind)) return false;
144
+ if (!isNonEmptyString(value.name)) return false;
145
+ if (!isNonEmptyString(value.timestamp)) return false;
146
+ if (!isAttributionConfidence(value.confidence)) return false;
147
+ if (!isPersistedEventSource(value.source)) return false;
148
+ if (value.parentId !== void 0 && !isNonEmptyString(value.parentId)) {
149
+ return false;
150
+ }
151
+ if (value.status !== void 0 && !isPersistedEventStatus(value.status)) {
152
+ return false;
153
+ }
154
+ if (!isOptionalString(value.startedAt)) return false;
155
+ if (!isOptionalString(value.endedAt)) return false;
156
+ if (value.durationMs !== void 0 && !isNonNegativeNumber(value.durationMs)) {
157
+ return false;
158
+ }
159
+ if (value.attributes !== void 0 && !isRecord(value.attributes)) {
160
+ return false;
161
+ }
162
+ if (value.error !== void 0 && !isPersistedInspectError(value.error)) {
163
+ return false;
164
+ }
165
+ if (value.tokenUsage !== void 0 && !isPersistedTokenUsage(value.tokenUsage)) {
166
+ return false;
167
+ }
168
+ if (value.trace !== void 0 && !isPersistedTraceContext(value.trace)) {
169
+ return false;
170
+ }
171
+ return true;
172
+ }
173
+
174
+ // packages/core/src/utils/duration.ts
175
+ function parseDuration(duration) {
176
+ const raw = typeof duration === "string" ? duration.trim() : "";
177
+ const match = raw.match(/^(\d+)(ms|[smhd])$/);
178
+ if (!match) {
179
+ throw new Error(
180
+ `Invalid duration format: ${duration}. Use a positive integer followed by ms, s, m, h, or d (e.g. 500ms, 30s, 5m, 2h, 7d).`
181
+ );
182
+ }
183
+ const amount = Number.parseInt(match[1], 10);
184
+ const unit = match[2];
185
+ if (!Number.isFinite(amount) || amount <= 0) {
186
+ throw new Error(
187
+ `Invalid duration amount: ${duration}. Amount must be a positive integer.`
188
+ );
189
+ }
190
+ switch (unit) {
191
+ case "ms":
192
+ return amount;
193
+ case "s":
194
+ return amount * 1e3;
195
+ case "m":
196
+ return amount * 60 * 1e3;
197
+ case "h":
198
+ return amount * 60 * 60 * 1e3;
199
+ case "d":
200
+ return amount * 24 * 60 * 60 * 1e3;
201
+ default: {
202
+ throw new Error(`Unknown duration unit: ${unit}`);
203
+ }
204
+ }
205
+ }
206
+ function formatDuration(ms) {
207
+ if (!Number.isFinite(ms)) {
208
+ return "0ms";
209
+ }
210
+ if (ms < 0) {
211
+ throw new Error(`formatDuration: ms must be non-negative (got ${ms})`);
212
+ }
213
+ if (ms < 1e3) {
214
+ return `${Math.floor(ms)}ms`;
215
+ }
216
+ if (ms < 6e4) {
217
+ return `${(ms / 1e3).toFixed(2)}s`;
218
+ }
219
+ if (ms < 36e5) {
220
+ return `${(ms / 6e4).toFixed(1)}m`;
221
+ }
222
+ return `${(ms / 36e5).toFixed(1)}h`;
223
+ }
224
+
225
+ // node_modules/.pnpm/nanoid@5.1.11/node_modules/nanoid/url-alphabet/index.js
226
+ var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
227
+
228
+ // node_modules/.pnpm/nanoid@5.1.11/node_modules/nanoid/index.js
229
+ var POOL_SIZE_MULTIPLIER = 128;
230
+ var pool;
231
+ var poolOffset;
232
+ function fillPool(bytes) {
233
+ if (bytes < 0 || bytes > 1024) throw new RangeError("Wrong ID size");
234
+ if (!pool || pool.length < bytes) {
235
+ pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
236
+ webcrypto.getRandomValues(pool);
237
+ poolOffset = 0;
238
+ } else if (poolOffset + bytes > pool.length) {
239
+ webcrypto.getRandomValues(pool);
240
+ poolOffset = 0;
241
+ }
242
+ poolOffset += bytes;
243
+ }
244
+ function nanoid(size = 21) {
245
+ fillPool(size |= 0);
246
+ let id = "";
247
+ for (let i = poolOffset - size; i < poolOffset; i++) {
248
+ id += urlAlphabet[pool[i] & 63];
249
+ }
250
+ return id;
251
+ }
252
+
253
+ // packages/core/src/utils.ts
254
+ var DEFAULT_TRACE_DIR_NAME = ".agent-inspect";
255
+ var RUNS_DIR_NAME = "runs";
256
+ var FALLBACK_TRACE_DIR = path.join(
257
+ os.tmpdir(),
258
+ "agent-inspect",
259
+ RUNS_DIR_NAME
260
+ );
261
+ var MAX_NAME_LENGTH = 100;
262
+ function formatDuration2(ms) {
263
+ return formatDuration(ms);
264
+ }
265
+ function formatTimestamp(timestamp) {
266
+ if (!Number.isFinite(timestamp)) {
267
+ return "Invalid date";
268
+ }
269
+ const d = new Date(timestamp);
270
+ if (Number.isNaN(d.getTime())) {
271
+ return "Invalid date";
272
+ }
273
+ const y = d.getFullYear();
274
+ const mo = String(d.getMonth() + 1).padStart(2, "0");
275
+ const day = String(d.getDate()).padStart(2, "0");
276
+ const h = String(d.getHours()).padStart(2, "0");
277
+ const min = String(d.getMinutes()).padStart(2, "0");
278
+ const s = String(d.getSeconds()).padStart(2, "0");
279
+ return `${y}-${mo}-${day} ${h}:${min}:${s}`;
280
+ }
281
+ function getDefaultTraceDir() {
282
+ const envDir = process.env.AGENT_INSPECT_TRACE_DIR;
283
+ if (typeof envDir === "string" && envDir.trim() !== "") {
284
+ return envDir.trim();
285
+ }
286
+ try {
287
+ const home = os.homedir();
288
+ if (typeof home !== "string" || home.trim() === "") {
289
+ return FALLBACK_TRACE_DIR;
290
+ }
291
+ return path.join(home, DEFAULT_TRACE_DIR_NAME, RUNS_DIR_NAME);
292
+ } catch {
293
+ return FALLBACK_TRACE_DIR;
294
+ }
295
+ }
296
+ function getTraceFilePath(runId, traceDir) {
297
+ const baseDir = traceDir ?? getDefaultTraceDir();
298
+ let safeId = typeof runId === "string" && runId.trim() !== "" ? runId.trim() : "run_unknown";
299
+ safeId = path.basename(safeId);
300
+ if (safeId === "" || safeId === "." || safeId === "..") {
301
+ safeId = "run_unknown";
302
+ }
303
+ return path.join(baseDir, `${safeId}.jsonl`);
304
+ }
305
+ function formatError(error) {
306
+ if (error instanceof Error) {
307
+ const out = { message: error.message };
308
+ if (typeof error.stack === "string" && error.stack.length > 0) {
309
+ out.stack = error.stack;
310
+ }
311
+ return out;
312
+ }
313
+ if (typeof error === "string") {
314
+ return { message: error };
315
+ }
316
+ if (error === null) {
317
+ return { message: "Unknown error: null" };
318
+ }
319
+ if (error === void 0) {
320
+ return { message: "Unknown error: undefined" };
321
+ }
322
+ if (typeof error === "number" || typeof error === "boolean" || typeof error === "bigint") {
323
+ return { message: String(error) };
324
+ }
325
+ if (typeof error === "object") {
326
+ try {
327
+ return { message: JSON.stringify(error) };
328
+ } catch {
329
+ return { message: "Unknown error" };
330
+ }
331
+ }
332
+ return { message: "Unknown error" };
333
+ }
334
+ function truncateName(name, maxLength = MAX_NAME_LENGTH) {
335
+ if (typeof name !== "string" || name.trim() === "") {
336
+ return "unnamed";
337
+ }
338
+ const trimmed = name.trim();
339
+ if (trimmed.length <= maxLength) {
340
+ return trimmed;
341
+ }
342
+ const ellipsis = "...";
343
+ const head = Math.max(0, maxLength - ellipsis.length);
344
+ return `${trimmed.slice(0, head)}${ellipsis}`;
345
+ }
346
+ function warn(message, error) {
347
+ const base = `[AgentInspect] ${message}`;
348
+ if (error === void 0) {
349
+ console.warn(base);
350
+ return;
351
+ }
352
+ console.warn(`${base}: ${formatError(error).message}`);
353
+ }
354
+
355
+ // packages/core/src/persisted/to-trace-event.ts
356
+ function parseIsoToMs(iso) {
357
+ const parsed = Date.parse(iso);
358
+ return Number.isFinite(parsed) ? parsed : 0;
359
+ }
360
+ function mapInspectKindToStepType(kind) {
361
+ switch (kind) {
362
+ case "LLM":
363
+ return "llm";
364
+ case "TOOL":
365
+ return "tool";
366
+ case "DECISION":
367
+ return "decision";
368
+ case "RUN":
369
+ return "run";
370
+ default:
371
+ return "logic";
372
+ }
373
+ }
374
+ function mapPersistedStatusToStepStatus(status) {
375
+ switch (status) {
376
+ case "ok":
377
+ return "success";
378
+ case "error":
379
+ return "error";
380
+ case "running":
381
+ return "running";
382
+ default:
383
+ return void 0;
384
+ }
385
+ }
386
+ function mapPersistedStatusToRunStatus(status) {
387
+ switch (status) {
388
+ case "ok":
389
+ return "success";
390
+ case "error":
391
+ return "error";
392
+ case "running":
393
+ return "running";
394
+ default:
395
+ return void 0;
396
+ }
397
+ }
398
+ function mapPersistedError(error, attributes) {
399
+ if (!error?.message) return void 0;
400
+ const out = { message: error.message };
401
+ const stack = typeof attributes?.errorStack === "string" && attributes.errorStack.length > 0 ? attributes.errorStack : void 0;
402
+ if (stack) {
403
+ out.stack = stack;
404
+ }
405
+ return out;
406
+ }
407
+ function mapTokenUsageToMetadata(tokenUsage, attributes) {
408
+ const metadata = {};
409
+ if (attributes?.metadata && typeof attributes.metadata === "object") {
410
+ Object.assign(metadata, attributes.metadata);
411
+ }
412
+ if (tokenUsage) {
413
+ metadata.tokens = {
414
+ ...tokenUsage.input !== void 0 ? { input: tokenUsage.input } : {},
415
+ ...tokenUsage.output !== void 0 ? { output: tokenUsage.output } : {},
416
+ ...tokenUsage.total !== void 0 ? { total: tokenUsage.total } : {},
417
+ ...tokenUsage.cached !== void 0 ? { cached: tokenUsage.cached } : {}
418
+ };
419
+ }
420
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
421
+ }
422
+ function pickRunMetadata(attributes) {
423
+ if (!attributes) return void 0;
424
+ const metadata = attributes.metadata && typeof attributes.metadata === "object" ? { ...attributes.metadata } : {};
425
+ for (const key of [
426
+ "correlationId",
427
+ "requestId",
428
+ "decisionId",
429
+ "groupId"
430
+ ]) {
431
+ const value = attributes[key];
432
+ if (typeof value === "string" && value.trim() !== "") {
433
+ metadata[key] = value;
434
+ }
435
+ }
436
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
437
+ }
438
+ function resolveStepId(event) {
439
+ const attrs = event.attributes;
440
+ if (attrs && typeof attrs.stepId === "string" && attrs.stepId.trim() !== "") {
441
+ return attrs.stepId;
442
+ }
443
+ return event.eventId;
444
+ }
445
+ function resolveStepType(event) {
446
+ const attrs = event.attributes;
447
+ if (attrs && typeof attrs.stepType === "string") {
448
+ const t = attrs.stepType;
449
+ if (t === "run" || t === "llm" || t === "tool" || t === "decision" || t === "logic" || t === "state" || t === "custom") {
450
+ return t;
451
+ }
452
+ }
453
+ return mapInspectKindToStepType(event.kind);
454
+ }
455
+ function resolveTimes(event) {
456
+ const timestamp = parseIsoToMs(event.timestamp);
457
+ const startTime = event.startedAt !== void 0 ? parseIsoToMs(event.startedAt) : timestamp;
458
+ let endTime = event.endedAt !== void 0 ? parseIsoToMs(event.endedAt) : timestamp;
459
+ if (event.durationMs !== void 0 && Number.isFinite(event.durationMs) && event.durationMs >= 0 && event.endedAt === void 0) {
460
+ endTime = startTime + event.durationMs;
461
+ }
462
+ return { timestamp, startTime, endTime };
463
+ }
464
+ function fromLegacyRunStarted(event) {
465
+ const { timestamp, startTime } = resolveTimes(event);
466
+ const out = {
467
+ schemaVersion: "0.1",
468
+ event: "run_started",
469
+ timestamp,
470
+ runId: event.runId,
471
+ name: event.name,
472
+ startTime
473
+ };
474
+ const metadata = pickRunMetadata(event.attributes);
475
+ if (metadata) out.metadata = metadata;
476
+ return out;
477
+ }
478
+ function fromLegacyRunCompleted(event) {
479
+ const { timestamp, endTime } = resolveTimes(event);
480
+ const status = mapPersistedStatusToRunStatus(event.status) ?? "success";
481
+ const out = {
482
+ schemaVersion: "0.1",
483
+ event: "run_completed",
484
+ timestamp,
485
+ runId: event.runId,
486
+ status: status === "running" ? "success" : status,
487
+ endTime,
488
+ durationMs: event.durationMs ?? Math.max(0, endTime - timestamp)
489
+ };
490
+ const error = mapPersistedError(event.error, event.attributes);
491
+ if (error) out.error = error;
492
+ return out;
493
+ }
494
+ function fromLegacyStepStarted(event) {
495
+ const { timestamp, startTime } = resolveTimes(event);
496
+ const out = {
497
+ schemaVersion: "0.1",
498
+ event: "step_started",
499
+ timestamp,
500
+ runId: event.runId,
501
+ stepId: resolveStepId(event),
502
+ name: event.name,
503
+ type: resolveStepType(event),
504
+ startTime
505
+ };
506
+ if (event.parentId !== void 0) out.parentId = event.parentId;
507
+ const metadata = mapTokenUsageToMetadata(event.tokenUsage, event.attributes);
508
+ if (metadata) out.metadata = metadata;
509
+ return out;
510
+ }
511
+ function fromLegacyStepCompleted(event) {
512
+ const { timestamp, endTime } = resolveTimes(event);
513
+ const status = mapPersistedStatusToStepStatus(event.status) ?? "success";
514
+ const out = {
515
+ schemaVersion: "0.1",
516
+ event: "step_completed",
517
+ timestamp,
518
+ runId: event.runId,
519
+ stepId: resolveStepId(event),
520
+ status: status === "running" ? "success" : status,
521
+ endTime,
522
+ durationMs: event.durationMs ?? Math.max(0, endTime - timestamp)
523
+ };
524
+ const error = mapPersistedError(event.error, event.attributes);
525
+ if (error) out.error = error;
526
+ return out;
527
+ }
528
+ function fromNativeRun(event) {
529
+ const { timestamp, startTime, endTime } = resolveTimes(event);
530
+ const runStatus = mapPersistedStatusToRunStatus(event.status);
531
+ const out = [];
532
+ if (runStatus === "running" || event.startedAt !== void 0) {
533
+ const started = {
534
+ schemaVersion: "0.1",
535
+ event: "run_started",
536
+ timestamp,
537
+ runId: event.runId,
538
+ name: event.name,
539
+ startTime
540
+ };
541
+ const metadata = pickRunMetadata(event.attributes);
542
+ if (metadata) started.metadata = metadata;
543
+ out.push(started);
544
+ }
545
+ if (runStatus === "success" || runStatus === "error" || event.endedAt !== void 0) {
546
+ const completed = {
547
+ schemaVersion: "0.1",
548
+ event: "run_completed",
549
+ timestamp,
550
+ runId: event.runId,
551
+ status: runStatus === "error" ? "error" : "success",
552
+ endTime,
553
+ durationMs: event.durationMs ?? Math.max(0, endTime - startTime)
554
+ };
555
+ const error = mapPersistedError(event.error, event.attributes);
556
+ if (error) completed.error = error;
557
+ out.push(completed);
558
+ }
559
+ if (out.length === 0) {
560
+ out.push(fromLegacyRunStarted(event));
561
+ }
562
+ return out;
563
+ }
564
+ function fromNativeStep(event) {
565
+ const { timestamp, startTime, endTime } = resolveTimes(event);
566
+ const stepStatus = mapPersistedStatusToStepStatus(event.status);
567
+ const stepId = resolveStepId(event);
568
+ const out = [];
569
+ const shouldEmitStarted = stepStatus === "running" || event.startedAt !== void 0 || stepStatus === "success" || stepStatus === "error";
570
+ if (shouldEmitStarted) {
571
+ const started = {
572
+ schemaVersion: "0.1",
573
+ event: "step_started",
574
+ timestamp,
575
+ runId: event.runId,
576
+ stepId,
577
+ name: event.name,
578
+ type: resolveStepType(event),
579
+ startTime
580
+ };
581
+ if (event.parentId !== void 0) started.parentId = event.parentId;
582
+ const metadata = mapTokenUsageToMetadata(event.tokenUsage, event.attributes);
583
+ if (metadata) started.metadata = metadata;
584
+ out.push(started);
585
+ }
586
+ if (stepStatus === "success" || stepStatus === "error" || event.endedAt !== void 0 || event.durationMs !== void 0) {
587
+ const completed = {
588
+ schemaVersion: "0.1",
589
+ event: "step_completed",
590
+ timestamp,
591
+ runId: event.runId,
592
+ stepId,
593
+ status: stepStatus === "error" ? "error" : "success",
594
+ endTime,
595
+ durationMs: event.durationMs ?? Math.max(0, endTime - startTime)
596
+ };
597
+ const error = mapPersistedError(event.error, event.attributes);
598
+ if (error) completed.error = error;
599
+ out.push(completed);
600
+ }
601
+ if (out.length === 0) {
602
+ out.push(fromLegacyStepStarted(event));
603
+ }
604
+ return out;
605
+ }
606
+ function persistedInspectEventToTraceEvents(event) {
607
+ if (!isPersistedInspectEvent(event)) {
608
+ throw new Error("Invalid PersistedInspectEvent: failed isPersistedInspectEvent");
609
+ }
610
+ const legacyEvent = event.attributes?.legacyEvent;
611
+ if (legacyEvent === "run_started") return [fromLegacyRunStarted(event)];
612
+ if (legacyEvent === "run_completed") return [fromLegacyRunCompleted(event)];
613
+ if (legacyEvent === "step_started") return [fromLegacyStepStarted(event)];
614
+ if (legacyEvent === "step_completed") return [fromLegacyStepCompleted(event)];
615
+ if (event.kind === "RUN") {
616
+ return fromNativeRun(event);
617
+ }
618
+ return fromNativeStep(event);
619
+ }
620
+ function persistedInspectEventsToTraceEvents(events, options) {
621
+ const out = [];
622
+ events.forEach((event, index) => {
623
+ const rows = persistedInspectEventToTraceEvents(event);
624
+ if (rows.length === 0 && options?.eventIndex !== void 0) {
625
+ void options.eventIndex;
626
+ }
627
+ out.push(...rows);
628
+ });
629
+ return out;
630
+ }
631
+
632
+ // packages/core/src/types.ts
633
+ var STEP_TYPES = [
634
+ "run",
635
+ "llm",
636
+ "tool",
637
+ "decision",
638
+ "logic",
639
+ "state",
640
+ "custom"
641
+ ];
642
+ function isRecord2(value) {
643
+ return typeof value === "object" && value !== null && !Array.isArray(value);
644
+ }
645
+ function isStepType(value) {
646
+ return typeof value === "string" && STEP_TYPES.includes(value);
647
+ }
648
+ function isTraceEvent(value) {
649
+ if (!isRecord2(value)) return false;
650
+ if (value.schemaVersion !== "0.1") return false;
651
+ if (typeof value.timestamp !== "number") return false;
652
+ if (typeof value.event !== "string") return false;
653
+ switch (value.event) {
654
+ case "run_started": {
655
+ return typeof value.runId === "string" && typeof value.name === "string" && typeof value.startTime === "number";
656
+ }
657
+ case "run_completed": {
658
+ return typeof value.runId === "string" && (value.status === "success" || value.status === "error") && typeof value.endTime === "number" && typeof value.durationMs === "number";
659
+ }
660
+ case "step_started": {
661
+ return typeof value.runId === "string" && typeof value.stepId === "string" && typeof value.name === "string" && isStepType(value.type) && typeof value.startTime === "number";
662
+ }
663
+ case "step_completed": {
664
+ return typeof value.runId === "string" && typeof value.stepId === "string" && (value.status === "success" || value.status === "error") && typeof value.endTime === "number" && typeof value.durationMs === "number";
665
+ }
666
+ default:
667
+ return false;
668
+ }
669
+ }
670
+
671
+ // packages/core/src/read-trace.ts
672
+ function isRecord3(value) {
673
+ return typeof value === "object" && value !== null && !Array.isArray(value);
674
+ }
675
+ function detectLineFormat(parsed) {
676
+ if (!isRecord3(parsed)) return "unknown";
677
+ if (parsed.schemaVersion === "0.1") return "0.1";
678
+ if (parsed.schemaVersion === "0.2") return "0.2";
679
+ if (parsed.schemaVersion === "1.0") return "1.0";
680
+ return "unknown";
681
+ }
682
+ function parseTraceJsonl(raw, options = {}) {
683
+ const validate = options.validate ?? isTraceEvent;
684
+ const emitWarning = (message) => {
685
+ if (options.warnings !== false) warn(message);
686
+ };
687
+ const persisted = [];
688
+ const traceEvents = [];
689
+ const rows = [];
690
+ let sourceEventCount = 0;
691
+ let saw01 = false;
692
+ let saw02 = false;
693
+ let saw10 = false;
694
+ let lineNumber = 0;
695
+ for (const line of raw.split(/\r?\n/)) {
696
+ lineNumber += 1;
697
+ const trimmed = line.trim();
698
+ if (trimmed === "") continue;
699
+ let parsed;
700
+ try {
701
+ parsed = JSON.parse(trimmed);
702
+ } catch {
703
+ emitWarning("Skipped invalid JSON line in trace file");
704
+ continue;
705
+ }
706
+ const format2 = detectLineFormat(parsed);
707
+ if (format2 === "0.1") {
708
+ saw01 = true;
709
+ if (validate(parsed)) {
710
+ sourceEventCount += 1;
711
+ traceEvents.push(parsed);
712
+ rows.push({ format: "0.1", event: parsed, sourceLine: lineNumber });
713
+ } else {
714
+ emitWarning("Skipped invalid trace event line in trace file");
715
+ }
716
+ continue;
717
+ }
718
+ if (format2 === "0.2" || format2 === "1.0") {
719
+ if (format2 === "0.2") saw02 = true;
720
+ else saw10 = true;
721
+ if (isPersistedInspectEvent(parsed)) {
722
+ sourceEventCount += 1;
723
+ persisted.push(parsed);
724
+ rows.push({ format: format2, event: parsed, sourceLine: lineNumber });
725
+ traceEvents.push(...persistedInspectEventToTraceEvents(parsed));
726
+ } else {
727
+ emitWarning("Skipped invalid persisted inspect event line in trace file");
728
+ }
729
+ continue;
730
+ }
731
+ emitWarning("Skipped trace line with unknown schemaVersion");
732
+ }
733
+ const seenFormats = [saw01, saw02, saw10].filter(Boolean).length;
734
+ if (seenFormats > 1) {
735
+ emitWarning(
736
+ "Trace file mixes AgentInspect schemaVersion rows; normalizing all rows"
737
+ );
738
+ }
739
+ let format = "empty";
740
+ if (seenFormats > 1) format = "mixed";
741
+ else if (saw01) format = "0.1";
742
+ else if (saw02) format = "0.2";
743
+ else if (saw10) format = "1.0";
744
+ return { format, sourceEventCount, events: traceEvents, persisted, rows };
745
+ }
746
+ var DEFAULT_REDACT_KEYS = [
747
+ "authorization",
748
+ "cookie",
749
+ "token",
750
+ "apiKey",
751
+ "password",
752
+ "secret",
753
+ "email"
754
+ ];
755
+ function isRecord4(v) {
756
+ return typeof v === "object" && v !== null && !Array.isArray(v);
757
+ }
758
+ function toKey(s) {
759
+ return s.toLowerCase();
760
+ }
761
+ function stableHash(value) {
762
+ const h = crypto2.createHash("sha256").update(value, "utf8").digest("hex");
763
+ return h.slice(0, 8);
764
+ }
765
+ function compileRules(rules, extraKeys) {
766
+ const out = /* @__PURE__ */ new Map();
767
+ const set = (r) => {
768
+ const k = toKey(r.key);
769
+ out.set(k, { ...r, key: k });
770
+ };
771
+ for (const k of DEFAULT_REDACT_KEYS) {
772
+ set({ key: k, strategy: "full" });
773
+ }
774
+ for (const k of extraKeys ?? []) {
775
+ if (typeof k === "string" && k.length > 0) {
776
+ set({ key: k, strategy: "full" });
777
+ }
778
+ }
779
+ for (const r of rules ?? []) {
780
+ if (typeof r === "string") {
781
+ set({ key: r, strategy: "full" });
782
+ continue;
783
+ }
784
+ const key = r.key;
785
+ if (r.strategy === "full") set({ key, strategy: "full" });
786
+ if (r.strategy === "hash") set({ key, strategy: "hash" });
787
+ if (r.strategy === "prefix") {
788
+ set({ key, strategy: "prefix", keep: typeof r.keep === "number" ? r.keep : 8 });
789
+ }
790
+ }
791
+ return [...out.values()];
792
+ }
793
+ var Redactor = class {
794
+ #rules;
795
+ constructor(options) {
796
+ this.#rules = compileRules(options?.rules, options?.extraKeys);
797
+ }
798
+ redactValue(key, value) {
799
+ const k = toKey(key);
800
+ const rule = this.#rules.find((r) => r.key === k);
801
+ if (!rule) {
802
+ return this.#redactNested(value);
803
+ }
804
+ if (rule.strategy === "full") return "[REDACTED]";
805
+ const asString = typeof value === "string" ? value : typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" ? String(value) : void 0;
806
+ if (rule.strategy === "prefix") {
807
+ if (asString === void 0) return "[REDACTED]";
808
+ const keep = Math.max(0, Math.floor(rule.keep));
809
+ return asString.length <= keep ? `${asString}\u2026` : `${asString.slice(0, keep)}\u2026`;
810
+ }
811
+ if (rule.strategy === "hash") {
812
+ if (asString === void 0) return "[HASH:unknown]";
813
+ return `[HASH:${stableHash(asString)}]`;
814
+ }
815
+ return this.#redactNested(value);
816
+ }
817
+ redactRecord(record) {
818
+ const out = {};
819
+ for (const [k, v] of Object.entries(record)) {
820
+ out[k] = this.redactValue(k, v);
821
+ }
822
+ return out;
823
+ }
824
+ #redactNested(value) {
825
+ if (Array.isArray(value)) {
826
+ return value.map((v) => this.#redactNested(v));
827
+ }
828
+ if (isRecord4(value)) {
829
+ const out = {};
830
+ for (const [k, v] of Object.entries(value)) {
831
+ out[k] = this.redactValue(k, v);
832
+ }
833
+ return out;
834
+ }
835
+ return value;
836
+ }
837
+ };
838
+
839
+ // packages/core/src/redaction-profiles.ts
840
+ var SHARE_PROFILE_EXTRA_KEYS = [
841
+ "userEmail",
842
+ "customerEmail",
843
+ "phone",
844
+ "phoneNumber",
845
+ "address",
846
+ "ip",
847
+ "ipAddress",
848
+ "sessionId",
849
+ "requestId",
850
+ "correlationId",
851
+ "decisionId",
852
+ "groupId",
853
+ "customerId",
854
+ "userId",
855
+ "accountId",
856
+ "tenantId",
857
+ "orgId",
858
+ "organizationId",
859
+ "traceId",
860
+ "spanId",
861
+ "parentSpanId"
862
+ ];
863
+ var STRICT_PROFILE_EXTRA_KEYS = [
864
+ "prompt",
865
+ "completion",
866
+ "input",
867
+ "output",
868
+ "inputPreview",
869
+ "outputPreview",
870
+ "message",
871
+ "messages",
872
+ "transcript",
873
+ "context",
874
+ "document",
875
+ "documents",
876
+ "chunk",
877
+ "chunks",
878
+ "retrieval",
879
+ "query"
880
+ ];
881
+ function resolveRedactionProfile(profile = "local") {
882
+ switch (profile) {
883
+ case "local":
884
+ return { profile: "local", extraKeys: [] };
885
+ case "share":
886
+ return {
887
+ profile: "share",
888
+ extraKeys: SHARE_PROFILE_EXTRA_KEYS,
889
+ maxMetadataValueLengthCap: 500,
890
+ maxPreviewLengthCap: 200
891
+ };
892
+ case "strict":
893
+ return {
894
+ profile: "strict",
895
+ extraKeys: [...SHARE_PROFILE_EXTRA_KEYS, ...STRICT_PROFILE_EXTRA_KEYS],
896
+ maxMetadataValueLengthCap: 200,
897
+ maxPreviewLengthCap: 80
898
+ };
899
+ default:
900
+ return { profile: "local", extraKeys: [] };
901
+ }
902
+ }
903
+ function isPreviewKey(key) {
904
+ return key.toLowerCase().includes("preview");
905
+ }
906
+ function applyProfileMetadataCaps(maxMetadataValueLength, maxPreviewLength, resolved) {
907
+ let meta = maxMetadataValueLength;
908
+ let preview = maxPreviewLength;
909
+ if (resolved.maxMetadataValueLengthCap !== void 0) {
910
+ meta = Math.min(meta, resolved.maxMetadataValueLengthCap);
911
+ }
912
+ if (resolved.maxPreviewLengthCap !== void 0) {
913
+ preview = Math.min(preview, resolved.maxPreviewLengthCap);
914
+ }
915
+ return { maxMetadataValueLength: meta, maxPreviewLength: preview };
916
+ }
917
+ function truncateStringForProfile(value, key, maxMetadataValueLength, maxPreviewLength) {
918
+ const max = isPreviewKey(key) ? maxPreviewLength : maxMetadataValueLength;
919
+ if (max <= 0) return "\u2026";
920
+ if (value.length <= max) return value;
921
+ return `${value.slice(0, max)}\u2026`;
922
+ }
923
+
924
+ // packages/core/src/storage.ts
925
+ function isRecord5(value) {
926
+ return typeof value === "object" && value !== null && !Array.isArray(value);
927
+ }
928
+ function nonEmptyString(value) {
929
+ return typeof value === "string" && value.trim() !== "";
930
+ }
931
+ function finiteNumber(value) {
932
+ return typeof value === "number" && Number.isFinite(value);
933
+ }
934
+ function optionalErrorInfo(value) {
935
+ if (value === void 0) return true;
936
+ if (!isRecord5(value)) return false;
937
+ if (typeof value.message !== "string") return false;
938
+ if ("stack" in value && value.stack !== void 0) {
939
+ if (typeof value.stack !== "string") return false;
940
+ }
941
+ return true;
942
+ }
943
+ function validateEvent(event) {
944
+ if (!isRecord5(event)) return false;
945
+ if (event.schemaVersion !== "0.1") return false;
946
+ if (!finiteNumber(event.timestamp)) return false;
947
+ if (typeof event.event !== "string") return false;
948
+ switch (event.event) {
949
+ case "run_started": {
950
+ if (!nonEmptyString(event.runId) || !nonEmptyString(event.name) || !finiteNumber(event.startTime)) {
951
+ return false;
952
+ }
953
+ if (event.metadata !== void 0 && !isRecord5(event.metadata)) {
954
+ return false;
955
+ }
956
+ return true;
957
+ }
958
+ case "run_completed": {
959
+ return nonEmptyString(event.runId) && (event.status === "success" || event.status === "error") && finiteNumber(event.endTime) && finiteNumber(event.durationMs) && optionalErrorInfo(event.error);
960
+ }
961
+ case "step_started": {
962
+ if (!nonEmptyString(event.runId) || !nonEmptyString(event.stepId) || !nonEmptyString(event.name) || !isStepType(event.type) || !finiteNumber(event.startTime)) {
963
+ return false;
964
+ }
965
+ if (event.parentId !== void 0 && typeof event.parentId !== "string") {
966
+ return false;
967
+ }
968
+ if (event.metadata !== void 0 && !isRecord5(event.metadata)) {
969
+ return false;
970
+ }
971
+ return true;
972
+ }
973
+ case "step_completed": {
974
+ return nonEmptyString(event.runId) && nonEmptyString(event.stepId) && (event.status === "success" || event.status === "error") && finiteNumber(event.endTime) && finiteNumber(event.durationMs) && optionalErrorInfo(event.error);
975
+ }
976
+ default:
977
+ return false;
978
+ }
979
+ }
980
+ async function readTraceEventsFromFile(filePath) {
981
+ try {
982
+ const raw = await readFile(filePath, "utf-8");
983
+ return parseTraceJsonl(raw, { validate: validateEvent }).events;
984
+ } catch (e) {
985
+ if (e && typeof e === "object" && "code" in e && e.code === "ENOENT") {
986
+ return [];
987
+ }
988
+ warn("Failed to read trace events from file", e);
989
+ return [];
990
+ }
991
+ }
992
+
993
+ // node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
994
+ var ANSI_BACKGROUND_OFFSET = 10;
995
+ var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
996
+ var wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
997
+ var wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
998
+ var styles = {
999
+ modifier: {
1000
+ reset: [0, 0],
1001
+ // 21 isn't widely supported and 22 does the same thing
1002
+ bold: [1, 22],
1003
+ dim: [2, 22],
1004
+ italic: [3, 23],
1005
+ underline: [4, 24],
1006
+ overline: [53, 55],
1007
+ inverse: [7, 27],
1008
+ hidden: [8, 28],
1009
+ strikethrough: [9, 29]
1010
+ },
1011
+ color: {
1012
+ black: [30, 39],
1013
+ red: [31, 39],
1014
+ green: [32, 39],
1015
+ yellow: [33, 39],
1016
+ blue: [34, 39],
1017
+ magenta: [35, 39],
1018
+ cyan: [36, 39],
1019
+ white: [37, 39],
1020
+ // Bright color
1021
+ blackBright: [90, 39],
1022
+ gray: [90, 39],
1023
+ // Alias of `blackBright`
1024
+ grey: [90, 39],
1025
+ // Alias of `blackBright`
1026
+ redBright: [91, 39],
1027
+ greenBright: [92, 39],
1028
+ yellowBright: [93, 39],
1029
+ blueBright: [94, 39],
1030
+ magentaBright: [95, 39],
1031
+ cyanBright: [96, 39],
1032
+ whiteBright: [97, 39]
1033
+ },
1034
+ bgColor: {
1035
+ bgBlack: [40, 49],
1036
+ bgRed: [41, 49],
1037
+ bgGreen: [42, 49],
1038
+ bgYellow: [43, 49],
1039
+ bgBlue: [44, 49],
1040
+ bgMagenta: [45, 49],
1041
+ bgCyan: [46, 49],
1042
+ bgWhite: [47, 49],
1043
+ // Bright color
1044
+ bgBlackBright: [100, 49],
1045
+ bgGray: [100, 49],
1046
+ // Alias of `bgBlackBright`
1047
+ bgGrey: [100, 49],
1048
+ // Alias of `bgBlackBright`
1049
+ bgRedBright: [101, 49],
1050
+ bgGreenBright: [102, 49],
1051
+ bgYellowBright: [103, 49],
1052
+ bgBlueBright: [104, 49],
1053
+ bgMagentaBright: [105, 49],
1054
+ bgCyanBright: [106, 49],
1055
+ bgWhiteBright: [107, 49]
1056
+ }
1057
+ };
1058
+ Object.keys(styles.modifier);
1059
+ var foregroundColorNames = Object.keys(styles.color);
1060
+ var backgroundColorNames = Object.keys(styles.bgColor);
1061
+ [...foregroundColorNames, ...backgroundColorNames];
1062
+ function assembleStyles() {
1063
+ const codes = /* @__PURE__ */ new Map();
1064
+ for (const [groupName, group] of Object.entries(styles)) {
1065
+ for (const [styleName, style] of Object.entries(group)) {
1066
+ styles[styleName] = {
1067
+ open: `\x1B[${style[0]}m`,
1068
+ close: `\x1B[${style[1]}m`
1069
+ };
1070
+ group[styleName] = styles[styleName];
1071
+ codes.set(style[0], style[1]);
1072
+ }
1073
+ Object.defineProperty(styles, groupName, {
1074
+ value: group,
1075
+ enumerable: false
1076
+ });
1077
+ }
1078
+ Object.defineProperty(styles, "codes", {
1079
+ value: codes,
1080
+ enumerable: false
1081
+ });
1082
+ styles.color.close = "\x1B[39m";
1083
+ styles.bgColor.close = "\x1B[49m";
1084
+ styles.color.ansi = wrapAnsi16();
1085
+ styles.color.ansi256 = wrapAnsi256();
1086
+ styles.color.ansi16m = wrapAnsi16m();
1087
+ styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
1088
+ styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
1089
+ styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
1090
+ Object.defineProperties(styles, {
1091
+ rgbToAnsi256: {
1092
+ value(red, green, blue) {
1093
+ if (red === green && green === blue) {
1094
+ if (red < 8) {
1095
+ return 16;
1096
+ }
1097
+ if (red > 248) {
1098
+ return 231;
1099
+ }
1100
+ return Math.round((red - 8) / 247 * 24) + 232;
1101
+ }
1102
+ return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
1103
+ },
1104
+ enumerable: false
1105
+ },
1106
+ hexToRgb: {
1107
+ value(hex) {
1108
+ const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
1109
+ if (!matches) {
1110
+ return [0, 0, 0];
1111
+ }
1112
+ let [colorString] = matches;
1113
+ if (colorString.length === 3) {
1114
+ colorString = [...colorString].map((character) => character + character).join("");
1115
+ }
1116
+ const integer = Number.parseInt(colorString, 16);
1117
+ return [
1118
+ /* eslint-disable no-bitwise */
1119
+ integer >> 16 & 255,
1120
+ integer >> 8 & 255,
1121
+ integer & 255
1122
+ /* eslint-enable no-bitwise */
1123
+ ];
1124
+ },
1125
+ enumerable: false
1126
+ },
1127
+ hexToAnsi256: {
1128
+ value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
1129
+ enumerable: false
1130
+ },
1131
+ ansi256ToAnsi: {
1132
+ value(code) {
1133
+ if (code < 8) {
1134
+ return 30 + code;
1135
+ }
1136
+ if (code < 16) {
1137
+ return 90 + (code - 8);
1138
+ }
1139
+ let red;
1140
+ let green;
1141
+ let blue;
1142
+ if (code >= 232) {
1143
+ red = ((code - 232) * 10 + 8) / 255;
1144
+ green = red;
1145
+ blue = red;
1146
+ } else {
1147
+ code -= 16;
1148
+ const remainder = code % 36;
1149
+ red = Math.floor(code / 36) / 5;
1150
+ green = Math.floor(remainder / 6) / 5;
1151
+ blue = remainder % 6 / 5;
1152
+ }
1153
+ const value = Math.max(red, green, blue) * 2;
1154
+ if (value === 0) {
1155
+ return 30;
1156
+ }
1157
+ let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
1158
+ if (value === 2) {
1159
+ result += 60;
1160
+ }
1161
+ return result;
1162
+ },
1163
+ enumerable: false
1164
+ },
1165
+ rgbToAnsi: {
1166
+ value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
1167
+ enumerable: false
1168
+ },
1169
+ hexToAnsi: {
1170
+ value: (hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
1171
+ enumerable: false
1172
+ }
1173
+ });
1174
+ return styles;
1175
+ }
1176
+ var ansiStyles = assembleStyles();
1177
+ var ansi_styles_default = ansiStyles;
1178
+ function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
1179
+ const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
1180
+ const position = argv.indexOf(prefix + flag);
1181
+ const terminatorPosition = argv.indexOf("--");
1182
+ return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
1183
+ }
1184
+ var { env } = process2;
1185
+ var flagForceColor;
1186
+ if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
1187
+ flagForceColor = 0;
1188
+ } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
1189
+ flagForceColor = 1;
1190
+ }
1191
+ function envForceColor() {
1192
+ if ("FORCE_COLOR" in env) {
1193
+ if (env.FORCE_COLOR === "true") {
1194
+ return 1;
1195
+ }
1196
+ if (env.FORCE_COLOR === "false") {
1197
+ return 0;
1198
+ }
1199
+ return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
1200
+ }
1201
+ }
1202
+ function translateLevel(level) {
1203
+ if (level === 0) {
1204
+ return false;
1205
+ }
1206
+ return {
1207
+ level,
1208
+ hasBasic: true,
1209
+ has256: level >= 2,
1210
+ has16m: level >= 3
1211
+ };
1212
+ }
1213
+ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
1214
+ const noFlagForceColor = envForceColor();
1215
+ if (noFlagForceColor !== void 0) {
1216
+ flagForceColor = noFlagForceColor;
1217
+ }
1218
+ const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
1219
+ if (forceColor === 0) {
1220
+ return 0;
1221
+ }
1222
+ if (sniffFlags) {
1223
+ if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
1224
+ return 3;
1225
+ }
1226
+ if (hasFlag("color=256")) {
1227
+ return 2;
1228
+ }
1229
+ }
1230
+ if ("TF_BUILD" in env && "AGENT_NAME" in env) {
1231
+ return 1;
1232
+ }
1233
+ if (haveStream && !streamIsTTY && forceColor === void 0) {
1234
+ return 0;
1235
+ }
1236
+ const min = forceColor || 0;
1237
+ if (env.TERM === "dumb") {
1238
+ return min;
1239
+ }
1240
+ if (process2.platform === "win32") {
1241
+ const osRelease = os.release().split(".");
1242
+ if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
1243
+ return Number(osRelease[2]) >= 14931 ? 3 : 2;
1244
+ }
1245
+ return 1;
1246
+ }
1247
+ if ("CI" in env) {
1248
+ if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => key in env)) {
1249
+ return 3;
1250
+ }
1251
+ if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
1252
+ return 1;
1253
+ }
1254
+ return min;
1255
+ }
1256
+ if ("TEAMCITY_VERSION" in env) {
1257
+ return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
1258
+ }
1259
+ if (env.COLORTERM === "truecolor") {
1260
+ return 3;
1261
+ }
1262
+ if (env.TERM === "xterm-kitty") {
1263
+ return 3;
1264
+ }
1265
+ if (env.TERM === "xterm-ghostty") {
1266
+ return 3;
1267
+ }
1268
+ if (env.TERM === "wezterm") {
1269
+ return 3;
1270
+ }
1271
+ if ("TERM_PROGRAM" in env) {
1272
+ const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
1273
+ switch (env.TERM_PROGRAM) {
1274
+ case "iTerm.app": {
1275
+ return version >= 3 ? 3 : 2;
1276
+ }
1277
+ case "Apple_Terminal": {
1278
+ return 2;
1279
+ }
1280
+ }
1281
+ }
1282
+ if (/-256(color)?$/i.test(env.TERM)) {
1283
+ return 2;
1284
+ }
1285
+ if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
1286
+ return 1;
1287
+ }
1288
+ if ("COLORTERM" in env) {
1289
+ return 1;
1290
+ }
1291
+ return min;
1292
+ }
1293
+ function createSupportsColor(stream, options = {}) {
1294
+ const level = _supportsColor(stream, {
1295
+ streamIsTTY: stream && stream.isTTY,
1296
+ ...options
1297
+ });
1298
+ return translateLevel(level);
1299
+ }
1300
+ var supportsColor = {
1301
+ stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
1302
+ stderr: createSupportsColor({ isTTY: tty.isatty(2) })
1303
+ };
1304
+ var supports_color_default = supportsColor;
1305
+
1306
+ // node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/utilities.js
1307
+ function stringReplaceAll(string, substring, replacer) {
1308
+ let index = string.indexOf(substring);
1309
+ if (index === -1) {
1310
+ return string;
1311
+ }
1312
+ const substringLength = substring.length;
1313
+ let endIndex = 0;
1314
+ let returnValue = "";
1315
+ do {
1316
+ returnValue += string.slice(endIndex, index) + substring + replacer;
1317
+ endIndex = index + substringLength;
1318
+ index = string.indexOf(substring, endIndex);
1319
+ } while (index !== -1);
1320
+ returnValue += string.slice(endIndex);
1321
+ return returnValue;
1322
+ }
1323
+ function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
1324
+ let endIndex = 0;
1325
+ let returnValue = "";
1326
+ do {
1327
+ const gotCR = string[index - 1] === "\r";
1328
+ returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
1329
+ endIndex = index + 1;
1330
+ index = string.indexOf("\n", endIndex);
1331
+ } while (index !== -1);
1332
+ returnValue += string.slice(endIndex);
1333
+ return returnValue;
1334
+ }
1335
+
1336
+ // node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/index.js
1337
+ var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
1338
+ var GENERATOR = /* @__PURE__ */ Symbol("GENERATOR");
1339
+ var STYLER = /* @__PURE__ */ Symbol("STYLER");
1340
+ var IS_EMPTY = /* @__PURE__ */ Symbol("IS_EMPTY");
1341
+ var levelMapping = [
1342
+ "ansi",
1343
+ "ansi",
1344
+ "ansi256",
1345
+ "ansi16m"
1346
+ ];
1347
+ var styles2 = /* @__PURE__ */ Object.create(null);
1348
+ var applyOptions = (object, options = {}) => {
1349
+ if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
1350
+ throw new Error("The `level` option should be an integer from 0 to 3");
1351
+ }
1352
+ const colorLevel = stdoutColor ? stdoutColor.level : 0;
1353
+ object.level = options.level === void 0 ? colorLevel : options.level;
1354
+ };
1355
+ var chalkFactory = (options) => {
1356
+ const chalk2 = (...strings) => strings.join(" ");
1357
+ applyOptions(chalk2, options);
1358
+ Object.setPrototypeOf(chalk2, createChalk.prototype);
1359
+ return chalk2;
1360
+ };
1361
+ function createChalk(options) {
1362
+ return chalkFactory(options);
1363
+ }
1364
+ Object.setPrototypeOf(createChalk.prototype, Function.prototype);
1365
+ for (const [styleName, style] of Object.entries(ansi_styles_default)) {
1366
+ styles2[styleName] = {
1367
+ get() {
1368
+ const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
1369
+ Object.defineProperty(this, styleName, { value: builder });
1370
+ return builder;
1371
+ }
1372
+ };
1373
+ }
1374
+ styles2.visible = {
1375
+ get() {
1376
+ const builder = createBuilder(this, this[STYLER], true);
1377
+ Object.defineProperty(this, "visible", { value: builder });
1378
+ return builder;
1379
+ }
1380
+ };
1381
+ var getModelAnsi = (model, level, type, ...arguments_) => {
1382
+ if (model === "rgb") {
1383
+ if (level === "ansi16m") {
1384
+ return ansi_styles_default[type].ansi16m(...arguments_);
1385
+ }
1386
+ if (level === "ansi256") {
1387
+ return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
1388
+ }
1389
+ return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
1390
+ }
1391
+ if (model === "hex") {
1392
+ return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
1393
+ }
1394
+ return ansi_styles_default[type][model](...arguments_);
1395
+ };
1396
+ var usedModels = ["rgb", "hex", "ansi256"];
1397
+ for (const model of usedModels) {
1398
+ styles2[model] = {
1399
+ get() {
1400
+ const { level } = this;
1401
+ return function(...arguments_) {
1402
+ const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
1403
+ return createBuilder(this, styler, this[IS_EMPTY]);
1404
+ };
1405
+ }
1406
+ };
1407
+ const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
1408
+ styles2[bgModel] = {
1409
+ get() {
1410
+ const { level } = this;
1411
+ return function(...arguments_) {
1412
+ const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
1413
+ return createBuilder(this, styler, this[IS_EMPTY]);
1414
+ };
1415
+ }
1416
+ };
1417
+ }
1418
+ var proto = Object.defineProperties(() => {
1419
+ }, {
1420
+ ...styles2,
1421
+ level: {
1422
+ enumerable: true,
1423
+ get() {
1424
+ return this[GENERATOR].level;
1425
+ },
1426
+ set(level) {
1427
+ this[GENERATOR].level = level;
1428
+ }
1429
+ }
1430
+ });
1431
+ var createStyler = (open, close, parent) => {
1432
+ let openAll;
1433
+ let closeAll;
1434
+ if (parent === void 0) {
1435
+ openAll = open;
1436
+ closeAll = close;
1437
+ } else {
1438
+ openAll = parent.openAll + open;
1439
+ closeAll = close + parent.closeAll;
1440
+ }
1441
+ return {
1442
+ open,
1443
+ close,
1444
+ openAll,
1445
+ closeAll,
1446
+ parent
1447
+ };
1448
+ };
1449
+ var createBuilder = (self, _styler, _isEmpty) => {
1450
+ const builder = (...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
1451
+ Object.setPrototypeOf(builder, proto);
1452
+ builder[GENERATOR] = self;
1453
+ builder[STYLER] = _styler;
1454
+ builder[IS_EMPTY] = _isEmpty;
1455
+ return builder;
1456
+ };
1457
+ var applyStyle = (self, string) => {
1458
+ if (self.level <= 0 || !string) {
1459
+ return self[IS_EMPTY] ? "" : string;
1460
+ }
1461
+ let styler = self[STYLER];
1462
+ if (styler === void 0) {
1463
+ return string;
1464
+ }
1465
+ const { openAll, closeAll } = styler;
1466
+ if (string.includes("\x1B")) {
1467
+ while (styler !== void 0) {
1468
+ string = stringReplaceAll(string, styler.close, styler.open);
1469
+ styler = styler.parent;
1470
+ }
1471
+ }
1472
+ const lfIndex = string.indexOf("\n");
1473
+ if (lfIndex !== -1) {
1474
+ string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
1475
+ }
1476
+ return openAll + string + closeAll;
1477
+ };
1478
+ Object.defineProperties(createChalk.prototype, styles2);
1479
+ var chalk = createChalk();
1480
+ createChalk({ level: stderrColor ? stderrColor.level : 0 });
1481
+ var source_default = chalk;
1482
+
1483
+ // packages/core/src/correlation-metadata.ts
1484
+ var TRACE_CORRELATION_KEYS = [
1485
+ "correlationId",
1486
+ "requestId",
1487
+ "decisionId",
1488
+ "groupId"
1489
+ ];
1490
+ function isNonEmptyString2(value) {
1491
+ return typeof value === "string" && value.length > 0;
1492
+ }
1493
+ function extractCorrelationMetadata(record) {
1494
+ if (!record) {
1495
+ return void 0;
1496
+ }
1497
+ const out = {};
1498
+ let found = false;
1499
+ for (const key of TRACE_CORRELATION_KEYS) {
1500
+ const value = record[key];
1501
+ if (isNonEmptyString2(value)) {
1502
+ out[key] = value;
1503
+ found = true;
1504
+ }
1505
+ }
1506
+ return found ? out : void 0;
1507
+ }
1508
+
1509
+ // packages/core/src/context.ts
1510
+ new AsyncLocalStorage();
1511
+
1512
+ // packages/core/src/terminal.ts
1513
+ var TERMINAL_INDENT = " ";
1514
+ var MAX_TERMINAL_NAME_LENGTH = 80;
1515
+ var MAX_TERMINAL_DEPTH = 10;
1516
+ function normalizeDepth(depth) {
1517
+ if (!Number.isFinite(depth) || depth < 0) {
1518
+ return 0;
1519
+ }
1520
+ return Math.min(Math.floor(depth), MAX_TERMINAL_DEPTH);
1521
+ }
1522
+ function getIndent(depth) {
1523
+ return TERMINAL_INDENT.repeat(normalizeDepth(depth));
1524
+ }
1525
+ function formatTerminalName(name) {
1526
+ if (typeof name !== "string" || name.trim() === "") {
1527
+ return "unnamed";
1528
+ }
1529
+ return truncateName(name, MAX_TERMINAL_NAME_LENGTH);
1530
+ }
1531
+ function getStatusIcon(status) {
1532
+ if (status === "success") return source_default.green("\u2714");
1533
+ if (status === "error") return source_default.red("\u2716");
1534
+ return source_default.yellow("\u23F3");
1535
+ }
1536
+ function renderStepLine(name, durationMs, status, depth) {
1537
+ try {
1538
+ const nm = formatTerminalName(name);
1539
+ const ind = getIndent(depth ?? 0);
1540
+ if (status === "running" && durationMs === void 0) {
1541
+ return `${ind}${source_default.yellow("\u23F3")} ${nm}`;
1542
+ }
1543
+ const hasDur = durationMs !== void 0 && Number.isFinite(durationMs);
1544
+ const dur = hasDur ? formatDuration2(durationMs) : void 0;
1545
+ if (status === "running") {
1546
+ return dur !== void 0 ? `${ind}${source_default.yellow("\u23F3")} ${nm} (${dur})` : `${ind}${source_default.yellow("\u23F3")} ${nm}`;
1547
+ }
1548
+ if (!hasDur || dur === void 0) {
1549
+ return `${ind}${source_default.yellow("\u23F3")} ${nm}`;
1550
+ }
1551
+ if (status === "success") {
1552
+ return `${ind}${getStatusIcon("success")} ${nm} (${dur})`;
1553
+ }
1554
+ return `${ind}${getStatusIcon("error")} ${nm} (${dur})`;
1555
+ } catch {
1556
+ return "";
1557
+ }
1558
+ }
1559
+ function renderErrorLine(error, depth) {
1560
+ try {
1561
+ const msg = typeof error.message === "string" ? error.message : "";
1562
+ const ind = getIndent((depth ?? 0) + 1);
1563
+ return `${ind}Error: ${msg}`;
1564
+ } catch {
1565
+ return "";
1566
+ }
1567
+ }
1568
+ function resolveTraceDir(options = {}) {
1569
+ if (typeof options.dir === "string" && options.dir.trim() !== "") {
1570
+ return options.dir.trim();
1571
+ }
1572
+ const envDir = process.env.AGENT_INSPECT_TRACE_DIR;
1573
+ if (typeof envDir === "string" && envDir.trim() !== "") {
1574
+ return envDir.trim();
1575
+ }
1576
+ return getDefaultTraceDir();
1577
+ }
1578
+ var TraceDirectory = class {
1579
+ #dir;
1580
+ constructor(options = {}) {
1581
+ this.#dir = resolveTraceDir(options);
1582
+ }
1583
+ getPath(filename) {
1584
+ return filename ? path.join(this.#dir, filename) : this.#dir;
1585
+ }
1586
+ async list() {
1587
+ try {
1588
+ const files = await readdir(this.#dir);
1589
+ return files.filter((f) => f.endsWith(".jsonl"));
1590
+ } catch (e) {
1591
+ if (e && typeof e === "object" && "code" in e && e.code === "ENOENT") {
1592
+ return [];
1593
+ }
1594
+ throw e;
1595
+ }
1596
+ }
1597
+ async getFileStats(filename) {
1598
+ return await stat(this.getPath(filename));
1599
+ }
1600
+ };
1601
+ function isFiniteNumber(v) {
1602
+ return typeof v === "number" && Number.isFinite(v);
1603
+ }
1604
+ function parseIsoToMs2(value) {
1605
+ if (value === void 0) return void 0;
1606
+ const parsed = Date.parse(value);
1607
+ return Number.isFinite(parsed) ? parsed : void 0;
1608
+ }
1609
+ async function extractMetadata(filePath, _quickScan) {
1610
+ const stats = await stat(filePath);
1611
+ let runIdFromFile = path.basename(filePath);
1612
+ if (runIdFromFile.endsWith(".jsonl")) {
1613
+ runIdFromFile = runIdFromFile.slice(0, -".jsonl".length);
1614
+ }
1615
+ const raw = await readFile(filePath, "utf-8");
1616
+ const parsedTrace = parseTraceJsonl(raw, { warnings: false });
1617
+ let runId;
1618
+ let name;
1619
+ let startedAt;
1620
+ let endedAt;
1621
+ let explicitDurationMs;
1622
+ let hasRunStarted = false;
1623
+ let hasRunCompleted = false;
1624
+ let runCompletedStatus;
1625
+ let anyStepError = false;
1626
+ const anyKnownEvent = parsedTrace.sourceEventCount > 0;
1627
+ let persistedStatus;
1628
+ const persistedRun = parsedTrace.persisted.find(
1629
+ (event) => event.kind === "RUN"
1630
+ );
1631
+ if (persistedRun) {
1632
+ runId = persistedRun.runId;
1633
+ if (persistedRun.name.trim() !== "") {
1634
+ name = persistedRun.name;
1635
+ }
1636
+ startedAt = parseIsoToMs2(persistedRun.startedAt) ?? parseIsoToMs2(persistedRun.timestamp);
1637
+ endedAt = parseIsoToMs2(persistedRun.endedAt);
1638
+ if (isFiniteNumber(persistedRun.durationMs)) {
1639
+ explicitDurationMs = persistedRun.durationMs;
1640
+ if (endedAt === void 0 && startedAt !== void 0) {
1641
+ endedAt = startedAt + persistedRun.durationMs;
1642
+ }
1643
+ }
1644
+ if (persistedRun.status === "ok") persistedStatus = "success";
1645
+ else if (persistedRun.status === "error") persistedStatus = "error";
1646
+ else if (persistedRun.status === "running") persistedStatus = "running";
1647
+ else if (persistedRun.status === "unknown") persistedStatus = "unknown";
1648
+ } else {
1649
+ runId = parsedTrace.persisted[0]?.runId;
1650
+ }
1651
+ for (const e of parsedTrace.events) {
1652
+ if (runId === void 0 && typeof e.runId === "string") {
1653
+ runId = e.runId;
1654
+ }
1655
+ if (e.event === "run_started") {
1656
+ hasRunStarted = true;
1657
+ const rs = e;
1658
+ if (typeof rs.name === "string" && rs.name.trim() !== "") {
1659
+ name = rs.name;
1660
+ }
1661
+ if (isFiniteNumber(rs.startTime)) {
1662
+ startedAt = rs.startTime;
1663
+ } else if (isFiniteNumber(rs.timestamp)) {
1664
+ startedAt = rs.timestamp;
1665
+ }
1666
+ }
1667
+ if (e.event === "run_completed") {
1668
+ hasRunCompleted = true;
1669
+ const rc = e;
1670
+ runCompletedStatus = rc.status;
1671
+ if (isFiniteNumber(rc.endTime)) endedAt = rc.endTime;
1672
+ else if (isFiniteNumber(rc.timestamp)) endedAt = rc.timestamp;
1673
+ if (isFiniteNumber(rc.durationMs)) explicitDurationMs = rc.durationMs;
1674
+ }
1675
+ if (e.event === "step_completed") {
1676
+ const sc = e;
1677
+ if (sc.status === "error") {
1678
+ anyStepError = true;
1679
+ }
1680
+ }
1681
+ }
1682
+ const resolvedRunId = runId ?? runIdFromFile;
1683
+ let status = "unknown";
1684
+ if (hasRunCompleted && (runCompletedStatus === "success" || runCompletedStatus === "error")) {
1685
+ status = runCompletedStatus;
1686
+ } else if (anyStepError) {
1687
+ status = "error";
1688
+ } else if (persistedStatus !== void 0) {
1689
+ status = persistedStatus;
1690
+ } else if (hasRunStarted && !hasRunCompleted) {
1691
+ status = "running";
1692
+ } else if (anyKnownEvent) {
1693
+ status = "unknown";
1694
+ } else {
1695
+ status = "unknown";
1696
+ }
1697
+ const durationMs = explicitDurationMs ?? (startedAt !== void 0 && endedAt !== void 0 && Number.isFinite(startedAt) && Number.isFinite(endedAt) && endedAt >= startedAt ? endedAt - startedAt : void 0);
1698
+ return {
1699
+ runId: resolvedRunId,
1700
+ name,
1701
+ status,
1702
+ startedAt,
1703
+ endedAt,
1704
+ durationMs,
1705
+ eventCount: parsedTrace.sourceEventCount,
1706
+ filePath,
1707
+ fileSize: stats.size,
1708
+ createdAt: stats.birthtime
1709
+ };
1710
+ }
1711
+ function isNonNegativeFiniteNumber(value) {
1712
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
1713
+ }
1714
+ function buildRunSummary(events) {
1715
+ const started = events.find(
1716
+ (e) => e.event === "run_started"
1717
+ );
1718
+ const completed = events.filter(
1719
+ (e) => e.event === "run_completed"
1720
+ );
1721
+ const lastCompleted = completed[completed.length - 1];
1722
+ const runId = started?.runId ?? events.find((e) => typeof e.runId === "string")?.runId ?? "unknown-run";
1723
+ const name = typeof started?.name === "string" && started.name.trim() !== "" ? started.name : void 0;
1724
+ const status = lastCompleted ? lastCompleted.status : started ? "running" : "unknown";
1725
+ const durationMs = lastCompleted && isFiniteNumber(lastCompleted.durationMs) ? lastCompleted.durationMs : void 0;
1726
+ started && isFiniteNumber(started.startTime) ? started.startTime : void 0;
1727
+ const steps = /* @__PURE__ */ new Map();
1728
+ for (const e of events) {
1729
+ if (e.event === "step_started") {
1730
+ const s = e;
1731
+ steps.set(s.stepId, {
1732
+ type: s.type,
1733
+ name: s.name,
1734
+ status: "running",
1735
+ parentId: s.parentId,
1736
+ tokensInput: isNonNegativeFiniteNumber(s.metadata?.tokens?.input) ? s.metadata.tokens.input : void 0,
1737
+ tokensOutput: isNonNegativeFiniteNumber(s.metadata?.tokens?.output) ? s.metadata.tokens.output : void 0,
1738
+ tokensTotal: isNonNegativeFiniteNumber(s.metadata?.tokens?.total) ? s.metadata.tokens.total : void 0,
1739
+ tokensCached: isNonNegativeFiniteNumber(s.metadata?.tokens?.cached) ? s.metadata.tokens.cached : void 0
1740
+ });
1741
+ }
1742
+ }
1743
+ for (const e of events) {
1744
+ if (e.event === "step_completed") {
1745
+ const c = e;
1746
+ const existing = steps.get(c.stepId);
1747
+ if (!existing) continue;
1748
+ existing.status = c.status;
1749
+ existing.durationMs = c.durationMs;
1750
+ }
1751
+ }
1752
+ let totalSteps = 0;
1753
+ let llmSteps = 0;
1754
+ let toolSteps = 0;
1755
+ let logicSteps = 0;
1756
+ let errorSteps = 0;
1757
+ let maxDepth = 0;
1758
+ let longestStep;
1759
+ let totalTokensInput = 0;
1760
+ let totalTokensOutput = 0;
1761
+ let totalTokensTotal = 0;
1762
+ let totalTokensCached = 0;
1763
+ let tokenBearingSteps = 0;
1764
+ let stepsWithKnownTotal = 0;
1765
+ let hasCachedTokens = false;
1766
+ const depthCache = /* @__PURE__ */ new Map();
1767
+ const computeDepth = (stepId) => {
1768
+ const cached = depthCache.get(stepId);
1769
+ if (cached !== void 0) return cached;
1770
+ const node = steps.get(stepId);
1771
+ if (!node) return 0;
1772
+ const parent = node.parentId;
1773
+ if (typeof parent !== "string" || parent.trim() === "" || !steps.has(parent)) {
1774
+ depthCache.set(stepId, 0);
1775
+ return 0;
1776
+ }
1777
+ const d = Math.min(1e3, computeDepth(parent) + 1);
1778
+ depthCache.set(stepId, d);
1779
+ return d;
1780
+ };
1781
+ for (const [id, s] of steps.entries()) {
1782
+ totalSteps += 1;
1783
+ if (s.type === "llm") llmSteps += 1;
1784
+ else if (s.type === "tool") toolSteps += 1;
1785
+ else logicSteps += 1;
1786
+ if (s.status === "error") errorSteps += 1;
1787
+ const depth = computeDepth(id);
1788
+ if (depth > maxDepth) maxDepth = depth;
1789
+ if (typeof s.durationMs === "number" && Number.isFinite(s.durationMs)) {
1790
+ if (!longestStep || s.durationMs > longestStep.durationMs) {
1791
+ longestStep = { name: s.name, durationMs: s.durationMs, type: s.type };
1792
+ }
1793
+ }
1794
+ if (s.tokensInput !== void 0 || s.tokensOutput !== void 0 || s.tokensTotal !== void 0 || s.tokensCached !== void 0) {
1795
+ tokenBearingSteps += 1;
1796
+ if (s.tokensInput !== void 0) totalTokensInput += s.tokensInput;
1797
+ if (s.tokensOutput !== void 0) totalTokensOutput += s.tokensOutput;
1798
+ if (s.tokensTotal !== void 0) {
1799
+ totalTokensTotal += s.tokensTotal;
1800
+ stepsWithKnownTotal += 1;
1801
+ } else if (s.tokensInput !== void 0 && s.tokensOutput !== void 0) {
1802
+ totalTokensTotal += s.tokensInput + s.tokensOutput;
1803
+ stepsWithKnownTotal += 1;
1804
+ }
1805
+ if (s.tokensCached !== void 0) {
1806
+ totalTokensCached += s.tokensCached;
1807
+ hasCachedTokens = true;
1808
+ }
1809
+ }
1810
+ }
1811
+ const summary = {
1812
+ runId,
1813
+ name,
1814
+ status,
1815
+ durationMs,
1816
+ totalSteps,
1817
+ llmSteps,
1818
+ toolSteps,
1819
+ logicSteps,
1820
+ errorSteps,
1821
+ maxDepth,
1822
+ ...longestStep ? { longestStep } : {},
1823
+ ...tokenBearingSteps > 0 ? {
1824
+ totalTokens: {
1825
+ input: totalTokensInput,
1826
+ output: totalTokensOutput,
1827
+ ...stepsWithKnownTotal === tokenBearingSteps ? { total: totalTokensTotal } : {},
1828
+ ...hasCachedTokens ? { cached: totalTokensCached } : {}
1829
+ }
1830
+ } : {}
1831
+ };
1832
+ return summary;
1833
+ }
1834
+
1835
+ // packages/core/src/trace-filter.ts
1836
+ function toLower(s) {
1837
+ return typeof s === "string" ? s.toLowerCase() : "";
1838
+ }
1839
+ function filterTraces(traces, options) {
1840
+ const input = [...traces];
1841
+ let out = input.filter((t) => {
1842
+ if (options.status && t.status !== options.status) return false;
1843
+ if (options.name) {
1844
+ const q = options.name.toLowerCase();
1845
+ const hay = `${toLower(t.name)} ${toLower(t.runId)}`;
1846
+ if (!hay.includes(q)) return false;
1847
+ }
1848
+ if (options.since) {
1849
+ const windowMs = parseDuration(options.since);
1850
+ const cutoff = Date.now() - windowMs;
1851
+ const started = typeof t.startedAt === "number" ? t.startedAt : void 0;
1852
+ const basis = started ?? t.createdAt.getTime();
1853
+ if (!Number.isFinite(basis) || basis < cutoff) return false;
1854
+ }
1855
+ return true;
1856
+ });
1857
+ out.sort((a, b) => {
1858
+ const aTime = (typeof a.startedAt === "number" ? a.startedAt : void 0) ?? a.createdAt.getTime();
1859
+ const bTime = (typeof b.startedAt === "number" ? b.startedAt : void 0) ?? b.createdAt.getTime();
1860
+ return bTime - aTime;
1861
+ });
1862
+ if (typeof options.limit === "number" && Number.isFinite(options.limit)) {
1863
+ const n = Math.max(0, Math.floor(options.limit));
1864
+ out = out.slice(0, n);
1865
+ }
1866
+ return out;
1867
+ }
1868
+
1869
+ // packages/core/src/timeline.ts
1870
+ function finite(n) {
1871
+ return typeof n === "number" && Number.isFinite(n);
1872
+ }
1873
+ function pickStreamingMeta(metadata) {
1874
+ if (!metadata || typeof metadata !== "object") return void 0;
1875
+ const chunkCount = metadata.chunkCount;
1876
+ const streamDurationMs = metadata.streamDurationMs;
1877
+ const streamedCharCount = metadata.streamedCharCount;
1878
+ if (!finite(chunkCount) && !finite(streamDurationMs) && !finite(streamedCharCount)) {
1879
+ return void 0;
1880
+ }
1881
+ return {
1882
+ ...finite(chunkCount) ? { chunkCount } : {},
1883
+ ...finite(streamDurationMs) ? { streamDurationMs } : {},
1884
+ ...finite(streamedCharCount) ? { streamedCharCount } : {}
1885
+ };
1886
+ }
1887
+ function pickCorrelation(metadata) {
1888
+ if (!metadata || typeof metadata !== "object") return void 0;
1889
+ const out = {};
1890
+ for (const key of [
1891
+ "correlationId",
1892
+ "requestId",
1893
+ "decisionId",
1894
+ "groupId"
1895
+ ]) {
1896
+ const v = metadata[key];
1897
+ if (typeof v === "string" && v.trim() !== "") {
1898
+ out[key] = v;
1899
+ }
1900
+ }
1901
+ return Object.keys(out).length > 0 ? out : void 0;
1902
+ }
1903
+ function buildRunTimeline(events, options = {}) {
1904
+ const started = events.find(
1905
+ (e) => e.event === "run_started"
1906
+ );
1907
+ const completed = events.filter(
1908
+ (e) => e.event === "run_completed"
1909
+ );
1910
+ const lastCompleted = completed[completed.length - 1];
1911
+ const runId = started?.runId ?? events.find((e) => typeof e.runId === "string")?.runId ?? "unknown-run";
1912
+ const runStart = started && finite(started.startTime) ? started.startTime : started && finite(started.timestamp) ? started.timestamp : void 0;
1913
+ const status = lastCompleted ? lastCompleted.status : started ? "running" : "unknown";
1914
+ const steps = /* @__PURE__ */ new Map();
1915
+ for (const e of events) {
1916
+ if (e.event === "step_started") {
1917
+ const s = e;
1918
+ steps.set(s.stepId, {
1919
+ name: s.name,
1920
+ type: s.type,
1921
+ parentId: s.parentId,
1922
+ startedAt: finite(s.startTime) ? s.startTime : s.timestamp,
1923
+ status: "running",
1924
+ metadata: s.metadata
1925
+ });
1926
+ }
1927
+ }
1928
+ for (const e of events) {
1929
+ if (e.event !== "step_completed") continue;
1930
+ const c = e;
1931
+ const node = steps.get(c.stepId);
1932
+ if (!node) continue;
1933
+ node.status = c.status;
1934
+ if (finite(c.durationMs)) node.durationMs = c.durationMs;
1935
+ }
1936
+ const depthCache = /* @__PURE__ */ new Map();
1937
+ const computeDepth = (stepId) => {
1938
+ const cached = depthCache.get(stepId);
1939
+ if (cached !== void 0) return cached;
1940
+ const node = steps.get(stepId);
1941
+ if (!node) return 0;
1942
+ const parent = node.parentId;
1943
+ if (typeof parent !== "string" || parent.trim() === "" || !steps.has(parent)) {
1944
+ depthCache.set(stepId, 0);
1945
+ return 0;
1946
+ }
1947
+ const d = Math.min(1e3, computeDepth(parent) + 1);
1948
+ depthCache.set(stepId, d);
1949
+ return d;
1950
+ };
1951
+ const entries = [];
1952
+ for (const [stepId, s] of steps.entries()) {
1953
+ const offsetMs = runStart !== void 0 && finite(s.startedAt) ? Math.max(0, s.startedAt - runStart) : 0;
1954
+ entries.push({
1955
+ stepId,
1956
+ name: s.name,
1957
+ type: s.type,
1958
+ status: s.status,
1959
+ depth: computeDepth(stepId),
1960
+ startedAt: s.startedAt,
1961
+ offsetMs,
1962
+ durationMs: s.durationMs,
1963
+ isError: s.status === "error",
1964
+ streaming: pickStreamingMeta(s.metadata)
1965
+ });
1966
+ }
1967
+ entries.sort((a, b) => a.startedAt - b.startedAt);
1968
+ const slowTopN = options.slowTopN ?? 3;
1969
+ if (options.focus === "slow" && entries.length > 0) {
1970
+ const ranked = [...entries].filter((e) => finite(e.durationMs)).sort((a, b) => (b.durationMs ?? 0) - (a.durationMs ?? 0));
1971
+ const slowIds = new Set(
1972
+ ranked.slice(0, slowTopN).map((e) => e.stepId)
1973
+ );
1974
+ for (const e of entries) {
1975
+ if (slowIds.has(e.stepId)) e.slow = true;
1976
+ }
1977
+ }
1978
+ return {
1979
+ runId,
1980
+ name: typeof started?.name === "string" && started.name.trim() !== "" ? started.name : void 0,
1981
+ status,
1982
+ startedAt: runStart,
1983
+ endedAt: lastCompleted && finite(lastCompleted.endTime) ? lastCompleted.endTime : void 0,
1984
+ durationMs: lastCompleted && finite(lastCompleted.durationMs) ? lastCompleted.durationMs : void 0,
1985
+ correlation: pickCorrelation(
1986
+ started?.metadata
1987
+ ),
1988
+ entries
1989
+ };
1990
+ }
1991
+ function renderTimeline(timeline, options = {}) {
1992
+ const lines = [];
1993
+ lines.push(`Timeline: ${timeline.name ?? timeline.runId}`);
1994
+ lines.push(`Run ID: ${timeline.runId}`);
1995
+ lines.push(`Status: ${timeline.status}`);
1996
+ if (timeline.startedAt !== void 0) {
1997
+ lines.push(`Started: ${formatTimestamp(timeline.startedAt)}`);
1998
+ }
1999
+ if (timeline.durationMs !== void 0) {
2000
+ lines.push(`Duration: ${formatDuration2(timeline.durationMs)}`);
2001
+ }
2002
+ if (timeline.correlation) {
2003
+ const parts = Object.entries(timeline.correlation).filter(([, v]) => typeof v === "string").map(([k, v]) => `${k}=${v}`);
2004
+ if (parts.length > 0) {
2005
+ lines.push(`Correlation: ${parts.join(", ")}`);
2006
+ }
2007
+ }
2008
+ lines.push("");
2009
+ lines.push("Steps (chronological):");
2010
+ const show = timeline.entries.filter((e) => {
2011
+ if (options.focus === "slow") return e.slow === true;
2012
+ return true;
2013
+ });
2014
+ if (show.length === 0) {
2015
+ lines.push(
2016
+ options.focus === "slow" ? "(no steps with duration for slow focus)" : "(no steps)"
2017
+ );
2018
+ return lines.join("\n");
2019
+ }
2020
+ for (const e of show) {
2021
+ const prefix = e.slow ? "[slow] " : "";
2022
+ const typeTag = e.type === "llm" ? "llm" : e.type === "tool" ? "tool" : e.type;
2023
+ const dur = e.durationMs !== void 0 ? formatDuration2(e.durationMs) : "-";
2024
+ const err = e.isError ? " error" : "";
2025
+ const off = formatDuration2(e.offsetMs);
2026
+ let line = `${prefix}+${off} ${typeTag}:${e.name} (${dur})${err}`;
2027
+ if (e.streaming?.chunkCount !== void 0) {
2028
+ line += ` chunks=${e.streaming.chunkCount}`;
2029
+ }
2030
+ if (e.streaming?.streamDurationMs !== void 0) {
2031
+ line += ` stream=${formatDuration2(e.streaming.streamDurationMs)}`;
2032
+ }
2033
+ lines.push(line);
2034
+ }
2035
+ return lines.join("\n");
2036
+ }
2037
+
2038
+ // packages/core/src/what.ts
2039
+ function pickCorrelation2(metadata) {
2040
+ if (!metadata) return void 0;
2041
+ const out = {};
2042
+ for (const key of [
2043
+ "correlationId",
2044
+ "requestId",
2045
+ "decisionId",
2046
+ "groupId"
2047
+ ]) {
2048
+ const value = metadata[key];
2049
+ if (typeof value === "string" && value.trim() !== "") {
2050
+ out[key] = value;
2051
+ }
2052
+ }
2053
+ return Object.keys(out).length > 0 ? out : void 0;
2054
+ }
2055
+ function stepMixLine(summary) {
2056
+ const parts = [];
2057
+ if (summary.llmSteps > 0) parts.push(`${summary.llmSteps} LLM`);
2058
+ if (summary.toolSteps > 0) parts.push(`${summary.toolSteps} tool`);
2059
+ if (summary.logicSteps > 0) parts.push(`${summary.logicSteps} logic`);
2060
+ return parts.length > 0 ? parts.join(", ") : "none";
2061
+ }
2062
+ function outcomeLine(summary) {
2063
+ if (summary.status === "success") {
2064
+ return summary.errorSteps > 0 ? "Completed with step errors recorded." : "Completed successfully.";
2065
+ }
2066
+ if (summary.status === "error") {
2067
+ if (summary.failedStepNames.length > 0) {
2068
+ const names = summary.failedStepNames.slice(0, 3).join(", ");
2069
+ const suffix = summary.failedStepNames.length > 3 ? ` (+${summary.failedStepNames.length - 3} more)` : "";
2070
+ return `Failed at step(s): ${names}${suffix}.`;
2071
+ }
2072
+ if (summary.runErrorMessage) {
2073
+ return `Run failed: ${summary.runErrorMessage}`;
2074
+ }
2075
+ return "Run failed.";
2076
+ }
2077
+ if (summary.status === "running") {
2078
+ return "Run is still in progress (no run_completed).";
2079
+ }
2080
+ return "Outcome unknown \u2014 inspect events may be incomplete.";
2081
+ }
2082
+ function buildRunWhatSummary(events) {
2083
+ const base = buildRunSummary(events);
2084
+ const started = events.find(
2085
+ (e) => e.event === "run_started"
2086
+ );
2087
+ const completed = events.filter(
2088
+ (e) => e.event === "run_completed"
2089
+ );
2090
+ const lastCompleted = completed[completed.length - 1];
2091
+ const failedStepNames = [];
2092
+ const stepNames = /* @__PURE__ */ new Map();
2093
+ for (const e of events) {
2094
+ if (e.event === "step_started") {
2095
+ const s = e;
2096
+ stepNames.set(s.stepId, s.name);
2097
+ }
2098
+ }
2099
+ for (const e of events) {
2100
+ if (e.event === "step_completed") {
2101
+ const sc = e;
2102
+ if (sc.status === "error") {
2103
+ failedStepNames.push(stepNames.get(sc.stepId) ?? sc.stepId);
2104
+ }
2105
+ }
2106
+ }
2107
+ return {
2108
+ runId: base.runId,
2109
+ name: base.name,
2110
+ status: base.status,
2111
+ durationMs: base.durationMs,
2112
+ totalSteps: base.totalSteps,
2113
+ llmSteps: base.llmSteps,
2114
+ toolSteps: base.toolSteps,
2115
+ logicSteps: base.logicSteps,
2116
+ errorSteps: base.errorSteps,
2117
+ maxDepth: base.maxDepth,
2118
+ longestStep: base.longestStep,
2119
+ totalTokens: base.totalTokens,
2120
+ correlation: pickCorrelation2(started?.metadata),
2121
+ failedStepNames,
2122
+ runErrorMessage: lastCompleted?.error?.message
2123
+ };
2124
+ }
2125
+ function renderRunWhat(summary, options = {}) {
2126
+ const showCorrelation = options.correlation !== false;
2127
+ const lines = [];
2128
+ const label = summary.name ?? summary.runId;
2129
+ lines.push(`What: ${label}`);
2130
+ const duration = summary.durationMs !== void 0 ? formatDuration2(summary.durationMs) : "\u2014";
2131
+ lines.push(
2132
+ `Status: ${summary.status} \xB7 Duration: ${duration} \xB7 Steps: ${summary.totalSteps} (${stepMixLine(summary)})`
2133
+ );
2134
+ if (summary.totalTokens) {
2135
+ const tokenParts = [
2136
+ `${summary.totalTokens.input} in`,
2137
+ `${summary.totalTokens.output} out`
2138
+ ];
2139
+ if (summary.totalTokens.total !== void 0) {
2140
+ tokenParts.push(`${summary.totalTokens.total} total`);
2141
+ }
2142
+ if (summary.totalTokens.cached !== void 0) {
2143
+ tokenParts.push(`${summary.totalTokens.cached} cached`);
2144
+ }
2145
+ lines.push(`Tokens: ${tokenParts.join(" / ")}`);
2146
+ }
2147
+ if (showCorrelation && summary.correlation) {
2148
+ const parts = [];
2149
+ if (summary.correlation.correlationId) {
2150
+ parts.push(`correlationId=${summary.correlation.correlationId}`);
2151
+ }
2152
+ if (summary.correlation.requestId) {
2153
+ parts.push(`requestId=${summary.correlation.requestId}`);
2154
+ }
2155
+ if (summary.correlation.decisionId) {
2156
+ parts.push(`decisionId=${summary.correlation.decisionId}`);
2157
+ }
2158
+ if (summary.correlation.groupId) {
2159
+ parts.push(`groupId=${summary.correlation.groupId}`);
2160
+ }
2161
+ if (parts.length > 0) {
2162
+ lines.push(`Correlation: ${parts.join(", ")}`);
2163
+ }
2164
+ }
2165
+ lines.push(`Outcome: ${outcomeLine(summary)}`);
2166
+ if (summary.longestStep && summary.totalSteps > 0) {
2167
+ lines.push(
2168
+ `Slowest: ${summary.longestStep.name} (${formatDuration2(summary.longestStep.durationMs)}, ${summary.longestStep.type})`
2169
+ );
2170
+ }
2171
+ if (summary.maxDepth > 0) {
2172
+ lines.push(`Max depth: ${summary.maxDepth}`);
2173
+ }
2174
+ return lines.join("\n");
2175
+ }
2176
+
2177
+ // packages/core/src/explain.ts
2178
+ function flatten(nodes, out = []) {
2179
+ for (const node of nodes) {
2180
+ out.push({ node, index: out.length + 1 });
2181
+ flatten(node.children, out);
2182
+ }
2183
+ return out;
2184
+ }
2185
+ function redactValue(redactor, key, value) {
2186
+ return redactor.redactValue(key, value);
2187
+ }
2188
+ function fact(id, label, value, redactor) {
2189
+ return {
2190
+ id,
2191
+ label,
2192
+ value: redactValue(redactor, id.split(".").at(-1) ?? id, value),
2193
+ source: "trace",
2194
+ confidence: "observed"
2195
+ };
2196
+ }
2197
+ function topKinds(run) {
2198
+ return Object.entries(run.metadata.kinds).filter(([, count]) => count > 0).sort((a, b) => {
2199
+ if (b[1] !== a[1]) return b[1] - a[1];
2200
+ return a[0].localeCompare(b[0]);
2201
+ }).slice(0, 5).map(([kind, count]) => `${kind}:${count}`);
2202
+ }
2203
+ function countErrorNodes(nodes) {
2204
+ return nodes.filter((entry) => entry.node.event.status === "error").length;
2205
+ }
2206
+ function slowestNode(nodes) {
2207
+ return nodes.filter((entry) => entry.node.event.durationMs !== void 0).sort((a, b) => {
2208
+ const delta = (b.node.event.durationMs ?? 0) - (a.node.event.durationMs ?? 0);
2209
+ return delta !== 0 ? delta : a.index - b.index;
2210
+ })[0];
2211
+ }
2212
+ function attributeFacts(nodes, redactor) {
2213
+ const facts = [];
2214
+ for (const entry of nodes) {
2215
+ const attrs = entry.node.event.attributes;
2216
+ if (attrs === void 0) continue;
2217
+ for (const key of Object.keys(attrs).sort()) {
2218
+ facts.push({
2219
+ id: `node.${entry.index}.attributes.${key}`,
2220
+ label: `${entry.node.event.name} attribute ${key}`,
2221
+ value: redactValue(redactor, key, attrs[key]),
2222
+ source: "trace",
2223
+ confidence: "observed"
2224
+ });
2225
+ if (facts.length >= 8) return facts;
2226
+ }
2227
+ }
2228
+ return facts;
2229
+ }
2230
+ function buildFacts(run, redactor) {
2231
+ const nodes = flatten(run.children);
2232
+ const facts = [
2233
+ fact("run.id", "Run id", run.runId, redactor),
2234
+ fact("run.name", "Run name", run.name ?? run.runId, redactor),
2235
+ fact("run.status", "Run status", run.status ?? "unknown", redactor),
2236
+ fact("run.totalEvents", "Total events", run.metadata.totalEvents, redactor),
2237
+ fact("run.stepCount", "Top-level step count", run.children.length, redactor),
2238
+ fact("run.nodeCount", "Total node count", nodes.length, redactor),
2239
+ fact("run.errorNodeCount", "Error node count", countErrorNodes(nodes), redactor),
2240
+ fact("run.kinds", "Observed kind mix", topKinds(run), redactor)
2241
+ ];
2242
+ if (run.durationMs !== void 0) {
2243
+ facts.push(fact("run.durationMs", "Run duration milliseconds", run.durationMs, redactor));
2244
+ }
2245
+ const slowest = slowestNode(nodes);
2246
+ if (slowest !== void 0) {
2247
+ facts.push(
2248
+ fact("run.slowestNode", "Slowest observed node", {
2249
+ name: slowest.node.event.name,
2250
+ kind: slowest.node.event.kind,
2251
+ durationMs: slowest.node.event.durationMs
2252
+ }, redactor)
2253
+ );
2254
+ }
2255
+ facts.push(...attributeFacts(nodes, redactor));
2256
+ return facts;
2257
+ }
2258
+ function buildInferences(run, facts) {
2259
+ const inferences = [];
2260
+ const errorFact = facts.find((item) => item.id === "run.errorNodeCount");
2261
+ const kindFact = facts.find((item) => item.id === "run.kinds");
2262
+ const durationFact = facts.find((item) => item.id === "run.durationMs");
2263
+ const errorNodeCount = typeof errorFact?.value === "number" ? errorFact.value : 0;
2264
+ if (run.status === "error" || errorNodeCount > 0) {
2265
+ inferences.push({
2266
+ id: "outcome.error",
2267
+ label: "Outcome",
2268
+ text: "The run recorded an error status or at least one error node.",
2269
+ evidence: ["run.status", "run.errorNodeCount"],
2270
+ confidence: "deterministic"
2271
+ });
2272
+ } else if (run.status === "ok") {
2273
+ inferences.push({
2274
+ id: "outcome.success",
2275
+ label: "Outcome",
2276
+ text: "The run completed without observed error nodes.",
2277
+ evidence: ["run.status", "run.errorNodeCount"],
2278
+ confidence: "deterministic"
2279
+ });
2280
+ }
2281
+ if (kindFact !== void 0) {
2282
+ inferences.push({
2283
+ id: "shape.kind-mix",
2284
+ label: "Trace shape",
2285
+ text: "The explanation is based on the observed event kind mix, not generated content.",
2286
+ evidence: [kindFact.id],
2287
+ confidence: "deterministic"
2288
+ });
2289
+ }
2290
+ if (durationFact !== void 0) {
2291
+ inferences.push({
2292
+ id: "timing.duration",
2293
+ label: "Timing",
2294
+ text: "Timing claims are limited to persisted duration fields in the trace.",
2295
+ evidence: [durationFact.id],
2296
+ confidence: "deterministic"
2297
+ });
2298
+ }
2299
+ return inferences;
2300
+ }
2301
+ function buildLocalExplanation(run, options = {}) {
2302
+ const redactionProfile = options.redactionProfile ?? "local";
2303
+ const resolved = resolveRedactionProfile(redactionProfile);
2304
+ const redactor = new Redactor({ extraKeys: resolved.extraKeys });
2305
+ const mode = options.mode ?? "local";
2306
+ const facts = buildFacts(run, redactor);
2307
+ return {
2308
+ mode,
2309
+ runId: String(redactValue(redactor, "runId", run.runId)),
2310
+ ...run.name !== void 0 ? { name: String(redactValue(redactor, "name", run.name)) } : {},
2311
+ ...run.status !== void 0 ? { status: run.status } : {},
2312
+ redactionProfile,
2313
+ facts,
2314
+ inferences: mode === "dry-run" ? [] : buildInferences(run, facts),
2315
+ notes: [
2316
+ "Generated locally without provider or network calls.",
2317
+ "Facts are observed from normalized trace data; inferences are deterministic labels."
2318
+ ]
2319
+ };
2320
+ }
2321
+
2322
+ // packages/core/src/stats.ts
2323
+ function percentile(sorted, p) {
2324
+ if (sorted.length === 0) return void 0;
2325
+ const idx = Math.min(
2326
+ sorted.length - 1,
2327
+ Math.max(0, Math.ceil(p / 100 * sorted.length) - 1)
2328
+ );
2329
+ return sorted[idx];
2330
+ }
2331
+ async function readRunStartedMetadata(filePath) {
2332
+ try {
2333
+ const events = await readTraceEventsFromFile(filePath);
2334
+ for (const event of events) {
2335
+ if (event.event !== "run_started") continue;
2336
+ const rs = event;
2337
+ if (rs.metadata && typeof rs.metadata === "object") {
2338
+ return rs.metadata;
2339
+ }
2340
+ return void 0;
2341
+ }
2342
+ } catch {
2343
+ }
2344
+ return void 0;
2345
+ }
2346
+ function metaMatchesCorrelation(metadata, correlationId, groupId) {
2347
+ if (correlationId) {
2348
+ const v = metadata?.correlationId;
2349
+ if (typeof v !== "string" || v !== correlationId) return false;
2350
+ }
2351
+ if (groupId) {
2352
+ const v = metadata?.groupId;
2353
+ if (typeof v !== "string" || v !== groupId) return false;
2354
+ }
2355
+ return true;
2356
+ }
2357
+ async function buildTraceStats(metas, options) {
2358
+ let filtered = filterTraces(metas, { since: options.since });
2359
+ if (options.correlationId || options.groupId) {
2360
+ const next = [];
2361
+ for (const m of filtered) {
2362
+ const md = await readRunStartedMetadata(m.filePath);
2363
+ if (metaMatchesCorrelation(md, options.correlationId, options.groupId)) {
2364
+ next.push(m);
2365
+ }
2366
+ }
2367
+ filtered = next;
2368
+ }
2369
+ let successCount = 0;
2370
+ let errorCount = 0;
2371
+ let runningCount = 0;
2372
+ let unknownCount = 0;
2373
+ const durations = [];
2374
+ let totalSteps = 0;
2375
+ let totalLlmSteps = 0;
2376
+ let totalToolSteps = 0;
2377
+ let totalErrorSteps = 0;
2378
+ const slowestRuns = [];
2379
+ const slowestSteps = [];
2380
+ for (const m of filtered) {
2381
+ if (m.status === "success") successCount += 1;
2382
+ else if (m.status === "error") errorCount += 1;
2383
+ else if (m.status === "running") runningCount += 1;
2384
+ else unknownCount += 1;
2385
+ if (typeof m.durationMs === "number" && Number.isFinite(m.durationMs) && m.durationMs >= 0) {
2386
+ durations.push(m.durationMs);
2387
+ slowestRuns.push({
2388
+ runId: m.runId,
2389
+ name: m.name,
2390
+ durationMs: m.durationMs,
2391
+ status: m.status
2392
+ });
2393
+ }
2394
+ try {
2395
+ const events = await readTraceEventsFromFile(m.filePath);
2396
+ if (events.length === 0) continue;
2397
+ const summary = buildRunSummary(events);
2398
+ totalSteps += summary.totalSteps;
2399
+ totalLlmSteps += summary.llmSteps;
2400
+ totalToolSteps += summary.toolSteps;
2401
+ totalErrorSteps += summary.errorSteps;
2402
+ const steps = collectCompletedSteps(events, m.runId);
2403
+ for (const s of steps) {
2404
+ slowestSteps.push(s);
2405
+ }
2406
+ } catch {
2407
+ }
2408
+ }
2409
+ slowestRuns.sort((a, b) => (b.durationMs ?? 0) - (a.durationMs ?? 0));
2410
+ slowestSteps.sort((a, b) => b.durationMs - a.durationMs);
2411
+ const runLimit = options.slowRunLimit ?? 5;
2412
+ const stepLimit = options.slowStepLimit ?? 5;
2413
+ const sortedDur = [...durations].sort((a, b) => a - b);
2414
+ const totalRuns = filtered.length;
2415
+ const errorRate = totalRuns > 0 ? errorCount / totalRuns : 0;
2416
+ const sumDur = durations.reduce((a, b) => a + b, 0);
2417
+ return {
2418
+ traceDir: options.traceDir,
2419
+ ...options.since ? { since: options.since } : {},
2420
+ ...options.correlationId ? { correlationId: options.correlationId } : {},
2421
+ ...options.groupId ? { groupId: options.groupId } : {},
2422
+ totalRuns,
2423
+ successCount,
2424
+ errorCount,
2425
+ runningCount,
2426
+ unknownCount,
2427
+ errorRate,
2428
+ duration: {
2429
+ ...sortedDur.length > 0 ? {
2430
+ minMs: sortedDur[0],
2431
+ maxMs: sortedDur[sortedDur.length - 1],
2432
+ avgMs: sumDur / sortedDur.length,
2433
+ p50Ms: percentile(sortedDur, 50),
2434
+ p95Ms: percentile(sortedDur, 95)
2435
+ } : {}
2436
+ },
2437
+ totalSteps,
2438
+ avgStepsPerRun: totalRuns > 0 ? totalSteps / totalRuns : 0,
2439
+ totalLlmSteps,
2440
+ totalToolSteps,
2441
+ totalErrorSteps,
2442
+ slowestRuns: slowestRuns.slice(0, runLimit),
2443
+ slowestSteps: slowestSteps.slice(0, stepLimit)
2444
+ };
2445
+ }
2446
+ function collectCompletedSteps(events, runId) {
2447
+ const started = /* @__PURE__ */ new Map();
2448
+ const out = [];
2449
+ for (const e of events) {
2450
+ if (e.event === "step_started") {
2451
+ const s = e;
2452
+ started.set(s.stepId, { name: s.name, type: s.type });
2453
+ }
2454
+ if (e.event === "step_completed") {
2455
+ const c = e;
2456
+ if (c.status !== "success" && c.status !== "error") continue;
2457
+ if (typeof c.durationMs !== "number" || !Number.isFinite(c.durationMs)) {
2458
+ continue;
2459
+ }
2460
+ const meta = started.get(c.stepId);
2461
+ out.push({
2462
+ runId,
2463
+ stepName: meta?.name ?? c.stepId,
2464
+ stepType: meta?.type ?? "logic",
2465
+ durationMs: c.durationMs
2466
+ });
2467
+ }
2468
+ }
2469
+ return out;
2470
+ }
2471
+ function renderTraceStats(stats) {
2472
+ const lines = [];
2473
+ lines.push("Trace stats (local)");
2474
+ lines.push(`Directory: ${stats.traceDir}`);
2475
+ if (stats.since) lines.push(`Since: ${stats.since}`);
2476
+ if (stats.correlationId) lines.push(`Correlation ID: ${stats.correlationId}`);
2477
+ if (stats.groupId) lines.push(`Group ID: ${stats.groupId}`);
2478
+ lines.push("");
2479
+ lines.push(`Runs: ${stats.totalRuns}`);
2480
+ lines.push(
2481
+ ` success: ${stats.successCount} error: ${stats.errorCount} running: ${stats.runningCount} unknown: ${stats.unknownCount}`
2482
+ );
2483
+ lines.push(`Error rate: ${(stats.errorRate * 100).toFixed(1)}%`);
2484
+ if (stats.duration.avgMs !== void 0) {
2485
+ lines.push(
2486
+ `Duration: min ${formatDuration2(stats.duration.minMs ?? 0)} | avg ${formatDuration2(stats.duration.avgMs)} | p50 ${formatDuration2(stats.duration.p50Ms ?? 0)} | p95 ${formatDuration2(stats.duration.p95Ms ?? 0)} | max ${formatDuration2(stats.duration.maxMs ?? 0)}`
2487
+ );
2488
+ }
2489
+ lines.push("");
2490
+ lines.push(`Steps: ${stats.totalSteps} (avg ${stats.avgStepsPerRun.toFixed(1)} per run)`);
2491
+ lines.push(
2492
+ ` LLM: ${stats.totalLlmSteps} tool: ${stats.totalToolSteps} errors: ${stats.totalErrorSteps}`
2493
+ );
2494
+ if (stats.slowestRuns.length > 0) {
2495
+ lines.push("");
2496
+ lines.push("Slowest runs:");
2497
+ for (const r of stats.slowestRuns) {
2498
+ lines.push(
2499
+ ` ${r.runId} | ${r.name ?? "-"} | ${formatDuration2(r.durationMs ?? 0)} | ${r.status}`
2500
+ );
2501
+ }
2502
+ }
2503
+ if (stats.slowestSteps.length > 0) {
2504
+ lines.push("");
2505
+ lines.push("Slowest steps:");
2506
+ for (const s of stats.slowestSteps) {
2507
+ lines.push(
2508
+ ` ${s.runId} | ${s.stepType}:${s.stepName} | ${formatDuration2(s.durationMs)}`
2509
+ );
2510
+ }
2511
+ }
2512
+ return lines.join("\n");
2513
+ }
2514
+
2515
+ // packages/core/src/search.ts
2516
+ function parseDurationFilter(expr) {
2517
+ const raw = expr.trim();
2518
+ const m = raw.match(/^(>=|<=|>|<)\s*(.+)$/);
2519
+ if (!m) {
2520
+ throw new Error(
2521
+ `Invalid --duration "${expr}". Use forms like >5s, >=500ms, <2m.`
2522
+ );
2523
+ }
2524
+ const op = m[1];
2525
+ const ms = parseDuration(m[2].trim());
2526
+ return { op, ms };
2527
+ }
2528
+ function durationMatches(valueMs, filter) {
2529
+ if (valueMs === void 0 || !Number.isFinite(valueMs)) return false;
2530
+ switch (filter.op) {
2531
+ case ">":
2532
+ return valueMs > filter.ms;
2533
+ case ">=":
2534
+ return valueMs >= filter.ms;
2535
+ case "<":
2536
+ return valueMs < filter.ms;
2537
+ case "<=":
2538
+ return valueMs <= filter.ms;
2539
+ default:
2540
+ return false;
2541
+ }
2542
+ }
2543
+ function normalizeStepTypeFilter(kind, type) {
2544
+ const v = (kind ?? type)?.trim().toLowerCase();
2545
+ return v && v !== "" ? v : void 0;
2546
+ }
2547
+ function nameMatches(hay, needle) {
2548
+ return hay.toLowerCase().includes(needle.toLowerCase());
2549
+ }
2550
+ async function searchTraces(metas, options) {
2551
+ let filtered = filterTraces(metas, { since: options.since });
2552
+ const stepTypeFilter = normalizeStepTypeFilter(options.kind, options.type);
2553
+ const nameQuery = options.name?.trim();
2554
+ const toolQuery = options.tool?.trim();
2555
+ let durationFilter;
2556
+ if (options.duration) {
2557
+ durationFilter = parseDurationFilter(options.duration);
2558
+ }
2559
+ const limit = options.limit ?? 50;
2560
+ const sessionId = options.session?.trim();
2561
+ const hasContentFilter = Boolean(
2562
+ options.status || stepTypeFilter || nameQuery || toolQuery || durationFilter
2563
+ );
2564
+ const results = [];
2565
+ const sessionLabel = sessionId && sessionId !== "" ? sessionId : void 0;
2566
+ if (!hasContentFilter) {
2567
+ for (const m of filtered) {
2568
+ results.push({
2569
+ runId: m.runId,
2570
+ runName: m.name,
2571
+ runStatus: m.status,
2572
+ timestamp: m.startedAt,
2573
+ durationMs: m.durationMs,
2574
+ matchReason: sessionLabel ? `trace in session ${sessionLabel}` : "trace in directory",
2575
+ matchedFields: sessionLabel ? ["run", "session"] : ["run"],
2576
+ filePath: m.filePath,
2577
+ ...sessionLabel ? { sessionId: sessionLabel } : {}
2578
+ });
2579
+ }
2580
+ return results.slice(0, limit);
2581
+ }
2582
+ for (const m of filtered) {
2583
+ if (options.status && m.status !== options.status) continue;
2584
+ let events = [];
2585
+ try {
2586
+ events = await readTraceEventsFromFile(m.filePath);
2587
+ } catch {
2588
+ continue;
2589
+ }
2590
+ if (events.length === 0) continue;
2591
+ const runMatches = matchRunLevel(m, {
2592
+ stepTypeFilter,
2593
+ nameQuery,
2594
+ toolQuery,
2595
+ durationFilter,
2596
+ statusFilter: options.status
2597
+ });
2598
+ results.push(...runMatches);
2599
+ const stepMatches = matchStepLevel(m, events, {
2600
+ stepTypeFilter,
2601
+ nameQuery,
2602
+ toolQuery,
2603
+ durationFilter,
2604
+ statusFilter: options.status
2605
+ });
2606
+ results.push(...stepMatches);
2607
+ }
2608
+ results.sort((a, b) => {
2609
+ const ta = a.timestamp ?? 0;
2610
+ const tb = b.timestamp ?? 0;
2611
+ if (ta !== tb) return ta - tb;
2612
+ const runCmp = a.runId.localeCompare(b.runId);
2613
+ if (runCmp !== 0) return runCmp;
2614
+ return (a.stepName ?? "").localeCompare(b.stepName ?? "");
2615
+ });
2616
+ return results.slice(0, limit);
2617
+ }
2618
+ function matchRunLevel(m, opts) {
2619
+ if (opts.stepTypeFilter || opts.toolQuery) return [];
2620
+ const out = [];
2621
+ const fields = [];
2622
+ if (opts.statusFilter && m.status === opts.statusFilter) {
2623
+ fields.push("run.status");
2624
+ }
2625
+ if (opts.nameQuery && nameMatches(m.name ?? m.runId, opts.nameQuery)) {
2626
+ fields.push("run.name");
2627
+ }
2628
+ if (opts.durationFilter && durationMatches(m.durationMs, opts.durationFilter)) {
2629
+ fields.push("run.durationMs");
2630
+ }
2631
+ if (fields.length === 0) return out;
2632
+ out.push({
2633
+ runId: m.runId,
2634
+ runName: m.name,
2635
+ runStatus: m.status,
2636
+ timestamp: m.startedAt,
2637
+ durationMs: m.durationMs,
2638
+ matchReason: `run match: ${fields.join(", ")}`,
2639
+ matchedFields: fields,
2640
+ filePath: m.filePath
2641
+ });
2642
+ return out;
2643
+ }
2644
+ function matchStepLevel(m, events, opts) {
2645
+ const out = [];
2646
+ const started = /* @__PURE__ */ new Map();
2647
+ for (const e of events) {
2648
+ if (e.event === "step_started") {
2649
+ started.set(e.stepId, e);
2650
+ }
2651
+ }
2652
+ for (const e of events) {
2653
+ if (e.event !== "step_completed") continue;
2654
+ const c = e;
2655
+ const s = started.get(c.stepId);
2656
+ if (!s) continue;
2657
+ const fields = [];
2658
+ const stepType = s.type;
2659
+ if (opts.stepTypeFilter && stepType !== opts.stepTypeFilter) {
2660
+ continue;
2661
+ }
2662
+ const hasStepFilters = opts.stepTypeFilter || opts.nameQuery || opts.toolQuery || opts.durationFilter || opts.statusFilter === "error" || opts.statusFilter === "success";
2663
+ if (!hasStepFilters) continue;
2664
+ if (opts.statusFilter === "error" && c.status === "error") {
2665
+ fields.push("step.status");
2666
+ } else if (opts.statusFilter === "success" && c.status === "success") {
2667
+ fields.push("step.status");
2668
+ } else if (opts.statusFilter === "error" || opts.statusFilter === "success") {
2669
+ continue;
2670
+ }
2671
+ if (opts.nameQuery) {
2672
+ if (!nameMatches(s.name, opts.nameQuery)) continue;
2673
+ fields.push("step.name");
2674
+ }
2675
+ if (opts.toolQuery) {
2676
+ const toolName = typeof s.metadata?.toolName === "string" ? s.metadata.toolName : s.name;
2677
+ if (!nameMatches(toolName, opts.toolQuery)) continue;
2678
+ fields.push("step.tool");
2679
+ }
2680
+ if (opts.durationFilter) {
2681
+ if (!durationMatches(c.durationMs, opts.durationFilter)) continue;
2682
+ fields.push("step.durationMs");
2683
+ }
2684
+ if (opts.stepTypeFilter) {
2685
+ fields.push("step.type");
2686
+ }
2687
+ if (fields.length === 0) continue;
2688
+ out.push({
2689
+ runId: m.runId,
2690
+ runName: m.name,
2691
+ runStatus: m.status,
2692
+ stepId: c.stepId,
2693
+ stepName: s.name,
2694
+ stepType,
2695
+ timestamp: s.startTime ?? s.timestamp,
2696
+ durationMs: c.durationMs,
2697
+ matchReason: `step match: ${fields.join(", ")}`,
2698
+ matchedFields: fields,
2699
+ filePath: m.filePath
2700
+ });
2701
+ }
2702
+ return out;
2703
+ }
2704
+ async function loadTraceMetadataList(_traceDir, fileNames, getPath) {
2705
+ const metas = [];
2706
+ for (const fileName of fileNames) {
2707
+ try {
2708
+ const filePath = getPath(fileName);
2709
+ const meta = await extractMetadata(filePath);
2710
+ metas.push(meta);
2711
+ } catch {
2712
+ }
2713
+ }
2714
+ return metas;
2715
+ }
2716
+
2717
+ // packages/core/src/sessions/activity.ts
2718
+ function statusLine(session) {
2719
+ const name = session.workflowId ?? session.correlationId ?? session.sessionId;
2720
+ const status = session.status;
2721
+ if (session.lastError) {
2722
+ return `${name} session ${session.sessionId} failed at ${session.lastError.message}`;
2723
+ }
2724
+ if (session.observationSummary) {
2725
+ return `${name} session ${session.sessionId} ${status} with observation warning`;
2726
+ }
2727
+ return `${name} session ${session.sessionId} ${status}`;
2728
+ }
2729
+ function parseSinceMs(since, nowMs) {
2730
+ if (!since || since.trim() === "") return nowMs - 7 * 864e5;
2731
+ const trimmed = since.trim().toLowerCase();
2732
+ const match = /^(\d+)([smhd])$/.exec(trimmed);
2733
+ if (!match) return nowMs - 7 * 864e5;
2734
+ const amount = Number.parseInt(match[1], 10);
2735
+ const unit = match[2];
2736
+ const mult = unit === "s" ? 1e3 : unit === "m" ? 6e4 : unit === "h" ? 36e5 : 864e5;
2737
+ return nowMs - amount * mult;
2738
+ }
2739
+ function isFailed(status) {
2740
+ return status === "error";
2741
+ }
2742
+ function isStale(status) {
2743
+ return status === "stale";
2744
+ }
2745
+ function guardrailWarnings(session) {
2746
+ const summary = session.checkSummary;
2747
+ if (!summary) return 0;
2748
+ return summary.warn;
2749
+ }
2750
+ function buildActivitySummary(index, options = {}) {
2751
+ const nowMs = options.nowMs ?? Date.now();
2752
+ const sinceMs = parseSinceMs(options.since, nowMs);
2753
+ const sinceIso = new Date(sinceMs).toISOString();
2754
+ const limit = Number.isInteger(options.limit) && options.limit > 0 ? options.limit : 20;
2755
+ const inWindow = index.sessions.filter((session) => {
2756
+ const activityMs2 = Date.parse(session.lastActivity);
2757
+ return Number.isFinite(activityMs2) && activityMs2 >= sinceMs;
2758
+ });
2759
+ const entries = [...inWindow].sort((a, b) => Date.parse(b.lastActivity) - Date.parse(a.lastActivity)).slice(0, limit).map((session) => ({
2760
+ sessionId: session.sessionId,
2761
+ status: session.status,
2762
+ summary: statusLine(session),
2763
+ lastActivity: session.lastActivity,
2764
+ runCount: session.runIds.length
2765
+ }));
2766
+ let failed = 0;
2767
+ let stale = 0;
2768
+ let guardrailWarningTotal = 0;
2769
+ for (const session of inWindow) {
2770
+ if (isFailed(session.status)) failed += 1;
2771
+ if (isStale(session.status)) stale += 1;
2772
+ guardrailWarningTotal += guardrailWarnings(session);
2773
+ }
2774
+ return {
2775
+ since: sinceIso,
2776
+ sessions: inWindow.length,
2777
+ failed,
2778
+ stale,
2779
+ guardrailWarnings: guardrailWarningTotal,
2780
+ entries
2781
+ };
2782
+ }
2783
+ function renderActivitySummaryHuman(summary) {
2784
+ const lines = [];
2785
+ const todayStart = /* @__PURE__ */ new Date();
2786
+ todayStart.setHours(0, 0, 0, 0);
2787
+ const todayMs = todayStart.getTime();
2788
+ const today = summary.entries.filter(
2789
+ (entry) => Date.parse(entry.lastActivity) >= todayMs
2790
+ );
2791
+ if (today.length > 0) {
2792
+ lines.push("Today");
2793
+ for (const entry of today) {
2794
+ lines.push(` ${entry.summary}`);
2795
+ }
2796
+ lines.push("");
2797
+ }
2798
+ lines.push(`Since ${summary.since}`);
2799
+ lines.push(` ${summary.sessions} sessions`);
2800
+ lines.push(` ${summary.failed} failed`);
2801
+ lines.push(` ${summary.stale} stale`);
2802
+ lines.push(` ${summary.guardrailWarnings} guardrail warnings`);
2803
+ return lines.join("\n");
2804
+ }
2805
+
2806
+ // packages/core/src/sessions/load.ts
2807
+ async function enrichSessionRunRecord(meta) {
2808
+ let metadata;
2809
+ try {
2810
+ const events = await readTraceEventsFromFile(meta.filePath);
2811
+ for (const event of events) {
2812
+ if (event.event !== "run_started") continue;
2813
+ if (event.metadata && typeof event.metadata === "object") {
2814
+ metadata = event.metadata;
2815
+ }
2816
+ break;
2817
+ }
2818
+ } catch {
2819
+ }
2820
+ return {
2821
+ runId: meta.runId,
2822
+ name: meta.name,
2823
+ status: meta.status,
2824
+ startedAt: meta.startedAt,
2825
+ endedAt: meta.endedAt,
2826
+ durationMs: meta.durationMs,
2827
+ filePath: meta.filePath,
2828
+ metadata
2829
+ };
2830
+ }
2831
+ async function loadSessionRunRecords(metas) {
2832
+ const out = [];
2833
+ for (const meta of metas) {
2834
+ out.push(await enrichSessionRunRecord(meta));
2835
+ }
2836
+ return out;
2837
+ }
2838
+
2839
+ // packages/core/src/sessions/metadata.ts
2840
+ function isNonEmptyString3(value) {
2841
+ return typeof value === "string" && value.trim() !== "";
2842
+ }
2843
+ function finitePositiveInt(value) {
2844
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 1) {
2845
+ return void 0;
2846
+ }
2847
+ return Math.trunc(value);
2848
+ }
2849
+ function extractSessionWorkflowMetadata(record) {
2850
+ if (!record) return void 0;
2851
+ const out = {};
2852
+ let found = false;
2853
+ const assignString = (key, value) => {
2854
+ if (isNonEmptyString3(value)) {
2855
+ out[key] = value.trim();
2856
+ found = true;
2857
+ }
2858
+ };
2859
+ assignString("sessionId", record.sessionId);
2860
+ assignString("conversationId", record.conversationId);
2861
+ assignString("groupId", record.groupId);
2862
+ assignString("parentGroupId", record.parentGroupId);
2863
+ assignString("retryOf", record.retryOf);
2864
+ assignString("retryReason", record.retryReason);
2865
+ assignString("handoffFrom", record.handoffFrom);
2866
+ assignString("handoffTo", record.handoffTo);
2867
+ assignString("subAgentId", record.subAgentId);
2868
+ assignString("subAgentName", record.subAgentName);
2869
+ assignString("jobId", record.jobId);
2870
+ assignString("queueName", record.queueName);
2871
+ assignString("workflowName", record.workflowName);
2872
+ assignString("workflowStep", record.workflowStep);
2873
+ assignString("toolCallId", record.toolCallId);
2874
+ assignString("mcpToolCallId", record.mcpToolCallId);
2875
+ assignString("linkedStepId", record.linkedStepId);
2876
+ assignString("correlationId", record.correlationId);
2877
+ assignString("requestId", record.requestId);
2878
+ assignString("decisionId", record.decisionId);
2879
+ const attempt = finitePositiveInt(record.attempt);
2880
+ if (attempt !== void 0) {
2881
+ out.attempt = attempt;
2882
+ found = true;
2883
+ }
2884
+ return found ? out : void 0;
2885
+ }
2886
+ function sessionKeyForRun(meta, options) {
2887
+ if (meta?.sessionId) return meta.sessionId;
2888
+ if (options?.correlateByGroupId && meta?.groupId) {
2889
+ return `group:${meta.groupId}`;
2890
+ }
2891
+ return void 0;
2892
+ }
2893
+
2894
+ // packages/core/src/sessions/status.ts
2895
+ var DEFAULT_STALE_THRESHOLD_MS = 864e5;
2896
+ var EXPLICIT_STATUS_PRIORITY = {
2897
+ error: 5,
2898
+ waiting_input: 4,
2899
+ idle: 3,
2900
+ stale: 2,
2901
+ completed: 1
2902
+ };
2903
+ var EXPLICIT_SESSION_STATUSES = /* @__PURE__ */ new Set([
2904
+ "running",
2905
+ "waiting_input",
2906
+ "idle",
2907
+ "completed",
2908
+ "error",
2909
+ "stale",
2910
+ "unknown"
2911
+ ]);
2912
+ function isExplicitSessionStatus(value) {
2913
+ return typeof value === "string" && EXPLICIT_SESSION_STATUSES.has(value);
2914
+ }
2915
+ function activityMs(run) {
2916
+ return run.endedAt ?? run.startedAt ?? 0;
2917
+ }
2918
+ function latestActivityMs(runs) {
2919
+ let latest = 0;
2920
+ for (const run of runs) {
2921
+ const ms = activityMs(run);
2922
+ if (ms > latest) latest = ms;
2923
+ }
2924
+ return latest;
2925
+ }
2926
+ function earliestStart(runs) {
2927
+ let earliest;
2928
+ for (const run of runs) {
2929
+ if (run.startedAt === void 0) continue;
2930
+ if (earliest === void 0 || run.startedAt < earliest) {
2931
+ earliest = run.startedAt;
2932
+ }
2933
+ }
2934
+ return earliest;
2935
+ }
2936
+ function latestEndWhenAllEnded(runs) {
2937
+ if (runs.length === 0) return void 0;
2938
+ let latest;
2939
+ for (const run of runs) {
2940
+ if (run.endedAt === void 0) return void 0;
2941
+ if (latest === void 0 || run.endedAt > latest) latest = run.endedAt;
2942
+ }
2943
+ return latest;
2944
+ }
2945
+ function pickExplicitStatus(runs) {
2946
+ let best;
2947
+ let bestPriority = 0;
2948
+ for (const run of runs) {
2949
+ const raw = run.metadata?.sessionStatus;
2950
+ if (!isExplicitSessionStatus(raw)) continue;
2951
+ const priority = EXPLICIT_STATUS_PRIORITY[raw] ?? 0;
2952
+ if (priority > bestPriority) {
2953
+ bestPriority = priority;
2954
+ best = raw;
2955
+ }
2956
+ }
2957
+ return best;
2958
+ }
2959
+ function deriveLastError(runs) {
2960
+ const errorRuns = runs.filter((run) => run.status === "error").sort((a, b) => activityMs(b) - activityMs(a));
2961
+ const latest = errorRuns[0];
2962
+ if (!latest) return void 0;
2963
+ const meta = latest.metadata ?? {};
2964
+ const message = typeof meta.errorMessage === "string" && meta.errorMessage.trim() !== "" ? meta.errorMessage.trim() : latest.name ?? latest.runId;
2965
+ const code = typeof meta.errorCode === "string" && meta.errorCode.trim() !== "" ? meta.errorCode.trim() : void 0;
2966
+ return { runId: latest.runId, message, code };
2967
+ }
2968
+ function deriveCheckSummary(runs) {
2969
+ let pass = 0;
2970
+ let fail = 0;
2971
+ let warn2 = 0;
2972
+ let found = false;
2973
+ for (const run of runs) {
2974
+ const summary = run.metadata?.checkSummary;
2975
+ if (!summary || typeof summary !== "object") continue;
2976
+ const record = summary;
2977
+ if (typeof record.pass === "number") {
2978
+ pass += record.pass;
2979
+ found = true;
2980
+ }
2981
+ if (typeof record.fail === "number") {
2982
+ fail += record.fail;
2983
+ found = true;
2984
+ }
2985
+ if (typeof record.warn === "number") {
2986
+ warn2 += record.warn;
2987
+ found = true;
2988
+ }
2989
+ }
2990
+ return found ? { pass, fail, warn: warn2 } : void 0;
2991
+ }
2992
+ function deriveObservationSummary(runs) {
2993
+ for (const run of [...runs].sort((a, b) => activityMs(b) - activityMs(a))) {
2994
+ const value = run.metadata?.observationSummary;
2995
+ if (typeof value === "string" && value.trim() !== "") {
2996
+ return value.trim();
2997
+ }
2998
+ }
2999
+ return void 0;
3000
+ }
3001
+ function deriveSessionStatus(runs, options = {}) {
3002
+ if (runs.length === 0) return "unknown";
3003
+ if (runs.some((run) => run.status === "running")) return "running";
3004
+ const explicit = pickExplicitStatus(runs);
3005
+ if (explicit && explicit !== "running") return explicit;
3006
+ if (runs.some((run) => run.status === "error")) return "error";
3007
+ if (runs.every((run) => run.status === "success")) return "completed";
3008
+ const nowMs = options.nowMs ?? Date.now();
3009
+ const staleThresholdMs = options.staleThresholdMs ?? DEFAULT_STALE_THRESHOLD_MS;
3010
+ const lastMs = latestActivityMs(runs);
3011
+ if (lastMs > 0 && nowMs - lastMs > staleThresholdMs) return "stale";
3012
+ return "unknown";
3013
+ }
3014
+ function enrichSessionSummary(summary, runs, options = {}) {
3015
+ const sessionRuns = runs.filter((run) => summary.runIds.includes(run.runId)).sort((a, b) => a.runId.localeCompare(b.runId));
3016
+ const startedAt = earliestStart(sessionRuns);
3017
+ const endedAt = latestEndWhenAllEnded(sessionRuns);
3018
+ const durationMs = startedAt !== void 0 && endedAt !== void 0 ? endedAt - startedAt : void 0;
3019
+ let correlationId;
3020
+ let jobId;
3021
+ let workflowId;
3022
+ for (const run of sessionRuns) {
3023
+ const meta = extractSessionWorkflowMetadata(run.metadata);
3024
+ if (!correlationId && meta?.correlationId) correlationId = meta.correlationId;
3025
+ if (!jobId && meta?.jobId) jobId = meta.jobId;
3026
+ if (!workflowId && meta?.workflowName) workflowId = meta.workflowName;
3027
+ else if (!workflowId && meta?.workflowStep) workflowId = meta.workflowStep;
3028
+ }
3029
+ const lastMs = latestActivityMs(sessionRuns);
3030
+ const lastActivity = lastMs > 0 ? new Date(lastMs).toISOString() : (/* @__PURE__ */ new Date(0)).toISOString();
3031
+ const retryCount = summary.retries.filter(
3032
+ (retry) => retry.retryOf !== void 0 || (retry.attempt ?? 0) > 1
3033
+ ).length;
3034
+ return {
3035
+ ...summary,
3036
+ status: deriveSessionStatus(sessionRuns, options),
3037
+ startedAt,
3038
+ endedAt,
3039
+ durationMs,
3040
+ correlationId,
3041
+ jobId,
3042
+ workflowId,
3043
+ lastError: deriveLastError(sessionRuns),
3044
+ lastActivity,
3045
+ retryCount,
3046
+ observationSummary: deriveObservationSummary(sessionRuns),
3047
+ checkSummary: deriveCheckSummary(sessionRuns)
3048
+ };
3049
+ }
3050
+
3051
+ // packages/core/src/sessions/checks.ts
3052
+ function emptySummary() {
3053
+ return { passed: 0, failed: 0, warnings: 0, errors: 0 };
3054
+ }
3055
+ function mergeSummary(target, source) {
3056
+ return {
3057
+ passed: target.passed + source.passed,
3058
+ failed: target.failed + source.failed,
3059
+ warnings: target.warnings + source.warnings,
3060
+ errors: target.errors + source.errors
3061
+ };
3062
+ }
3063
+ function sessionDiagnostic(code, message) {
3064
+ return { code, message, severity: "error" };
3065
+ }
3066
+ function aggregateSessionCheckResults(perRun, scope) {
3067
+ if (scope.notFound) {
3068
+ return {
3069
+ ok: false,
3070
+ status: "error",
3071
+ format: perRun[0]?.format ?? "agent-inspect-jsonl",
3072
+ scopeKind: scope.scopeKind,
3073
+ scopeLabel: scope.scopeLabel,
3074
+ runIds: [],
3075
+ runResults: [],
3076
+ summary: { ...emptySummary(), errors: 1 },
3077
+ findings: [],
3078
+ diagnostics: [
3079
+ sessionDiagnostic(
3080
+ "AI_CHECK_INVALID_ARGUMENTS",
3081
+ `${scope.scopeKind} not found: ${scope.scopeLabel}`
3082
+ )
3083
+ ],
3084
+ ...scope.sessionWarnings?.length ? { sessionWarnings: [...scope.sessionWarnings] } : {}
3085
+ };
3086
+ }
3087
+ if (scope.empty || perRun.length === 0) {
3088
+ return {
3089
+ ok: false,
3090
+ status: "error",
3091
+ format: perRun[0]?.format ?? "agent-inspect-jsonl",
3092
+ scopeKind: scope.scopeKind,
3093
+ scopeLabel: scope.scopeLabel,
3094
+ runIds: scope.runIds,
3095
+ runResults: [],
3096
+ summary: { ...emptySummary(), errors: 1 },
3097
+ findings: [],
3098
+ diagnostics: [
3099
+ sessionDiagnostic(
3100
+ "AI_CHECK_TRACE_UNREADABLE",
3101
+ `No readable traces in ${scope.scopeKind}: ${scope.scopeLabel}`
3102
+ )
3103
+ ],
3104
+ ...scope.sessionWarnings?.length ? { sessionWarnings: [...scope.sessionWarnings] } : {}
3105
+ };
3106
+ }
3107
+ let summary = emptySummary();
3108
+ const findings = [];
3109
+ const diagnostics = [];
3110
+ const runResults = [];
3111
+ for (const result of perRun) {
3112
+ summary = mergeSummary(summary, result.summary);
3113
+ findings.push(...result.findings);
3114
+ diagnostics.push(...result.diagnostics);
3115
+ if (result.runId) {
3116
+ runResults.push({ runId: result.runId, status: result.status });
3117
+ }
3118
+ }
3119
+ runResults.sort((a, b) => a.runId.localeCompare(b.runId));
3120
+ findings.sort((a, b) => {
3121
+ const runCmp = (a.evidence[0]?.runId ?? "").localeCompare(
3122
+ b.evidence[0]?.runId ?? ""
3123
+ );
3124
+ if (runCmp !== 0) return runCmp;
3125
+ return a.ruleId.localeCompare(b.ruleId);
3126
+ });
3127
+ const hasErrors = diagnostics.some((item) => item.severity === "error");
3128
+ const status = hasErrors ? "error" : summary.failed > 0 ? "fail" : "pass";
3129
+ return {
3130
+ ok: status === "pass",
3131
+ status,
3132
+ format: perRun[0]?.format ?? "agent-inspect-jsonl",
3133
+ scopeKind: scope.scopeKind,
3134
+ scopeLabel: scope.scopeLabel,
3135
+ runIds: scope.runIds,
3136
+ runResults,
3137
+ summary,
3138
+ findings,
3139
+ diagnostics,
3140
+ ...scope.sessionWarnings?.length ? { sessionWarnings: [...scope.sessionWarnings] } : {}
3141
+ };
3142
+ }
3143
+
3144
+ // packages/core/src/sessions/index.ts
3145
+ function compareRuns(a, b) {
3146
+ const aStart = a.startedAt ?? 0;
3147
+ const bStart = b.startedAt ?? 0;
3148
+ if (aStart !== bStart) return aStart - bStart;
3149
+ return a.runId.localeCompare(b.runId);
3150
+ }
3151
+ function buildGroups(runIds, metaByRunId) {
3152
+ const byGroup = /* @__PURE__ */ new Map();
3153
+ for (const runId of runIds) {
3154
+ const groupId = metaByRunId.get(runId)?.groupId;
3155
+ if (!groupId) continue;
3156
+ const existing = byGroup.get(groupId);
3157
+ if (existing) {
3158
+ existing.runIds.push(runId);
3159
+ } else {
3160
+ byGroup.set(groupId, {
3161
+ groupId,
3162
+ parentGroupId: metaByRunId.get(runId)?.parentGroupId,
3163
+ runIds: [runId]
3164
+ });
3165
+ }
3166
+ }
3167
+ return [...byGroup.values()].map((group) => ({
3168
+ ...group,
3169
+ runIds: [...group.runIds].sort((a, b) => a.localeCompare(b))
3170
+ }));
3171
+ }
3172
+ function buildHandoffs(runIds, metaByRunId, warnings, sessionId) {
3173
+ const edges = [];
3174
+ const seen = /* @__PURE__ */ new Set();
3175
+ const pushEdge = (edge) => {
3176
+ const key = `${edge.from}->${edge.to}:${edge.confidence}`;
3177
+ if (seen.has(key)) return;
3178
+ seen.add(key);
3179
+ edges.push(edge);
3180
+ };
3181
+ for (const runId of runIds) {
3182
+ const meta = metaByRunId.get(runId);
3183
+ if (!meta) continue;
3184
+ if (meta.handoffFrom && meta.handoffTo) {
3185
+ pushEdge({
3186
+ from: meta.handoffFrom,
3187
+ to: meta.handoffTo,
3188
+ source: "manual",
3189
+ confidence: "explicit"
3190
+ });
3191
+ continue;
3192
+ }
3193
+ if (meta.handoffFrom) {
3194
+ pushEdge({
3195
+ from: meta.handoffFrom,
3196
+ to: runId,
3197
+ source: "manual",
3198
+ confidence: "explicit"
3199
+ });
3200
+ }
3201
+ if (meta.handoffTo) {
3202
+ pushEdge({
3203
+ from: runId,
3204
+ to: meta.handoffTo,
3205
+ source: "manual",
3206
+ confidence: "explicit"
3207
+ });
3208
+ }
3209
+ if (meta.subAgentId && meta.parentGroupId && !meta.handoffFrom && !meta.handoffTo) {
3210
+ pushEdge({
3211
+ from: meta.parentGroupId,
3212
+ to: meta.subAgentId,
3213
+ source: "inferred",
3214
+ confidence: "correlated"
3215
+ });
3216
+ warnings.push({
3217
+ code: "ambiguous-handoff-endpoints",
3218
+ message: "Handoff inferred from parentGroupId and subAgentId without explicit handoffFrom/handoffTo.",
3219
+ runId,
3220
+ sessionId
3221
+ });
3222
+ }
3223
+ }
3224
+ return edges.sort((a, b) => {
3225
+ const from = a.from.localeCompare(b.from);
3226
+ if (from !== 0) return from;
3227
+ return a.to.localeCompare(b.to);
3228
+ });
3229
+ }
3230
+ function buildRetries(runIds, metaByRunId, warnings, sessionId) {
3231
+ const retries = [];
3232
+ for (const runId of runIds) {
3233
+ const meta = metaByRunId.get(runId);
3234
+ if (!meta) continue;
3235
+ if (meta.retryOf) {
3236
+ retries.push({
3237
+ runId,
3238
+ retryOf: meta.retryOf,
3239
+ attempt: meta.attempt,
3240
+ source: "manual",
3241
+ confidence: "explicit"
3242
+ });
3243
+ continue;
3244
+ }
3245
+ if (meta.attempt !== void 0 && meta.attempt > 1) {
3246
+ retries.push({
3247
+ runId,
3248
+ attempt: meta.attempt,
3249
+ source: "inferred",
3250
+ confidence: "correlated"
3251
+ });
3252
+ warnings.push({
3253
+ code: "ambiguous-retry-link",
3254
+ message: "attempt > 1 without retryOf; retry link is correlated only.",
3255
+ runId,
3256
+ sessionId
3257
+ });
3258
+ }
3259
+ }
3260
+ return retries.sort((a, b) => a.runId.localeCompare(b.runId));
3261
+ }
3262
+ function buildCriticalPath(runs, handoffs) {
3263
+ const runById = new Map(runs.map((run) => [run.runId, run]));
3264
+ const explicitTargets = new Set(
3265
+ handoffs.filter((edge) => edge.confidence === "explicit").map((edge) => edge.to)
3266
+ );
3267
+ const explicitSources = new Set(
3268
+ handoffs.filter((edge) => edge.confidence === "explicit").map((edge) => edge.from)
3269
+ );
3270
+ const ordered = [...runs].sort(compareRuns);
3271
+ const path5 = [];
3272
+ const visited = /* @__PURE__ */ new Set();
3273
+ const pushRun = (run, confidence, source) => {
3274
+ if (visited.has(run.runId)) return;
3275
+ visited.add(run.runId);
3276
+ path5.push({
3277
+ runId: run.runId,
3278
+ name: run.name,
3279
+ startedAt: run.startedAt,
3280
+ durationMs: run.durationMs,
3281
+ confidence,
3282
+ source
3283
+ });
3284
+ };
3285
+ for (const edge of handoffs) {
3286
+ if (edge.confidence !== "explicit") continue;
3287
+ const fromRun = [...runById.values()].find(
3288
+ (run) => run.runId === edge.from || metaRunIdMatches(run, edge.from, runById)
3289
+ );
3290
+ const toRun = [...runById.values()].find(
3291
+ (run) => run.runId === edge.to || metaRunIdMatches(run, edge.to, runById)
3292
+ );
3293
+ if (fromRun) pushRun(fromRun, "explicit", "manual");
3294
+ if (toRun) pushRun(toRun, "explicit", "manual");
3295
+ }
3296
+ for (const run of ordered) {
3297
+ if (visited.has(run.runId)) continue;
3298
+ const confidence = explicitTargets.has(run.runId) || explicitSources.has(run.runId) ? "explicit" : "correlated";
3299
+ pushRun(run, confidence, confidence === "explicit" ? "manual" : "inferred");
3300
+ }
3301
+ return path5;
3302
+ }
3303
+ function metaRunIdMatches(run, token, runById) {
3304
+ const meta = extractSessionWorkflowMetadata(run.metadata);
3305
+ return meta?.subAgentId === token || meta?.groupId === token || runById.has(token);
3306
+ }
3307
+ function buildSessionIndex(inputRuns, options = {}) {
3308
+ const warnings = [];
3309
+ const runs = [...inputRuns].sort(compareRuns);
3310
+ const metaByRunId = /* @__PURE__ */ new Map();
3311
+ for (const run of runs) {
3312
+ metaByRunId.set(run.runId, extractSessionWorkflowMetadata(run.metadata));
3313
+ }
3314
+ const sessionsByKey = /* @__PURE__ */ new Map();
3315
+ const unscopedRunIds = [];
3316
+ for (const run of runs) {
3317
+ const meta = metaByRunId.get(run.runId);
3318
+ const key = sessionKeyForRun(meta, {
3319
+ correlateByGroupId: options.correlateByGroupId === true
3320
+ });
3321
+ if (!key) {
3322
+ unscopedRunIds.push(run.runId);
3323
+ continue;
3324
+ }
3325
+ const bucket = sessionsByKey.get(key) ?? [];
3326
+ bucket.push(run);
3327
+ sessionsByKey.set(key, bucket);
3328
+ }
3329
+ const sessions = [...sessionsByKey.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([sessionId, sessionRuns]) => {
3330
+ const runIds = sessionRuns.map((run) => run.runId).sort();
3331
+ const handoffs = buildHandoffs(runIds, metaByRunId, warnings, sessionId);
3332
+ const retries = buildRetries(runIds, metaByRunId, warnings, sessionId);
3333
+ const groups = buildGroups(runIds, metaByRunId);
3334
+ const criticalPath = buildCriticalPath(sessionRuns, handoffs);
3335
+ const confidences = new Set(handoffs.map((edge) => edge.confidence));
3336
+ if (confidences.has("explicit") && confidences.has("correlated")) {
3337
+ warnings.push({
3338
+ code: "mixed-confidence-group",
3339
+ message: "Session aggregates explicit and correlated handoff edges.",
3340
+ sessionId
3341
+ });
3342
+ }
3343
+ return enrichSessionSummary(
3344
+ {
3345
+ sessionId,
3346
+ runIds,
3347
+ groups,
3348
+ handoffs,
3349
+ retries,
3350
+ criticalPath
3351
+ },
3352
+ runs,
3353
+ {
3354
+ nowMs: options.nowMs,
3355
+ staleThresholdMs: options.staleThresholdMs
3356
+ }
3357
+ );
3358
+ });
3359
+ if (sessions.length === 0 && runs.length > 0) {
3360
+ warnings.push({
3361
+ code: "missing-session-id",
3362
+ message: "No sessionId (or correlated groupId) found on input runs."
3363
+ });
3364
+ }
3365
+ warnings.sort((a, b) => {
3366
+ const code = a.code.localeCompare(b.code);
3367
+ if (code !== 0) return code;
3368
+ return (a.runId ?? "").localeCompare(b.runId ?? "");
3369
+ });
3370
+ return {
3371
+ runs,
3372
+ sessions,
3373
+ unscopedRunIds: unscopedRunIds.sort(),
3374
+ warnings
3375
+ };
3376
+ }
3377
+
3378
+ // packages/core/src/sessions/scope.ts
3379
+ function filterMetasBySessionScope(metas, records, options) {
3380
+ const sessionId = options.sessionId?.trim();
3381
+ const groupId = options.groupId?.trim();
3382
+ const warnings = [];
3383
+ if (sessionId) {
3384
+ const index = buildSessionIndex(records, {
3385
+ correlateByGroupId: options.correlateByGroupId === true
3386
+ });
3387
+ warnings.push(...index.warnings);
3388
+ const session = index.sessions.find((item) => item.sessionId === sessionId);
3389
+ if (!session) {
3390
+ return {
3391
+ metas: [],
3392
+ scopeLabel: sessionId,
3393
+ scopeKind: "session",
3394
+ runIds: [],
3395
+ warnings,
3396
+ notFound: true
3397
+ };
3398
+ }
3399
+ const runIdSet = new Set(session.runIds);
3400
+ const filtered = metas.filter((meta) => runIdSet.has(meta.runId));
3401
+ return {
3402
+ metas: filtered,
3403
+ scopeLabel: sessionId,
3404
+ scopeKind: "session",
3405
+ runIds: session.runIds,
3406
+ warnings,
3407
+ notFound: false
3408
+ };
3409
+ }
3410
+ if (groupId) {
3411
+ const runIds = records.filter((run) => extractSessionWorkflowMetadata(run.metadata)?.groupId === groupId).map((run) => run.runId).sort();
3412
+ if (runIds.length === 0) {
3413
+ return {
3414
+ metas: [],
3415
+ scopeLabel: groupId,
3416
+ scopeKind: "group",
3417
+ runIds: [],
3418
+ warnings,
3419
+ notFound: true
3420
+ };
3421
+ }
3422
+ const runIdSet = new Set(runIds);
3423
+ return {
3424
+ metas: metas.filter((meta) => runIdSet.has(meta.runId)),
3425
+ scopeLabel: groupId,
3426
+ scopeKind: "group",
3427
+ runIds,
3428
+ warnings,
3429
+ notFound: false
3430
+ };
3431
+ }
3432
+ return {
3433
+ metas: [...metas],
3434
+ scopeLabel: "",
3435
+ scopeKind: "session",
3436
+ runIds: [],
3437
+ warnings,
3438
+ notFound: false
3439
+ };
3440
+ }
3441
+ var KNOWN_EVENTS = /* @__PURE__ */ new Set([
3442
+ "run_started",
3443
+ "run_completed",
3444
+ "step_started",
3445
+ "step_completed"
3446
+ ]);
3447
+ function isRecord6(value) {
3448
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3449
+ }
3450
+ function safeParse(line) {
3451
+ try {
3452
+ return JSON.parse(line);
3453
+ } catch {
3454
+ return void 0;
3455
+ }
3456
+ }
3457
+ async function isAgentInspectTrace(filePath) {
3458
+ try {
3459
+ const rl = createInterface({
3460
+ input: createReadStream(filePath, { encoding: "utf8" }),
3461
+ crlfDelay: Infinity
3462
+ });
3463
+ let checked = 0;
3464
+ for await (const line of rl) {
3465
+ const trimmed = line.trim();
3466
+ if (trimmed === "") continue;
3467
+ const parsed = safeParse(trimmed);
3468
+ if (!parsed) continue;
3469
+ if (!isRecord6(parsed)) continue;
3470
+ checked += 1;
3471
+ if (isTraceEvent(parsed)) return true;
3472
+ const ev = parsed.event;
3473
+ const runId = parsed.runId;
3474
+ if (typeof ev === "string" && KNOWN_EVENTS.has(ev) && typeof runId === "string") {
3475
+ return true;
3476
+ }
3477
+ if (checked >= 20) break;
3478
+ }
3479
+ return false;
3480
+ } catch {
3481
+ return false;
3482
+ }
3483
+ }
3484
+
3485
+ export { Redactor, TraceDirectory, __commonJS, __require, __toESM, aggregateSessionCheckResults, applyProfileMetadataCaps, buildActivitySummary, buildLocalExplanation, buildRunSummary, buildRunTimeline, buildRunWhatSummary, buildSessionIndex, buildTraceStats, enrichSessionRunRecord, extractCorrelationMetadata, extractMetadata, filterMetasBySessionScope, filterTraces, formatDuration2 as formatDuration, formatTimestamp, getIndent, getTraceFilePath, isAgentInspectTrace, isPersistedInspectEvent, loadSessionRunRecords, loadTraceMetadataList, nanoid, parseDuration, parseDurationFilter, parseTraceJsonl, persistedInspectEventsToTraceEvents, renderActivitySummaryHuman, renderErrorLine, renderRunWhat, renderStepLine, renderTimeline, renderTraceStats, resolveRedactionProfile, resolveTraceDir, searchTraces, source_default, truncateName, truncateStringForProfile, validateEvent };
3486
+ //# sourceMappingURL=chunk-5VSPJEZ7.mjs.map
3487
+ //# sourceMappingURL=chunk-5VSPJEZ7.mjs.map