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.
@@ -826,6 +826,159 @@ function zeroKinds() {
826
826
  };
827
827
  }
828
828
 
829
+ // packages/core/src/exporters/presentation-lifecycle.ts
830
+ function stepIdOf(event) {
831
+ const value = event.attributes?.stepId;
832
+ return typeof value === "string" && value.trim() !== "" ? value : void 0;
833
+ }
834
+ function attemptIdOf(event) {
835
+ const direct = event.attributes?.attemptId;
836
+ if (typeof direct === "string" && direct.trim() !== "") return direct;
837
+ const meta = event.attributes?.metadata;
838
+ if (meta && typeof meta === "object" && !Array.isArray(meta)) {
839
+ const nested = meta.attemptId;
840
+ if (typeof nested === "string" && nested.trim() !== "") return nested;
841
+ }
842
+ return void 0;
843
+ }
844
+ function lifecycleKey(event) {
845
+ if (event.kind === "RUN") return `run:${event.runId}`;
846
+ const stepId = stepIdOf(event);
847
+ if (stepId !== void 0) return `step:${stepId}`;
848
+ return `event:${event.eventId}`;
849
+ }
850
+ function isTerminal(status) {
851
+ return status === "ok" || status === "error";
852
+ }
853
+ function eventTime(event) {
854
+ return typeof event.timestamp === "number" ? event.timestamp : 0;
855
+ }
856
+ function cloneNode(node) {
857
+ return {
858
+ event: {
859
+ ...node.event,
860
+ ...node.event.attributes !== void 0 ? { attributes: { ...node.event.attributes } } : {}
861
+ },
862
+ children: node.children.map(cloneNode),
863
+ depth: node.depth
864
+ };
865
+ }
866
+ function joinOnePair(start, terminal) {
867
+ const childMap = /* @__PURE__ */ new Map();
868
+ if (start) {
869
+ for (const child of start.children) {
870
+ childMap.set(child.event.eventId, child);
871
+ }
872
+ }
873
+ for (const child of terminal.children) {
874
+ childMap.set(child.event.eventId, child);
875
+ }
876
+ return {
877
+ event: {
878
+ ...terminal.event,
879
+ name: start?.event.name ?? terminal.event.name,
880
+ kind: start?.event.kind ?? terminal.event.kind,
881
+ ...start && attemptIdOf(terminal.event) === void 0 && attemptIdOf(start.event) ? {
882
+ attributes: {
883
+ ...terminal.event.attributes,
884
+ attemptId: attemptIdOf(start.event)
885
+ }
886
+ } : {}
887
+ },
888
+ children: presentSiblingNodes([...childMap.values()]),
889
+ depth: terminal.depth
890
+ };
891
+ }
892
+ function joinSiblingGroup(group) {
893
+ if (group.length <= 1) return group;
894
+ const terminals = group.filter((n) => isTerminal(n.event.status)).sort((a, b) => eventTime(a.event) - eventTime(b.event));
895
+ const runnings = group.filter((n) => n.event.status === "running").sort((a, b) => eventTime(a.event) - eventTime(b.event));
896
+ const others = group.filter(
897
+ (n) => !isTerminal(n.event.status) && n.event.status !== "running"
898
+ );
899
+ const terminalStatuses = new Set(terminals.map((n) => n.event.status));
900
+ if (terminalStatuses.size > 1) {
901
+ return group;
902
+ }
903
+ if (terminals.length > 1 && terminals.every((t) => attemptIdOf(t.event) === void 0) && runnings.every((r) => attemptIdOf(r.event) === void 0)) {
904
+ return group;
905
+ }
906
+ const usedRunning = /* @__PURE__ */ new Set();
907
+ const out = [];
908
+ for (const terminal of terminals) {
909
+ const terminalAttempt = attemptIdOf(terminal.event);
910
+ const terminalTs = eventTime(terminal.event);
911
+ const candidate = runnings.find((r) => {
912
+ if (usedRunning.has(r.event.eventId)) return false;
913
+ if (eventTime(r.event) > terminalTs) return false;
914
+ const runningAttempt = attemptIdOf(r.event);
915
+ if (terminalAttempt !== void 0) {
916
+ return runningAttempt === terminalAttempt;
917
+ }
918
+ if (runningAttempt !== void 0) {
919
+ return true;
920
+ }
921
+ return true;
922
+ });
923
+ if (candidate) {
924
+ usedRunning.add(candidate.event.eventId);
925
+ out.push(joinOnePair(candidate, terminal));
926
+ } else {
927
+ out.push({
928
+ ...terminal,
929
+ children: presentSiblingNodes(terminal.children)
930
+ });
931
+ }
932
+ }
933
+ for (const running of runnings) {
934
+ if (usedRunning.has(running.event.eventId)) continue;
935
+ out.push({
936
+ ...running,
937
+ children: presentSiblingNodes(running.children)
938
+ });
939
+ }
940
+ for (const other of others) {
941
+ out.push({
942
+ ...other,
943
+ children: presentSiblingNodes(other.children)
944
+ });
945
+ }
946
+ return out;
947
+ }
948
+ function presentSiblingNodes(nodes) {
949
+ const prepared = nodes.map((n) => ({
950
+ ...cloneNode(n),
951
+ children: presentSiblingNodes(n.children)
952
+ }));
953
+ const order = [];
954
+ const groups = /* @__PURE__ */ new Map();
955
+ for (const node of prepared) {
956
+ const key = lifecycleKey(node.event);
957
+ if (!groups.has(key)) {
958
+ groups.set(key, []);
959
+ order.push(key);
960
+ }
961
+ groups.get(key).push(node);
962
+ }
963
+ const out = [];
964
+ for (const key of order) {
965
+ out.push(...joinSiblingGroup(groups.get(key)));
966
+ }
967
+ return out;
968
+ }
969
+ function presentLifecycleJoinedTree(tree) {
970
+ return {
971
+ ...tree,
972
+ children: presentSiblingNodes(tree.children),
973
+ metadata: {
974
+ ...tree.metadata,
975
+ confidenceBreakdown: { ...tree.metadata.confidenceBreakdown },
976
+ kinds: { ...tree.metadata.kinds },
977
+ ...tree.metadata.relationshipSummary !== void 0 ? { relationshipSummary: { ...tree.metadata.relationshipSummary } } : {}
978
+ }
979
+ };
980
+ }
981
+
829
982
  // packages/core/src/exporters/html-exporter.ts
830
983
  function renderTreeHtml(nodes, ulClass = "tree") {
831
984
  if (nodes.length === 0) return "";
@@ -853,32 +1006,33 @@ function exportHtml(tree, options) {
853
1006
  const includeErrors = options?.includeErrors ?? true;
854
1007
  const maxLen = options?.maxAttributeLength ?? 500;
855
1008
  const redacted = options?.redacted ?? true;
856
- const titleName = escapeHtml(tree.name ?? tree.runId);
1009
+ const view = presentLifecycleJoinedTree(tree);
1010
+ const titleName = escapeHtml(view.name ?? view.runId);
857
1011
  const summaryRows = [];
858
1012
  summaryRows.push(
859
- `<tr><th scope="row">runId</th><td><code>${escapeHtml(tree.runId)}</code></td></tr>`
1013
+ `<tr><th scope="row">runId</th><td><code>${escapeHtml(view.runId)}</code></td></tr>`
860
1014
  );
861
- if (tree.name !== void 0) {
862
- summaryRows.push(`<tr><th scope="row">name</th><td>${escapeHtml(tree.name)}</td></tr>`);
1015
+ if (view.name !== void 0) {
1016
+ summaryRows.push(`<tr><th scope="row">name</th><td>${escapeHtml(view.name)}</td></tr>`);
863
1017
  }
864
1018
  summaryRows.push(
865
- `<tr><th scope="row">status</th><td>${escapeHtml(String(tree.status ?? "unknown"))}</td></tr>`
1019
+ `<tr><th scope="row">status</th><td>${escapeHtml(String(view.status ?? "unknown"))}</td></tr>`
866
1020
  );
867
1021
  summaryRows.push(
868
- `<tr><th scope="row">durationMs</th><td>${tree.durationMs !== void 0 ? escapeHtml(String(tree.durationMs)) : "\u2014"}</td></tr>`
1022
+ `<tr><th scope="row">durationMs</th><td>${view.durationMs !== void 0 ? escapeHtml(String(view.durationMs)) : "\u2014"}</td></tr>`
869
1023
  );
870
1024
  summaryRows.push(
871
- `<tr><th scope="row">startedAt</th><td>${tree.startedAt !== void 0 ? escapeHtml(String(tree.startedAt)) : "\u2014"}</td></tr>`
1025
+ `<tr><th scope="row">startedAt</th><td>${view.startedAt !== void 0 ? escapeHtml(String(view.startedAt)) : "\u2014"}</td></tr>`
872
1026
  );
873
1027
  summaryRows.push(
874
- `<tr><th scope="row">endedAt</th><td>${tree.endedAt !== void 0 ? escapeHtml(String(tree.endedAt)) : "\u2014"}</td></tr>`
1028
+ `<tr><th scope="row">endedAt</th><td>${view.endedAt !== void 0 ? escapeHtml(String(view.endedAt)) : "\u2014"}</td></tr>`
875
1029
  );
876
1030
  summaryRows.push(
877
- `<tr><th scope="row">totalEvents</th><td>${escapeHtml(String(tree.metadata.totalEvents))}</td></tr>`
1031
+ `<tr><th scope="row">totalEvents</th><td>${escapeHtml(String(view.metadata.totalEvents))}</td></tr>`
878
1032
  );
879
1033
  let confidenceHtml = "";
880
1034
  if (includeMetadata) {
881
- const cb = tree.metadata.confidenceBreakdown;
1035
+ const cb = view.metadata.confidenceBreakdown;
882
1036
  confidenceHtml += "<h3>Confidence breakdown</h3><table><thead><tr><th>bucket</th><th>count</th></tr></thead><tbody>";
883
1037
  for (const k of Object.keys(cb).sort()) {
884
1038
  const key = k;
@@ -886,14 +1040,14 @@ function exportHtml(tree, options) {
886
1040
  }
887
1041
  confidenceHtml += "</tbody></table>";
888
1042
  confidenceHtml += "<h3>Kind breakdown</h3><table><thead><tr><th>kind</th><th>count</th></tr></thead><tbody>";
889
- for (const k of Object.keys(tree.metadata.kinds).sort()) {
1043
+ for (const k of Object.keys(view.metadata.kinds).sort()) {
890
1044
  const key = k;
891
- const c = tree.metadata.kinds[key];
1045
+ const c = view.metadata.kinds[key];
892
1046
  if (c > 0) confidenceHtml += `<tr><td>${escapeHtml(key)}</td><td>${c}</td></tr>`;
893
1047
  }
894
1048
  confidenceHtml += "</tbody></table>";
895
1049
  }
896
- const flat = flattenTree(tree);
1050
+ const flat = flattenTree(view);
897
1051
  const errors = flat.filter((n) => n.event.status === "error");
898
1052
  let errorsHtml = "";
899
1053
  if (includeErrors && errors.length > 0) {
@@ -948,7 +1102,7 @@ footer{margin-top:2rem;font-size:0.85rem;color:#555}
948
1102
  <header><h1>AgentInspect Run: ${titleName}</h1></header>
949
1103
  <p class="note">Generated locally by AgentInspect.</p>
950
1104
  ${includeMetadata ? `<section class="summary"><h2>Summary</h2><table>${summaryRows.join("")}</table>${confidenceHtml}</section>` : ""}
951
- <section class="tree"><h2>Execution tree</h2>${tree.children.length > 0 ? renderTreeHtml(tree.children) : "<p>No steps recorded.</p>"}</section>
1105
+ <section class="tree"><h2>Execution tree</h2>${view.children.length > 0 ? renderTreeHtml(view.children) : "<p>No steps recorded.</p>"}</section>
952
1106
  ${errorsHtml}
953
1107
  ${attrsHtml}
954
1108
  <footer>Generated locally by AgentInspect. Review for sensitive data before sharing.</footer>
@@ -989,7 +1143,8 @@ function exportMarkdown(tree, options) {
989
1143
  const includeErrors = options?.includeErrors ?? true;
990
1144
  const maxLen = options?.maxAttributeLength ?? 500;
991
1145
  const redacted = options?.redacted ?? true;
992
- const titleName = tree.name ?? tree.runId;
1146
+ const view = presentLifecycleJoinedTree(tree);
1147
+ const titleName = view.name ?? view.runId;
993
1148
  const lines = [];
994
1149
  lines.push(`# AgentInspect Run: ${escapeMarkdown(titleName)}`);
995
1150
  lines.push("");
@@ -998,28 +1153,28 @@ function exportMarkdown(tree, options) {
998
1153
  if (includeMetadata) {
999
1154
  lines.push("## Summary");
1000
1155
  lines.push("");
1001
- lines.push(`- **runId**: ${escapeMarkdown(tree.runId)}`);
1002
- if (tree.name !== void 0) lines.push(`- **name**: ${escapeMarkdown(tree.name)}`);
1003
- lines.push(`- **status**: ${escapeMarkdown(String(tree.status ?? "unknown"))}`);
1156
+ lines.push(`- **runId**: ${escapeMarkdown(view.runId)}`);
1157
+ if (view.name !== void 0) lines.push(`- **name**: ${escapeMarkdown(view.name)}`);
1158
+ lines.push(`- **status**: ${escapeMarkdown(String(view.status ?? "unknown"))}`);
1004
1159
  lines.push(
1005
- `- **durationMs**: ${tree.durationMs !== void 0 ? escapeMarkdown(String(tree.durationMs)) : "-"}`
1160
+ `- **durationMs**: ${view.durationMs !== void 0 ? escapeMarkdown(String(view.durationMs)) : "-"}`
1006
1161
  );
1007
1162
  lines.push(
1008
- `- **startedAt**: ${tree.startedAt !== void 0 ? escapeMarkdown(String(tree.startedAt)) : "-"}`
1163
+ `- **startedAt**: ${view.startedAt !== void 0 ? escapeMarkdown(String(view.startedAt)) : "-"}`
1009
1164
  );
1010
1165
  lines.push(
1011
- `- **endedAt**: ${tree.endedAt !== void 0 ? escapeMarkdown(String(tree.endedAt)) : "-"}`
1166
+ `- **endedAt**: ${view.endedAt !== void 0 ? escapeMarkdown(String(view.endedAt)) : "-"}`
1012
1167
  );
1013
- lines.push(`- **totalEvents**: ${tree.metadata.totalEvents}`);
1168
+ lines.push(`- **totalEvents**: ${view.metadata.totalEvents}`);
1014
1169
  lines.push("");
1015
1170
  lines.push("### Confidence breakdown");
1016
1171
  lines.push("");
1017
1172
  lines.push("| bucket | count |");
1018
1173
  lines.push("| --- | --- |");
1019
- for (const k of Object.keys(tree.metadata.confidenceBreakdown).sort()) {
1174
+ for (const k of Object.keys(view.metadata.confidenceBreakdown).sort()) {
1020
1175
  const key = k;
1021
1176
  lines.push(
1022
- `| ${escapeMarkdown(key)} | ${tree.metadata.confidenceBreakdown[key]} |`
1177
+ `| ${escapeMarkdown(key)} | ${view.metadata.confidenceBreakdown[key]} |`
1023
1178
  );
1024
1179
  }
1025
1180
  lines.push("");
@@ -1027,9 +1182,9 @@ function exportMarkdown(tree, options) {
1027
1182
  lines.push("");
1028
1183
  lines.push("| kind | count |");
1029
1184
  lines.push("| --- | --- |");
1030
- for (const k of Object.keys(tree.metadata.kinds).sort()) {
1185
+ for (const k of Object.keys(view.metadata.kinds).sort()) {
1031
1186
  const key = k;
1032
- const c = tree.metadata.kinds[key];
1187
+ const c = view.metadata.kinds[key];
1033
1188
  if (c > 0) lines.push(`| ${escapeMarkdown(key)} | ${c} |`);
1034
1189
  }
1035
1190
  lines.push("");
@@ -1038,11 +1193,11 @@ function exportMarkdown(tree, options) {
1038
1193
  lines.push("");
1039
1194
  lines.push("```text");
1040
1195
  lines.push(
1041
- tree.children.length > 0 ? renderTreeAscii(tree.children) : "(no steps)"
1196
+ view.children.length > 0 ? renderTreeAscii(view.children) : "(no steps)"
1042
1197
  );
1043
1198
  lines.push("```");
1044
1199
  lines.push("");
1045
- const flat = flattenTree(tree);
1200
+ const flat = flattenTree(view);
1046
1201
  const errors = flat.filter((n) => n.event.status === "error");
1047
1202
  if (includeErrors && errors.length > 0) {
1048
1203
  lines.push("## Errors");