agent-inspect 6.31.29 → 6.31.31

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.
@@ -418,6 +418,159 @@ function redactRunTreeForExport(tree, options) {
418
418
  return clone;
419
419
  }
420
420
 
421
+ // packages/core/src/exporters/presentation-lifecycle.ts
422
+ function stepIdOf(event) {
423
+ const value = event.attributes?.stepId;
424
+ return typeof value === "string" && value.trim() !== "" ? value : void 0;
425
+ }
426
+ function attemptIdOf(event) {
427
+ const direct = event.attributes?.attemptId;
428
+ if (typeof direct === "string" && direct.trim() !== "") return direct;
429
+ const meta = event.attributes?.metadata;
430
+ if (meta && typeof meta === "object" && !Array.isArray(meta)) {
431
+ const nested = meta.attemptId;
432
+ if (typeof nested === "string" && nested.trim() !== "") return nested;
433
+ }
434
+ return void 0;
435
+ }
436
+ function lifecycleKey(event) {
437
+ if (event.kind === "RUN") return `run:${event.runId}`;
438
+ const stepId = stepIdOf(event);
439
+ if (stepId !== void 0) return `step:${stepId}`;
440
+ return `event:${event.eventId}`;
441
+ }
442
+ function isTerminal(status) {
443
+ return status === "ok" || status === "error";
444
+ }
445
+ function eventTime(event) {
446
+ return typeof event.timestamp === "number" ? event.timestamp : 0;
447
+ }
448
+ function cloneNode(node) {
449
+ return {
450
+ event: {
451
+ ...node.event,
452
+ ...node.event.attributes !== void 0 ? { attributes: { ...node.event.attributes } } : {}
453
+ },
454
+ children: node.children.map(cloneNode),
455
+ depth: node.depth
456
+ };
457
+ }
458
+ function joinOnePair(start, terminal) {
459
+ const childMap = /* @__PURE__ */ new Map();
460
+ if (start) {
461
+ for (const child of start.children) {
462
+ childMap.set(child.event.eventId, child);
463
+ }
464
+ }
465
+ for (const child of terminal.children) {
466
+ childMap.set(child.event.eventId, child);
467
+ }
468
+ return {
469
+ event: {
470
+ ...terminal.event,
471
+ name: start?.event.name ?? terminal.event.name,
472
+ kind: start?.event.kind ?? terminal.event.kind,
473
+ ...start && attemptIdOf(terminal.event) === void 0 && attemptIdOf(start.event) ? {
474
+ attributes: {
475
+ ...terminal.event.attributes,
476
+ attemptId: attemptIdOf(start.event)
477
+ }
478
+ } : {}
479
+ },
480
+ children: presentSiblingNodes([...childMap.values()]),
481
+ depth: terminal.depth
482
+ };
483
+ }
484
+ function joinSiblingGroup(group) {
485
+ if (group.length <= 1) return group;
486
+ const terminals = group.filter((n) => isTerminal(n.event.status)).sort((a, b) => eventTime(a.event) - eventTime(b.event));
487
+ const runnings = group.filter((n) => n.event.status === "running").sort((a, b) => eventTime(a.event) - eventTime(b.event));
488
+ const others = group.filter(
489
+ (n) => !isTerminal(n.event.status) && n.event.status !== "running"
490
+ );
491
+ const terminalStatuses = new Set(terminals.map((n) => n.event.status));
492
+ if (terminalStatuses.size > 1) {
493
+ return group;
494
+ }
495
+ if (terminals.length > 1 && terminals.every((t) => attemptIdOf(t.event) === void 0) && runnings.every((r) => attemptIdOf(r.event) === void 0)) {
496
+ return group;
497
+ }
498
+ const usedRunning = /* @__PURE__ */ new Set();
499
+ const out = [];
500
+ for (const terminal of terminals) {
501
+ const terminalAttempt = attemptIdOf(terminal.event);
502
+ const terminalTs = eventTime(terminal.event);
503
+ const candidate = runnings.find((r) => {
504
+ if (usedRunning.has(r.event.eventId)) return false;
505
+ if (eventTime(r.event) > terminalTs) return false;
506
+ const runningAttempt = attemptIdOf(r.event);
507
+ if (terminalAttempt !== void 0) {
508
+ return runningAttempt === terminalAttempt;
509
+ }
510
+ if (runningAttempt !== void 0) {
511
+ return true;
512
+ }
513
+ return true;
514
+ });
515
+ if (candidate) {
516
+ usedRunning.add(candidate.event.eventId);
517
+ out.push(joinOnePair(candidate, terminal));
518
+ } else {
519
+ out.push({
520
+ ...terminal,
521
+ children: presentSiblingNodes(terminal.children)
522
+ });
523
+ }
524
+ }
525
+ for (const running of runnings) {
526
+ if (usedRunning.has(running.event.eventId)) continue;
527
+ out.push({
528
+ ...running,
529
+ children: presentSiblingNodes(running.children)
530
+ });
531
+ }
532
+ for (const other of others) {
533
+ out.push({
534
+ ...other,
535
+ children: presentSiblingNodes(other.children)
536
+ });
537
+ }
538
+ return out;
539
+ }
540
+ function presentSiblingNodes(nodes) {
541
+ const prepared = nodes.map((n) => ({
542
+ ...cloneNode(n),
543
+ children: presentSiblingNodes(n.children)
544
+ }));
545
+ const order = [];
546
+ const groups = /* @__PURE__ */ new Map();
547
+ for (const node of prepared) {
548
+ const key = lifecycleKey(node.event);
549
+ if (!groups.has(key)) {
550
+ groups.set(key, []);
551
+ order.push(key);
552
+ }
553
+ groups.get(key).push(node);
554
+ }
555
+ const out = [];
556
+ for (const key of order) {
557
+ out.push(...joinSiblingGroup(groups.get(key)));
558
+ }
559
+ return out;
560
+ }
561
+ function presentLifecycleJoinedTree(tree) {
562
+ return {
563
+ ...tree,
564
+ children: presentSiblingNodes(tree.children),
565
+ metadata: {
566
+ ...tree.metadata,
567
+ confidenceBreakdown: { ...tree.metadata.confidenceBreakdown },
568
+ kinds: { ...tree.metadata.kinds },
569
+ ...tree.metadata.relationshipSummary !== void 0 ? { relationshipSummary: { ...tree.metadata.relationshipSummary } } : {}
570
+ }
571
+ };
572
+ }
573
+
421
574
  // packages/core/src/exporters/html-exporter.ts
422
575
  function renderTreeHtml(nodes, ulClass = "tree") {
423
576
  if (nodes.length === 0) return "";
@@ -445,32 +598,33 @@ function exportHtml(tree, options) {
445
598
  const includeErrors = options?.includeErrors ?? true;
446
599
  const maxLen = options?.maxAttributeLength ?? 500;
447
600
  const redacted = options?.redacted ?? true;
448
- const titleName = escapeHtml(tree.name ?? tree.runId);
601
+ const view = presentLifecycleJoinedTree(tree);
602
+ const titleName = escapeHtml(view.name ?? view.runId);
449
603
  const summaryRows = [];
450
604
  summaryRows.push(
451
- `<tr><th scope="row">runId</th><td><code>${escapeHtml(tree.runId)}</code></td></tr>`
605
+ `<tr><th scope="row">runId</th><td><code>${escapeHtml(view.runId)}</code></td></tr>`
452
606
  );
453
- if (tree.name !== void 0) {
454
- summaryRows.push(`<tr><th scope="row">name</th><td>${escapeHtml(tree.name)}</td></tr>`);
607
+ if (view.name !== void 0) {
608
+ summaryRows.push(`<tr><th scope="row">name</th><td>${escapeHtml(view.name)}</td></tr>`);
455
609
  }
456
610
  summaryRows.push(
457
- `<tr><th scope="row">status</th><td>${escapeHtml(String(tree.status ?? "unknown"))}</td></tr>`
611
+ `<tr><th scope="row">status</th><td>${escapeHtml(String(view.status ?? "unknown"))}</td></tr>`
458
612
  );
459
613
  summaryRows.push(
460
- `<tr><th scope="row">durationMs</th><td>${tree.durationMs !== void 0 ? escapeHtml(String(tree.durationMs)) : "\u2014"}</td></tr>`
614
+ `<tr><th scope="row">durationMs</th><td>${view.durationMs !== void 0 ? escapeHtml(String(view.durationMs)) : "\u2014"}</td></tr>`
461
615
  );
462
616
  summaryRows.push(
463
- `<tr><th scope="row">startedAt</th><td>${tree.startedAt !== void 0 ? escapeHtml(String(tree.startedAt)) : "\u2014"}</td></tr>`
617
+ `<tr><th scope="row">startedAt</th><td>${view.startedAt !== void 0 ? escapeHtml(String(view.startedAt)) : "\u2014"}</td></tr>`
464
618
  );
465
619
  summaryRows.push(
466
- `<tr><th scope="row">endedAt</th><td>${tree.endedAt !== void 0 ? escapeHtml(String(tree.endedAt)) : "\u2014"}</td></tr>`
620
+ `<tr><th scope="row">endedAt</th><td>${view.endedAt !== void 0 ? escapeHtml(String(view.endedAt)) : "\u2014"}</td></tr>`
467
621
  );
468
622
  summaryRows.push(
469
- `<tr><th scope="row">totalEvents</th><td>${escapeHtml(String(tree.metadata.totalEvents))}</td></tr>`
623
+ `<tr><th scope="row">totalEvents</th><td>${escapeHtml(String(view.metadata.totalEvents))}</td></tr>`
470
624
  );
471
625
  let confidenceHtml = "";
472
626
  if (includeMetadata) {
473
- const cb = tree.metadata.confidenceBreakdown;
627
+ const cb = view.metadata.confidenceBreakdown;
474
628
  confidenceHtml += "<h3>Confidence breakdown</h3><table><thead><tr><th>bucket</th><th>count</th></tr></thead><tbody>";
475
629
  for (const k of Object.keys(cb).sort()) {
476
630
  const key = k;
@@ -478,14 +632,14 @@ function exportHtml(tree, options) {
478
632
  }
479
633
  confidenceHtml += "</tbody></table>";
480
634
  confidenceHtml += "<h3>Kind breakdown</h3><table><thead><tr><th>kind</th><th>count</th></tr></thead><tbody>";
481
- for (const k of Object.keys(tree.metadata.kinds).sort()) {
635
+ for (const k of Object.keys(view.metadata.kinds).sort()) {
482
636
  const key = k;
483
- const c = tree.metadata.kinds[key];
637
+ const c = view.metadata.kinds[key];
484
638
  if (c > 0) confidenceHtml += `<tr><td>${escapeHtml(key)}</td><td>${c}</td></tr>`;
485
639
  }
486
640
  confidenceHtml += "</tbody></table>";
487
641
  }
488
- const flat = flattenTree(tree);
642
+ const flat = flattenTree(view);
489
643
  const errors = flat.filter((n) => n.event.status === "error");
490
644
  let errorsHtml = "";
491
645
  if (includeErrors && errors.length > 0) {
@@ -540,7 +694,7 @@ footer{margin-top:2rem;font-size:0.85rem;color:#555}
540
694
  <header><h1>AgentInspect Run: ${titleName}</h1></header>
541
695
  <p class="note">Generated locally by AgentInspect.</p>
542
696
  ${includeMetadata ? `<section class="summary"><h2>Summary</h2><table>${summaryRows.join("")}</table>${confidenceHtml}</section>` : ""}
543
- <section class="tree"><h2>Execution tree</h2>${tree.children.length > 0 ? renderTreeHtml(tree.children) : "<p>No steps recorded.</p>"}</section>
697
+ <section class="tree"><h2>Execution tree</h2>${view.children.length > 0 ? renderTreeHtml(view.children) : "<p>No steps recorded.</p>"}</section>
544
698
  ${errorsHtml}
545
699
  ${attrsHtml}
546
700
  <footer>Generated locally by AgentInspect. Review for sensitive data before sharing.</footer>
@@ -581,7 +735,8 @@ function exportMarkdown(tree, options) {
581
735
  const includeErrors = options?.includeErrors ?? true;
582
736
  const maxLen = options?.maxAttributeLength ?? 500;
583
737
  const redacted = options?.redacted ?? true;
584
- const titleName = tree.name ?? tree.runId;
738
+ const view = presentLifecycleJoinedTree(tree);
739
+ const titleName = view.name ?? view.runId;
585
740
  const lines = [];
586
741
  lines.push(`# AgentInspect Run: ${escapeMarkdown(titleName)}`);
587
742
  lines.push("");
@@ -590,28 +745,28 @@ function exportMarkdown(tree, options) {
590
745
  if (includeMetadata) {
591
746
  lines.push("## Summary");
592
747
  lines.push("");
593
- lines.push(`- **runId**: ${escapeMarkdown(tree.runId)}`);
594
- if (tree.name !== void 0) lines.push(`- **name**: ${escapeMarkdown(tree.name)}`);
595
- lines.push(`- **status**: ${escapeMarkdown(String(tree.status ?? "unknown"))}`);
748
+ lines.push(`- **runId**: ${escapeMarkdown(view.runId)}`);
749
+ if (view.name !== void 0) lines.push(`- **name**: ${escapeMarkdown(view.name)}`);
750
+ lines.push(`- **status**: ${escapeMarkdown(String(view.status ?? "unknown"))}`);
596
751
  lines.push(
597
- `- **durationMs**: ${tree.durationMs !== void 0 ? escapeMarkdown(String(tree.durationMs)) : "-"}`
752
+ `- **durationMs**: ${view.durationMs !== void 0 ? escapeMarkdown(String(view.durationMs)) : "-"}`
598
753
  );
599
754
  lines.push(
600
- `- **startedAt**: ${tree.startedAt !== void 0 ? escapeMarkdown(String(tree.startedAt)) : "-"}`
755
+ `- **startedAt**: ${view.startedAt !== void 0 ? escapeMarkdown(String(view.startedAt)) : "-"}`
601
756
  );
602
757
  lines.push(
603
- `- **endedAt**: ${tree.endedAt !== void 0 ? escapeMarkdown(String(tree.endedAt)) : "-"}`
758
+ `- **endedAt**: ${view.endedAt !== void 0 ? escapeMarkdown(String(view.endedAt)) : "-"}`
604
759
  );
605
- lines.push(`- **totalEvents**: ${tree.metadata.totalEvents}`);
760
+ lines.push(`- **totalEvents**: ${view.metadata.totalEvents}`);
606
761
  lines.push("");
607
762
  lines.push("### Confidence breakdown");
608
763
  lines.push("");
609
764
  lines.push("| bucket | count |");
610
765
  lines.push("| --- | --- |");
611
- for (const k of Object.keys(tree.metadata.confidenceBreakdown).sort()) {
766
+ for (const k of Object.keys(view.metadata.confidenceBreakdown).sort()) {
612
767
  const key = k;
613
768
  lines.push(
614
- `| ${escapeMarkdown(key)} | ${tree.metadata.confidenceBreakdown[key]} |`
769
+ `| ${escapeMarkdown(key)} | ${view.metadata.confidenceBreakdown[key]} |`
615
770
  );
616
771
  }
617
772
  lines.push("");
@@ -619,9 +774,9 @@ function exportMarkdown(tree, options) {
619
774
  lines.push("");
620
775
  lines.push("| kind | count |");
621
776
  lines.push("| --- | --- |");
622
- for (const k of Object.keys(tree.metadata.kinds).sort()) {
777
+ for (const k of Object.keys(view.metadata.kinds).sort()) {
623
778
  const key = k;
624
- const c = tree.metadata.kinds[key];
779
+ const c = view.metadata.kinds[key];
625
780
  if (c > 0) lines.push(`| ${escapeMarkdown(key)} | ${c} |`);
626
781
  }
627
782
  lines.push("");
@@ -630,11 +785,11 @@ function exportMarkdown(tree, options) {
630
785
  lines.push("");
631
786
  lines.push("```text");
632
787
  lines.push(
633
- tree.children.length > 0 ? renderTreeAscii(tree.children) : "(no steps)"
788
+ view.children.length > 0 ? renderTreeAscii(view.children) : "(no steps)"
634
789
  );
635
790
  lines.push("```");
636
791
  lines.push("");
637
- const flat = flattenTree(tree);
792
+ const flat = flattenTree(view);
638
793
  const errors = flat.filter((n) => n.event.status === "error");
639
794
  if (includeErrors && errors.length > 0) {
640
795
  lines.push("## Errors");