agentfootprint-lens 0.62.0 → 0.63.1

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.
package/README.md CHANGED
@@ -78,7 +78,7 @@ changes.
78
78
  |---|---|
79
79
  | `agentfootprint-lens/why` | Replay a recording as the agent's own milestones. `<WhyLens recording={...} />` takes the recording straight (`recordRun()`'s `{ snapshot, events, structure }`, or the `persistRecording` envelope), validates it at mount, and mounts the shipped `<Lens>` shell on the milestone axis — plus the axis helpers (`scrubAxisFor`, `stepForCommitIdx`, `stepForRuntimeStageId`, `resolveNavigation`) for hosts holding one cursor across views. |
80
80
  | `agentfootprint-lens/skillgraph` | Debug how a run routed through its skills. `<SkillGraphDebugger recorder={...} />` plus its headless selectors (`selectSkillRoute`, `selectSkillBeats`, `selectSkillTopology`, `selectSkillFrameContext`, `stepForRuntimeStageId`, `resolveNavigation`). |
81
- | `agentfootprint-lens/context` | What the model HAD at a stop — the served document of that epoch on top (the Served tab itself: pieces, messages, tools, verdicts, delta since the previous call) — and what it was BUILT from beneath: the record key by key, who wrote each, what moved; a long value opens in place (0.54.0). `<ContextView runner={...} />` walks the milestone axis on its own; hand it `cursor` and it follows the ONE cursor (0.53.1). Under the record, the **Findings** band (0.61.0): on an armed run (`.findings()`, agentfootprint 9.101) the model's own ledger at the stop, folded for reading — facts, conflicts as first seen (each witness with its current standing, no verdict), open, ruled out, noise, undeclared — every string off the record, absent on an unarmed run. Beside it, the **Reasoning** lens (0.62.0): `<ReasoningLens runner={...} shared={shared} />` — the same ledger read BY CALL, one card per tool call at the cursor (basis before, result, current standing after, the model's words quoted) and an answer card; absent on an unarmed run. |
81
+ | `agentfootprint-lens/context` | What the model HAD at a stop — the served document of that epoch on top (the Served tab itself: pieces, messages, tools, verdicts, delta since the previous call) — and what it was BUILT from beneath: the record key by key, who wrote each, what moved; a long value opens in place (0.54.0). `<ContextView runner={...} />` walks the milestone axis on its own; hand it `cursor` and it follows the ONE cursor (0.53.1). Under the record, the **Findings** band (0.61.0): on an armed run (`.findings()`, agentfootprint 9.101) the model's own ledger at the stop, folded for reading — facts, conflicts as first seen (each witness with its current standing, no verdict), open, ruled out, noise, undeclared — every string off the record, absent on an unarmed run. Beside it, the **Reasoning** lens (0.62.0): `<ReasoningLens runner={...} shared={shared} />` — the same ledger read BY CALL, one card per tool call at the cursor (basis before, result, current standing after, the model's words quoted) and an answer card; absent on an unarmed run. Its `exchange` view (0.63.0) lays the same beats out as the transcript between model and tools — the call with its `_findings` JSON, the result, the ticket served instead, the findings piece, the answer — only what crossed the wire. |
82
82
 
83
83
  The axis model in three sentences: one run leaves one causal trace, and each
84
84
  lens replays one AXIS of it — the Why reading scrubs the milestones, the Flow
@@ -601,8 +601,8 @@ var list2 = { margin: "4px 0 0", paddingLeft: 18 };
601
601
  var btn = { fontSize: 12, padding: "2px 8px" };
602
602
 
603
603
  // src/react/components/ReasoningLens.tsx
604
- import { useMemo as useMemo3 } from "react";
605
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
604
+ import { useMemo as useMemo3, useState as useState2 } from "react";
605
+ import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
606
606
  var LABELS3 = Object.freeze({
607
607
  lens: "Reasoning",
608
608
  calls: "calls",
@@ -637,7 +637,19 @@ var LABELS3 = Object.freeze({
637
637
  nextSteps: "nextSteps",
638
638
  noise: "noise",
639
639
  serve: "serve",
640
- answerAsk: "answer ask"
640
+ answerAsk: "answer ask",
641
+ /** The exchange view (0.63.0). */
642
+ view: "view",
643
+ cards: "cards",
644
+ exchange: "exchange",
645
+ model: "model",
646
+ tool: "tool",
647
+ call: "call",
648
+ served: "served",
649
+ args: "args",
650
+ findings: "_findings",
651
+ fromLedger: "from ledger",
652
+ lines: "lines"
641
653
  });
642
654
  var isRecord2 = (v) => typeof v === "object" && v !== null;
643
655
  function basisOf(row2) {
@@ -689,9 +701,9 @@ function resultsById(history, toolResults) {
689
701
  function collapsedById(asSent) {
690
702
  const out = /* @__PURE__ */ new Map();
691
703
  for (const m of asSent ?? []) {
692
- if (!isRecord2(m) || m.role !== "tool") continue;
704
+ if (!isRecord2(m) || m.role !== "tool" || typeof m.content !== "string") continue;
693
705
  const t = collapsedTicketOf(m.content);
694
- if (t !== void 0) out.set(t.toolCallId, t.standing);
706
+ if (t !== void 0) out.set(t.toolCallId, { standing: t.standing, content: m.content });
695
707
  }
696
708
  return out;
697
709
  }
@@ -721,7 +733,7 @@ function foldReasoning(input) {
721
733
  toolCallId: id,
722
734
  before,
723
735
  ...results.has(id) ? { result: resultShapeOf(results.get(id)) } : {},
724
- ...onWire !== void 0 ? { collapsed: onWire } : {},
736
+ ...onWire !== void 0 ? { collapsed: onWire.standing } : {},
725
737
  ...after !== void 0 ? { after } : {},
726
738
  conflicts: Object.freeze(witnessed.get(id) ?? [])
727
739
  })
@@ -744,6 +756,105 @@ function foldReasoning(input) {
744
756
  findings
745
757
  });
746
758
  }
759
+ function emittedById(history) {
760
+ const out = /* @__PURE__ */ new Map();
761
+ for (const m of history ?? []) {
762
+ if (!isRecord2(m) || m.role !== "assistant" || !Array.isArray(m.toolCalls)) continue;
763
+ for (const c of m.toolCalls) {
764
+ if (!isRecord2(c) || typeof c.id !== "string" || out.has(c.id)) continue;
765
+ out.set(c.id, {
766
+ id: c.id,
767
+ ...typeof c.name === "string" ? { name: c.name } : {},
768
+ ...isRecord2(c.args) ? { args: c.args } : {}
769
+ });
770
+ }
771
+ }
772
+ return out;
773
+ }
774
+ function ledgerFindings(before) {
775
+ return {
776
+ basis: before.basis,
777
+ ...before.expect !== void 0 ? { expect: before.expect } : {},
778
+ ...before.proposition !== void 0 ? { proposition: before.proposition } : {},
779
+ ...before.predicts !== void 0 ? { predicts: before.predicts } : {}
780
+ };
781
+ }
782
+ function callBeatOf(card, emitted) {
783
+ const id = card.toolCallId;
784
+ const e = emitted.get(id);
785
+ const toolName = e?.name ?? card.before.toolName;
786
+ if (e === void 0) {
787
+ return Object.freeze({
788
+ kind: "call",
789
+ side: "model",
790
+ toolCallId: id,
791
+ ...toolName !== void 0 ? { toolName } : {},
792
+ findings: ledgerFindings(card.before),
793
+ fromLedger: true
794
+ });
795
+ }
796
+ const { _findings, ...rest } = e.args ?? {};
797
+ return Object.freeze({
798
+ kind: "call",
799
+ side: "model",
800
+ toolCallId: id,
801
+ ...toolName !== void 0 ? { toolName } : {},
802
+ ..._findings !== void 0 ? { findings: _findings } : {},
803
+ ...e.args !== void 0 ? { args: Object.freeze(rest) } : {},
804
+ fromLedger: false
805
+ });
806
+ }
807
+ function resultBeatOf(card, content, collapsed, toolName) {
808
+ const placed = placedTicketOf(content);
809
+ return Object.freeze({
810
+ kind: "result",
811
+ side: "tool",
812
+ toolCallId: card.toolCallId,
813
+ ...toolName !== void 0 ? { toolName } : {},
814
+ content,
815
+ ...placed !== void 0 ? { placed } : {},
816
+ ...collapsed !== void 0 ? { collapsed } : {},
817
+ ...card.after !== void 0 ? { after: card.after } : {}
818
+ });
819
+ }
820
+ function findingsPieceOf(pieces) {
821
+ for (const p of pieces ?? []) {
822
+ if (!isRecord2(p) || p.source !== "findings" || typeof p.text !== "string") continue;
823
+ return Object.freeze({ kind: "served", side: "model", source: p.source, text: p.text });
824
+ }
825
+ return void 0;
826
+ }
827
+ var nonEmpty = (v) => typeof v === "string" && v.length > 0;
828
+ function answerOf(input) {
829
+ const history = input.history ?? [];
830
+ const last = history[history.length - 1];
831
+ if (isRecord2(last) && last.role === "assistant" && nonEmpty(last.content) && (!Array.isArray(last.toolCalls) || last.toolCalls.length === 0)) {
832
+ return Object.freeze({ kind: "answer", side: "model", text: last.content, from: "history" });
833
+ }
834
+ if (nonEmpty(input.finalContent)) return Object.freeze({ kind: "answer", side: "model", text: input.finalContent, from: "finalContent" });
835
+ const calls = input.llmLatestToolCalls;
836
+ if (nonEmpty(input.llmLatestContent) && (!Array.isArray(calls) || calls.length === 0)) {
837
+ return Object.freeze({ kind: "answer", side: "model", text: input.llmLatestContent, from: "llmLatestContent" });
838
+ }
839
+ return void 0;
840
+ }
841
+ function foldExchange(input) {
842
+ const reasoning = foldReasoning(input);
843
+ const emitted = emittedById(input.history);
844
+ const results = resultsById(input.history, input.toolResults);
845
+ const collapsed = collapsedById(input.asSent);
846
+ const beats = [];
847
+ for (const card of reasoning.cards) {
848
+ const call = callBeatOf(card, emitted);
849
+ beats.push(call);
850
+ if (results.has(card.toolCallId)) beats.push(resultBeatOf(card, results.get(card.toolCallId), collapsed.get(card.toolCallId), call.toolName));
851
+ }
852
+ const served = findingsPieceOf(input.pieces);
853
+ if (served !== void 0) beats.push(served);
854
+ const answer = answerOf(input);
855
+ if (answer !== void 0) beats.push(answer);
856
+ return Object.freeze({ beats: Object.freeze(beats), reasoning });
857
+ }
747
858
  function positionsOf2(snapshot) {
748
859
  return tagAxisPositions(snapshot, MILESTONE_AXIS, []) ?? [];
749
860
  }
@@ -757,6 +868,7 @@ function arrayValue(context, path) {
757
868
  }
758
869
  function ReasoningLens(props) {
759
870
  const { runner, events, shared, recorder } = props;
871
+ const [view, setView] = useState2(props.defaultView ?? "cards");
760
872
  const fresh = snapshotOfRunner(runner);
761
873
  const logKey = snapshotLogKey(fresh);
762
874
  const snapshot = useMemo3(() => fresh, [runner, logKey]);
@@ -772,32 +884,82 @@ function ReasoningLens(props) {
772
884
  [snapshot, cursor.at.runtimeStageId, cursor.at.commitIdx, events]
773
885
  );
774
886
  const rows = arrayValue(context, "findingsLedger");
775
- const fold = useMemo3(() => {
887
+ const exchange = useMemo3(() => {
776
888
  if (rows === void 0) return void 0;
777
889
  const toolResults = arrayValue(context, "toolResults");
778
890
  const history = arrayValue(context, "history");
779
891
  const wire = context.served?.row.view.messages.asSent;
780
- return foldReasoning({
892
+ const pieces = context.served?.row.view.system.pieces;
893
+ return foldExchange({
781
894
  rows,
782
895
  ...toolResults !== void 0 ? { toolResults } : {},
783
896
  ...history !== void 0 ? { history } : {},
784
897
  ...Array.isArray(wire) ? { asSent: wire } : {},
898
+ ...Array.isArray(pieces) ? { pieces } : {},
785
899
  findingsServe: keyValue(context, "findingsServe"),
786
- findingsAnswerAsk: keyValue(context, "findingsAnswerAsk")
900
+ findingsAnswerAsk: keyValue(context, "findingsAnswerAsk"),
901
+ finalContent: keyValue(context, "finalContent"),
902
+ llmLatestContent: keyValue(context, "llmLatestContent"),
903
+ llmLatestToolCalls: keyValue(context, "llmLatestToolCalls")
787
904
  });
788
905
  }, [context, rows]);
789
- if (fold === void 0) return null;
790
- return /* @__PURE__ */ jsxs3("div", { style: panel2, "data-testid": "reasoning-lens", "data-step": cursor.at.step, "data-commit": cursor.at.commitIdx, "data-calls": fold.cards.length, children: [
791
- /* @__PURE__ */ jsxs3("div", { style: header2, children: [
792
- /* @__PURE__ */ jsx3("span", { style: title2, children: LABELS3.lens }),
793
- /* @__PURE__ */ jsxs3("span", { style: dim3, children: [
794
- fold.cards.length,
795
- " ",
796
- LABELS3.calls
797
- ] })
798
- ] }),
799
- fold.cards.map((card) => /* @__PURE__ */ jsx3(Card, { card }, card.toolCallId)),
800
- fold.answer !== void 0 && /* @__PURE__ */ jsx3(Answer, { answer: fold.answer })
906
+ const mover = props.cursor === void 0 && shared !== void 0 && cursor.total > 0 && cursor.at.step >= 0;
907
+ if (exchange === void 0) return null;
908
+ const fold = exchange.reasoning;
909
+ return /* @__PURE__ */ jsxs3(
910
+ "div",
911
+ {
912
+ style: panel2,
913
+ "data-testid": "reasoning-lens",
914
+ "data-step": cursor.at.step,
915
+ "data-commit": cursor.at.commitIdx,
916
+ "data-calls": fold.cards.length,
917
+ "data-view": view,
918
+ children: [
919
+ /* @__PURE__ */ jsxs3("div", { style: header2, children: [
920
+ /* @__PURE__ */ jsx3("span", { style: title2, children: LABELS3.lens }),
921
+ /* @__PURE__ */ jsxs3("span", { style: dim3, children: [
922
+ fold.cards.length,
923
+ " ",
924
+ LABELS3.calls
925
+ ] }),
926
+ /* @__PURE__ */ jsx3(ViewToggle, { view, onView: setView })
927
+ ] }),
928
+ mover && /* @__PURE__ */ jsx3("div", { "data-testid": "reasoning-transport", children: /* @__PURE__ */ jsx3(
929
+ TimeTravel,
930
+ {
931
+ total: cursor.total,
932
+ focusSeq: Math.max(0, cursor.at.step),
933
+ onFocusChange: (n) => cursor.moveTo(n),
934
+ isLive: false,
935
+ compact: true
936
+ }
937
+ ) }),
938
+ view === "cards" && /* @__PURE__ */ jsxs3("div", { style: column, "data-testid": "reasoning-cards", children: [
939
+ fold.cards.map((card) => /* @__PURE__ */ jsx3(Card, { card }, card.toolCallId)),
940
+ fold.answer !== void 0 && /* @__PURE__ */ jsx3(Answer, { answer: fold.answer })
941
+ ] }),
942
+ view === "exchange" && /* @__PURE__ */ jsx3(Exchange, { beats: exchange.beats })
943
+ ]
944
+ }
945
+ );
946
+ }
947
+ function ViewToggle({ view, onView }) {
948
+ const button = (value, label) => /* @__PURE__ */ jsx3(
949
+ "button",
950
+ {
951
+ type: "button",
952
+ role: "tab",
953
+ "aria-selected": view === value,
954
+ "data-testid": `reasoning-view-${value}`,
955
+ style: toggleButton(view === value),
956
+ onClick: () => onView(value),
957
+ children: label
958
+ }
959
+ );
960
+ return /* @__PURE__ */ jsxs3("span", { role: "tablist", "aria-label": LABELS3.view, style: toggleRow, "data-testid": "reasoning-view-toggle", children: [
961
+ button("cards", LABELS3.cards),
962
+ button("exchange", LABELS3.exchange)
801
963
  ] });
802
964
  }
803
965
  var SHORT_ID = 12;
@@ -998,6 +1160,127 @@ function Answer({ answer }) {
998
1160
  ] }, label)) })
999
1161
  ] });
1000
1162
  }
1163
+ function Exchange({ beats }) {
1164
+ return /* @__PURE__ */ jsx3("div", { style: exchangeStyle, "data-testid": "reasoning-exchange", "data-beats": beats.length, children: beats.map((beat, i) => /* @__PURE__ */ jsx3(Beat, { beat }, i)) });
1165
+ }
1166
+ function Beat({ beat }) {
1167
+ const side = beat.side === "model" ? modelBeat : toolBeat;
1168
+ const id = beat.kind === "call" || beat.kind === "result" ? beat.toolCallId : void 0;
1169
+ return /* @__PURE__ */ jsxs3(
1170
+ "div",
1171
+ {
1172
+ style: { ...cardStyle, ...side },
1173
+ "data-testid": "reasoning-beat",
1174
+ "data-side": beat.side,
1175
+ "data-kind": beat.kind,
1176
+ ...id !== void 0 ? { "data-tool-call-id": id } : {},
1177
+ children: [
1178
+ beat.kind === "call" && /* @__PURE__ */ jsx3(CallBody, { beat }),
1179
+ beat.kind === "result" && /* @__PURE__ */ jsx3(ResultBody, { beat }),
1180
+ beat.kind === "served" && /* @__PURE__ */ jsx3(ServedBody, { beat }),
1181
+ beat.kind === "answer" && /* @__PURE__ */ jsx3(AnswerBody, { beat })
1182
+ ]
1183
+ }
1184
+ );
1185
+ }
1186
+ function CallBody({ beat }) {
1187
+ return /* @__PURE__ */ jsxs3(Fragment3, { children: [
1188
+ /* @__PURE__ */ jsxs3("div", { style: row, children: [
1189
+ /* @__PURE__ */ jsx3("span", { style: dim3, children: LABELS3.model }),
1190
+ /* @__PURE__ */ jsx3("span", { style: strong, children: LABELS3.call }),
1191
+ beat.toolName !== void 0 && /* @__PURE__ */ jsx3("code", { style: strong, children: beat.toolName }),
1192
+ /* @__PURE__ */ jsx3("code", { style: mono3, children: beat.toolCallId }),
1193
+ beat.fromLedger && /* @__PURE__ */ jsx3(Chip, { testId: "reasoning-from-ledger", color: T.warning, children: LABELS3.fromLedger })
1194
+ ] }),
1195
+ beat.findings !== void 0 && /* @__PURE__ */ jsxs3("div", { "data-testid": "reasoning-beat-findings", children: [
1196
+ /* @__PURE__ */ jsx3("span", { style: dim3, children: LABELS3.findings }),
1197
+ /* @__PURE__ */ jsx3(Clipped, { text: pretty(beat.findings) })
1198
+ ] }),
1199
+ beat.args !== void 0 && /* @__PURE__ */ jsxs3("div", { "data-testid": "reasoning-beat-args", children: [
1200
+ /* @__PURE__ */ jsx3("span", { style: dim3, children: LABELS3.args }),
1201
+ /* @__PURE__ */ jsx3(Clipped, { text: pretty(beat.args) })
1202
+ ] })
1203
+ ] });
1204
+ }
1205
+ function ResultBody({ beat }) {
1206
+ const standing = beat.after?.standing;
1207
+ return /* @__PURE__ */ jsxs3(Fragment3, { children: [
1208
+ /* @__PURE__ */ jsxs3("div", { style: row, children: [
1209
+ /* @__PURE__ */ jsx3("span", { style: dim3, children: LABELS3.tool }),
1210
+ /* @__PURE__ */ jsx3("span", { style: strong, children: LABELS3.result }),
1211
+ beat.toolName !== void 0 && /* @__PURE__ */ jsx3("code", { style: strong, children: beat.toolName }),
1212
+ /* @__PURE__ */ jsx3("code", { style: mono3, children: beat.toolCallId }),
1213
+ beat.collapsed !== void 0 && /* @__PURE__ */ jsxs3(Chip, { testId: "reasoning-collapsed", color: T.textMuted, title: beat.collapsed.standing, children: [
1214
+ LABELS3.collapsed,
1215
+ " ",
1216
+ beat.collapsed.standing
1217
+ ] })
1218
+ ] }),
1219
+ beat.placed !== void 0 ? /* @__PURE__ */ jsx3(ResultLine, { result: { placed: beat.placed } }) : /* @__PURE__ */ jsx3(Clipped, { text: prettyContent(beat.content), testId: "reasoning-beat-content" }),
1220
+ beat.collapsed !== void 0 && /* @__PURE__ */ jsxs3("div", { "data-testid": "reasoning-beat-ticket", children: [
1221
+ /* @__PURE__ */ jsx3("span", { style: dim3, children: LABELS3.ticket }),
1222
+ /* @__PURE__ */ jsx3(Clipped, { text: prettyContent(beat.collapsed.content) })
1223
+ ] }),
1224
+ /* @__PURE__ */ jsxs3("div", { style: row, "data-testid": "reasoning-after", children: [
1225
+ /* @__PURE__ */ jsx3("span", { style: dim3, children: LABELS3.standing }),
1226
+ /* @__PURE__ */ jsx3(Chip, { testId: "reasoning-standing", color: standing !== void 0 ? standingColor(standing) : T.textMuted, children: standing ?? LABELS3.undeclared }),
1227
+ beat.after?.declaredOn !== void 0 && /* @__PURE__ */ jsxs3("span", { style: dim3, "data-testid": "reasoning-declared-on", children: [
1228
+ LABELS3.declaredOn,
1229
+ " ",
1230
+ /* @__PURE__ */ jsx3("code", { style: mono3, children: beat.after.declaredOn === "answer" ? beat.after.declaredOn : beat.after.declaredOn.toolCallId })
1231
+ ] })
1232
+ ] }),
1233
+ beat.after !== void 0 && /* @__PURE__ */ jsx3(QuotedLine, { after: beat.after })
1234
+ ] });
1235
+ }
1236
+ function ServedBody({ beat }) {
1237
+ return /* @__PURE__ */ jsxs3(Fragment3, { children: [
1238
+ /* @__PURE__ */ jsxs3("div", { style: row, children: [
1239
+ /* @__PURE__ */ jsx3("span", { style: dim3, children: LABELS3.model }),
1240
+ /* @__PURE__ */ jsx3("span", { style: strong, children: LABELS3.served }),
1241
+ /* @__PURE__ */ jsx3("code", { style: mono3, children: beat.source })
1242
+ ] }),
1243
+ /* @__PURE__ */ jsx3(Clipped, { text: beat.text, testId: "reasoning-beat-content" })
1244
+ ] });
1245
+ }
1246
+ function AnswerBody({ beat }) {
1247
+ return /* @__PURE__ */ jsxs3(Fragment3, { children: [
1248
+ /* @__PURE__ */ jsxs3("div", { style: row, children: [
1249
+ /* @__PURE__ */ jsx3("span", { style: dim3, children: LABELS3.model }),
1250
+ /* @__PURE__ */ jsx3("span", { style: strong, children: LABELS3.answer }),
1251
+ /* @__PURE__ */ jsx3("code", { style: mono3, "data-testid": "reasoning-answer-from", children: beat.from })
1252
+ ] }),
1253
+ /* @__PURE__ */ jsx3(Clipped, { text: beat.text, testId: "reasoning-beat-content" })
1254
+ ] });
1255
+ }
1256
+ var CLIP_LINES = 12;
1257
+ function Clipped({ text, testId }) {
1258
+ const lines = text.split("\n");
1259
+ const head = lines.slice(0, CLIP_LINES).join("\n");
1260
+ const tail = lines.slice(CLIP_LINES);
1261
+ return /* @__PURE__ */ jsxs3("div", { "data-testid": testId ?? "reasoning-clipped", "data-lines": lines.length, children: [
1262
+ /* @__PURE__ */ jsx3("pre", { style: pre2, "data-testid": "reasoning-pre", children: head }),
1263
+ tail.length > 0 && /* @__PURE__ */ jsxs3("details", { style: detailsStyle, "data-testid": "reasoning-more", children: [
1264
+ /* @__PURE__ */ jsxs3("summary", { style: summaryStyle, children: [
1265
+ tail.length,
1266
+ " ",
1267
+ LABELS3.lines
1268
+ ] }),
1269
+ /* @__PURE__ */ jsx3("pre", { style: pre2, "data-testid": "reasoning-pre", children: tail.join("\n") })
1270
+ ] })
1271
+ ] });
1272
+ }
1273
+ function pretty(value) {
1274
+ return JSON.stringify(value, null, 2) ?? String(value);
1275
+ }
1276
+ function prettyContent(content) {
1277
+ if (typeof content !== "string") return pretty(content);
1278
+ try {
1279
+ return pretty(JSON.parse(content));
1280
+ } catch {
1281
+ return content;
1282
+ }
1283
+ }
1001
1284
  function standingColor(standing) {
1002
1285
  if (standing === "fact") return T.success;
1003
1286
  if (standing === "ruled-out") return T.error;
@@ -1045,6 +1328,24 @@ var chip = {
1045
1328
  whiteSpace: "nowrap"
1046
1329
  };
1047
1330
  var detailsStyle = { fontSize: 12 };
1331
+ var column = { display: "flex", flexDirection: "column", gap: 8 };
1332
+ var exchangeStyle = column;
1333
+ var modelBeat = { alignSelf: "flex-start", width: "max(50%,min(100%,320px))", borderColor: T.primary };
1334
+ var toolBeat = { alignSelf: "flex-end", width: "max(50%,min(100%,320px))", borderColor: T.border };
1335
+ var pre2 = { ...mono3, margin: "2px 0 0", whiteSpace: "pre-wrap", maxWidth: "100%" };
1336
+ var toggleRow = { display: "inline-flex", gap: 4, marginLeft: "auto" };
1337
+ function toggleButton(on) {
1338
+ return {
1339
+ fontSize: 10.5,
1340
+ padding: "1px 6px",
1341
+ borderRadius: 6,
1342
+ border: "1px solid",
1343
+ borderColor: on ? T.primary : T.border,
1344
+ background: on ? T.bgTertiary : T.bgElevated,
1345
+ color: on ? T.textPrimary : T.textSecondary,
1346
+ cursor: "pointer"
1347
+ };
1348
+ }
1048
1349
  var summaryStyle = { cursor: "pointer", color: T.textMuted };
1049
1350
  var detailsBody = { display: "flex", flexDirection: "column", gap: 2, paddingTop: 4 };
1050
1351
  var list3 = { margin: "2px 0 0", paddingLeft: 18 };
@@ -1055,6 +1356,7 @@ export {
1055
1356
  ContextView,
1056
1357
  LABELS3 as LABELS2,
1057
1358
  foldReasoning,
1359
+ foldExchange,
1058
1360
  ReasoningLens
1059
1361
  };
1060
- //# sourceMappingURL=chunk-P4XTLLMA.js.map
1362
+ //# sourceMappingURL=chunk-LXQNLCPV.js.map