@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/icons.cjs +7 -0
- package/dist/icons.cjs.map +1 -1
- package/dist/icons.d.cts +2 -1
- package/dist/icons.d.ts +2 -1
- package/dist/icons.js +7 -1
- package/dist/icons.js.map +1 -1
- package/dist/index.cjs +877 -350
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +232 -25
- package/dist/index.d.ts +232 -25
- package/dist/index.js +871 -348
- package/dist/index.js.map +1 -1
- package/dist/styles-full.css +1 -1
- package/dist/styles.css +1 -1
- package/dist/types.cjs +4 -0
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +41 -2
- package/dist/types.d.ts +41 -2
- package/dist/types.js +4 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.cjs +56 -8
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +8 -1
- package/dist/utils.d.ts +8 -1
- package/dist/utils.js +56 -9
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { createContext, useState, useRef, useEffect,
|
|
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
|
|
43
|
+
limit,
|
|
44
|
+
linesRead: limit
|
|
45
|
+
// Use limit as approximate lines read if specified
|
|
44
46
|
};
|
|
45
|
-
|
|
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:
|
|
50
|
-
newString:
|
|
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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
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
|
-
|
|
1334
|
-
setDisplayedToolCall(toolCall);
|
|
1559
|
+
return null;
|
|
1335
1560
|
}
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
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-
|
|
1348
|
-
|
|
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__ */
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
/* @__PURE__ */
|
|
1375
|
-
|
|
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
|
-
"
|
|
1727
|
+
"span",
|
|
1381
1728
|
{
|
|
1382
1729
|
className: cn(
|
|
1383
|
-
"
|
|
1384
|
-
|
|
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
|
-
|
|
1390
|
-
|
|
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
|
|
1396
|
-
const
|
|
1397
|
-
const
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
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
|
|
1412
|
-
const
|
|
1413
|
-
const
|
|
1414
|
-
const
|
|
1415
|
-
|
|
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 (
|
|
1817
|
+
if (toolCalls.length === 0) {
|
|
1418
1818
|
return null;
|
|
1419
1819
|
}
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
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
|
-
"
|
|
1506
|
-
|
|
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
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
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
|
|
1547
|
-
|
|
1548
|
-
|
|
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
|
-
|
|
1551
|
-
return cleaned.charAt(0).toUpperCase() + cleaned.slice(1);
|
|
1924
|
+
return Array.from(fileMap.values());
|
|
1552
1925
|
}
|
|
1553
|
-
function
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
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
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
case "
|
|
1571
|
-
return
|
|
1572
|
-
case "
|
|
1573
|
-
return
|
|
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
|
|
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
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
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
|
-
"
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
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
|