agent-inspect 6.7.2 → 6.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +1 -1
  3. package/docs/EXPORTS.md +9 -0
  4. package/docs/PERFORMANCE.md +18 -0
  5. package/docs/STANDARDS.md +4 -0
  6. package/package.json +2 -2
  7. package/packages/cli/dist/{chunk-M6PC5KUT.mjs → chunk-FVEQ7JFF.mjs} +251 -209
  8. package/packages/cli/dist/chunk-FVEQ7JFF.mjs.map +1 -0
  9. package/packages/cli/dist/index.cjs +292 -229
  10. package/packages/cli/dist/index.cjs.map +1 -1
  11. package/packages/cli/dist/index.mjs +35 -15
  12. package/packages/cli/dist/index.mjs.map +1 -1
  13. package/packages/cli/dist/{src-27LC2BB3.mjs → src-I5NA7BLK.mjs} +3 -3
  14. package/packages/cli/dist/{src-27LC2BB3.mjs.map → src-I5NA7BLK.mjs.map} +1 -1
  15. package/packages/core/dist/advanced.cjs +249 -207
  16. package/packages/core/dist/advanced.cjs.map +1 -1
  17. package/packages/core/dist/advanced.mjs +51 -250
  18. package/packages/core/dist/advanced.mjs.map +1 -1
  19. package/packages/core/dist/checks.cjs +56 -4
  20. package/packages/core/dist/checks.cjs.map +1 -1
  21. package/packages/core/dist/checks.mjs +1 -1
  22. package/packages/core/dist/{chunk-X2FLDF7M.mjs → chunk-CTA6XNDP.mjs} +3 -3
  23. package/packages/core/dist/{chunk-X2FLDF7M.mjs.map → chunk-CTA6XNDP.mjs.map} +1 -1
  24. package/packages/core/dist/{chunk-EWHN6NA4.mjs → chunk-EQVXDGGU.mjs} +58 -6
  25. package/packages/core/dist/chunk-EQVXDGGU.mjs.map +1 -0
  26. package/packages/core/dist/{chunk-3USJVBLA.mjs → chunk-KDDU2R5P.mjs} +236 -5
  27. package/packages/core/dist/chunk-KDDU2R5P.mjs.map +1 -0
  28. package/packages/core/dist/{chunk-E5F2LQCX.mjs → chunk-T5MASTIW.mjs} +15 -4
  29. package/packages/core/dist/chunk-T5MASTIW.mjs.map +1 -0
  30. package/packages/core/dist/{chunk-KNYL56KZ.mjs → chunk-UOPVGCOB.mjs} +3 -3
  31. package/packages/core/dist/{chunk-KNYL56KZ.mjs.map → chunk-UOPVGCOB.mjs.map} +1 -1
  32. package/packages/core/dist/diff.cjs +4 -0
  33. package/packages/core/dist/diff.cjs.map +1 -1
  34. package/packages/core/dist/diff.mjs +4 -0
  35. package/packages/core/dist/diff.mjs.map +1 -1
  36. package/packages/core/dist/exporters.cjs +145 -133
  37. package/packages/core/dist/exporters.cjs.map +1 -1
  38. package/packages/core/dist/exporters.d.cts +3 -2
  39. package/packages/core/dist/exporters.d.ts +3 -2
  40. package/packages/core/dist/exporters.mjs +10 -5
  41. package/packages/core/dist/exporters.mjs.map +1 -1
  42. package/packages/core/dist/logs.cjs +16 -4
  43. package/packages/core/dist/logs.cjs.map +1 -1
  44. package/packages/core/dist/logs.mjs +5 -4
  45. package/packages/core/dist/logs.mjs.map +1 -1
  46. package/packages/core/dist/persisted.cjs +13 -2
  47. package/packages/core/dist/persisted.cjs.map +1 -1
  48. package/packages/core/dist/persisted.mjs +3 -3
  49. package/packages/core/dist/readers.cjs +13 -2
  50. package/packages/core/dist/readers.cjs.map +1 -1
  51. package/packages/core/dist/readers.mjs +3 -3
  52. package/packages/cli/dist/chunk-M6PC5KUT.mjs.map +0 -1
  53. package/packages/core/dist/chunk-3USJVBLA.mjs.map +0 -1
  54. package/packages/core/dist/chunk-E5F2LQCX.mjs.map +0 -1
  55. package/packages/core/dist/chunk-EWHN6NA4.mjs.map +0 -1
@@ -3394,6 +3394,202 @@ function filterTraces(traces, options) {
3394
3394
  return out;
3395
3395
  }
3396
3396
 
3397
+ // packages/core/src/stats.ts
3398
+ function percentile(sorted, p) {
3399
+ if (sorted.length === 0) return void 0;
3400
+ const idx = Math.min(
3401
+ sorted.length - 1,
3402
+ Math.max(0, Math.ceil(p / 100 * sorted.length) - 1)
3403
+ );
3404
+ return sorted[idx];
3405
+ }
3406
+ async function readRunStartedMetadata(filePath) {
3407
+ try {
3408
+ const events = await readTraceEventsFromFile(filePath);
3409
+ for (const event of events) {
3410
+ if (event.event !== "run_started") continue;
3411
+ const rs = event;
3412
+ if (rs.metadata && typeof rs.metadata === "object") {
3413
+ return rs.metadata;
3414
+ }
3415
+ return void 0;
3416
+ }
3417
+ } catch {
3418
+ }
3419
+ return void 0;
3420
+ }
3421
+ function metaMatchesCorrelation(metadata, correlationId, groupId) {
3422
+ if (correlationId) {
3423
+ const v = metadata?.correlationId;
3424
+ if (typeof v !== "string" || v !== correlationId) return false;
3425
+ }
3426
+ if (groupId) {
3427
+ const v = metadata?.groupId;
3428
+ if (typeof v !== "string" || v !== groupId) return false;
3429
+ }
3430
+ return true;
3431
+ }
3432
+ async function buildTraceStats(metas, options) {
3433
+ let filtered = filterTraces(metas, { since: options.since });
3434
+ if (options.correlationId || options.groupId) {
3435
+ const next = [];
3436
+ for (const m of filtered) {
3437
+ const md = await readRunStartedMetadata(m.filePath);
3438
+ if (metaMatchesCorrelation(md, options.correlationId, options.groupId)) {
3439
+ next.push(m);
3440
+ }
3441
+ }
3442
+ filtered = next;
3443
+ }
3444
+ let successCount = 0;
3445
+ let errorCount = 0;
3446
+ let runningCount = 0;
3447
+ let unknownCount = 0;
3448
+ const durations = [];
3449
+ let totalSteps = 0;
3450
+ let totalLlmSteps = 0;
3451
+ let totalToolSteps = 0;
3452
+ let totalErrorSteps = 0;
3453
+ const slowestRuns = [];
3454
+ const slowestSteps = [];
3455
+ for (const m of filtered) {
3456
+ if (m.status === "success") successCount += 1;
3457
+ else if (m.status === "error") errorCount += 1;
3458
+ else if (m.status === "running") runningCount += 1;
3459
+ else unknownCount += 1;
3460
+ if (typeof m.durationMs === "number" && Number.isFinite(m.durationMs) && m.durationMs >= 0) {
3461
+ durations.push(m.durationMs);
3462
+ slowestRuns.push({
3463
+ runId: m.runId,
3464
+ name: m.name,
3465
+ durationMs: m.durationMs,
3466
+ status: m.status
3467
+ });
3468
+ }
3469
+ try {
3470
+ const events = await readTraceEventsFromFile(m.filePath);
3471
+ if (events.length === 0) continue;
3472
+ const summary = buildRunSummary(events);
3473
+ totalSteps += summary.totalSteps;
3474
+ totalLlmSteps += summary.llmSteps;
3475
+ totalToolSteps += summary.toolSteps;
3476
+ totalErrorSteps += summary.errorSteps;
3477
+ const steps = collectCompletedSteps(events, m.runId);
3478
+ for (const s of steps) {
3479
+ slowestSteps.push(s);
3480
+ }
3481
+ } catch {
3482
+ }
3483
+ }
3484
+ slowestRuns.sort((a, b) => (b.durationMs ?? 0) - (a.durationMs ?? 0));
3485
+ slowestSteps.sort((a, b) => b.durationMs - a.durationMs);
3486
+ const runLimit = options.slowRunLimit ?? 5;
3487
+ const stepLimit = options.slowStepLimit ?? 5;
3488
+ const sortedDur = [...durations].sort((a, b) => a - b);
3489
+ const totalRuns = filtered.length;
3490
+ const errorRate = totalRuns > 0 ? errorCount / totalRuns : 0;
3491
+ const sumDur = durations.reduce((a, b) => a + b, 0);
3492
+ return {
3493
+ traceDir: options.traceDir,
3494
+ ...options.since ? { since: options.since } : {},
3495
+ ...options.correlationId ? { correlationId: options.correlationId } : {},
3496
+ ...options.groupId ? { groupId: options.groupId } : {},
3497
+ totalRuns,
3498
+ successCount,
3499
+ errorCount,
3500
+ runningCount,
3501
+ unknownCount,
3502
+ errorRate,
3503
+ duration: {
3504
+ ...sortedDur.length > 0 ? {
3505
+ minMs: sortedDur[0],
3506
+ maxMs: sortedDur[sortedDur.length - 1],
3507
+ avgMs: sumDur / sortedDur.length,
3508
+ p50Ms: percentile(sortedDur, 50),
3509
+ p95Ms: percentile(sortedDur, 95)
3510
+ } : {}
3511
+ },
3512
+ totalSteps,
3513
+ avgStepsPerRun: totalRuns > 0 ? totalSteps / totalRuns : 0,
3514
+ totalLlmSteps,
3515
+ totalToolSteps,
3516
+ totalErrorSteps,
3517
+ slowestRuns: slowestRuns.slice(0, runLimit),
3518
+ slowestSteps: slowestSteps.slice(0, stepLimit)
3519
+ };
3520
+ }
3521
+ function collectCompletedSteps(events, runId) {
3522
+ const started = /* @__PURE__ */ new Map();
3523
+ const out = [];
3524
+ for (const e of events) {
3525
+ if (e.event === "step_started") {
3526
+ const s = e;
3527
+ started.set(s.stepId, { name: s.name, type: s.type });
3528
+ }
3529
+ if (e.event === "step_completed") {
3530
+ const c = e;
3531
+ if (c.status !== "success" && c.status !== "error") continue;
3532
+ if (typeof c.durationMs !== "number" || !Number.isFinite(c.durationMs)) {
3533
+ continue;
3534
+ }
3535
+ const meta = started.get(c.stepId);
3536
+ out.push({
3537
+ runId,
3538
+ stepName: meta?.name ?? c.stepId,
3539
+ stepType: meta?.type ?? "logic",
3540
+ durationMs: c.durationMs
3541
+ });
3542
+ }
3543
+ }
3544
+ return out;
3545
+ }
3546
+ function formatStepLabel(stepType, stepName) {
3547
+ return stepName.startsWith(`${stepType}:`) ? stepName : `${stepType}:${stepName}`;
3548
+ }
3549
+ function renderTraceStats(stats) {
3550
+ const lines = [];
3551
+ lines.push("Trace stats (local)");
3552
+ lines.push(`Directory: ${stats.traceDir}`);
3553
+ if (stats.since) lines.push(`Since: ${stats.since}`);
3554
+ if (stats.correlationId) lines.push(`Correlation ID: ${stats.correlationId}`);
3555
+ if (stats.groupId) lines.push(`Group ID: ${stats.groupId}`);
3556
+ lines.push("");
3557
+ lines.push(`Runs: ${stats.totalRuns}`);
3558
+ lines.push(
3559
+ ` success: ${stats.successCount} error: ${stats.errorCount} running: ${stats.runningCount} unknown: ${stats.unknownCount}`
3560
+ );
3561
+ lines.push(`Error rate: ${(stats.errorRate * 100).toFixed(1)}%`);
3562
+ if (stats.duration.avgMs !== void 0) {
3563
+ lines.push(
3564
+ `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)}`
3565
+ );
3566
+ }
3567
+ lines.push("");
3568
+ lines.push(`Steps: ${stats.totalSteps} (avg ${stats.avgStepsPerRun.toFixed(1)} per run)`);
3569
+ lines.push(
3570
+ ` LLM: ${stats.totalLlmSteps} tool: ${stats.totalToolSteps} errors: ${stats.totalErrorSteps}`
3571
+ );
3572
+ if (stats.slowestRuns.length > 0) {
3573
+ lines.push("");
3574
+ lines.push("Slowest runs:");
3575
+ for (const r of stats.slowestRuns) {
3576
+ lines.push(
3577
+ ` ${r.runId} | ${r.name ?? "-"} | ${formatDuration2(r.durationMs ?? 0)} | ${r.status}`
3578
+ );
3579
+ }
3580
+ }
3581
+ if (stats.slowestSteps.length > 0) {
3582
+ lines.push("");
3583
+ lines.push("Slowest steps:");
3584
+ for (const s of stats.slowestSteps) {
3585
+ lines.push(
3586
+ ` ${s.runId} | ${formatStepLabel(s.stepType, s.stepName)} | ${formatDuration2(s.durationMs)}`
3587
+ );
3588
+ }
3589
+ }
3590
+ return lines.join("\n");
3591
+ }
3592
+
3397
3593
  // packages/core/src/timeline.ts
3398
3594
  function finite(n) {
3399
3595
  return typeof n === "number" && Number.isFinite(n);
@@ -3551,7 +3747,7 @@ function renderTimeline(timeline, options = {}) {
3551
3747
  const dur = e.durationMs !== void 0 ? formatDuration2(e.durationMs) : "-";
3552
3748
  const err = e.isError ? " error" : "";
3553
3749
  const off = formatDuration2(e.offsetMs);
3554
- let line = `${prefix}+${off} ${typeTag}:${e.name} (${dur})${err}`;
3750
+ let line = `${prefix}+${off} ${formatStepLabel(typeTag, e.name)} (${dur})${err}`;
3555
3751
  if (e.streaming?.chunkCount !== void 0) {
3556
3752
  line += ` chunks=${e.streaming.chunkCount}`;
3557
3753
  }
@@ -3703,6 +3899,12 @@ function renderRunWhat(summary, options = {}) {
3703
3899
  }
3704
3900
 
3705
3901
  // packages/core/src/explain.ts
3902
+ function toDisplayStatus(status) {
3903
+ if (status === "ok") return "success";
3904
+ if (status === "error") return "error";
3905
+ if (status === "running") return "running";
3906
+ return "unknown";
3907
+ }
3706
3908
  function flatten(nodes, out = []) {
3707
3909
  for (const node of nodes) {
3708
3910
  out.push({ node, index: out.length + 1 });
@@ -3760,7 +3962,7 @@ function buildFacts(run, redactor) {
3760
3962
  const facts = [
3761
3963
  fact("run.id", "Run id", run.runId, redactor),
3762
3964
  fact("run.name", "Run name", run.name ?? run.runId, redactor),
3763
- fact("run.status", "Run status", run.status ?? "unknown", redactor),
3965
+ fact("run.status", "Run status", toDisplayStatus(run.status), redactor),
3764
3966
  fact("run.totalEvents", "Total events", run.metadata.totalEvents, redactor),
3765
3967
  fact("run.stepCount", "Top-level step count", run.children.length, redactor),
3766
3968
  fact("run.nodeCount", "Total node count", nodes.length, redactor),
@@ -3836,7 +4038,7 @@ function buildLocalExplanation(run, options = {}) {
3836
4038
  mode,
3837
4039
  runId: String(redactValue(redactor, "runId", run.runId)),
3838
4040
  ...run.name !== void 0 ? { name: String(redactValue(redactor, "name", run.name)) } : {},
3839
- ...run.status !== void 0 ? { status: run.status } : {},
4041
+ ...run.status !== void 0 ? { status: toDisplayStatus(run.status) } : {},
3840
4042
  redactionProfile,
3841
4043
  facts,
3842
4044
  inferences: mode === "dry-run" ? [] : buildInferences(run, facts),
@@ -3847,199 +4049,6 @@ function buildLocalExplanation(run, options = {}) {
3847
4049
  };
3848
4050
  }
3849
4051
 
3850
- // packages/core/src/stats.ts
3851
- function percentile(sorted, p) {
3852
- if (sorted.length === 0) return void 0;
3853
- const idx = Math.min(
3854
- sorted.length - 1,
3855
- Math.max(0, Math.ceil(p / 100 * sorted.length) - 1)
3856
- );
3857
- return sorted[idx];
3858
- }
3859
- async function readRunStartedMetadata(filePath) {
3860
- try {
3861
- const events = await readTraceEventsFromFile(filePath);
3862
- for (const event of events) {
3863
- if (event.event !== "run_started") continue;
3864
- const rs = event;
3865
- if (rs.metadata && typeof rs.metadata === "object") {
3866
- return rs.metadata;
3867
- }
3868
- return void 0;
3869
- }
3870
- } catch {
3871
- }
3872
- return void 0;
3873
- }
3874
- function metaMatchesCorrelation(metadata, correlationId, groupId) {
3875
- if (correlationId) {
3876
- const v = metadata?.correlationId;
3877
- if (typeof v !== "string" || v !== correlationId) return false;
3878
- }
3879
- if (groupId) {
3880
- const v = metadata?.groupId;
3881
- if (typeof v !== "string" || v !== groupId) return false;
3882
- }
3883
- return true;
3884
- }
3885
- async function buildTraceStats(metas, options) {
3886
- let filtered = filterTraces(metas, { since: options.since });
3887
- if (options.correlationId || options.groupId) {
3888
- const next = [];
3889
- for (const m of filtered) {
3890
- const md = await readRunStartedMetadata(m.filePath);
3891
- if (metaMatchesCorrelation(md, options.correlationId, options.groupId)) {
3892
- next.push(m);
3893
- }
3894
- }
3895
- filtered = next;
3896
- }
3897
- let successCount = 0;
3898
- let errorCount = 0;
3899
- let runningCount = 0;
3900
- let unknownCount = 0;
3901
- const durations = [];
3902
- let totalSteps = 0;
3903
- let totalLlmSteps = 0;
3904
- let totalToolSteps = 0;
3905
- let totalErrorSteps = 0;
3906
- const slowestRuns = [];
3907
- const slowestSteps = [];
3908
- for (const m of filtered) {
3909
- if (m.status === "success") successCount += 1;
3910
- else if (m.status === "error") errorCount += 1;
3911
- else if (m.status === "running") runningCount += 1;
3912
- else unknownCount += 1;
3913
- if (typeof m.durationMs === "number" && Number.isFinite(m.durationMs) && m.durationMs >= 0) {
3914
- durations.push(m.durationMs);
3915
- slowestRuns.push({
3916
- runId: m.runId,
3917
- name: m.name,
3918
- durationMs: m.durationMs,
3919
- status: m.status
3920
- });
3921
- }
3922
- try {
3923
- const events = await readTraceEventsFromFile(m.filePath);
3924
- if (events.length === 0) continue;
3925
- const summary = buildRunSummary(events);
3926
- totalSteps += summary.totalSteps;
3927
- totalLlmSteps += summary.llmSteps;
3928
- totalToolSteps += summary.toolSteps;
3929
- totalErrorSteps += summary.errorSteps;
3930
- const steps = collectCompletedSteps(events, m.runId);
3931
- for (const s of steps) {
3932
- slowestSteps.push(s);
3933
- }
3934
- } catch {
3935
- }
3936
- }
3937
- slowestRuns.sort((a, b) => (b.durationMs ?? 0) - (a.durationMs ?? 0));
3938
- slowestSteps.sort((a, b) => b.durationMs - a.durationMs);
3939
- const runLimit = options.slowRunLimit ?? 5;
3940
- const stepLimit = options.slowStepLimit ?? 5;
3941
- const sortedDur = [...durations].sort((a, b) => a - b);
3942
- const totalRuns = filtered.length;
3943
- const errorRate = totalRuns > 0 ? errorCount / totalRuns : 0;
3944
- const sumDur = durations.reduce((a, b) => a + b, 0);
3945
- return {
3946
- traceDir: options.traceDir,
3947
- ...options.since ? { since: options.since } : {},
3948
- ...options.correlationId ? { correlationId: options.correlationId } : {},
3949
- ...options.groupId ? { groupId: options.groupId } : {},
3950
- totalRuns,
3951
- successCount,
3952
- errorCount,
3953
- runningCount,
3954
- unknownCount,
3955
- errorRate,
3956
- duration: {
3957
- ...sortedDur.length > 0 ? {
3958
- minMs: sortedDur[0],
3959
- maxMs: sortedDur[sortedDur.length - 1],
3960
- avgMs: sumDur / sortedDur.length,
3961
- p50Ms: percentile(sortedDur, 50),
3962
- p95Ms: percentile(sortedDur, 95)
3963
- } : {}
3964
- },
3965
- totalSteps,
3966
- avgStepsPerRun: totalRuns > 0 ? totalSteps / totalRuns : 0,
3967
- totalLlmSteps,
3968
- totalToolSteps,
3969
- totalErrorSteps,
3970
- slowestRuns: slowestRuns.slice(0, runLimit),
3971
- slowestSteps: slowestSteps.slice(0, stepLimit)
3972
- };
3973
- }
3974
- function collectCompletedSteps(events, runId) {
3975
- const started = /* @__PURE__ */ new Map();
3976
- const out = [];
3977
- for (const e of events) {
3978
- if (e.event === "step_started") {
3979
- const s = e;
3980
- started.set(s.stepId, { name: s.name, type: s.type });
3981
- }
3982
- if (e.event === "step_completed") {
3983
- const c = e;
3984
- if (c.status !== "success" && c.status !== "error") continue;
3985
- if (typeof c.durationMs !== "number" || !Number.isFinite(c.durationMs)) {
3986
- continue;
3987
- }
3988
- const meta = started.get(c.stepId);
3989
- out.push({
3990
- runId,
3991
- stepName: meta?.name ?? c.stepId,
3992
- stepType: meta?.type ?? "logic",
3993
- durationMs: c.durationMs
3994
- });
3995
- }
3996
- }
3997
- return out;
3998
- }
3999
- function renderTraceStats(stats) {
4000
- const lines = [];
4001
- lines.push("Trace stats (local)");
4002
- lines.push(`Directory: ${stats.traceDir}`);
4003
- if (stats.since) lines.push(`Since: ${stats.since}`);
4004
- if (stats.correlationId) lines.push(`Correlation ID: ${stats.correlationId}`);
4005
- if (stats.groupId) lines.push(`Group ID: ${stats.groupId}`);
4006
- lines.push("");
4007
- lines.push(`Runs: ${stats.totalRuns}`);
4008
- lines.push(
4009
- ` success: ${stats.successCount} error: ${stats.errorCount} running: ${stats.runningCount} unknown: ${stats.unknownCount}`
4010
- );
4011
- lines.push(`Error rate: ${(stats.errorRate * 100).toFixed(1)}%`);
4012
- if (stats.duration.avgMs !== void 0) {
4013
- lines.push(
4014
- `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)}`
4015
- );
4016
- }
4017
- lines.push("");
4018
- lines.push(`Steps: ${stats.totalSteps} (avg ${stats.avgStepsPerRun.toFixed(1)} per run)`);
4019
- lines.push(
4020
- ` LLM: ${stats.totalLlmSteps} tool: ${stats.totalToolSteps} errors: ${stats.totalErrorSteps}`
4021
- );
4022
- if (stats.slowestRuns.length > 0) {
4023
- lines.push("");
4024
- lines.push("Slowest runs:");
4025
- for (const r of stats.slowestRuns) {
4026
- lines.push(
4027
- ` ${r.runId} | ${r.name ?? "-"} | ${formatDuration2(r.durationMs ?? 0)} | ${r.status}`
4028
- );
4029
- }
4030
- }
4031
- if (stats.slowestSteps.length > 0) {
4032
- lines.push("");
4033
- lines.push("Slowest steps:");
4034
- for (const s of stats.slowestSteps) {
4035
- lines.push(
4036
- ` ${s.runId} | ${s.stepType}:${s.stepName} | ${formatDuration2(s.durationMs)}`
4037
- );
4038
- }
4039
- }
4040
- return lines.join("\n");
4041
- }
4042
-
4043
4052
  // packages/core/src/search.ts
4044
4053
  function parseDurationFilter(expr) {
4045
4054
  const raw = expr.trim();
@@ -4106,6 +4115,12 @@ async function searchTraces(metas, options) {
4106
4115
  ...sessionLabel ? { sessionId: sessionLabel } : {}
4107
4116
  });
4108
4117
  }
4118
+ results.sort((a, b) => {
4119
+ const ta = a.timestamp ?? 0;
4120
+ const tb = b.timestamp ?? 0;
4121
+ if (ta !== tb) return tb - ta;
4122
+ return a.runId.localeCompare(b.runId);
4123
+ });
4109
4124
  return results.slice(0, limit);
4110
4125
  }
4111
4126
  for (const m of filtered) {
@@ -4153,7 +4168,7 @@ async function searchTraces(metas, options) {
4153
4168
  results.sort((a, b) => {
4154
4169
  const ta = a.timestamp ?? 0;
4155
4170
  const tb = b.timestamp ?? 0;
4156
- if (ta !== tb) return ta - tb;
4171
+ if (ta !== tb) return tb - ta;
4157
4172
  const runCmp = a.runId.localeCompare(b.runId);
4158
4173
  if (runCmp !== 0) return runCmp;
4159
4174
  return (a.stepName ?? "").localeCompare(b.stepName ?? "");
@@ -6421,13 +6436,24 @@ function inc(map, key) {
6421
6436
  map[key] = (map[key] ?? 0) + 1;
6422
6437
  }
6423
6438
  function computeRunStatus(events) {
6439
+ let runTerminal;
6440
+ let sawRunEvent = false;
6441
+ for (const e of events) {
6442
+ if (e.kind !== "RUN") continue;
6443
+ sawRunEvent = true;
6444
+ if (e.status === "ok" || e.status === "error") {
6445
+ runTerminal = e.status;
6446
+ }
6447
+ }
6448
+ if (sawRunEvent) {
6449
+ return runTerminal ?? "running";
6450
+ }
6424
6451
  let hasRunning = false;
6425
6452
  for (const e of events) {
6426
6453
  if (e.status === "error") return "error";
6427
6454
  if (e.status === "running") hasRunning = true;
6428
6455
  }
6429
- if (hasRunning) return "running";
6430
- return "ok";
6456
+ return hasRunning ? "running" : "ok";
6431
6457
  }
6432
6458
  var TreeBuilder = class {
6433
6459
  constructor(options) {
@@ -8643,7 +8669,9 @@ function compareCohortAggregates(groups, options) {
8643
8669
  metric,
8644
8670
  "Average duration (ms)",
8645
8671
  baselineAgg?.avgDurationMs,
8646
- candidateAgg?.avgDurationMs
8672
+ candidateAgg?.avgDurationMs,
8673
+ true,
8674
+ tolerance
8647
8675
  );
8648
8676
  if (item) comparisons.push(item);
8649
8677
  break;
@@ -8653,7 +8681,9 @@ function compareCohortAggregates(groups, options) {
8653
8681
  metric,
8654
8682
  "Average LLM calls",
8655
8683
  baselineAgg?.avgLlmCallCount,
8656
- candidateAgg?.avgLlmCallCount
8684
+ candidateAgg?.avgLlmCallCount,
8685
+ true,
8686
+ tolerance
8657
8687
  );
8658
8688
  if (item) comparisons.push(item);
8659
8689
  break;
@@ -8663,7 +8693,9 @@ function compareCohortAggregates(groups, options) {
8663
8693
  metric,
8664
8694
  "Average token usage",
8665
8695
  baselineAgg?.avgTokenUsage,
8666
- candidateAgg?.avgTokenUsage
8696
+ candidateAgg?.avgTokenUsage,
8697
+ true,
8698
+ tolerance
8667
8699
  );
8668
8700
  if (item) comparisons.push(item);
8669
8701
  break;
@@ -8673,7 +8705,9 @@ function compareCohortAggregates(groups, options) {
8673
8705
  metric,
8674
8706
  "Average retries",
8675
8707
  baselineAgg?.avgRetryCount,
8676
- candidateAgg?.avgRetryCount
8708
+ candidateAgg?.avgRetryCount,
8709
+ true,
8710
+ tolerance
8677
8711
  );
8678
8712
  if (item) comparisons.push(item);
8679
8713
  break;
@@ -8683,7 +8717,9 @@ function compareCohortAggregates(groups, options) {
8683
8717
  metric,
8684
8718
  "Observation failure rate",
8685
8719
  baselineAgg?.observationFailureRate,
8686
- candidateAgg?.observationFailureRate
8720
+ candidateAgg?.observationFailureRate,
8721
+ true,
8722
+ tolerance
8687
8723
  );
8688
8724
  if (item) comparisons.push(item);
8689
8725
  break;
@@ -8719,7 +8755,9 @@ function compareCohortAggregates(groups, options) {
8719
8755
  metric,
8720
8756
  "Guardrail failures",
8721
8757
  baselineAgg?.avgGuardrailFailures,
8722
- candidateAgg?.avgGuardrailFailures
8758
+ candidateAgg?.avgGuardrailFailures,
8759
+ true,
8760
+ tolerance
8723
8761
  );
8724
8762
  if (item) comparisons.push(item);
8725
8763
  break;
@@ -8729,7 +8767,9 @@ function compareCohortAggregates(groups, options) {
8729
8767
  metric,
8730
8768
  "Circuit violations",
8731
8769
  baselineAgg?.avgCircuitViolations,
8732
- candidateAgg?.avgCircuitViolations
8770
+ candidateAgg?.avgCircuitViolations,
8771
+ true,
8772
+ tolerance
8733
8773
  );
8734
8774
  if (item) comparisons.push(item);
8735
8775
  break;
@@ -8739,7 +8779,9 @@ function compareCohortAggregates(groups, options) {
8739
8779
  metric,
8740
8780
  "Redaction warnings",
8741
8781
  baselineAgg?.avgRedactionWarnings,
8742
- candidateAgg?.avgRedactionWarnings
8782
+ candidateAgg?.avgRedactionWarnings,
8783
+ true,
8784
+ tolerance
8743
8785
  );
8744
8786
  if (item) comparisons.push(item);
8745
8787
  break;