langchain_agentx_stream_ui 0.8.2 → 0.8.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.
@@ -11,6 +11,7 @@ import {
11
11
  SILENT_TASK_TOOL_NAMES,
12
12
  SubagentTranscriptBlock,
13
13
  Write,
14
+ absorbPreToolHookIntoFold,
14
15
  classifyFinishErrorPresentation,
15
16
  classifyToolCancelSoftKind,
16
17
  coerceSubagentProgressEntries,
@@ -19,10 +20,11 @@ import {
19
20
  extractToolCancelSignals,
20
21
  formatExploreSummaryText,
21
22
  formatThoughtDurationPrefix,
23
+ resolveActiveAgentParentToolId,
22
24
  resolveHookStoppedMessage,
23
25
  resolveInterruptDisplayText,
24
26
  resolveToolCancelDisplayText
25
- } from "./chunk-GLUQUP3A.js";
27
+ } from "./chunk-BAMDIFNS.js";
26
28
 
27
29
  // src/types/tree.ts
28
30
  function createEmptyTree() {
@@ -83,6 +85,7 @@ var DEFAULT_EVENT_TIERS = {
83
85
  "subagent-tool-result": "collapsed",
84
86
  "subagent-transcript-message": "collapsed",
85
87
  "subagent-model-step": "collapsed",
88
+ "skill-progress": "collapsed",
86
89
  "hook-progress": "debug",
87
90
  "hook-finished": "debug",
88
91
  "api-retry": "debug",
@@ -150,6 +153,8 @@ function classifyEvent(event, ctx, overrides, eventIndex = 0) {
150
153
  if (tier === "collapsed") {
151
154
  if (isSubagentFoldEvent(event)) {
152
155
  parentNodeId = resolveAgentToolParentId(event);
156
+ } else if (event.event_type === "skill-progress") {
157
+ parentNodeId = resolveAgentToolParentId(event);
153
158
  } else if (event.event_type.startsWith("tool-") || event.event_type === "start-step" || event.event_type === "finish-step") {
154
159
  parentNodeId = resolveToolParentId(event, ctx, eventIndex);
155
160
  }
@@ -160,6 +165,76 @@ function classifyEvent(event, ctx, overrides, eventIndex = 0) {
160
165
  return { event, tier, parentNodeId };
161
166
  }
162
167
 
168
+ // src/core/projection/systemSummaryText.ts
169
+ function isRecord(value) {
170
+ return value !== null && typeof value === "object" && !Array.isArray(value);
171
+ }
172
+ function hookLabel(data) {
173
+ const raw = data.hook ?? data.hook_name ?? data.hookName;
174
+ return typeof raw === "string" ? raw.trim() : "hook";
175
+ }
176
+ function normalizedHookLabel(data) {
177
+ return hookLabel(data).toLowerCase().replace(/-/g, "_");
178
+ }
179
+ function isOkStopHook(data) {
180
+ const label = normalizedHookLabel(data);
181
+ if (label !== "stop" && label !== "stop_hook") return false;
182
+ const status = String(data.status ?? "").toLowerCase();
183
+ if (status === "blocked" || status === "prevented") return false;
184
+ if (data.prevented === true) return false;
185
+ return true;
186
+ }
187
+ function isPreToolHook(data) {
188
+ const label = normalizedHookLabel(data);
189
+ return label === "pre_tool" || label.includes("pre_tool") || label === "pretooluse";
190
+ }
191
+ function isHookVisibleInTimeline(data) {
192
+ if (isOkStopHook(data)) return false;
193
+ if (isPreToolHook(data)) return false;
194
+ return true;
195
+ }
196
+ function formatHookFinishedSummary(data) {
197
+ const label = hookLabel(data).toLowerCase();
198
+ const status = String(data.status ?? "").toLowerCase();
199
+ if (label === "stop" || label === "stop_hook") {
200
+ if (status === "blocked" || status === "prevented" || data.prevented === true) {
201
+ return "Stop hook blocked";
202
+ }
203
+ return "Ran stop hook";
204
+ }
205
+ const readable = hookLabel(data).replace(/_/g, "-");
206
+ return `Ran ${readable} hook`;
207
+ }
208
+ function formatSystemEventSummary(eventType, data) {
209
+ const payload = isRecord(data) ? data : {};
210
+ switch (eventType) {
211
+ case "hook-finished":
212
+ return formatHookFinishedSummary(payload);
213
+ case "compact-boundary":
214
+ return "Conversation compacted";
215
+ default:
216
+ return null;
217
+ }
218
+ }
219
+ function mergeSystemSummaryLines(lines) {
220
+ const counts = /* @__PURE__ */ new Map();
221
+ for (const line of lines) {
222
+ counts.set(line, (counts.get(line) ?? 0) + 1);
223
+ }
224
+ return [...counts.entries()].map(([line, count]) => count > 1 ? `${line} (\xD7${count})` : line).join(" \xB7 ");
225
+ }
226
+ function summarizeSystemEvents(events) {
227
+ const lines = [];
228
+ for (const evt of events) {
229
+ if (evt.eventType === "hook-finished" && isRecord(evt.data) && !isHookVisibleInTimeline(evt.data)) {
230
+ continue;
231
+ }
232
+ const line = formatSystemEventSummary(evt.eventType, evt.data);
233
+ if (line) lines.push(line);
234
+ }
235
+ return mergeSystemSummaryLines(lines);
236
+ }
237
+
163
238
  // src/core/mainTextDefer.ts
164
239
  function deferMainText(buffer, text) {
165
240
  if (!text) return buffer ?? "";
@@ -206,7 +281,7 @@ var VISIBILITY_KEYS = [
206
281
  "display_hint",
207
282
  "skip_transcript"
208
283
  ];
209
- function isRecord(value) {
284
+ function isRecord2(value) {
210
285
  return value !== null && typeof value === "object" && !Array.isArray(value);
211
286
  }
212
287
  function resolveParentAgentToolCallId(data) {
@@ -235,7 +310,7 @@ function bridgeEventDisplayMetadata(data) {
235
310
  if (!data) return null;
236
311
  const merged = {};
237
312
  const meta = data.meta;
238
- if (isRecord(meta)) {
313
+ if (isRecord2(meta)) {
239
314
  for (const key of VISIBILITY_KEYS) {
240
315
  if (key in meta) merged[key] = meta[key];
241
316
  }
@@ -694,6 +769,22 @@ function applyTaskNotification(tree, data, endedAt) {
694
769
  return true;
695
770
  }
696
771
 
772
+ // src/core/skillProgress.ts
773
+ function appendSkillProgressMessage(existing, data, seq) {
774
+ return [
775
+ ...existing,
776
+ {
777
+ id: `skill-progress:${seq}`,
778
+ agentId: data.agent_id,
779
+ messageKind: data.message_kind,
780
+ message: data.message,
781
+ step: data.step,
782
+ toolName: data.tool_name,
783
+ prompt: data.prompt
784
+ }
785
+ ];
786
+ }
787
+
697
788
  // src/core/reducer.ts
698
789
  function isInternalTool(toolName) {
699
790
  return INTERNAL_TOOL_NAMES.has(toolName);
@@ -772,6 +863,15 @@ function warnSubagentOrphanParent(eventType, data) {
772
863
  });
773
864
  }
774
865
  }
866
+ function warnSkillProgressOrphan(data, reason) {
867
+ if (import.meta.env?.DEV) {
868
+ console.warn("[langchain_agentx_stream_ui] skill-progress orphan", {
869
+ reason,
870
+ tool_call_id: data.tool_call_id,
871
+ agent_id: data.agent_id
872
+ });
873
+ }
874
+ }
775
875
  function ensureSyntheticAgentToolParent(tree, parentNodeId, event, data) {
776
876
  const existing = tree.byId[parentNodeId];
777
877
  if (existing?.kind === "tool_call") return;
@@ -1092,6 +1192,18 @@ function handleHookProgress(tree, event) {
1092
1192
  }
1093
1193
  }
1094
1194
  }
1195
+ function handleSubagentPreToolHookFold(tree, event) {
1196
+ if (event.event_type !== "hook-finished") return;
1197
+ const data = event.data;
1198
+ if (!isPreToolHook(data)) return;
1199
+ const parentId = resolveActiveAgentParentToolId(tree);
1200
+ if (!parentId) return;
1201
+ const tool = agentToolNode(tree, parentId);
1202
+ if (!tool) return;
1203
+ patchToolNode(tree, parentId, {
1204
+ subagentHookFold: absorbPreToolHookIntoFold(tool.subagentHookFold, data)
1205
+ });
1206
+ }
1095
1207
  function handleHookFinished(tree, event) {
1096
1208
  const data = event.data;
1097
1209
  const toolUseID = data.tool_use_id;
@@ -1534,6 +1646,9 @@ function handleSubagentBoundaryStart(tree, event, parentNodeId, options) {
1534
1646
  endedAt: null
1535
1647
  })
1536
1648
  });
1649
+ if (tree.openSubAgentStack[tree.openSubAgentStack.length - 1] !== parentId) {
1650
+ tree.openSubAgentStack.push(parentId);
1651
+ }
1537
1652
  }
1538
1653
  function handleSubagentBoundaryEnd(tree, event, parentNodeId) {
1539
1654
  const tool = agentToolNode(tree, parentNodeId);
@@ -1552,6 +1667,10 @@ function handleSubagentBoundaryEnd(tree, event, parentNodeId) {
1552
1667
  endedAt: eventTimeToMs(event.timestamp)
1553
1668
  })
1554
1669
  });
1670
+ const stackTop = tree.openSubAgentStack[tree.openSubAgentStack.length - 1];
1671
+ if (stackTop === parentNodeId) {
1672
+ tree.openSubAgentStack.pop();
1673
+ }
1555
1674
  }
1556
1675
  function handleSubagentToolCall(tree, _event, parentNodeId, data) {
1557
1676
  const tool = agentToolNode(tree, parentNodeId);
@@ -1589,6 +1708,26 @@ function handleSubagentToolResult(tree, _event, parentNodeId, data) {
1589
1708
  })
1590
1709
  });
1591
1710
  }
1711
+ function handleSkillProgress(tree, event, parentNodeId, seq) {
1712
+ const data = event.data;
1713
+ const parentId = parentNodeId ?? (typeof data.tool_call_id === "string" && data.tool_call_id ? `tool:${data.tool_call_id}` : void 0);
1714
+ if (!parentId) {
1715
+ warnSkillProgressOrphan(data, "missing_parent_id");
1716
+ return;
1717
+ }
1718
+ const tool = tree.byId[parentId];
1719
+ if (tool?.kind !== "tool_call") {
1720
+ warnSkillProgressOrphan(data, "parent_not_tool_call");
1721
+ return;
1722
+ }
1723
+ patchToolNode(tree, parentId, {
1724
+ skillProgressMessages: appendSkillProgressMessage(
1725
+ tool.skillProgressMessages ?? [],
1726
+ data,
1727
+ seq
1728
+ )
1729
+ });
1730
+ }
1592
1731
  function handleSubagentTranscriptMessage(tree, parentNodeId, data) {
1593
1732
  const tool = agentToolNode(tree, parentNodeId);
1594
1733
  if (!tool || !parentNodeId) return;
@@ -1711,6 +1850,7 @@ function handleDebug(tree, event, eventIndex, parentNodeId, collectDebug) {
1711
1850
  break;
1712
1851
  case "hook-finished":
1713
1852
  handleHookFinished(tree, event);
1853
+ handleSubagentPreToolHookFold(tree, event);
1714
1854
  break;
1715
1855
  }
1716
1856
  pushSystemSummarySource(tree, event, eventIndex);
@@ -1892,6 +2032,9 @@ function applyClassified(tree, classified, eventIndex, options) {
1892
2032
  event.data
1893
2033
  );
1894
2034
  break;
2035
+ case "skill-progress":
2036
+ handleSkillProgress(tree, event, parentNodeId, seq);
2037
+ break;
1895
2038
  case "subagent-model-step":
1896
2039
  break;
1897
2040
  case "task-notification":
@@ -2654,7 +2797,7 @@ function isGroupableToolName(toolName) {
2654
2797
  }
2655
2798
 
2656
2799
  // src/core/projection/mountCandidates.ts
2657
- function isRecord2(value) {
2800
+ function isRecord3(value) {
2658
2801
  return value !== null && typeof value === "object" && !Array.isArray(value);
2659
2802
  }
2660
2803
  function isToolUseEntry(entry) {
@@ -2754,8 +2897,8 @@ function iterMountCandidates(entries, options) {
2754
2897
  }
2755
2898
  if (exploreDetail) {
2756
2899
  if (collapsedPresent) {
2757
- const toolInput2 = isRecord2(entry.payload.tool_input) ? entry.payload.tool_input : null;
2758
- const display2 = isRecord2(entry.payload.display) ? entry.payload.display : null;
2900
+ const toolInput2 = isRecord3(entry.payload.tool_input) ? entry.payload.tool_input : null;
2901
+ const display2 = isRecord3(entry.payload.display) ? entry.payload.display : null;
2759
2902
  if (classifier?.isExploreCollapsible(
2760
2903
  typeof toolName === "string" ? toolName : null,
2761
2904
  toolInput2,
@@ -2771,8 +2914,8 @@ function iterMountCandidates(entries, options) {
2771
2914
  out.push([entryKey(entry), entry]);
2772
2915
  continue;
2773
2916
  }
2774
- const toolInput = isRecord2(entry.payload.tool_input) ? entry.payload.tool_input : null;
2775
- const display = isRecord2(entry.payload.display) ? entry.payload.display : null;
2917
+ const toolInput = isRecord3(entry.payload.tool_input) ? entry.payload.tool_input : null;
2918
+ const display = isRecord3(entry.payload.display) ? entry.payload.display : null;
2776
2919
  if (classifier.isExploreCollapsible(
2777
2920
  typeof toolName === "string" ? toolName : null,
2778
2921
  toolInput,
@@ -2787,76 +2930,6 @@ function iterMountCandidates(entries, options) {
2787
2930
  return out;
2788
2931
  }
2789
2932
 
2790
- // src/core/projection/systemSummaryText.ts
2791
- function isRecord3(value) {
2792
- return value !== null && typeof value === "object" && !Array.isArray(value);
2793
- }
2794
- function hookLabel(data) {
2795
- const raw = data.hook ?? data.hook_name ?? data.hookName;
2796
- return typeof raw === "string" ? raw.trim() : "hook";
2797
- }
2798
- function normalizedHookLabel(data) {
2799
- return hookLabel(data).toLowerCase().replace(/-/g, "_");
2800
- }
2801
- function isOkStopHook(data) {
2802
- const label = normalizedHookLabel(data);
2803
- if (label !== "stop" && label !== "stop_hook") return false;
2804
- const status = String(data.status ?? "").toLowerCase();
2805
- if (status === "blocked" || status === "prevented") return false;
2806
- if (data.prevented === true) return false;
2807
- return true;
2808
- }
2809
- function isPreToolHook(data) {
2810
- const label = normalizedHookLabel(data);
2811
- return label === "pre_tool" || label.includes("pre_tool") || label === "pretooluse";
2812
- }
2813
- function isHookVisibleInTimeline(data) {
2814
- if (isOkStopHook(data)) return false;
2815
- if (isPreToolHook(data)) return false;
2816
- return true;
2817
- }
2818
- function formatHookFinishedSummary(data) {
2819
- const label = hookLabel(data).toLowerCase();
2820
- const status = String(data.status ?? "").toLowerCase();
2821
- if (label === "stop" || label === "stop_hook") {
2822
- if (status === "blocked" || status === "prevented" || data.prevented === true) {
2823
- return "Stop hook blocked";
2824
- }
2825
- return "Ran stop hook";
2826
- }
2827
- const readable = hookLabel(data).replace(/_/g, "-");
2828
- return `Ran ${readable} hook`;
2829
- }
2830
- function formatSystemEventSummary(eventType, data) {
2831
- const payload = isRecord3(data) ? data : {};
2832
- switch (eventType) {
2833
- case "hook-finished":
2834
- return formatHookFinishedSummary(payload);
2835
- case "compact-boundary":
2836
- return "Conversation compacted";
2837
- default:
2838
- return null;
2839
- }
2840
- }
2841
- function mergeSystemSummaryLines(lines) {
2842
- const counts = /* @__PURE__ */ new Map();
2843
- for (const line of lines) {
2844
- counts.set(line, (counts.get(line) ?? 0) + 1);
2845
- }
2846
- return [...counts.entries()].map(([line, count]) => count > 1 ? `${line} (\xD7${count})` : line).join(" \xB7 ");
2847
- }
2848
- function summarizeSystemEvents(events) {
2849
- const lines = [];
2850
- for (const evt of events) {
2851
- if (evt.eventType === "hook-finished" && isRecord3(evt.data) && !isHookVisibleInTimeline(evt.data)) {
2852
- continue;
2853
- }
2854
- const line = formatSystemEventSummary(evt.eventType, evt.data);
2855
- if (line) lines.push(line);
2856
- }
2857
- return mergeSystemSummaryLines(lines);
2858
- }
2859
-
2860
2933
  // src/core/projection/shellProgress.ts
2861
2934
  var SHELL_PROGRESS_MIN_ELAPSED_SECONDS = 2;
2862
2935
  function formatDuration(totalSeconds) {
@@ -4414,9 +4487,15 @@ function CollapsedExploreNode({ entry, registry }) {
4414
4487
  }
4415
4488
 
4416
4489
  // src/view/nodes/SystemSummaryNode.tsx
4417
- import { jsx as jsx3 } from "react/jsx-runtime";
4490
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
4418
4491
  function SystemSummaryNode({ summaryText }) {
4419
- return /* @__PURE__ */ jsx3("div", { className: "lax-system-summary", "data-kind": "system_summary", children: summaryText });
4492
+ return /* @__PURE__ */ jsxs2("div", { className: "lax-system-summary", "data-kind": "system_summary", children: [
4493
+ /* @__PURE__ */ jsxs2("span", { className: "lax-system-summary__prefix", "aria-hidden": true, children: [
4494
+ "\u23BF",
4495
+ " "
4496
+ ] }),
4497
+ /* @__PURE__ */ jsx3("span", { className: "lax-system-summary__text", children: summaryText })
4498
+ ] });
4420
4499
  }
4421
4500
 
4422
4501
  // src/core/agent/agentAuthoritySelectors.ts
@@ -4518,7 +4597,7 @@ function selectVisibleTasks(tasks, options) {
4518
4597
  }
4519
4598
 
4520
4599
  // src/view/TaskList.tsx
4521
- import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
4600
+ import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
4522
4601
  var TASK_ICONS = {
4523
4602
  completed: "\u2714",
4524
4603
  in_progress: "\u25FC",
@@ -4617,25 +4696,25 @@ function TaskList({
4617
4696
  const completedCount = tasks.filter((t) => t.status === "completed").length;
4618
4697
  const inProgressCount = tasks.filter((t) => t.status === "in_progress").length;
4619
4698
  const pendingCount = tasks.filter((t) => t.status === "pending").length;
4620
- const items = /* @__PURE__ */ jsxs2("div", { className: "lax-task-list__items", children: [
4699
+ const items = /* @__PURE__ */ jsxs3("div", { className: "lax-task-list__items", children: [
4621
4700
  visibleTasks.map((task) => /* @__PURE__ */ jsx4(TaskItem, { task, allTasks: tasks }, task.id)),
4622
4701
  hiddenSummary ? /* @__PURE__ */ jsx4("div", { className: "lax-task-list__hidden-summary", children: hiddenSummary }) : null
4623
4702
  ] });
4624
4703
  if (!isStandalone) {
4625
4704
  return /* @__PURE__ */ jsx4("div", { className: "lax-task-list lax-task-list--embedded", "data-testid": "lax-task-list", children: items });
4626
4705
  }
4627
- return /* @__PURE__ */ jsxs2("div", { className: "lax-task-list", "data-testid": "lax-task-list", children: [
4628
- /* @__PURE__ */ jsxs2("div", { className: "lax-task-list__stats", children: [
4706
+ return /* @__PURE__ */ jsxs3("div", { className: "lax-task-list", "data-testid": "lax-task-list", children: [
4707
+ /* @__PURE__ */ jsxs3("div", { className: "lax-task-list__stats", children: [
4629
4708
  /* @__PURE__ */ jsx4("span", { className: "lax-task-list__stat-count", children: tasks.length }),
4630
4709
  /* @__PURE__ */ jsx4("span", { children: " tasks (" }),
4631
4710
  /* @__PURE__ */ jsx4("span", { className: "lax-task-list__stat-count", children: completedCount }),
4632
4711
  /* @__PURE__ */ jsx4("span", { children: " done" }),
4633
- inProgressCount > 0 && /* @__PURE__ */ jsxs2(Fragment, { children: [
4712
+ inProgressCount > 0 && /* @__PURE__ */ jsxs3(Fragment, { children: [
4634
4713
  ", ",
4635
4714
  /* @__PURE__ */ jsx4("span", { className: "lax-task-list__stat-count", children: inProgressCount }),
4636
4715
  " in progress"
4637
4716
  ] }),
4638
- pendingCount > 0 && /* @__PURE__ */ jsxs2(Fragment, { children: [
4717
+ pendingCount > 0 && /* @__PURE__ */ jsxs3(Fragment, { children: [
4639
4718
  ", ",
4640
4719
  /* @__PURE__ */ jsx4("span", { className: "lax-task-list__stat-count", children: pendingCount }),
4641
4720
  " open"
@@ -4680,7 +4759,7 @@ function TaskItem({ task, allTasks }) {
4680
4759
  }
4681
4760
  if (parts.length > 0) metaText = parts.join(" \xB7 ");
4682
4761
  }
4683
- return /* @__PURE__ */ jsxs2(
4762
+ return /* @__PURE__ */ jsxs3(
4684
4763
  "div",
4685
4764
  {
4686
4765
  className: `lax-task-item lax-task-item--${task.status}${isBlocked ? " lax-task-item--blocked" : ""}`,
@@ -4689,11 +4768,11 @@ function TaskItem({ task, allTasks }) {
4689
4768
  children: [
4690
4769
  /* @__PURE__ */ jsx4("span", { className: iconClassName, children: icon }),
4691
4770
  /* @__PURE__ */ jsx4("span", { className: subjectClassName, children: task.subject }),
4692
- task.owner ? /* @__PURE__ */ jsxs2("span", { className: "lax-task-item__owner", children: [
4771
+ task.owner ? /* @__PURE__ */ jsxs3("span", { className: "lax-task-item__owner", children: [
4693
4772
  " @",
4694
4773
  task.owner
4695
4774
  ] }) : null,
4696
- metaText && /* @__PURE__ */ jsxs2("span", { className: "lax-task-item__meta", children: [
4775
+ metaText && /* @__PURE__ */ jsxs3("span", { className: "lax-task-item__meta", children: [
4697
4776
  " (",
4698
4777
  metaText,
4699
4778
  ")"
@@ -4709,7 +4788,7 @@ import { useSyncExternalStore } from "react";
4709
4788
 
4710
4789
  // src/view/ModelRetryBlock.tsx
4711
4790
  import { useEffect as useEffect4, useState as useState4 } from "react";
4712
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
4791
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
4713
4792
  var MAX_ERROR_CHARS = 1e3;
4714
4793
  function formatRetryCountdownSeconds(retryDelayMs, updatedAt, nowMs) {
4715
4794
  const elapsed = Math.max(0, nowMs - updatedAt);
@@ -4728,7 +4807,7 @@ function ModelRetryBlock({ state, verbose = false }) {
4728
4807
  const errorText = state.errorMessage.trim();
4729
4808
  const truncated = !verbose && errorText.length > MAX_ERROR_CHARS;
4730
4809
  const visibleError = truncated ? `${errorText.slice(0, MAX_ERROR_CHARS)}\u2026` : errorText;
4731
- return /* @__PURE__ */ jsxs3("div", { className: "lax-model-retry", "data-testid": "lax-model-retry", children: [
4810
+ return /* @__PURE__ */ jsxs4("div", { className: "lax-model-retry", "data-testid": "lax-model-retry", children: [
4732
4811
  /* @__PURE__ */ jsx5(
4733
4812
  "button",
4734
4813
  {
@@ -4737,10 +4816,10 @@ function ModelRetryBlock({ state, verbose = false }) {
4737
4816
  onClick: () => setExpanded((prev) => !prev),
4738
4817
  "aria-expanded": expanded,
4739
4818
  "data-testid": "lax-model-retry-toggle",
4740
- children: /* @__PURE__ */ jsxs3("span", { className: "lax-model-retry__summary", "data-testid": "lax-model-retry-summary", children: [
4819
+ children: /* @__PURE__ */ jsxs4("span", { className: "lax-model-retry__summary", "data-testid": "lax-model-retry-summary", children: [
4741
4820
  "\u23BF ",
4742
4821
  summary,
4743
- !expanded && retryInSeconds > 0 ? /* @__PURE__ */ jsxs3("span", { className: "lax-model-retry__inline-countdown", children: [
4822
+ !expanded && retryInSeconds > 0 ? /* @__PURE__ */ jsxs4("span", { className: "lax-model-retry__inline-countdown", children: [
4744
4823
  " \xB7 ",
4745
4824
  retryInSeconds,
4746
4825
  "s"
@@ -4748,13 +4827,13 @@ function ModelRetryBlock({ state, verbose = false }) {
4748
4827
  ] })
4749
4828
  }
4750
4829
  ),
4751
- expanded ? /* @__PURE__ */ jsxs3("div", { className: "lax-model-retry__body", "data-testid": "lax-model-retry-body", children: [
4752
- errorText ? /* @__PURE__ */ jsxs3("div", { className: "lax-model-retry__error", "data-testid": "lax-model-retry-error", children: [
4830
+ expanded ? /* @__PURE__ */ jsxs4("div", { className: "lax-model-retry__body", "data-testid": "lax-model-retry-body", children: [
4831
+ errorText ? /* @__PURE__ */ jsxs4("div", { className: "lax-model-retry__error", "data-testid": "lax-model-retry-error", children: [
4753
4832
  /* @__PURE__ */ jsx5("span", { className: "lax-model-retry__category", children: categoryLabel }),
4754
4833
  visibleError ? /* @__PURE__ */ jsx5("pre", { className: "lax-model-retry__error-text", children: visibleError }) : null,
4755
4834
  truncated ? /* @__PURE__ */ jsx5("span", { className: "lax-model-retry__hint", children: "\u2026 (ctrl+o to expand)" }) : null
4756
4835
  ] }) : /* @__PURE__ */ jsx5("div", { className: "lax-model-retry__category-only", children: categoryLabel }),
4757
- /* @__PURE__ */ jsxs3("div", { className: "lax-model-retry__countdown", "data-testid": "lax-model-retry-countdown", children: [
4836
+ /* @__PURE__ */ jsxs4("div", { className: "lax-model-retry__countdown", "data-testid": "lax-model-retry-countdown", children: [
4758
4837
  "Retrying in ",
4759
4838
  retryInSeconds,
4760
4839
  " ",
@@ -4771,12 +4850,12 @@ function ModelRetryBlock({ state, verbose = false }) {
4771
4850
  }
4772
4851
 
4773
4852
  // src/view/CompactProgressBlock.tsx
4774
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
4853
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
4775
4854
  function CompactProgressBlock({ state }) {
4776
4855
  const bar = formatCompactProgressBar(state.percent);
4777
- return /* @__PURE__ */ jsxs4("div", { className: "lax-compact-progress", "data-testid": "lax-compact-progress", children: [
4856
+ return /* @__PURE__ */ jsxs5("div", { className: "lax-compact-progress", "data-testid": "lax-compact-progress", children: [
4778
4857
  /* @__PURE__ */ jsx6("div", { className: "lax-compact-progress__title", "data-testid": "lax-compact-progress-title", children: "\u273D Compacting conversation\u2026" }),
4779
- /* @__PURE__ */ jsxs4("div", { className: "lax-compact-progress__bar-line", "data-testid": "lax-compact-progress-bar", children: [
4858
+ /* @__PURE__ */ jsxs5("div", { className: "lax-compact-progress__bar-line", "data-testid": "lax-compact-progress-bar", children: [
4780
4859
  bar,
4781
4860
  " ",
4782
4861
  state.percent,
@@ -5016,7 +5095,7 @@ function getSpinnerFrameIndex(timeMs, reducedMotion = false) {
5016
5095
  import { useRef as useRef5 } from "react";
5017
5096
 
5018
5097
  // src/view/spinner/SpinnerGlimmerVerb.tsx
5019
- import { jsxs as jsxs5 } from "react/jsx-runtime";
5098
+ import { jsxs as jsxs6 } from "react/jsx-runtime";
5020
5099
  function SpinnerGlimmerVerb({
5021
5100
  verb,
5022
5101
  mode,
@@ -5042,7 +5121,7 @@ function SpinnerGlimmerVerb({
5042
5121
  ["--lax-spinner-flash-opacity"]: String(flashOpacity)
5043
5122
  }
5044
5123
  };
5045
- return /* @__PURE__ */ jsxs5("span", { className: classes.join(" "), style, children: [
5124
+ return /* @__PURE__ */ jsxs6("span", { className: classes.join(" "), style, children: [
5046
5125
  verb,
5047
5126
  "\u2026"
5048
5127
  ] });
@@ -5191,7 +5270,7 @@ function useStalledSpinnerIntensity(time, currentResponseLength, hasActiveTools
5191
5270
  }
5192
5271
 
5193
5272
  // src/view/spinner/SpinnerAnimationRow.tsx
5194
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
5273
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
5195
5274
  function SpinnerAnimationRow({
5196
5275
  mode,
5197
5276
  verb,
@@ -5249,7 +5328,7 @@ function SpinnerAnimationRow({
5249
5328
  className: thinkingStatus === "thinking" ? "lax-spinner-status-part--thinking" : void 0
5250
5329
  });
5251
5330
  }
5252
- return /* @__PURE__ */ jsxs6("div", { className: "lax-spinner", "data-testid": "lax-spinner", children: [
5331
+ return /* @__PURE__ */ jsxs7("div", { className: "lax-spinner", "data-testid": "lax-spinner", children: [
5253
5332
  /* @__PURE__ */ jsx7("span", { className: "lax-spinner-frame", "data-testid": "lax-spinner-frame", children: frame }),
5254
5333
  /* @__PURE__ */ jsx7(
5255
5334
  SpinnerGlimmerVerb,
@@ -5261,9 +5340,9 @@ function SpinnerAnimationRow({
5261
5340
  flashOpacity
5262
5341
  }
5263
5342
  ),
5264
- statusParts.length > 0 && /* @__PURE__ */ jsxs6("span", { className: "lax-spinner-status", children: [
5343
+ statusParts.length > 0 && /* @__PURE__ */ jsxs7("span", { className: "lax-spinner-status", children: [
5265
5344
  " (",
5266
- statusParts.map((part, i) => /* @__PURE__ */ jsxs6(
5345
+ statusParts.map((part, i) => /* @__PURE__ */ jsxs7(
5267
5346
  "span",
5268
5347
  {
5269
5348
  className: `lax-spinner-status-part${part.className ? ` ${part.className}` : ""}`,
@@ -5304,9 +5383,9 @@ function shouldShowNextTaskLine(showTaskList, tasks, sessionStatus) {
5304
5383
  }
5305
5384
 
5306
5385
  // src/view/Spinner.tsx
5307
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
5386
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
5308
5387
  function MessageResponse({ children }) {
5309
- return /* @__PURE__ */ jsxs7("div", { className: "lax-message-response", children: [
5388
+ return /* @__PURE__ */ jsxs8("div", { className: "lax-message-response", children: [
5310
5389
  /* @__PURE__ */ jsx8("span", { className: "lax-message-response__marker", children: "\u23BF " }),
5311
5390
  /* @__PURE__ */ jsx8("span", { className: "lax-message-response__content", children })
5312
5391
  ] });
@@ -5435,7 +5514,7 @@ function Spinner({
5435
5514
  } else if (typeof thinkingStatus === "number") {
5436
5515
  thinkingText = `thought for ${Math.max(1, Math.round(thinkingStatus / 1e3))}s`;
5437
5516
  }
5438
- return /* @__PURE__ */ jsxs7("div", { className: "lax-spinner-container", "data-testid": "lax-spinner-container", children: [
5517
+ return /* @__PURE__ */ jsxs8("div", { className: "lax-spinner-container", "data-testid": "lax-spinner-container", children: [
5439
5518
  modelRetry ? /* @__PURE__ */ jsx8(ModelRetryBlock, { state: modelRetry, verbose }) : null,
5440
5519
  compactProgress ? /* @__PURE__ */ jsx8(CompactProgressBlock, { state: compactProgress }) : null,
5441
5520
  /* @__PURE__ */ jsx8(
@@ -5461,9 +5540,9 @@ function Spinner({
5461
5540
  // src/view/TaskListFooter.tsx
5462
5541
  import { useMemo as useMemo6, useState as useState8 } from "react";
5463
5542
  import { useSyncExternalStore as useSyncExternalStore2 } from "react";
5464
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
5543
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
5465
5544
  function MessageResponse2({ children }) {
5466
- return /* @__PURE__ */ jsxs8("div", { className: "lax-message-response", children: [
5545
+ return /* @__PURE__ */ jsxs9("div", { className: "lax-message-response", children: [
5467
5546
  /* @__PURE__ */ jsx9("span", { className: "lax-message-response__marker", children: "\u23BF " }),
5468
5547
  /* @__PURE__ */ jsx9("span", { className: "lax-message-response__content", children })
5469
5548
  ] });
@@ -5524,8 +5603,8 @@ function TaskListFooter() {
5524
5603
  return null;
5525
5604
  }
5526
5605
  const label = formatTaskFooterLabel(tasks);
5527
- return /* @__PURE__ */ jsxs8("div", { className: "lax-task-list-footer", "data-testid": "lax-task-list-footer", children: [
5528
- /* @__PURE__ */ jsxs8(
5606
+ return /* @__PURE__ */ jsxs9("div", { className: "lax-task-list-footer", "data-testid": "lax-task-list-footer", children: [
5607
+ /* @__PURE__ */ jsxs9(
5529
5608
  "button",
5530
5609
  {
5531
5610
  type: "button",
@@ -5545,7 +5624,7 @@ function TaskListFooter() {
5545
5624
 
5546
5625
  // src/view/GroupedToolCallRow.tsx
5547
5626
  import { useCallback, useState as useState9 } from "react";
5548
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
5627
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
5549
5628
  var INITIALIZING = "Initializing\u2026";
5550
5629
  function readGroupMeta(payload) {
5551
5630
  const raw = payload.groupMeta;
@@ -5612,18 +5691,18 @@ function GroupedSubline({
5612
5691
  const toggleExpanded = useCallback(() => {
5613
5692
  setExpanded((prev) => !prev);
5614
5693
  }, []);
5615
- return /* @__PURE__ */ jsxs9(
5694
+ return /* @__PURE__ */ jsxs10(
5616
5695
  "div",
5617
5696
  {
5618
5697
  className: "lax-tool-group__item lax-tool-group__subline-block",
5619
5698
  "data-group-index": index + 1,
5620
5699
  "data-tool-call-id": callId,
5621
5700
  children: [
5622
- /* @__PURE__ */ jsxs9("div", { className: "lax-tool-group__subline", children: [
5701
+ /* @__PURE__ */ jsxs10("div", { className: "lax-tool-group__subline", children: [
5623
5702
  /* @__PURE__ */ jsx10("span", { className: "lax-tool-group__tree", "aria-hidden": true, children: treeChar }),
5624
- /* @__PURE__ */ jsxs9("span", { className: "lax-tool-group__subline-flow", children: [
5703
+ /* @__PURE__ */ jsxs10("span", { className: "lax-tool-group__subline-flow", children: [
5625
5704
  /* @__PURE__ */ jsx10("span", { className: "lax-tool-group__subline-title", children: subTitle }),
5626
- status ? /* @__PURE__ */ jsxs9("span", { className: "lax-tool-group__subline-status", children: [
5705
+ status ? /* @__PURE__ */ jsxs10("span", { className: "lax-tool-group__subline-status", children: [
5627
5706
  " \xB7 ",
5628
5707
  status
5629
5708
  ] }) : null,
@@ -5653,8 +5732,8 @@ function GroupedToolCallRow({ payload }) {
5653
5732
  const anyPending = Array.isArray(payload.pendingCallIds) && payload.pendingCallIds.length > 0;
5654
5733
  const anyError = Array.isArray(payload.erroredCallIds) && payload.erroredCallIds.length > 0;
5655
5734
  const enableTranscript = toolUses.length >= 2;
5656
- return /* @__PURE__ */ jsxs9("div", { className: "lax-tool-group", "data-tool-name": toolName, "data-kind": "grouped_tool_use", children: [
5657
- /* @__PURE__ */ jsxs9(
5735
+ return /* @__PURE__ */ jsxs10("div", { className: "lax-tool-group", "data-tool-name": toolName, "data-kind": "grouped_tool_use", children: [
5736
+ /* @__PURE__ */ jsxs10(
5658
5737
  "div",
5659
5738
  {
5660
5739
  className: [
@@ -5690,7 +5769,7 @@ function GroupedToolCallRow({ payload }) {
5690
5769
  }
5691
5770
 
5692
5771
  // src/view/nodes/ThinkingSummaryNode.tsx
5693
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
5772
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
5694
5773
  function formatThoughtDuration(seconds) {
5695
5774
  const rounded = Math.max(1, Math.round(seconds));
5696
5775
  return `${rounded}s`;
@@ -5715,18 +5794,18 @@ function ThinkingSummary({ node }) {
5715
5794
  const viewOptions = useSessionViewOptions();
5716
5795
  const showToolDetail = shouldShowReasoningInTimeline(viewOptions);
5717
5796
  const toolText = showToolDetail ? formatToolCounts(node) : null;
5718
- return /* @__PURE__ */ jsxs10(
5797
+ return /* @__PURE__ */ jsxs11(
5719
5798
  "div",
5720
5799
  {
5721
5800
  className: "lax-thought-summary",
5722
5801
  "data-kind": "thinking_summary",
5723
5802
  "data-round-id": node.roundId,
5724
5803
  children: [
5725
- /* @__PURE__ */ jsxs10("span", { className: "lax-thought-summary__text", children: [
5804
+ /* @__PURE__ */ jsxs11("span", { className: "lax-thought-summary__text", children: [
5726
5805
  "Thought for ",
5727
5806
  formatThoughtDuration(node.elapsedSeconds)
5728
5807
  ] }),
5729
- toolText ? /* @__PURE__ */ jsxs10("span", { className: "lax-thought-summary__tools", children: [
5808
+ toolText ? /* @__PURE__ */ jsxs11("span", { className: "lax-thought-summary__tools", children: [
5730
5809
  " \xB7 ",
5731
5810
  toolText
5732
5811
  ] }) : null,
@@ -5797,7 +5876,7 @@ function TimelineEntries({ registry }) {
5797
5876
  // src/view/Timeline.tsx
5798
5877
  import { useStore as useStore6 } from "zustand";
5799
5878
  import { useShallow as useShallow5 } from "zustand/shallow";
5800
- import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
5879
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
5801
5880
  function useContentCharCount() {
5802
5881
  const store = useSessionStoreApi();
5803
5882
  return useStore6(
@@ -5819,7 +5898,7 @@ function Timeline({ showTaskListFooter = true }) {
5819
5898
  const { verbose } = useSessionViewOptions();
5820
5899
  const { startedAt } = useStore6(store, (s) => s.tree.meta);
5821
5900
  const contentCharCount = useContentCharCount();
5822
- return /* @__PURE__ */ jsxs11("div", { className: "lax-timeline", "data-testid": "lax-timeline", children: [
5901
+ return /* @__PURE__ */ jsxs12("div", { className: "lax-timeline", "data-testid": "lax-timeline", children: [
5823
5902
  /* @__PURE__ */ jsx14(TimelineEntries, { registry }),
5824
5903
  /* @__PURE__ */ jsx14(
5825
5904
  Spinner,
@@ -5882,7 +5961,7 @@ function estimateProjectedEntrySize(entry, fallback = DEFAULT_ESTIMATE_SIZE) {
5882
5961
  import { useRef as useRef7 } from "react";
5883
5962
  import { useVirtualizer } from "@tanstack/react-virtual";
5884
5963
  import { useStore as useStore7 } from "zustand";
5885
- import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
5964
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
5886
5965
  var DEFAULT_VIRTUALIZE_THRESHOLD = 500;
5887
5966
  function useContentCharCount2() {
5888
5967
  const store = useSessionStoreApi();
@@ -5916,7 +5995,7 @@ function VirtualTimeline({
5916
5995
  },
5917
5996
  overscan: 5
5918
5997
  });
5919
- return /* @__PURE__ */ jsxs12(
5998
+ return /* @__PURE__ */ jsxs13(
5920
5999
  "div",
5921
6000
  {
5922
6001
  ref: parentRef,
@@ -5993,6 +6072,7 @@ export {
5993
6072
  DEFAULT_EVENT_TIERS,
5994
6073
  resolveEventTier,
5995
6074
  classifyEvent,
6075
+ formatHookFinishedSummary,
5996
6076
  streamChunk,
5997
6077
  reduceTree,
5998
6078
  reduceAgentLoopEvent,
@@ -6037,7 +6117,6 @@ export {
6037
6117
  isGroupableToolName,
6038
6118
  entryKey,
6039
6119
  iterMountCandidates,
6040
- formatHookFinishedSummary,
6041
6120
  SHELL_PROGRESS_MIN_ELAPSED_SECONDS,
6042
6121
  formatShellProgressSuffix,
6043
6122
  resolveShellProgressFromPayload,
@@ -6081,4 +6160,4 @@ export {
6081
6160
  VirtualTimeline,
6082
6161
  SessionTimeline
6083
6162
  };
6084
- //# sourceMappingURL=chunk-XEIQBTD2.js.map
6163
+ //# sourceMappingURL=chunk-EKAV2XFY.js.map