@ash-cloud/ash-ui 0.0.6 → 0.0.8

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/dist/index.js CHANGED
@@ -1,6 +1,5 @@
1
- import { createContext, useState, useRef, useEffect, useMemo, useCallback, useContext } from 'react';
1
+ import { lazy, createContext, useState, useRef, useMemo, useEffect, Suspense, useCallback, useContext } from 'react';
2
2
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
- import ReactMarkdown from 'react-markdown';
4
3
 
5
4
  // src/components/ToolCallCard.tsx
6
5
 
@@ -35,27 +34,41 @@ function mapToolToActionType(toolName, input) {
35
34
  command: inputObj.command || "",
36
35
  description: inputObj.description
37
36
  };
38
- case "Read":
37
+ case "Read": {
38
+ const limit = inputObj.limit;
39
39
  return {
40
40
  action: "file_read",
41
41
  path: inputObj.file_path || "",
42
42
  offset: inputObj.offset,
43
- limit: inputObj.limit
43
+ limit,
44
+ linesRead: limit
45
+ // Use limit as approximate lines read if specified
44
46
  };
45
- case "Edit":
47
+ }
48
+ case "Edit": {
49
+ const oldStr = inputObj.old_string;
50
+ const newStr = inputObj.new_string;
51
+ const oldLines = oldStr ? oldStr.split("\n").length : 0;
52
+ const newLines = newStr ? newStr.split("\n").length : 0;
46
53
  return {
47
54
  action: "file_edit",
48
55
  path: inputObj.file_path || "",
49
- oldString: inputObj.old_string,
50
- newString: inputObj.new_string,
51
- replaceAll: inputObj.replace_all
56
+ oldString: oldStr,
57
+ newString: newStr,
58
+ replaceAll: inputObj.replace_all,
59
+ linesAdded: newLines,
60
+ linesRemoved: oldLines
52
61
  };
53
- case "Write":
62
+ }
63
+ case "Write": {
64
+ const content = inputObj.content;
54
65
  return {
55
66
  action: "file_write",
56
67
  path: inputObj.file_path || "",
57
- content: inputObj.content
68
+ content,
69
+ linesWritten: content ? content.split("\n").length : void 0
58
70
  };
71
+ }
59
72
  case "Grep":
60
73
  return {
61
74
  action: "search",
@@ -95,6 +108,16 @@ function mapToolToActionType(toolName, input) {
95
108
  stats
96
109
  };
97
110
  }
111
+ case "Task": {
112
+ return {
113
+ action: "agent_tool",
114
+ agentType: inputObj.subagent_type || "general-purpose",
115
+ description: inputObj.description || "",
116
+ prompt: inputObj.prompt,
117
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
118
+ toolCallCount: 0
119
+ };
120
+ }
98
121
  default: {
99
122
  const mcpParts = parseMcpToolName(toolName);
100
123
  if (mcpParts) {
@@ -144,6 +167,8 @@ function generateToolSummary(_toolName, _input, actionType) {
144
167
  }
145
168
  return `${actionType.todos.length} tasks`;
146
169
  }
170
+ case "agent_tool":
171
+ return actionType.description;
147
172
  default:
148
173
  return "Unknown tool";
149
174
  }
@@ -211,6 +236,7 @@ function createToolCall(toolUse) {
211
236
  actionType,
212
237
  status: "pending",
213
238
  summary,
239
+ input: toolUse.input,
214
240
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
215
241
  };
216
242
  }
@@ -220,6 +246,7 @@ function updateToolCallWithResult(toolCall, content, isError) {
220
246
  updatedToolCall.status = isError ? "failed" : "success";
221
247
  updatedToolCall.completedAt = (/* @__PURE__ */ new Date()).toISOString();
222
248
  updatedToolCall.isError = isError;
249
+ updatedToolCall.output = content;
223
250
  if (actionType.action === "command_run") {
224
251
  const result = parseCommandResult(content);
225
252
  actionType.result = result;
@@ -257,6 +284,8 @@ function getActionIcon(actionType) {
257
284
  return "tool";
258
285
  case "todo_write":
259
286
  return "list-checks";
287
+ case "agent_tool":
288
+ return "bot";
260
289
  default:
261
290
  return "tool";
262
291
  }
@@ -285,6 +314,8 @@ function getActionLabel(actionType) {
285
314
  return "Tool";
286
315
  case "todo_write":
287
316
  return "Tasks";
317
+ case "agent_tool":
318
+ return actionType.agentType;
288
319
  default:
289
320
  return "Tool";
290
321
  }
@@ -307,6 +338,21 @@ function formatTimestamp(timestamp) {
307
338
  return timestamp;
308
339
  }
309
340
  }
341
+ function formatElapsedTime(startTime, endTime) {
342
+ const start = typeof startTime === "string" ? new Date(startTime) : startTime;
343
+ const end = endTime ? typeof endTime === "string" ? new Date(endTime) : endTime : /* @__PURE__ */ new Date();
344
+ const elapsedMs = end.getTime() - start.getTime();
345
+ const elapsedSeconds = Math.floor(elapsedMs / 1e3);
346
+ if (elapsedSeconds < 60) {
347
+ return `${elapsedSeconds}s`;
348
+ }
349
+ const minutes = Math.floor(elapsedSeconds / 60);
350
+ const seconds = elapsedSeconds % 60;
351
+ if (seconds === 0) {
352
+ return `${minutes}m`;
353
+ }
354
+ return `${minutes}m ${seconds}s`;
355
+ }
310
356
  function truncate(str, maxLength) {
311
357
  if (str.length <= maxLength) return str;
312
358
  return str.substring(0, maxLength - 3) + "...";
@@ -630,6 +676,12 @@ function ClipboardListIcon({ className }) {
630
676
  /* @__PURE__ */ jsx("path", { d: "M8 16h.01" })
631
677
  ] });
632
678
  }
679
+ function ClockIcon({ className }) {
680
+ return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
681
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
682
+ /* @__PURE__ */ jsx("polyline", { points: "12 6 12 12 16 14" })
683
+ ] });
684
+ }
633
685
  function SpinnerIcon({ className }) {
634
686
  return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
635
687
  }
@@ -685,6 +737,8 @@ function ActionIcon({ actionType, className = "w-4 h-4" }) {
685
737
  return /* @__PURE__ */ jsx(PlugIcon, { className });
686
738
  case "todo_write":
687
739
  return /* @__PURE__ */ jsx(ListChecksIcon, { className });
740
+ case "agent_tool":
741
+ return /* @__PURE__ */ jsx(BotIcon, { className });
688
742
  case "generic_tool":
689
743
  default:
690
744
  return /* @__PURE__ */ jsx(ToolIcon, { className });
@@ -738,6 +792,153 @@ function JsonDisplay({ value, maxHeight, className }) {
738
792
  const formatted = JSON.stringify(value, null, 2);
739
793
  return /* @__PURE__ */ jsx(CodeBlock, { maxHeight, className, children: formatted });
740
794
  }
795
+ function AgentToolCard({
796
+ toolCall,
797
+ defaultExpanded = false,
798
+ className,
799
+ depth = 0
800
+ }) {
801
+ const [expanded, setExpanded] = useState(defaultExpanded);
802
+ const [elapsedTime, setElapsedTime] = useState("");
803
+ const intervalRef = useRef(null);
804
+ const { actionType, status, summary, nestedToolCalls, nestedToolCallCount, startedAt } = toolCall;
805
+ const agentData = useMemo(() => {
806
+ if (actionType.action !== "agent_tool") {
807
+ return null;
808
+ }
809
+ const agentAction = actionType;
810
+ return {
811
+ agentType: agentAction.agentType,
812
+ description: agentAction.description,
813
+ prompt: agentAction.prompt
814
+ };
815
+ }, [actionType]);
816
+ const toolCount = nestedToolCallCount ?? nestedToolCalls?.length ?? 0;
817
+ const isRunning = status === "pending";
818
+ useEffect(() => {
819
+ if (isRunning && startedAt) {
820
+ setElapsedTime(formatElapsedTime(startedAt));
821
+ intervalRef.current = setInterval(() => {
822
+ setElapsedTime(formatElapsedTime(startedAt));
823
+ }, 1e3);
824
+ return () => {
825
+ if (intervalRef.current) {
826
+ clearInterval(intervalRef.current);
827
+ intervalRef.current = null;
828
+ }
829
+ };
830
+ } else if (!isRunning) {
831
+ if (intervalRef.current) {
832
+ clearInterval(intervalRef.current);
833
+ intervalRef.current = null;
834
+ }
835
+ setElapsedTime("");
836
+ }
837
+ return void 0;
838
+ }, [isRunning, startedAt]);
839
+ if (!agentData) {
840
+ return null;
841
+ }
842
+ const { agentType, description, prompt } = agentData;
843
+ const indentClass = depth > 0 ? "ml-4" : "";
844
+ return /* @__PURE__ */ jsxs(
845
+ "div",
846
+ {
847
+ className: cn(
848
+ "rounded-xl border bg-[var(--ash-surface-dark,#0a0a0a)] overflow-hidden",
849
+ isRunning ? "border-yellow-500/30" : status === "failed" ? "border-red-500/30" : "border-white/10",
850
+ indentClass,
851
+ className
852
+ ),
853
+ children: [
854
+ /* @__PURE__ */ jsxs(
855
+ "button",
856
+ {
857
+ onClick: () => setExpanded(!expanded),
858
+ className: "w-full px-4 py-3 flex items-center gap-3 hover:bg-white/5 cursor-pointer transition-colors",
859
+ children: [
860
+ /* @__PURE__ */ jsx(
861
+ ChevronRightIcon,
862
+ {
863
+ className: cn(
864
+ "w-4 h-4 text-white/40 transition-transform duration-200 shrink-0",
865
+ expanded && "rotate-90"
866
+ )
867
+ }
868
+ ),
869
+ /* @__PURE__ */ jsx(
870
+ "div",
871
+ {
872
+ className: cn(
873
+ "w-6 h-6 rounded-lg flex items-center justify-center shrink-0",
874
+ isRunning ? "bg-yellow-500/20" : status === "failed" ? "bg-red-500/20" : "bg-[var(--ash-accent)]/20"
875
+ ),
876
+ children: isRunning ? /* @__PURE__ */ jsx(
877
+ SpinnerIcon,
878
+ {
879
+ className: "w-3.5 h-3.5 text-yellow-400 animate-spin"
880
+ }
881
+ ) : /* @__PURE__ */ jsx(
882
+ BotIcon,
883
+ {
884
+ className: cn(
885
+ "w-3.5 h-3.5",
886
+ status === "failed" ? "text-red-400" : "text-[var(--ash-accent)]"
887
+ )
888
+ }
889
+ )
890
+ }
891
+ ),
892
+ /* @__PURE__ */ jsx(
893
+ "span",
894
+ {
895
+ className: cn(
896
+ "px-2 py-0.5 rounded text-xs font-medium shrink-0",
897
+ isRunning ? "bg-yellow-500/20 text-yellow-400" : status === "failed" ? "bg-red-500/20 text-red-400" : "bg-white/10 text-white/70"
898
+ ),
899
+ children: agentType
900
+ }
901
+ ),
902
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-white/80 truncate flex-1 text-left", children: description || summary }),
903
+ toolCount > 0 && /* @__PURE__ */ jsxs("span", { className: "text-xs text-white/50 shrink-0", children: [
904
+ toolCount,
905
+ " tool call",
906
+ toolCount !== 1 ? "s" : ""
907
+ ] }),
908
+ isRunning && elapsedTime && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-xs text-white/40 shrink-0", children: [
909
+ /* @__PURE__ */ jsx(ClockIcon, { className: "w-3 h-3" }),
910
+ /* @__PURE__ */ jsx("span", { children: elapsedTime })
911
+ ] }),
912
+ /* @__PURE__ */ jsx("span", { className: "text-white/30 shrink-0", children: "..." })
913
+ ]
914
+ }
915
+ ),
916
+ expanded && /* @__PURE__ */ jsxs("div", { className: "border-t border-white/5 bg-black/20", children: [
917
+ prompt && /* @__PURE__ */ jsx("div", { className: "px-4 py-3 border-b border-white/5", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-white/70 whitespace-pre-wrap", children: prompt.length > 500 ? prompt.substring(0, 500) + "..." : prompt }) }),
918
+ nestedToolCalls && nestedToolCalls.length > 0 && /* @__PURE__ */ jsx("div", { className: "p-3 space-y-2", children: nestedToolCalls.map((nestedCall) => /* @__PURE__ */ jsx("div", { children: nestedCall.actionType.action === "agent_tool" ? /* @__PURE__ */ jsx(
919
+ AgentToolCard,
920
+ {
921
+ toolCall: nestedCall,
922
+ defaultExpanded: false,
923
+ depth: depth + 1
924
+ }
925
+ ) : /* @__PURE__ */ jsx(
926
+ ToolCallCard,
927
+ {
928
+ toolCall: nestedCall,
929
+ defaultExpanded: false
930
+ }
931
+ ) }, nestedCall.id)) }),
932
+ (!nestedToolCalls || nestedToolCalls.length === 0) && isRunning && /* @__PURE__ */ jsx("div", { className: "px-4 py-6 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-white/40", children: [
933
+ /* @__PURE__ */ jsx(SpinnerIcon, { className: "w-4 h-4 animate-spin" }),
934
+ /* @__PURE__ */ jsx("span", { children: "Agent is working..." })
935
+ ] }) }),
936
+ (!nestedToolCalls || nestedToolCalls.length === 0) && !isRunning && /* @__PURE__ */ jsx("div", { className: "px-4 py-4 text-sm text-white/40 text-center", children: "No tool calls recorded" })
937
+ ] })
938
+ ]
939
+ }
940
+ );
941
+ }
741
942
  function SectionHeader({ children }) {
742
943
  return /* @__PURE__ */ jsx("div", { className: "ash-tool-section-header", children });
743
944
  }
@@ -1013,6 +1214,9 @@ function hasDetails(actionType) {
1013
1214
  return Boolean(actionType.arguments || actionType.result);
1014
1215
  case "todo_write":
1015
1216
  return actionType.todos.length > 0;
1217
+ case "agent_tool":
1218
+ return true;
1219
+ // Always expandable (handled by AgentToolCard)
1016
1220
  default:
1017
1221
  return false;
1018
1222
  }
@@ -1020,6 +1224,16 @@ function hasDetails(actionType) {
1020
1224
  function ToolCallCard({ toolCall, defaultExpanded = false, className }) {
1021
1225
  const [expanded, setExpanded] = useState(defaultExpanded);
1022
1226
  const { actionType, status, summary } = toolCall;
1227
+ if (actionType.action === "agent_tool") {
1228
+ return /* @__PURE__ */ jsx(
1229
+ AgentToolCard,
1230
+ {
1231
+ toolCall,
1232
+ defaultExpanded,
1233
+ className
1234
+ }
1235
+ );
1236
+ }
1023
1237
  const canExpand = hasDetails(actionType);
1024
1238
  const statusClasses = {
1025
1239
  pending: "border-yellow-500/30 ash-tool-status-pending",
@@ -1088,6 +1302,17 @@ function ToolCallCard({ toolCall, defaultExpanded = false, className }) {
1088
1302
  }
1089
1303
  );
1090
1304
  }
1305
+ var ReactMarkdown = lazy(() => import('react-markdown'));
1306
+ function LazyMarkdown({ children, fallback, className }) {
1307
+ const [mounted, setMounted] = useState(false);
1308
+ useEffect(() => {
1309
+ setMounted(true);
1310
+ }, []);
1311
+ if (!mounted) {
1312
+ return /* @__PURE__ */ jsx("span", { className, children: fallback ?? children });
1313
+ }
1314
+ return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("span", { className, children: fallback ?? children }), children: /* @__PURE__ */ jsx(ReactMarkdown, { children }) });
1315
+ }
1091
1316
  function OptionCards({ options, onSelect, className }) {
1092
1317
  return /* @__PURE__ */ jsx("div", { className: cn("grid gap-2 mt-3", className), style: {
1093
1318
  gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))"
@@ -1183,7 +1408,7 @@ function AssistantMessage({ entry, onOptionSelect, className }) {
1183
1408
  /* @__PURE__ */ jsx("div", { className: "w-7 h-7 rounded-full bg-[var(--ash-accent)]/20 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsx(BotIcon, { className: "w-4 h-4 text-[var(--ash-accent)]" }) }),
1184
1409
  /* @__PURE__ */ jsxs("div", { className: "flex-1 max-w-[85%]", children: [
1185
1410
  /* @__PURE__ */ jsx("div", { className: "ash-card-glass rounded-2xl p-4", children: /* @__PURE__ */ jsx("div", { className: "ash-message-content prose prose-sm prose-invert max-w-none text-sm leading-relaxed", children: parsedOptions ? /* @__PURE__ */ jsxs(Fragment, { children: [
1186
- parsedOptions.preamble && /* @__PURE__ */ jsx(ReactMarkdown, { children: parsedOptions.preamble }),
1411
+ parsedOptions.preamble && /* @__PURE__ */ jsx(LazyMarkdown, { children: parsedOptions.preamble }),
1187
1412
  /* @__PURE__ */ jsx(
1188
1413
  OptionCards,
1189
1414
  {
@@ -1191,7 +1416,7 @@ function AssistantMessage({ entry, onOptionSelect, className }) {
1191
1416
  onSelect: handleOptionSelect
1192
1417
  }
1193
1418
  )
1194
- ] }) : /* @__PURE__ */ jsx(ReactMarkdown, { children: entry.content }) }) }),
1419
+ ] }) : /* @__PURE__ */ jsx(LazyMarkdown, { children: entry.content }) }) }),
1195
1420
  entry.timestamp && /* @__PURE__ */ jsx("div", { className: "text-xs text-white/40 mt-2", children: formatTimestamp(entry.timestamp) })
1196
1421
  ] })
1197
1422
  ] });
@@ -1226,7 +1451,7 @@ function ErrorMessage({ entry, className }) {
1226
1451
  ] }) })
1227
1452
  ] });
1228
1453
  }
1229
- function MessageEntry({ entry, onOptionSelect, className }) {
1454
+ function MessageEntry({ entry, onOptionSelect, defaultExpanded, className }) {
1230
1455
  switch (entry.entryType.type) {
1231
1456
  case "user_message":
1232
1457
  return /* @__PURE__ */ jsx(UserMessage, { entry, className });
@@ -1235,7 +1460,7 @@ function MessageEntry({ entry, onOptionSelect, className }) {
1235
1460
  case "thinking":
1236
1461
  return /* @__PURE__ */ jsx(ThinkingMessage, { entry, className });
1237
1462
  case "tool_call":
1238
- return /* @__PURE__ */ jsx(ToolCallMessage, { entry, className });
1463
+ return /* @__PURE__ */ jsx(ToolCallMessage, { entry, defaultExpanded, className });
1239
1464
  case "error":
1240
1465
  return /* @__PURE__ */ jsx(ErrorMessage, { entry, className });
1241
1466
  default:
@@ -1297,282 +1522,429 @@ function StreamingText({
1297
1522
  className
1298
1523
  }) {
1299
1524
  return /* @__PURE__ */ jsx("div", { className: cn("relative", className), children: renderMarkdown ? /* @__PURE__ */ jsxs("div", { className: "ash-message-content prose prose-sm prose-invert max-w-none text-sm leading-relaxed", children: [
1300
- /* @__PURE__ */ jsx(ReactMarkdown, { children: content }),
1525
+ /* @__PURE__ */ jsx(LazyMarkdown, { children: content }),
1301
1526
  isStreaming && /* @__PURE__ */ jsx(LoadingIndicator, { variant: "cursor", size: "sm", className: "inline-block ml-0.5" })
1302
1527
  ] }) : /* @__PURE__ */ jsxs("p", { className: "whitespace-pre-wrap text-sm leading-relaxed", children: [
1303
1528
  content,
1304
1529
  isStreaming && /* @__PURE__ */ jsx(LoadingIndicator, { variant: "cursor", size: "sm", className: "inline-block ml-0.5" })
1305
1530
  ] }) });
1306
1531
  }
1307
- function CompactToolStatusLine({
1308
- toolCall,
1309
- previousToolCall,
1310
- animationDuration = 300,
1311
- className
1312
- }) {
1313
- const [isAnimating, setIsAnimating] = useState(false);
1314
- const [displayedToolCall, setDisplayedToolCall] = useState(toolCall);
1315
- const [exitingToolCall, setExitingToolCall] = useState(null);
1316
- const prevToolCallRef = useRef(null);
1317
- useEffect(() => {
1318
- if (toolCall.id !== prevToolCallRef.current) {
1319
- if (prevToolCallRef.current !== null && previousToolCall) {
1320
- setExitingToolCall(previousToolCall);
1321
- setIsAnimating(true);
1322
- const timer = setTimeout(() => {
1323
- setDisplayedToolCall(toolCall);
1324
- setExitingToolCall(null);
1325
- setIsAnimating(false);
1326
- }, animationDuration);
1327
- prevToolCallRef.current = toolCall.id;
1328
- return () => clearTimeout(timer);
1329
- } else {
1330
- setDisplayedToolCall(toolCall);
1331
- prevToolCallRef.current = toolCall.id;
1532
+ function getFilePath(actionType) {
1533
+ switch (actionType.action) {
1534
+ case "file_read":
1535
+ case "file_edit":
1536
+ case "file_write":
1537
+ return actionType.path;
1538
+ default:
1539
+ return null;
1540
+ }
1541
+ }
1542
+ function getFileName(path) {
1543
+ const parts = path.split("/");
1544
+ return parts[parts.length - 1] || path;
1545
+ }
1546
+ function getFileExtension(path) {
1547
+ const fileName = getFileName(path);
1548
+ const dotIndex = fileName.lastIndexOf(".");
1549
+ if (dotIndex === -1) return null;
1550
+ return fileName.slice(dotIndex + 1).toLowerCase();
1551
+ }
1552
+ function getDiffStats(actionType) {
1553
+ switch (actionType.action) {
1554
+ case "file_edit": {
1555
+ const edit = actionType;
1556
+ if (edit.linesAdded !== void 0 || edit.linesRemoved !== void 0) {
1557
+ return { added: edit.linesAdded, removed: edit.linesRemoved };
1332
1558
  }
1333
- } else {
1334
- setDisplayedToolCall(toolCall);
1559
+ return null;
1335
1560
  }
1336
- return void 0;
1337
- }, [toolCall, previousToolCall, animationDuration]);
1338
- const statusClasses = {
1339
- pending: "border-yellow-500/30",
1340
- success: "border-[var(--ash-accent)]/30",
1341
- failed: "border-red-500/30"
1342
- };
1343
- const renderToolCallContent = (tc, isExiting) => /* @__PURE__ */ jsxs(
1561
+ case "file_read": {
1562
+ const read = actionType;
1563
+ if (read.linesRead !== void 0) {
1564
+ return { read: read.linesRead };
1565
+ }
1566
+ return null;
1567
+ }
1568
+ case "file_write": {
1569
+ const write = actionType;
1570
+ if (write.linesWritten !== void 0) {
1571
+ return { written: write.linesWritten };
1572
+ }
1573
+ return null;
1574
+ }
1575
+ default:
1576
+ return null;
1577
+ }
1578
+ }
1579
+ function getFileTypeColor(ext) {
1580
+ switch (ext) {
1581
+ case "ts":
1582
+ case "tsx":
1583
+ return "text-blue-400";
1584
+ case "js":
1585
+ case "jsx":
1586
+ return "text-yellow-400";
1587
+ case "md":
1588
+ return "text-white/60";
1589
+ case "json":
1590
+ return "text-orange-400";
1591
+ case "sh":
1592
+ return "text-green-400";
1593
+ case "css":
1594
+ case "scss":
1595
+ return "text-pink-400";
1596
+ case "py":
1597
+ return "text-blue-300";
1598
+ default:
1599
+ return "text-white/70";
1600
+ }
1601
+ }
1602
+ function CompactToolRow({ toolCall, showFullPath = false, className }) {
1603
+ const { actionType, status, summary } = toolCall;
1604
+ const label = getActionLabel(actionType);
1605
+ const filePath = getFilePath(actionType);
1606
+ const diffStats = getDiffStats(actionType);
1607
+ const displayPath = filePath ? showFullPath ? filePath : getFileName(filePath) : null;
1608
+ const ext = filePath ? getFileExtension(filePath) : null;
1609
+ const fileColor = getFileTypeColor(ext);
1610
+ const showSummary = !filePath && summary;
1611
+ return /* @__PURE__ */ jsxs(
1344
1612
  "div",
1345
1613
  {
1346
1614
  className: cn(
1347
- "flex items-center gap-3 px-4 py-2.5",
1348
- isExiting ? "ash-status-line-exit" : isAnimating ? "ash-status-line-enter" : ""
1615
+ "flex items-center gap-2 py-1.5 text-sm min-w-0",
1616
+ className
1349
1617
  ),
1350
- style: {
1351
- animationDuration: `${animationDuration}ms`
1352
- },
1353
1618
  children: [
1354
- /* @__PURE__ */ jsx(
1355
- "div",
1356
- {
1357
- className: cn(
1358
- "w-6 h-6 rounded-lg flex items-center justify-center shrink-0",
1359
- tc.status === "pending" ? "bg-yellow-500/20" : tc.status === "failed" ? "bg-red-500/20" : "bg-[var(--ash-accent)]/20"
1360
- ),
1361
- children: /* @__PURE__ */ jsx(
1362
- ActionIcon,
1363
- {
1364
- actionType: tc.actionType,
1365
- className: cn(
1366
- "w-3.5 h-3.5",
1367
- tc.status === "pending" ? "text-yellow-400" : tc.status === "failed" ? "text-red-400" : "text-[var(--ash-accent)]"
1368
- )
1369
- }
1370
- )
1371
- }
1372
- ),
1373
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-white shrink-0", children: getActionLabel(tc.actionType) }),
1374
- /* @__PURE__ */ jsx("span", { className: "font-mono text-sm truncate text-white/60 flex-1 min-w-0", children: tc.summary }),
1375
- /* @__PURE__ */ jsx(StatusIndicator, { status: tc.status, size: "sm" })
1619
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 shrink-0", children: [
1620
+ /* @__PURE__ */ jsx(
1621
+ ActionIcon,
1622
+ {
1623
+ actionType,
1624
+ className: cn(
1625
+ "w-3.5 h-3.5",
1626
+ status === "pending" ? "text-yellow-400" : status === "failed" ? "text-red-400" : "text-white/50"
1627
+ )
1628
+ }
1629
+ ),
1630
+ /* @__PURE__ */ jsx("span", { className: cn(
1631
+ "font-medium",
1632
+ status === "pending" ? "text-white/90" : status === "failed" ? "text-red-400" : "text-white/60"
1633
+ ), children: label })
1634
+ ] }),
1635
+ displayPath && /* @__PURE__ */ jsx("code", { className: cn(
1636
+ "px-1.5 py-0.5 rounded bg-white/5 font-mono text-xs truncate max-w-[200px]",
1637
+ fileColor
1638
+ ), children: displayPath }),
1639
+ diffStats && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs shrink-0 font-mono", children: [
1640
+ diffStats.added !== void 0 && diffStats.added > 0 && /* @__PURE__ */ jsxs("span", { className: "text-emerald-400", children: [
1641
+ "+",
1642
+ diffStats.added
1643
+ ] }),
1644
+ diffStats.removed !== void 0 && diffStats.removed > 0 && /* @__PURE__ */ jsxs("span", { className: "text-red-400", children: [
1645
+ "-",
1646
+ diffStats.removed
1647
+ ] }),
1648
+ diffStats.read !== void 0 && /* @__PURE__ */ jsxs("span", { className: "text-white/40", children: [
1649
+ diffStats.read,
1650
+ " lines"
1651
+ ] }),
1652
+ diffStats.written !== void 0 && /* @__PURE__ */ jsxs("span", { className: "text-emerald-400", children: [
1653
+ "+",
1654
+ diffStats.written
1655
+ ] })
1656
+ ] }),
1657
+ showSummary && /* @__PURE__ */ jsx("span", { className: "text-white/40 truncate min-w-0 text-xs", children: summary })
1376
1658
  ]
1377
1659
  }
1378
1660
  );
1661
+ }
1662
+ function getFileExtension2(path) {
1663
+ const fileName = path.split("/").pop() || path;
1664
+ const dotIndex = fileName.lastIndexOf(".");
1665
+ if (dotIndex === -1) return null;
1666
+ return fileName.slice(dotIndex + 1).toLowerCase();
1667
+ }
1668
+ function getFileIcon(ext) {
1669
+ switch (ext) {
1670
+ case "ts":
1671
+ case "tsx":
1672
+ return "TS";
1673
+ case "js":
1674
+ case "jsx":
1675
+ return "JS";
1676
+ case "md":
1677
+ return "MD";
1678
+ case "json":
1679
+ return "{}";
1680
+ case "sh":
1681
+ return "$";
1682
+ case "css":
1683
+ case "scss":
1684
+ return "#";
1685
+ case "py":
1686
+ return "PY";
1687
+ default:
1688
+ return "";
1689
+ }
1690
+ }
1691
+ function getFileBgColor(ext) {
1692
+ switch (ext) {
1693
+ case "ts":
1694
+ case "tsx":
1695
+ return "bg-blue-500/20";
1696
+ case "js":
1697
+ case "jsx":
1698
+ return "bg-yellow-500/20";
1699
+ case "md":
1700
+ return "bg-white/10";
1701
+ case "json":
1702
+ return "bg-orange-500/20";
1703
+ case "sh":
1704
+ return "bg-green-500/20";
1705
+ case "css":
1706
+ case "scss":
1707
+ return "bg-pink-500/20";
1708
+ case "py":
1709
+ return "bg-blue-400/20";
1710
+ default:
1711
+ return "bg-white/10";
1712
+ }
1713
+ }
1714
+ function FileBadge({
1715
+ path,
1716
+ linesAdded,
1717
+ linesRemoved,
1718
+ showOnlyFilename = true,
1719
+ className
1720
+ }) {
1721
+ const fileName = showOnlyFilename ? path.split("/").pop() || path : path;
1722
+ const ext = getFileExtension2(path);
1723
+ const icon = getFileIcon(ext);
1724
+ const bgColor = getFileBgColor(ext);
1725
+ const hasDiff = linesAdded !== void 0 && linesAdded > 0 || linesRemoved !== void 0 && linesRemoved > 0;
1379
1726
  return /* @__PURE__ */ jsxs(
1380
- "div",
1727
+ "span",
1381
1728
  {
1382
1729
  className: cn(
1383
- "relative rounded-xl border bg-[var(--ash-surface-dark,#0a0a0a)] overflow-hidden",
1384
- statusClasses[displayedToolCall.status],
1385
- displayedToolCall.status === "pending" && "ash-tool-status-pending",
1730
+ "inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md text-xs font-mono",
1731
+ bgColor,
1386
1732
  className
1387
1733
  ),
1388
1734
  children: [
1389
- exitingToolCall && /* @__PURE__ */ jsx("div", { className: "absolute inset-0", children: renderToolCallContent(exitingToolCall, true) }),
1390
- renderToolCallContent(displayedToolCall, false)
1735
+ icon && /* @__PURE__ */ jsx("span", { className: "text-[10px] opacity-60 font-semibold", children: icon }),
1736
+ /* @__PURE__ */ jsx("span", { className: "text-white/80 truncate max-w-[120px]", children: fileName }),
1737
+ hasDiff && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-0.5", children: [
1738
+ linesAdded !== void 0 && linesAdded > 0 && /* @__PURE__ */ jsxs("span", { className: "text-emerald-400", children: [
1739
+ "+",
1740
+ linesAdded
1741
+ ] }),
1742
+ linesRemoved !== void 0 && linesRemoved > 0 && /* @__PURE__ */ jsxs("span", { className: "text-red-400", children: [
1743
+ "-",
1744
+ linesRemoved
1745
+ ] })
1746
+ ] })
1391
1747
  ]
1392
1748
  }
1393
1749
  );
1394
1750
  }
1395
- function calculateGroupStatus(toolCalls) {
1396
- const hasPending = toolCalls.some((tc) => tc.status === "pending");
1397
- const hasFailed = toolCalls.some((tc) => tc.status === "failed");
1398
- const allSuccess = toolCalls.every((tc) => tc.status === "success");
1399
- if (hasPending) return "pending";
1400
- if (allSuccess) return "success";
1401
- if (hasFailed && !hasPending) return toolCalls.some((tc) => tc.status === "success") ? "partial_failure" : "failed";
1402
- return "pending";
1751
+ function extractFileChanges(toolCalls) {
1752
+ const fileMap = /* @__PURE__ */ new Map();
1753
+ for (const tc of toolCalls) {
1754
+ const { actionType } = tc;
1755
+ if (actionType.action === "file_edit") {
1756
+ const edit = actionType;
1757
+ const existing = fileMap.get(edit.path);
1758
+ if (existing) {
1759
+ existing.linesAdded = (existing.linesAdded || 0) + (edit.linesAdded || 0);
1760
+ existing.linesRemoved = (existing.linesRemoved || 0) + (edit.linesRemoved || 0);
1761
+ } else {
1762
+ fileMap.set(edit.path, {
1763
+ path: edit.path,
1764
+ linesAdded: edit.linesAdded,
1765
+ linesRemoved: edit.linesRemoved
1766
+ });
1767
+ }
1768
+ } else if (actionType.action === "file_write") {
1769
+ const write = actionType;
1770
+ if (!fileMap.has(write.path)) {
1771
+ fileMap.set(write.path, {
1772
+ path: write.path,
1773
+ linesAdded: write.linesWritten
1774
+ });
1775
+ }
1776
+ }
1777
+ }
1778
+ return Array.from(fileMap.values());
1779
+ }
1780
+ function countActionTypes(toolCalls) {
1781
+ const counts = {};
1782
+ for (const tc of toolCalls) {
1783
+ const action = tc.actionType.action;
1784
+ counts[action] = (counts[action] || 0) + 1;
1785
+ }
1786
+ return counts;
1787
+ }
1788
+ function getActionIconComponent(action) {
1789
+ switch (action) {
1790
+ case "file_read":
1791
+ return FileIcon;
1792
+ case "file_edit":
1793
+ case "file_write":
1794
+ return EditIcon;
1795
+ case "command_run":
1796
+ return TerminalIcon;
1797
+ case "search":
1798
+ case "glob":
1799
+ return SearchIcon;
1800
+ default:
1801
+ return null;
1802
+ }
1403
1803
  }
1404
1804
  function ToolExecutionGroup({
1405
1805
  toolCalls,
1406
1806
  defaultExpanded = false,
1407
- animationDuration = 300,
1408
1807
  className
1409
1808
  }) {
1410
1809
  const [expanded, setExpanded] = useState(defaultExpanded);
1411
- const activeToolCall = toolCalls[toolCalls.length - 1];
1412
- const previousToolCall = toolCalls.length > 1 ? toolCalls[toolCalls.length - 2] : null;
1413
- const groupStatus = useMemo(() => calculateGroupStatus(toolCalls), [toolCalls]);
1414
- const completedCount = toolCalls.filter((tc) => tc.status === "success").length;
1415
- const failedCount = toolCalls.filter((tc) => tc.status === "failed").length;
1810
+ const [expandedCardId, setExpandedCardId] = useState(null);
1811
+ const fileChanges = useMemo(() => extractFileChanges(toolCalls), [toolCalls]);
1812
+ const actionCounts = useMemo(() => countActionTypes(toolCalls), [toolCalls]);
1813
+ const displayActions = useMemo(() => {
1814
+ return Object.entries(actionCounts).sort((a, b) => b[1] - a[1]).slice(0, 3).map(([action]) => action);
1815
+ }, [actionCounts]);
1416
1816
  const totalCount = toolCalls.length;
1417
- if (!activeToolCall) {
1817
+ if (toolCalls.length === 0) {
1418
1818
  return null;
1419
1819
  }
1420
- const borderClasses = {
1421
- pending: "border-yellow-500/30",
1422
- success: "border-[var(--ash-accent)]/30",
1423
- partial_failure: "border-orange-500/30",
1424
- failed: "border-red-500/30"
1425
- };
1426
- return /* @__PURE__ */ jsxs(
1427
- "div",
1428
- {
1429
- className: cn(
1430
- "rounded-xl border bg-[var(--ash-surface-dark,#0a0a0a)] overflow-hidden ash-animate-fade-in",
1431
- borderClasses[groupStatus],
1432
- groupStatus === "pending" && "ash-tool-status-pending",
1433
- className
1434
- ),
1435
- children: [
1436
- /* @__PURE__ */ jsx(
1437
- "button",
1438
- {
1439
- onClick: () => setExpanded(!expanded),
1440
- className: cn(
1441
- "w-full transition-colors hover:bg-white/5 cursor-pointer"
1442
- ),
1443
- children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1444
- /* @__PURE__ */ jsx(
1445
- CompactToolStatusLine,
1446
- {
1447
- toolCall: activeToolCall,
1448
- previousToolCall,
1449
- animationDuration,
1450
- className: "border-0 rounded-none"
1451
- }
1452
- ),
1453
- /* @__PURE__ */ jsxs("div", { className: "absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-2", children: [
1454
- totalCount > 1 && /* @__PURE__ */ jsx(
1455
- "div",
1456
- {
1457
- className: cn(
1458
- "flex items-center gap-1.5 px-2 py-0.5 rounded-full text-xs font-medium",
1459
- groupStatus === "pending" ? "bg-yellow-500/20 text-yellow-400" : groupStatus === "success" ? "bg-[var(--ash-accent)]/20 text-[var(--ash-accent)]" : groupStatus === "failed" ? "bg-red-500/20 text-red-400" : "bg-orange-500/20 text-orange-400"
1460
- ),
1461
- children: groupStatus === "pending" ? /* @__PURE__ */ jsxs("span", { children: [
1462
- completedCount,
1463
- "/",
1464
- totalCount
1465
- ] }) : failedCount > 0 ? /* @__PURE__ */ jsxs("span", { children: [
1466
- completedCount,
1467
- " ok, ",
1468
- failedCount,
1469
- " failed"
1470
- ] }) : /* @__PURE__ */ jsxs("span", { children: [
1471
- totalCount,
1472
- " tools"
1473
- ] })
1474
- }
1475
- ),
1476
- /* @__PURE__ */ jsx(
1477
- ChevronDownIcon,
1478
- {
1479
- className: cn(
1480
- "w-4 h-4 text-white/40 transition-transform duration-200",
1481
- expanded && "rotate-180"
1482
- )
1483
- }
1484
- )
1485
- ] })
1486
- ] })
1487
- }
1488
- ),
1489
- expanded && /* @__PURE__ */ jsxs("div", { className: "border-t border-white/5 bg-black/20", children: [
1490
- /* @__PURE__ */ jsx("div", { className: "p-3 space-y-2", children: toolCalls.map((toolCall, index) => /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1491
- index < toolCalls.length - 1 && /* @__PURE__ */ jsx("div", { className: "absolute left-[19px] top-10 bottom-0 w-px bg-white/10" }),
1492
- /* @__PURE__ */ jsx(
1493
- ToolCallCard,
1494
- {
1495
- toolCall,
1496
- defaultExpanded: false,
1497
- className: "relative z-10"
1498
- }
1499
- )
1500
- ] }, toolCall.id)) }),
1501
- groupStatus !== "pending" && /* @__PURE__ */ jsx(
1502
- "div",
1820
+ return /* @__PURE__ */ jsxs("div", { className: cn("ash-animate-fade-in", className), children: [
1821
+ /* @__PURE__ */ jsxs(
1822
+ "button",
1823
+ {
1824
+ onClick: () => setExpanded(!expanded),
1825
+ className: "w-full flex items-center gap-2 py-1 text-left group",
1826
+ children: [
1827
+ /* @__PURE__ */ jsx(
1828
+ ChevronRightIcon,
1503
1829
  {
1504
1830
  className: cn(
1505
- "px-4 py-3 border-t border-white/5 flex items-center gap-2",
1506
- groupStatus === "success" ? "bg-[var(--ash-accent)]/5" : groupStatus === "failed" ? "bg-red-500/5" : "bg-orange-500/5"
1507
- ),
1508
- children: groupStatus === "success" ? /* @__PURE__ */ jsxs(Fragment, { children: [
1509
- /* @__PURE__ */ jsx(CheckIcon, { className: "w-4 h-4 text-[var(--ash-accent)]" }),
1510
- /* @__PURE__ */ jsxs("span", { className: "text-sm text-[var(--ash-accent)] font-medium", children: [
1511
- "All ",
1512
- totalCount,
1513
- " tool",
1514
- totalCount !== 1 ? "s" : "",
1515
- " completed successfully"
1516
- ] })
1517
- ] }) : groupStatus === "failed" ? /* @__PURE__ */ jsxs(Fragment, { children: [
1518
- /* @__PURE__ */ jsx(StatusIndicator, { status: "failed", size: "sm" }),
1519
- /* @__PURE__ */ jsxs("span", { className: "text-sm text-red-400 font-medium", children: [
1520
- failedCount,
1521
- " tool",
1522
- failedCount !== 1 ? "s" : "",
1523
- " failed"
1524
- ] })
1525
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1526
- /* @__PURE__ */ jsx(StatusIndicator, { status: "failed", size: "sm" }),
1527
- /* @__PURE__ */ jsxs("span", { className: "text-sm text-orange-400 font-medium", children: [
1528
- completedCount,
1529
- " succeeded, ",
1530
- failedCount,
1531
- " failed"
1532
- ] })
1533
- ] })
1831
+ "w-3.5 h-3.5 text-white/40 transition-transform duration-200 shrink-0",
1832
+ expanded && "rotate-90"
1833
+ )
1534
1834
  }
1535
- )
1536
- ] })
1537
- ]
1538
- }
1539
- );
1540
- }
1541
- function formatDuration(startMs, endMs) {
1542
- const duration = endMs - startMs;
1543
- if (duration < 1e3) return `${duration}ms`;
1544
- return `${(duration / 1e3).toFixed(1)}s`;
1835
+ ),
1836
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-white/60", children: [
1837
+ totalCount,
1838
+ " tool call",
1839
+ totalCount !== 1 ? "s" : ""
1840
+ ] }),
1841
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: displayActions.map((action) => {
1842
+ const IconComponent = getActionIconComponent(action);
1843
+ if (!IconComponent) return null;
1844
+ return /* @__PURE__ */ jsx(
1845
+ IconComponent,
1846
+ {
1847
+ className: "w-3.5 h-3.5 text-white/30"
1848
+ },
1849
+ action
1850
+ );
1851
+ }) }),
1852
+ /* @__PURE__ */ jsx("div", { className: "flex-1" }),
1853
+ !expanded && fileChanges.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 flex-wrap justify-end", children: [
1854
+ fileChanges.slice(0, 4).map((fc) => /* @__PURE__ */ jsx(
1855
+ FileBadge,
1856
+ {
1857
+ path: fc.path,
1858
+ linesAdded: fc.linesAdded,
1859
+ linesRemoved: fc.linesRemoved
1860
+ },
1861
+ fc.path
1862
+ )),
1863
+ fileChanges.length > 4 && /* @__PURE__ */ jsxs("span", { className: "text-xs text-white/40", children: [
1864
+ "+",
1865
+ fileChanges.length - 4,
1866
+ " more"
1867
+ ] })
1868
+ ] })
1869
+ ]
1870
+ }
1871
+ ),
1872
+ expanded && /* @__PURE__ */ jsx("div", { className: "pl-5 border-l border-white/10 ml-1.5 mt-1 space-y-0.5", children: toolCalls.map((toolCall) => /* @__PURE__ */ jsx("div", { children: expandedCardId === toolCall.id ? /* @__PURE__ */ jsxs("div", { className: "py-1", children: [
1873
+ /* @__PURE__ */ jsx(
1874
+ ToolCallCard,
1875
+ {
1876
+ toolCall,
1877
+ defaultExpanded: true
1878
+ }
1879
+ ),
1880
+ /* @__PURE__ */ jsx(
1881
+ "button",
1882
+ {
1883
+ onClick: () => setExpandedCardId(null),
1884
+ className: "text-xs text-white/40 hover:text-white/60 mt-1 pl-1",
1885
+ children: "Collapse"
1886
+ }
1887
+ )
1888
+ ] }) : /* @__PURE__ */ jsx(
1889
+ "button",
1890
+ {
1891
+ onClick: () => setExpandedCardId(toolCall.id),
1892
+ className: "w-full text-left hover:bg-white/5 rounded px-1 -mx-1 transition-colors",
1893
+ children: /* @__PURE__ */ jsx(CompactToolRow, { toolCall })
1894
+ }
1895
+ ) }, toolCall.id)) })
1896
+ ] });
1545
1897
  }
1546
- function getToolLabel(toolName, summary) {
1547
- if (summary && summary.length > 0 && summary.length < 50) {
1548
- return summary;
1898
+ function extractFileChanges2(toolCalls) {
1899
+ const fileMap = /* @__PURE__ */ new Map();
1900
+ for (const tc of toolCalls) {
1901
+ const { actionType } = tc;
1902
+ if (actionType.action === "file_edit") {
1903
+ const edit = actionType;
1904
+ const existing = fileMap.get(edit.path);
1905
+ if (existing) {
1906
+ existing.linesAdded = (existing.linesAdded || 0) + (edit.linesAdded || 0);
1907
+ existing.linesRemoved = (existing.linesRemoved || 0) + (edit.linesRemoved || 0);
1908
+ } else {
1909
+ fileMap.set(edit.path, {
1910
+ path: edit.path,
1911
+ linesAdded: edit.linesAdded,
1912
+ linesRemoved: edit.linesRemoved
1913
+ });
1914
+ }
1915
+ } else if (actionType.action === "file_write") {
1916
+ if (!fileMap.has(actionType.path)) {
1917
+ fileMap.set(actionType.path, {
1918
+ path: actionType.path,
1919
+ linesAdded: actionType.linesWritten
1920
+ });
1921
+ }
1922
+ }
1549
1923
  }
1550
- const cleaned = toolName.replace(/^mcp__[^_]+__/, "").replace(/Tool$/, "").replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2");
1551
- return cleaned.charAt(0).toUpperCase() + cleaned.slice(1);
1924
+ return Array.from(fileMap.values());
1552
1925
  }
1553
- function toStepStatus(status) {
1554
- switch (status) {
1555
- case "pending":
1556
- return "running";
1557
- case "success":
1558
- return "success";
1559
- case "failed":
1560
- return "error";
1561
- default:
1562
- return "pending";
1926
+ function countActionTypes2(toolCalls) {
1927
+ const counts = {};
1928
+ for (const tc of toolCalls) {
1929
+ const action = tc.actionType.action;
1930
+ counts[action] = (counts[action] || 0) + 1;
1563
1931
  }
1932
+ return counts;
1564
1933
  }
1565
- function StepIcon({ status }) {
1566
- const iconClass = "w-3.5 h-3.5";
1567
- switch (status) {
1568
- case "running":
1569
- return /* @__PURE__ */ jsx(SpinnerIcon, { className: cn(iconClass, "animate-spin text-[var(--ash-accent)]") });
1570
- case "success":
1571
- return /* @__PURE__ */ jsx(CheckIcon, { className: cn(iconClass, "text-[var(--ash-accent)]") });
1572
- case "error":
1573
- return /* @__PURE__ */ jsx(ErrorIcon, { className: cn(iconClass, "text-red-500") });
1934
+ function getActionIconComponent2(action) {
1935
+ switch (action) {
1936
+ case "file_read":
1937
+ return FileIcon;
1938
+ case "file_edit":
1939
+ case "file_write":
1940
+ return EditIcon;
1941
+ case "command_run":
1942
+ return TerminalIcon;
1943
+ case "search":
1944
+ case "glob":
1945
+ return SearchIcon;
1574
1946
  default:
1575
- return /* @__PURE__ */ jsx(ToolIcon, { className: cn(iconClass, "text-white/40") });
1947
+ return null;
1576
1948
  }
1577
1949
  }
1578
1950
  function StepAccordion({
@@ -1591,109 +1963,70 @@ function StepAccordion({
1591
1963
  setInternalExpanded((prev) => !prev);
1592
1964
  }
1593
1965
  }, [onToggle]);
1966
+ const fileChanges = useMemo(() => extractFileChanges2(toolCalls), [toolCalls]);
1967
+ const actionCounts = useMemo(() => countActionTypes2(toolCalls), [toolCalls]);
1968
+ const displayActions = useMemo(() => {
1969
+ return Object.entries(actionCounts).sort((a, b) => b[1] - a[1]).slice(0, 3).map(([action]) => action);
1970
+ }, [actionCounts]);
1594
1971
  if (toolCalls.length === 0) {
1595
1972
  return null;
1596
1973
  }
1597
- const completedSteps = toolCalls.filter((tc) => tc.status === "success" || tc.status === "failed").length;
1598
- const runningStep = toolCalls.find((tc) => tc.status === "pending");
1599
- const hasError = toolCalls.some((tc) => tc.status === "failed");
1600
- const allComplete = completedSteps === toolCalls.length;
1601
- return /* @__PURE__ */ jsxs(
1602
- "div",
1603
- {
1604
- className: cn(
1605
- "rounded-xl border overflow-hidden",
1606
- hasError ? "border-red-500/30" : allComplete ? "border-[var(--ash-accent)]/30" : "border-yellow-500/30",
1607
- className
1608
- ),
1609
- children: [
1610
- /* @__PURE__ */ jsxs(
1611
- "button",
1612
- {
1613
- type: "button",
1614
- onClick: handleToggle,
1615
- className: "w-full flex items-center gap-2 px-3 py-2 bg-white/5 hover:bg-white/10 transition-colors text-left cursor-pointer",
1616
- children: [
1617
- /* @__PURE__ */ jsx(
1618
- ChevronDownIcon,
1619
- {
1620
- className: cn(
1621
- "w-4 h-4 text-white/40 transition-transform duration-200 flex-shrink-0",
1622
- !isExpanded && "-rotate-90"
1623
- )
1624
- }
1625
- ),
1626
- /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0 flex items-center gap-2", children: runningStep ? /* @__PURE__ */ jsxs(Fragment, { children: [
1627
- /* @__PURE__ */ jsx(SpinnerIcon, { className: "w-3.5 h-3.5 animate-spin text-[var(--ash-accent)] flex-shrink-0" }),
1628
- /* @__PURE__ */ jsx("span", { className: "text-sm text-white/80 truncate", children: getToolLabel(runningStep.toolName, runningStep.summary) })
1629
- ] }) : hasError ? /* @__PURE__ */ jsxs(Fragment, { children: [
1630
- /* @__PURE__ */ jsx(ErrorIcon, { className: "w-3.5 h-3.5 text-red-500 flex-shrink-0" }),
1631
- /* @__PURE__ */ jsx("span", { className: "text-sm text-red-400 truncate", children: "Completed with errors" })
1632
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1633
- /* @__PURE__ */ jsx(CheckIcon, { className: "w-3.5 h-3.5 text-[var(--ash-accent)] flex-shrink-0" }),
1634
- /* @__PURE__ */ jsxs("span", { className: "text-sm text-white/70 truncate", children: [
1635
- completedSteps,
1636
- " step",
1637
- completedSteps !== 1 ? "s" : "",
1638
- " completed"
1639
- ] })
1640
- ] }) }),
1641
- /* @__PURE__ */ jsxs("span", { className: "text-xs px-1.5 py-0.5 rounded-full bg-white/10 text-white/50 flex-shrink-0", children: [
1642
- completedSteps,
1643
- "/",
1644
- toolCalls.length
1645
- ] })
1646
- ]
1647
- }
1648
- ),
1649
- isExpanded && /* @__PURE__ */ jsx("div", { className: "border-t border-white/10 ash-accordion-content", children: /* @__PURE__ */ jsx("div", { className: "divide-y divide-white/5", children: toolCalls.map((toolCall, index) => {
1650
- const stepStatus = toStepStatus(toolCall.status);
1651
- const startTime = toolCall.startedAt ? new Date(toolCall.startedAt).getTime() : 0;
1652
- const endTime = toolCall.completedAt ? new Date(toolCall.completedAt).getTime() : 0;
1653
- const hasDuration = startTime > 0 && endTime > 0;
1654
- return /* @__PURE__ */ jsxs(
1655
- "div",
1974
+ const totalCount = toolCalls.length;
1975
+ return /* @__PURE__ */ jsxs("div", { className: cn("ash-animate-fade-in", className), children: [
1976
+ /* @__PURE__ */ jsxs(
1977
+ "button",
1978
+ {
1979
+ type: "button",
1980
+ onClick: handleToggle,
1981
+ className: "w-full flex items-center gap-2 py-1 text-left group",
1982
+ children: [
1983
+ /* @__PURE__ */ jsx(
1984
+ ChevronRightIcon,
1656
1985
  {
1657
1986
  className: cn(
1658
- "px-3 py-2 flex items-start gap-2",
1659
- stepStatus === "running" && "bg-[var(--ash-accent)]/5",
1660
- stepStatus === "error" && "bg-red-500/5"
1661
- ),
1662
- children: [
1663
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 flex-shrink-0 pt-0.5", children: [
1664
- /* @__PURE__ */ jsxs("span", { className: "text-xs text-white/40 w-4 text-right", children: [
1665
- index + 1,
1666
- "."
1667
- ] }),
1668
- /* @__PURE__ */ jsx(StepIcon, { status: stepStatus })
1669
- ] }),
1670
- /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1671
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1672
- /* @__PURE__ */ jsx(
1673
- "span",
1674
- {
1675
- className: cn(
1676
- "text-sm",
1677
- stepStatus === "running" && "text-[var(--ash-accent)]",
1678
- stepStatus === "success" && "text-white/70",
1679
- stepStatus === "error" && "text-red-400",
1680
- stepStatus === "pending" && "text-white/40"
1681
- ),
1682
- children: getToolLabel(toolCall.toolName, toolCall.summary)
1683
- }
1684
- ),
1685
- hasDuration && (stepStatus === "success" || stepStatus === "error") && /* @__PURE__ */ jsx("span", { className: "text-xs text-white/40", children: formatDuration(startTime, endTime) })
1686
- ] }),
1687
- toolCall.isError && toolCall.actionType && "result" in toolCall.actionType && /* @__PURE__ */ jsx("p", { className: "text-xs mt-1 text-red-400/80 truncate", children: String(toolCall.actionType.result?.value || "Error") })
1688
- ] })
1689
- ]
1690
- },
1691
- toolCall.id
1692
- );
1693
- }) }) })
1694
- ]
1695
- }
1696
- );
1987
+ "w-3.5 h-3.5 text-white/40 transition-transform duration-200 shrink-0",
1988
+ isExpanded && "rotate-90"
1989
+ )
1990
+ }
1991
+ ),
1992
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-white/60", children: [
1993
+ totalCount,
1994
+ " tool call",
1995
+ totalCount !== 1 ? "s" : ""
1996
+ ] }),
1997
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: displayActions.map((action) => {
1998
+ const IconComponent = getActionIconComponent2(action);
1999
+ if (!IconComponent) return null;
2000
+ return /* @__PURE__ */ jsx(
2001
+ IconComponent,
2002
+ {
2003
+ className: "w-3.5 h-3.5 text-white/30"
2004
+ },
2005
+ action
2006
+ );
2007
+ }) }),
2008
+ /* @__PURE__ */ jsx("div", { className: "flex-1" }),
2009
+ !isExpanded && fileChanges.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 flex-wrap justify-end", children: [
2010
+ fileChanges.slice(0, 4).map((fc) => /* @__PURE__ */ jsx(
2011
+ FileBadge,
2012
+ {
2013
+ path: fc.path,
2014
+ linesAdded: fc.linesAdded,
2015
+ linesRemoved: fc.linesRemoved
2016
+ },
2017
+ fc.path
2018
+ )),
2019
+ fileChanges.length > 4 && /* @__PURE__ */ jsxs("span", { className: "text-xs text-white/40", children: [
2020
+ "+",
2021
+ fileChanges.length - 4,
2022
+ " more"
2023
+ ] })
2024
+ ] })
2025
+ ]
2026
+ }
2027
+ ),
2028
+ isExpanded && /* @__PURE__ */ jsx("div", { className: "pl-5 border-l border-white/10 ml-1.5 mt-1 space-y-0.5", children: toolCalls.map((toolCall) => /* @__PURE__ */ jsx(CompactToolRow, { toolCall }, toolCall.id)) })
2029
+ ] });
1697
2030
  }
1698
2031
 
1699
2032
  // src/types.ts
@@ -1730,6 +2063,9 @@ function isGenericToolAction(action) {
1730
2063
  function isTodoWriteAction(action) {
1731
2064
  return action.action === "todo_write";
1732
2065
  }
2066
+ function isAgentToolAction(action) {
2067
+ return action.action === "agent_tool";
2068
+ }
1733
2069
  function isToolCallEntry(entry) {
1734
2070
  return entry.type === "tool_call";
1735
2071
  }
@@ -1796,10 +2132,18 @@ function MessageList({
1796
2132
  onOptionSelect,
1797
2133
  renderWidget,
1798
2134
  onWidgetAction,
2135
+ autoScroll = true,
1799
2136
  className
1800
2137
  }) {
1801
2138
  const contextConfig = useDisplayConfig();
1802
2139
  const config = displayConfigProp || contextConfig;
2140
+ const containerRef = useRef(null);
2141
+ const messagesEndRef = useRef(null);
2142
+ useEffect(() => {
2143
+ if (autoScroll && messagesEndRef.current && containerRef.current) {
2144
+ messagesEndRef.current.scrollIntoView({ behavior: "smooth", block: "end" });
2145
+ }
2146
+ }, [entries, streamingContent, loading, autoScroll]);
1803
2147
  const createWidgetActionHandler = useCallback(
1804
2148
  (entryId, widgetType) => {
1805
2149
  if (!onWidgetAction) return void 0;
@@ -1823,7 +2167,7 @@ function MessageList({
1823
2167
  }
1824
2168
  return groupEntriesForCompactMode(entries, config);
1825
2169
  }, [entries, config]);
1826
- return /* @__PURE__ */ jsxs("div", { className: cn("flex-1 overflow-y-auto p-4 space-y-4 ash-scrollbar", className), children: [
2170
+ return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: cn("flex-1 overflow-y-auto p-4 space-y-4 ash-scrollbar", className), children: [
1827
2171
  groupedEntries.map((groupedEntry) => {
1828
2172
  if (groupedEntry.type === "single") {
1829
2173
  const entry = groupedEntry.entry;
@@ -1839,7 +2183,7 @@ function MessageList({
1839
2183
  return /* @__PURE__ */ jsx("div", { className: "ash-animate-fade-in", children: widgetContent }, entry.id);
1840
2184
  }
1841
2185
  }
1842
- return /* @__PURE__ */ jsx(MessageEntry, { entry, onOptionSelect }, entry.id);
2186
+ return /* @__PURE__ */ jsx(MessageEntry, { entry, onOptionSelect, defaultExpanded: config.defaultExpanded }, entry.id);
1843
2187
  }
1844
2188
  const toolCalls = extractToolCallsFromGroup(groupedEntry.entries);
1845
2189
  return /* @__PURE__ */ jsxs("div", { className: "flex gap-3 ash-animate-fade-in", children: [
@@ -1867,7 +2211,8 @@ function MessageList({
1867
2211
  loading && !streamingContent && /* @__PURE__ */ jsxs("div", { className: "flex gap-3 ash-animate-fade-in", children: [
1868
2212
  /* @__PURE__ */ jsx("div", { className: "w-7 h-7 rounded-full bg-[var(--ash-accent)]/20 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsx(BotIcon, { className: "w-4 h-4 text-[var(--ash-accent)]" }) }),
1869
2213
  /* @__PURE__ */ jsx("div", { className: "rounded-xl p-3 bg-white/5", children: /* @__PURE__ */ jsx(LoadingIndicator, { variant: "dots" }) })
1870
- ] })
2214
+ ] }),
2215
+ /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
1871
2216
  ] });
1872
2217
  }
1873
2218
  function getLevelIcon(level) {
@@ -2014,6 +2359,94 @@ function LogsPanel({
2014
2359
  }
2015
2360
  );
2016
2361
  }
2362
+ function CompactToolStatusLine({
2363
+ toolCall,
2364
+ previousToolCall,
2365
+ animationDuration = 300,
2366
+ className
2367
+ }) {
2368
+ const [isAnimating, setIsAnimating] = useState(false);
2369
+ const [displayedToolCall, setDisplayedToolCall] = useState(toolCall);
2370
+ const [exitingToolCall, setExitingToolCall] = useState(null);
2371
+ const prevToolCallRef = useRef(null);
2372
+ useEffect(() => {
2373
+ if (toolCall.id !== prevToolCallRef.current) {
2374
+ if (prevToolCallRef.current !== null && previousToolCall) {
2375
+ setExitingToolCall(previousToolCall);
2376
+ setIsAnimating(true);
2377
+ const timer = setTimeout(() => {
2378
+ setDisplayedToolCall(toolCall);
2379
+ setExitingToolCall(null);
2380
+ setIsAnimating(false);
2381
+ }, animationDuration);
2382
+ prevToolCallRef.current = toolCall.id;
2383
+ return () => clearTimeout(timer);
2384
+ } else {
2385
+ setDisplayedToolCall(toolCall);
2386
+ prevToolCallRef.current = toolCall.id;
2387
+ }
2388
+ } else {
2389
+ setDisplayedToolCall(toolCall);
2390
+ }
2391
+ return void 0;
2392
+ }, [toolCall, previousToolCall, animationDuration]);
2393
+ const statusClasses = {
2394
+ pending: "border-yellow-500/30",
2395
+ success: "border-[var(--ash-accent)]/30",
2396
+ failed: "border-red-500/30"
2397
+ };
2398
+ const renderToolCallContent = (tc, isExiting) => /* @__PURE__ */ jsxs(
2399
+ "div",
2400
+ {
2401
+ className: cn(
2402
+ "flex items-center gap-3 px-4 py-2.5",
2403
+ isExiting ? "ash-status-line-exit" : isAnimating ? "ash-status-line-enter" : ""
2404
+ ),
2405
+ style: {
2406
+ animationDuration: `${animationDuration}ms`
2407
+ },
2408
+ children: [
2409
+ /* @__PURE__ */ jsx(
2410
+ "div",
2411
+ {
2412
+ className: cn(
2413
+ "w-6 h-6 rounded-lg flex items-center justify-center shrink-0",
2414
+ tc.status === "pending" ? "bg-yellow-500/20" : tc.status === "failed" ? "bg-red-500/20" : "bg-[var(--ash-accent)]/20"
2415
+ ),
2416
+ children: /* @__PURE__ */ jsx(
2417
+ ActionIcon,
2418
+ {
2419
+ actionType: tc.actionType,
2420
+ className: cn(
2421
+ "w-3.5 h-3.5",
2422
+ tc.status === "pending" ? "text-yellow-400" : tc.status === "failed" ? "text-red-400" : "text-[var(--ash-accent)]"
2423
+ )
2424
+ }
2425
+ )
2426
+ }
2427
+ ),
2428
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-white shrink-0", children: getActionLabel(tc.actionType) }),
2429
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-sm truncate text-white/60 flex-1 min-w-0", children: tc.summary }),
2430
+ /* @__PURE__ */ jsx(StatusIndicator, { status: tc.status, size: "sm" })
2431
+ ]
2432
+ }
2433
+ );
2434
+ return /* @__PURE__ */ jsxs(
2435
+ "div",
2436
+ {
2437
+ className: cn(
2438
+ "relative rounded-xl border bg-[var(--ash-surface-dark,#0a0a0a)] overflow-hidden",
2439
+ statusClasses[displayedToolCall.status],
2440
+ displayedToolCall.status === "pending" && "ash-tool-status-pending",
2441
+ className
2442
+ ),
2443
+ children: [
2444
+ exitingToolCall && /* @__PURE__ */ jsx("div", { className: "absolute inset-0", children: renderToolCallContent(exitingToolCall, true) }),
2445
+ renderToolCallContent(displayedToolCall, false)
2446
+ ]
2447
+ }
2448
+ );
2449
+ }
2017
2450
  function TodoStatusIcon({ status, className = "w-4 h-4" }) {
2018
2451
  switch (status) {
2019
2452
  case "completed":
@@ -3073,6 +3506,24 @@ function useAgentChat(options) {
3073
3506
  }
3074
3507
  }
3075
3508
  break;
3509
+ case "text":
3510
+ if (event.text && !currentTextRef.current) {
3511
+ currentTextIdRef.current = `text-${Date.now()}-${Math.random().toString(36).slice(2)}`;
3512
+ currentTextRef.current = event.text;
3513
+ newEntries.push(createTextEntry(currentTextIdRef.current, currentTextRef.current));
3514
+ }
3515
+ break;
3516
+ case "message":
3517
+ if (event.content && !currentTextRef.current) {
3518
+ const messageContent = event.content;
3519
+ const textBlock = messageContent?.find((c) => c.type === "text");
3520
+ if (textBlock?.text) {
3521
+ currentTextIdRef.current = `text-${Date.now()}-${Math.random().toString(36).slice(2)}`;
3522
+ currentTextRef.current = textBlock.text;
3523
+ newEntries.push(createTextEntry(currentTextIdRef.current, currentTextRef.current));
3524
+ }
3525
+ }
3526
+ break;
3076
3527
  case "sandbox_log":
3077
3528
  if (event.entry) {
3078
3529
  onSandboxLog?.(event.entry);
@@ -3118,7 +3569,7 @@ function useAgentChat(options) {
3118
3569
  abortControllerRef.current = controller;
3119
3570
  let localStreamingEntries = [];
3120
3571
  try {
3121
- const stream = createStream(prompt, sessionId || void 0);
3572
+ const stream = createStream(prompt, sessionId || void 0, controller.signal);
3122
3573
  for await (const event of stream) {
3123
3574
  if (controller.signal.aborted) break;
3124
3575
  localStreamingEntries = processEvent(event, localStreamingEntries);
@@ -3173,7 +3624,79 @@ function useAgentChat(options) {
3173
3624
  setEntries
3174
3625
  };
3175
3626
  }
3627
+ function textToBase64(text) {
3628
+ const encoder = new TextEncoder();
3629
+ const bytes = encoder.encode(text);
3630
+ let binary = "";
3631
+ for (let i = 0; i < bytes.length; i++) {
3632
+ const byte = bytes[i];
3633
+ if (byte !== void 0) {
3634
+ binary += String.fromCharCode(byte);
3635
+ }
3636
+ }
3637
+ return btoa(binary);
3638
+ }
3639
+ function generateFilename(template) {
3640
+ const timestamp = Date.now();
3641
+ const date = new Date(timestamp);
3642
+ const dateStr = date.toISOString().split("T")[0] ?? "unknown-date";
3643
+ const timeStr = (date.toTimeString().split(" ")[0] ?? "00-00-00").replace(/:/g, "-");
3644
+ return template.replace("{timestamp}", String(timestamp)).replace("{date}", dateStr).replace("{time}", timeStr);
3645
+ }
3646
+ function useLongTextConversion({
3647
+ threshold = 5e3,
3648
+ filenameTemplate = "pasted-text-{timestamp}.txt",
3649
+ onConversion
3650
+ } = {}) {
3651
+ const [lastConversion, setLastConversion] = useState(null);
3652
+ const processText = useCallback((text) => {
3653
+ if (text.length <= threshold) {
3654
+ return { text };
3655
+ }
3656
+ const filename = generateFilename(filenameTemplate);
3657
+ const content = textToBase64(text);
3658
+ const encoder = new TextEncoder();
3659
+ const size = encoder.encode(text).length;
3660
+ const lineCount = text.split("\n").length;
3661
+ const attachment = {
3662
+ filename,
3663
+ content,
3664
+ mimeType: "text/plain",
3665
+ size
3666
+ };
3667
+ const preview = text.slice(0, 100) + (text.length > 100 ? "..." : "");
3668
+ const conversionInfo = {
3669
+ originalLength: text.length,
3670
+ filename,
3671
+ preview,
3672
+ lineCount
3673
+ };
3674
+ setLastConversion(conversionInfo);
3675
+ onConversion?.(conversionInfo);
3676
+ return { text: "", attachment };
3677
+ }, [threshold, filenameTemplate, onConversion]);
3678
+ const handlePaste = useCallback((event, _currentValue, _setValue, addAttachment) => {
3679
+ const pastedText = event.clipboardData.getData("text/plain");
3680
+ if (pastedText.length > threshold) {
3681
+ event.preventDefault();
3682
+ const result = processText(pastedText);
3683
+ if (result.attachment) {
3684
+ addAttachment(result.attachment);
3685
+ }
3686
+ }
3687
+ }, [threshold, processText]);
3688
+ const clearLastConversion = useCallback(() => {
3689
+ setLastConversion(null);
3690
+ }, []);
3691
+ return {
3692
+ processText,
3693
+ handlePaste,
3694
+ lastConversion,
3695
+ clearLastConversion,
3696
+ threshold
3697
+ };
3698
+ }
3176
3699
 
3177
- export { ActionIcon, AlertCircleIcon, AlertTriangleIcon, AssistantMessage, BotIcon, BrainIcon, BugIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CircleIcon, ClipboardListIcon, CodeBlock, CodeIcon, CompactToolStatusLine, CopyIcon, DEFAULT_DISPLAY_CONFIG, DisplayModeProvider, DisplayModeToggle, EditIcon, EnvVarsPanel, ErrorIcon, ErrorMessage, FileIcon, FilePlusIcon, FolderSearchIcon, GlobeIcon, InfoIcon, JsonDisplay, ListChecksIcon, LoaderIcon, LoadingIndicator, LogsPanel, MessageEntry, MessageList, MessageSquareIcon, MoonIcon, OptionCards, PaperclipIcon, PlugIcon, SearchIcon, SendIcon, SparklesIcon, SpinnerIcon, StatusIndicator, StepAccordion, StopCircleIcon, StreamingText, SunIcon, TerminalIcon, ThemeProvider, ThinkingMessage, TodoPanel, ToolCallCard, ToolCallMessage, ToolExecutionGroup, ToolIcon, TypewriterText, UserIcon, UserMessage, XCircleIcon, XIcon, allKeyframesCss, borderRadius, cn, colors, createToolCall, extractTextContent, extractToolCallsFromGroup, formatFileSize, formatTimestamp, formatToolName, generateToolSummary, getActionIcon, getActionLabel, groupEntriesForCompactMode, inlineStyles, isCommandRunAction, isErrorEntry, isFileEditAction, isFileReadAction, isFileWriteAction, isGenericToolAction, isGlobAction, isMcpToolAction, isSearchAction, isTodoWriteAction, isToolCallEntry, isWebFetchAction, isWebSearchAction, isWidgetEntry, keyframes, keyframesCss, mapToolToActionType, normalizeToolResult, parseCommandResult, parseMcpToolName, parseOptionsFromContent, shadows, spacing, tokensToCssVariables, transitions, truncate, typography, updateToolCallWithResult, useAgentChat, useDisplayConfig, useDisplayMode, useFileUpload, useMessageQueue, useStopExecution, useTheme, widget, zIndex };
3700
+ export { ActionIcon, AgentToolCard, AlertCircleIcon, AlertTriangleIcon, AssistantMessage, BotIcon, BrainIcon, BugIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CircleIcon, ClipboardListIcon, ClockIcon, CodeBlock, CodeIcon, CompactToolRow, CompactToolStatusLine, CopyIcon, DEFAULT_DISPLAY_CONFIG, DisplayModeProvider, DisplayModeToggle, EditIcon, EnvVarsPanel, ErrorIcon, ErrorMessage, FileBadge, FileIcon, FilePlusIcon, FolderSearchIcon, GlobeIcon, InfoIcon, JsonDisplay, LazyMarkdown, ListChecksIcon, LoaderIcon, LoadingIndicator, LogsPanel, MessageEntry, MessageList, MessageSquareIcon, MoonIcon, OptionCards, PaperclipIcon, PlugIcon, SearchIcon, SendIcon, SparklesIcon, SpinnerIcon, StatusIndicator, StepAccordion, StopCircleIcon, StreamingText, SunIcon, TerminalIcon, ThemeProvider, ThinkingMessage, TodoPanel, ToolCallCard, ToolCallMessage, ToolExecutionGroup, ToolIcon, TypewriterText, UserIcon, UserMessage, XCircleIcon, XIcon, allKeyframesCss, borderRadius, cn, colors, createToolCall, extractTextContent, extractToolCallsFromGroup, formatElapsedTime, formatFileSize, formatTimestamp, formatToolName, generateToolSummary, getActionIcon, getActionLabel, groupEntriesForCompactMode, inlineStyles, isAgentToolAction, isCommandRunAction, isErrorEntry, isFileEditAction, isFileReadAction, isFileWriteAction, isGenericToolAction, isGlobAction, isMcpToolAction, isSearchAction, isTodoWriteAction, isToolCallEntry, isWebFetchAction, isWebSearchAction, isWidgetEntry, keyframes, keyframesCss, mapToolToActionType, normalizeToolResult, parseCommandResult, parseMcpToolName, parseOptionsFromContent, shadows, spacing, tokensToCssVariables, transitions, truncate, typography, updateToolCallWithResult, useAgentChat, useDisplayConfig, useDisplayMode, useFileUpload, useLongTextConversion, useMessageQueue, useStopExecution, useTheme, widget, zIndex };
3178
3701
  //# sourceMappingURL=index.js.map
3179
3702
  //# sourceMappingURL=index.js.map