@ash-cloud/ash-ui 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/design-tokens.cjs +20 -0
- package/dist/design-tokens.cjs.map +1 -1
- package/dist/design-tokens.d.cts +31 -1
- package/dist/design-tokens.d.ts +31 -1
- package/dist/design-tokens.js +20 -1
- package/dist/design-tokens.js.map +1 -1
- package/dist/icons.cjs +23 -0
- package/dist/icons.cjs.map +1 -1
- package/dist/icons.d.cts +4 -1
- package/dist/icons.d.ts +4 -1
- package/dist/icons.js +21 -1
- package/dist/icons.js.map +1 -1
- package/dist/index.cjs +592 -115
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +402 -22
- package/dist/index.d.ts +402 -22
- package/dist/index.js +610 -142
- package/dist/index.js.map +1 -1
- package/dist/styles-full.css +1 -1
- package/dist/styles.css +1 -1
- package/dist/types.cjs +8 -0
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +149 -1
- package/dist/types.d.ts +149 -1
- package/dist/types.js +8 -1
- package/dist/types.js.map +1 -1
- package/package.json +13 -13
package/dist/index.cjs
CHANGED
|
@@ -694,6 +694,26 @@ function ErrorIcon({ className }) {
|
|
|
694
694
|
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "9", y1: "9", x2: "15", y2: "15" })
|
|
695
695
|
] });
|
|
696
696
|
}
|
|
697
|
+
function MicrophoneIcon({ className }) {
|
|
698
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
699
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }),
|
|
700
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
|
|
701
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
|
|
702
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
|
|
703
|
+
] });
|
|
704
|
+
}
|
|
705
|
+
function HomeIcon({ className }) {
|
|
706
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
707
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" }),
|
|
708
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 22 9 12 15 12 15 22" })
|
|
709
|
+
] });
|
|
710
|
+
}
|
|
711
|
+
function ArrowUpIcon({ className }) {
|
|
712
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
713
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "19", x2: "12", y2: "5" }),
|
|
714
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "5 12 12 5 19 12" })
|
|
715
|
+
] });
|
|
716
|
+
}
|
|
697
717
|
function StatusIndicator({ status, size = "sm", className }) {
|
|
698
718
|
const sizeClasses = {
|
|
699
719
|
sm: "w-2 h-2",
|
|
@@ -754,14 +774,41 @@ function CodeBlock({
|
|
|
754
774
|
className
|
|
755
775
|
}) {
|
|
756
776
|
const [expanded, setExpanded] = react.useState(false);
|
|
777
|
+
const [copied, setCopied] = react.useState(false);
|
|
757
778
|
const lines = children.split("\n");
|
|
758
779
|
const isLong = lines.length > 10 || children.length > 500;
|
|
759
|
-
|
|
780
|
+
const handleCopy = react.useCallback(async () => {
|
|
781
|
+
try {
|
|
782
|
+
await navigator.clipboard.writeText(children);
|
|
783
|
+
setCopied(true);
|
|
784
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
785
|
+
} catch (err) {
|
|
786
|
+
console.error("Failed to copy:", err);
|
|
787
|
+
}
|
|
788
|
+
}, [children]);
|
|
789
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative rounded-lg overflow-hidden border border-white/10", className), children: [
|
|
790
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-2 bg-[var(--ash-code-header-bg)] border-b border-white/10", children: [
|
|
791
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-white/60 font-medium", children: language || "code" }),
|
|
792
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
793
|
+
"button",
|
|
794
|
+
{
|
|
795
|
+
onClick: handleCopy,
|
|
796
|
+
className: "flex items-center gap-1.5 text-xs text-white/60 hover:text-white transition-colors",
|
|
797
|
+
children: copied ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
798
|
+
/* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "w-3.5 h-3.5" }),
|
|
799
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Copied!" })
|
|
800
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
801
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyIcon, { className: "w-3.5 h-3.5" }),
|
|
802
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Copy" })
|
|
803
|
+
] })
|
|
804
|
+
}
|
|
805
|
+
)
|
|
806
|
+
] }),
|
|
760
807
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
761
808
|
"pre",
|
|
762
809
|
{
|
|
763
810
|
className: cn(
|
|
764
|
-
"
|
|
811
|
+
"text-xs font-mono text-white/90 p-4 bg-black/30 overflow-x-auto whitespace-pre-wrap break-words",
|
|
765
812
|
!expanded && isLong && "overflow-y-hidden"
|
|
766
813
|
),
|
|
767
814
|
style: !expanded && isLong ? { maxHeight } : void 0,
|
|
@@ -945,7 +992,7 @@ function SectionHeader({ children }) {
|
|
|
945
992
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ash-tool-section-header", children });
|
|
946
993
|
}
|
|
947
994
|
function SectionContent({ children }) {
|
|
948
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-
|
|
995
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-1.5", children });
|
|
949
996
|
}
|
|
950
997
|
function CommandRunDetails({ action }) {
|
|
951
998
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -1066,7 +1113,7 @@ function WebSearchDetails({ action }) {
|
|
|
1066
1113
|
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-white/90", children: action.query }) })
|
|
1067
1114
|
] });
|
|
1068
1115
|
}
|
|
1069
|
-
function McpToolDetails({ action }) {
|
|
1116
|
+
function McpToolDetails({ action, isError }) {
|
|
1070
1117
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1071
1118
|
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "TOOL" }),
|
|
1072
1119
|
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsxs("code", { className: "text-xs font-mono bg-white/10 text-white/90 px-1 py-0.5 rounded", children: [
|
|
@@ -1079,20 +1126,20 @@ function McpToolDetails({ action }) {
|
|
|
1079
1126
|
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx(JsonDisplay, { value: action.arguments }) })
|
|
1080
1127
|
] }),
|
|
1081
1128
|
action.result && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1082
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "RESULT" }),
|
|
1083
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: action.result.type === "markdown" ? /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { children: String(action.result.value) }) : /* @__PURE__ */ jsxRuntime.jsx(JsonDisplay, { value: action.result.value }) })
|
|
1129
|
+
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: isError ? "ERROR" : "RESULT" }),
|
|
1130
|
+
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: isError ? "text-red-400" : "", children: action.result.type === "markdown" ? /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { children: String(action.result.value) }) : /* @__PURE__ */ jsxRuntime.jsx(JsonDisplay, { value: action.result.value }) }) })
|
|
1084
1131
|
] })
|
|
1085
1132
|
] });
|
|
1086
1133
|
}
|
|
1087
|
-
function GenericToolDetails({ action }) {
|
|
1134
|
+
function GenericToolDetails({ action, isError }) {
|
|
1088
1135
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1089
1136
|
action.arguments && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1090
1137
|
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "ARGS" }),
|
|
1091
1138
|
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx(JsonDisplay, { value: action.arguments }) })
|
|
1092
1139
|
] }),
|
|
1093
1140
|
action.result && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1094
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "RESULT" }),
|
|
1095
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: action.result.type === "markdown" ? /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { children: String(action.result.value) }) : /* @__PURE__ */ jsxRuntime.jsx(JsonDisplay, { value: action.result.value }) })
|
|
1141
|
+
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: isError ? "ERROR" : "RESULT" }),
|
|
1142
|
+
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: isError ? "text-red-400" : "", children: action.result.type === "markdown" ? /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { children: String(action.result.value) }) : /* @__PURE__ */ jsxRuntime.jsx(JsonDisplay, { value: action.result.value }) }) })
|
|
1096
1143
|
] })
|
|
1097
1144
|
] });
|
|
1098
1145
|
}
|
|
@@ -1164,7 +1211,7 @@ function TodoWriteDetails({ action }) {
|
|
|
1164
1211
|
}) }) })
|
|
1165
1212
|
] });
|
|
1166
1213
|
}
|
|
1167
|
-
function ToolDetails({ actionType }) {
|
|
1214
|
+
function ToolDetails({ actionType, isError }) {
|
|
1168
1215
|
switch (actionType.action) {
|
|
1169
1216
|
case "command_run":
|
|
1170
1217
|
return /* @__PURE__ */ jsxRuntime.jsx(CommandRunDetails, { action: actionType });
|
|
@@ -1183,9 +1230,9 @@ function ToolDetails({ actionType }) {
|
|
|
1183
1230
|
case "web_search":
|
|
1184
1231
|
return /* @__PURE__ */ jsxRuntime.jsx(WebSearchDetails, { action: actionType });
|
|
1185
1232
|
case "mcp_tool":
|
|
1186
|
-
return /* @__PURE__ */ jsxRuntime.jsx(McpToolDetails, { action: actionType });
|
|
1233
|
+
return /* @__PURE__ */ jsxRuntime.jsx(McpToolDetails, { action: actionType, isError });
|
|
1187
1234
|
case "generic_tool":
|
|
1188
|
-
return /* @__PURE__ */ jsxRuntime.jsx(GenericToolDetails, { action: actionType });
|
|
1235
|
+
return /* @__PURE__ */ jsxRuntime.jsx(GenericToolDetails, { action: actionType, isError });
|
|
1189
1236
|
case "todo_write":
|
|
1190
1237
|
return /* @__PURE__ */ jsxRuntime.jsx(TodoWriteDetails, { action: actionType });
|
|
1191
1238
|
default:
|
|
@@ -1246,7 +1293,7 @@ function ToolCallCard({ toolCall, defaultExpanded = false, className }) {
|
|
|
1246
1293
|
"div",
|
|
1247
1294
|
{
|
|
1248
1295
|
className: cn(
|
|
1249
|
-
"rounded-
|
|
1296
|
+
"rounded-lg border bg-[var(--ash-surface-dark,#0a0a0a)] overflow-hidden",
|
|
1250
1297
|
statusClasses[status],
|
|
1251
1298
|
className
|
|
1252
1299
|
),
|
|
@@ -1256,35 +1303,35 @@ function ToolCallCard({ toolCall, defaultExpanded = false, className }) {
|
|
|
1256
1303
|
{
|
|
1257
1304
|
onClick: () => canExpand && setExpanded(!expanded),
|
|
1258
1305
|
className: cn(
|
|
1259
|
-
"w-full px-
|
|
1306
|
+
"w-full px-3 py-2 flex items-center justify-between transition-colors",
|
|
1260
1307
|
canExpand ? "hover:bg-white/5 cursor-pointer" : "cursor-default"
|
|
1261
1308
|
),
|
|
1262
1309
|
disabled: !canExpand,
|
|
1263
1310
|
children: [
|
|
1264
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-
|
|
1311
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [
|
|
1265
1312
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
|
|
1266
|
-
"w-
|
|
1313
|
+
"w-5 h-5 rounded flex items-center justify-center shrink-0",
|
|
1267
1314
|
status === "pending" ? "bg-yellow-500/20" : status === "failed" ? "bg-red-500/20" : "bg-[var(--ash-accent)]/20"
|
|
1268
1315
|
), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1269
1316
|
ActionIcon,
|
|
1270
1317
|
{
|
|
1271
1318
|
actionType,
|
|
1272
1319
|
className: cn(
|
|
1273
|
-
"w-3
|
|
1320
|
+
"w-3 h-3",
|
|
1274
1321
|
status === "pending" ? "text-yellow-400" : status === "failed" ? "text-red-400" : "text-[var(--ash-accent)]"
|
|
1275
1322
|
)
|
|
1276
1323
|
}
|
|
1277
1324
|
) }),
|
|
1278
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-
|
|
1279
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-
|
|
1325
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[13px] font-medium text-white shrink-0", children: getActionLabel(actionType) }),
|
|
1326
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[12px] truncate text-white/50 min-w-0", children: summary })
|
|
1280
1327
|
] }),
|
|
1281
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-
|
|
1328
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 shrink-0", children: [
|
|
1282
1329
|
/* @__PURE__ */ jsxRuntime.jsx(StatusIndicator, { status, size: "sm" }),
|
|
1283
1330
|
canExpand && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1284
1331
|
ChevronDownIcon,
|
|
1285
1332
|
{
|
|
1286
1333
|
className: cn(
|
|
1287
|
-
"w-
|
|
1334
|
+
"w-3.5 h-3.5 text-white/30 transition-transform duration-200",
|
|
1288
1335
|
expanded && "rotate-180"
|
|
1289
1336
|
)
|
|
1290
1337
|
}
|
|
@@ -1293,11 +1340,15 @@ function ToolCallCard({ toolCall, defaultExpanded = false, className }) {
|
|
|
1293
1340
|
]
|
|
1294
1341
|
}
|
|
1295
1342
|
),
|
|
1296
|
-
expanded && canExpand && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-white/5 max-h-[
|
|
1297
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolDetails, { actionType }),
|
|
1298
|
-
status === "success" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-
|
|
1299
|
-
/* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "w-
|
|
1300
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-
|
|
1343
|
+
expanded && canExpand && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-white/5 max-h-[350px] overflow-y-auto ash-scrollbar bg-black/20", children: [
|
|
1344
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolDetails, { actionType, isError: toolCall.isError || status === "failed" }),
|
|
1345
|
+
status === "success" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 border-t border-white/5 bg-[var(--ash-accent)]/5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
1346
|
+
/* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "w-3.5 h-3.5 text-[var(--ash-accent)]" }),
|
|
1347
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[12px] text-[var(--ash-accent)] font-medium", children: "Completed" })
|
|
1348
|
+
] }) }),
|
|
1349
|
+
status === "failed" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 border-t border-red-500/20 bg-red-500/10", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
1350
|
+
/* @__PURE__ */ jsxRuntime.jsx(XCircleIcon, { className: "w-3.5 h-3.5 text-red-400" }),
|
|
1351
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[12px] text-red-400 font-medium", children: "Failed" })
|
|
1301
1352
|
] }) })
|
|
1302
1353
|
] })
|
|
1303
1354
|
]
|
|
@@ -1305,15 +1356,19 @@ function ToolCallCard({ toolCall, defaultExpanded = false, className }) {
|
|
|
1305
1356
|
);
|
|
1306
1357
|
}
|
|
1307
1358
|
var ReactMarkdown = react.lazy(() => import('react-markdown'));
|
|
1308
|
-
function LazyMarkdown({ children, fallback, className }) {
|
|
1359
|
+
function LazyMarkdown({ children, fallback, components, className }) {
|
|
1309
1360
|
const [mounted, setMounted] = react.useState(false);
|
|
1310
1361
|
react.useEffect(() => {
|
|
1311
1362
|
setMounted(true);
|
|
1312
1363
|
}, []);
|
|
1364
|
+
const markdownComponents = react.useMemo(() => {
|
|
1365
|
+
if (!components) return void 0;
|
|
1366
|
+
return components;
|
|
1367
|
+
}, [components]);
|
|
1313
1368
|
if (!mounted) {
|
|
1314
1369
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { className, children: fallback ?? children });
|
|
1315
1370
|
}
|
|
1316
|
-
return /* @__PURE__ */ jsxRuntime.jsx(react.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx("span", { className, children: fallback ?? children }), children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown, { children }) });
|
|
1371
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx("span", { className, children: fallback ?? children }), children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown, { components: markdownComponents, children }) });
|
|
1317
1372
|
}
|
|
1318
1373
|
function DefaultMentionBadge({ segment }) {
|
|
1319
1374
|
const bgColor = segment.color ? `${segment.color}20` : "rgba(34, 197, 94, 0.2)";
|
|
@@ -1413,6 +1468,36 @@ function OptionCards({ options, onSelect, className }) {
|
|
|
1413
1468
|
option.id
|
|
1414
1469
|
)) });
|
|
1415
1470
|
}
|
|
1471
|
+
var scaleClasses = {
|
|
1472
|
+
dense: {
|
|
1473
|
+
text: "text-xs",
|
|
1474
|
+
padding: "px-2 py-1",
|
|
1475
|
+
gap: "gap-1.5",
|
|
1476
|
+
avatar: "w-4 h-4",
|
|
1477
|
+
messageGap: "space-y-0.5"
|
|
1478
|
+
},
|
|
1479
|
+
compact: {
|
|
1480
|
+
text: "text-[13px]",
|
|
1481
|
+
padding: "px-3 py-2",
|
|
1482
|
+
gap: "gap-2",
|
|
1483
|
+
avatar: "w-5 h-5",
|
|
1484
|
+
messageGap: "space-y-1"
|
|
1485
|
+
},
|
|
1486
|
+
default: {
|
|
1487
|
+
text: "text-sm",
|
|
1488
|
+
padding: "px-4 py-3",
|
|
1489
|
+
gap: "gap-3",
|
|
1490
|
+
avatar: "w-6 h-6",
|
|
1491
|
+
messageGap: "space-y-2"
|
|
1492
|
+
},
|
|
1493
|
+
comfortable: {
|
|
1494
|
+
text: "text-[15px]",
|
|
1495
|
+
padding: "px-5 py-4",
|
|
1496
|
+
gap: "gap-4",
|
|
1497
|
+
avatar: "w-7 h-7",
|
|
1498
|
+
messageGap: "space-y-3"
|
|
1499
|
+
}
|
|
1500
|
+
};
|
|
1416
1501
|
function parseFilesFromContent(content) {
|
|
1417
1502
|
const fileMarker = "[Uploaded files available at /uploads/]";
|
|
1418
1503
|
const markerIndex = content.indexOf(fileMarker);
|
|
@@ -1424,43 +1509,82 @@ function parseFilesFromContent(content) {
|
|
|
1424
1509
|
const files = fileSection.split("\n").filter((line) => line.startsWith("- ")).map((line) => line.substring(2).trim());
|
|
1425
1510
|
return { text, files };
|
|
1426
1511
|
}
|
|
1427
|
-
function UserMessage({
|
|
1512
|
+
function UserMessage({
|
|
1513
|
+
entry,
|
|
1514
|
+
variant = "bubble",
|
|
1515
|
+
scale = "compact",
|
|
1516
|
+
showAvatar = false,
|
|
1517
|
+
// Hidden by default for ChatGPT style
|
|
1518
|
+
showTimestamp = true,
|
|
1519
|
+
renderMetadata,
|
|
1520
|
+
metadata,
|
|
1521
|
+
className
|
|
1522
|
+
}) {
|
|
1428
1523
|
const { text, files } = parseFilesFromContent(entry.content);
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1524
|
+
const s = scaleClasses[scale];
|
|
1525
|
+
const variantClasses = {
|
|
1526
|
+
bubble: "rounded-[20px] bg-[var(--ash-user-bg)] text-[var(--ash-user-text)] border border-[var(--ash-user-border)]",
|
|
1527
|
+
plain: "bg-transparent text-[var(--ash-text-primary)]",
|
|
1528
|
+
minimal: "bg-transparent text-[var(--ash-text-secondary)]"
|
|
1529
|
+
};
|
|
1530
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1531
|
+
"div",
|
|
1532
|
+
{
|
|
1533
|
+
"data-message-role": "user",
|
|
1534
|
+
className: cn("flex justify-end ash-animate-fade-in pr-1", s.gap, className),
|
|
1535
|
+
children: [
|
|
1536
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-[85%] flex flex-col items-end", children: [
|
|
1537
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(variantClasses[variant], variant === "bubble" && "px-4 py-3"), children: [
|
|
1538
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: cn(s.text, "leading-snug whitespace-pre-wrap"), children: text || "(files attached)" }),
|
|
1539
|
+
files.length > 0 && variant === "bubble" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1.5 pt-1.5 border-t border-[var(--ash-user-text)]/15 flex flex-wrap gap-1", children: files.map((file, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1540
|
+
"span",
|
|
1541
|
+
{
|
|
1542
|
+
className: "inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-[var(--ash-user-text)]/10 text-[11px]",
|
|
1543
|
+
title: file,
|
|
1544
|
+
children: [
|
|
1545
|
+
/* @__PURE__ */ jsxRuntime.jsx(PaperclipIcon, { className: "w-2.5 h-2.5 opacity-60" }),
|
|
1546
|
+
file.split(" (")[0]
|
|
1547
|
+
]
|
|
1548
|
+
},
|
|
1549
|
+
index
|
|
1550
|
+
)) })
|
|
1551
|
+
] }),
|
|
1552
|
+
renderMetadata ? renderMetadata({ entry, metadata }) : showTimestamp && entry.timestamp && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[10px] text-[var(--ash-text-faint)] mt-0.5 mr-1 tabular-nums flex items-center gap-1.5", children: [
|
|
1553
|
+
metadata?.model && /* @__PURE__ */ jsxRuntime.jsx("span", { children: metadata.model }),
|
|
1554
|
+
metadata?.model && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-50", children: "\xB7" }),
|
|
1555
|
+
formatTimestamp(entry.timestamp)
|
|
1556
|
+
] })
|
|
1436
1557
|
] }),
|
|
1437
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
title: file,
|
|
1442
|
-
children: file.split(" (")[0]
|
|
1443
|
-
},
|
|
1444
|
-
index
|
|
1445
|
-
)) })
|
|
1446
|
-
] }),
|
|
1447
|
-
entry.timestamp && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-white/40 mt-2", children: formatTimestamp(entry.timestamp) })
|
|
1448
|
-
] }),
|
|
1449
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-7 h-7 rounded-full bg-white/10 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(UserIcon, { className: "w-4 h-4 text-white/50" }) })
|
|
1450
|
-
] });
|
|
1558
|
+
showAvatar && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(s.avatar, "rounded-full bg-[var(--ash-avatar-user-bg)] flex items-center justify-center shrink-0 mt-0.5"), children: /* @__PURE__ */ jsxRuntime.jsx(UserIcon, { className: "w-3 h-3 text-[var(--ash-text-muted)]" }) })
|
|
1559
|
+
]
|
|
1560
|
+
}
|
|
1561
|
+
);
|
|
1451
1562
|
}
|
|
1452
1563
|
function AssistantMessage({
|
|
1453
1564
|
entry,
|
|
1565
|
+
variant = "bubble",
|
|
1566
|
+
scale = "compact",
|
|
1567
|
+
showAvatar = true,
|
|
1568
|
+
showTimestamp = true,
|
|
1454
1569
|
onOptionSelect,
|
|
1455
1570
|
richContentRenderers,
|
|
1571
|
+
markdownComponents,
|
|
1572
|
+
renderMetadata,
|
|
1573
|
+
metadata,
|
|
1456
1574
|
className
|
|
1457
1575
|
}) {
|
|
1458
1576
|
const parsedOptions = !entry.richContent ? parseOptionsFromContent(entry.content) : null;
|
|
1577
|
+
const s = scaleClasses[scale];
|
|
1459
1578
|
const handleOptionSelect = (option) => {
|
|
1460
1579
|
if (onOptionSelect) {
|
|
1461
1580
|
onOptionSelect(`Option ${option.id}: ${option.label}`);
|
|
1462
1581
|
}
|
|
1463
1582
|
};
|
|
1583
|
+
const variantClasses = {
|
|
1584
|
+
bubble: "rounded-[16px] bg-[var(--ash-assistant-bg)] border border-[var(--ash-assistant-border)]",
|
|
1585
|
+
plain: "bg-transparent",
|
|
1586
|
+
minimal: "bg-transparent"
|
|
1587
|
+
};
|
|
1464
1588
|
const renderContent = (textContent) => {
|
|
1465
1589
|
if (entry.richContent && entry.richContent.length > 0) {
|
|
1466
1590
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1471,81 +1595,143 @@ function AssistantMessage({
|
|
|
1471
1595
|
}
|
|
1472
1596
|
);
|
|
1473
1597
|
}
|
|
1474
|
-
return /* @__PURE__ */ jsxRuntime.jsx(LazyMarkdown, { children: textContent || entry.content });
|
|
1598
|
+
return /* @__PURE__ */ jsxRuntime.jsx(LazyMarkdown, { components: markdownComponents, children: textContent || entry.content });
|
|
1475
1599
|
};
|
|
1476
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1600
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1601
|
+
"div",
|
|
1602
|
+
{
|
|
1603
|
+
"data-message-role": "assistant",
|
|
1604
|
+
className: cn("flex ash-animate-fade-in pl-1", s.gap, className),
|
|
1605
|
+
children: [
|
|
1606
|
+
showAvatar && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(s.avatar, "rounded-full bg-[var(--ash-avatar-assistant-bg)] flex items-center justify-center shrink-0 mt-0.5"), children: /* @__PURE__ */ jsxRuntime.jsx(SparklesIcon, { className: "w-3 h-3 text-white" }) }),
|
|
1607
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
1608
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(variantClasses[variant], variant === "bubble" && "px-4 py-3"), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("ash-message-content prose prose-sm prose-invert max-w-none leading-relaxed text-[var(--ash-assistant-text)]", s.text), children: parsedOptions ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1609
|
+
parsedOptions.preamble && renderContent(parsedOptions.preamble),
|
|
1610
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1611
|
+
OptionCards,
|
|
1612
|
+
{
|
|
1613
|
+
options: parsedOptions.options,
|
|
1614
|
+
onSelect: handleOptionSelect
|
|
1615
|
+
}
|
|
1616
|
+
)
|
|
1617
|
+
] }) : renderContent() }) }),
|
|
1618
|
+
renderMetadata ? renderMetadata({ entry, metadata }) : showTimestamp && entry.timestamp && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[10px] text-[var(--ash-text-faint)] mt-0.5 ml-1 tabular-nums flex items-center gap-1.5", children: [
|
|
1619
|
+
metadata?.model && /* @__PURE__ */ jsxRuntime.jsx("span", { children: metadata.model }),
|
|
1620
|
+
metadata?.model && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-50", children: "\xB7" }),
|
|
1621
|
+
formatTimestamp(entry.timestamp)
|
|
1622
|
+
] })
|
|
1623
|
+
] })
|
|
1624
|
+
]
|
|
1625
|
+
}
|
|
1626
|
+
);
|
|
1492
1627
|
}
|
|
1493
|
-
function ThinkingMessage({ entry, className }) {
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1628
|
+
function ThinkingMessage({ entry, scale = "compact", showAvatar = true, className }) {
|
|
1629
|
+
const s = scaleClasses[scale];
|
|
1630
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1631
|
+
"div",
|
|
1632
|
+
{
|
|
1633
|
+
"data-message-role": "thinking",
|
|
1634
|
+
className: cn("flex ash-animate-fade-in pl-1", s.gap, className),
|
|
1635
|
+
children: [
|
|
1636
|
+
showAvatar && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(s.avatar, "rounded-md bg-[var(--ash-avatar-thinking-bg)] flex items-center justify-center shrink-0 mt-0.5"), children: /* @__PURE__ */ jsxRuntime.jsx(SparklesIcon, { className: "w-3 h-3 text-purple-400" }) }),
|
|
1637
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("rounded-lg bg-[var(--ash-thinking-bg)] border border-[var(--ash-thinking-border)]", s.padding), children: [
|
|
1638
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-[var(--ash-thinking-text)] opacity-80 mb-1 font-medium uppercase tracking-wide", children: "Thinking" }),
|
|
1639
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(s.text, "text-[var(--ash-thinking-text)] opacity-70 italic whitespace-pre-wrap leading-relaxed"), children: entry.content })
|
|
1640
|
+
] }) })
|
|
1641
|
+
]
|
|
1642
|
+
}
|
|
1643
|
+
);
|
|
1501
1644
|
}
|
|
1502
|
-
function ToolCallMessage({ entry, defaultExpanded = false, className }) {
|
|
1645
|
+
function ToolCallMessage({ entry, scale = "compact", showAvatar = true, defaultExpanded = false, className }) {
|
|
1503
1646
|
if (entry.entryType.type !== "tool_call") return null;
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1647
|
+
const s = scaleClasses[scale];
|
|
1648
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1649
|
+
"div",
|
|
1650
|
+
{
|
|
1651
|
+
"data-message-role": "tool",
|
|
1652
|
+
className: cn("flex ash-animate-fade-in pl-1", s.gap, className),
|
|
1653
|
+
children: [
|
|
1654
|
+
showAvatar && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(s.avatar, "rounded-md bg-[var(--ash-avatar-assistant-bg)] flex items-center justify-center shrink-0 mt-0.5"), children: /* @__PURE__ */ jsxRuntime.jsx(BotIcon, { className: "w-3 h-3 text-[var(--ash-accent)]" }) }),
|
|
1655
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx(ToolCallCard, { toolCall: entry.entryType.toolCall, defaultExpanded }) })
|
|
1656
|
+
]
|
|
1657
|
+
}
|
|
1658
|
+
);
|
|
1508
1659
|
}
|
|
1509
|
-
function ErrorMessage({ entry, className }) {
|
|
1660
|
+
function ErrorMessage({ entry, scale = "compact", showAvatar = true, className }) {
|
|
1510
1661
|
if (entry.entryType.type !== "error") return null;
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1662
|
+
const s = scaleClasses[scale];
|
|
1663
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1664
|
+
"div",
|
|
1665
|
+
{
|
|
1666
|
+
"data-message-role": "error",
|
|
1667
|
+
className: cn("flex ash-animate-fade-in pl-1", s.gap, className),
|
|
1668
|
+
children: [
|
|
1669
|
+
showAvatar && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(s.avatar, "rounded-md bg-[var(--ash-avatar-error-bg)] flex items-center justify-center shrink-0 mt-0.5"), children: /* @__PURE__ */ jsxRuntime.jsx(AlertTriangleIcon, { className: "w-3 h-3 text-red-400" }) }),
|
|
1670
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("rounded-lg bg-[var(--ash-error-bg)] border border-[var(--ash-error-border)]", s.padding), children: [
|
|
1671
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-[var(--ash-error-text)] opacity-80 mb-1 font-medium uppercase tracking-wide", children: "Error" }),
|
|
1672
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: cn(s.text, "text-[var(--ash-error-text)] opacity-90"), children: entry.entryType.message }),
|
|
1673
|
+
entry.entryType.code && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[11px] text-[var(--ash-error-text)] opacity-60 mt-1 font-mono", children: [
|
|
1674
|
+
"Code: ",
|
|
1675
|
+
entry.entryType.code
|
|
1676
|
+
] })
|
|
1677
|
+
] }) })
|
|
1678
|
+
]
|
|
1679
|
+
}
|
|
1680
|
+
);
|
|
1522
1681
|
}
|
|
1523
1682
|
function MessageEntry({
|
|
1524
1683
|
entry,
|
|
1525
1684
|
onOptionSelect,
|
|
1526
1685
|
defaultExpanded,
|
|
1527
1686
|
richContentRenderers,
|
|
1687
|
+
markdownComponents,
|
|
1688
|
+
userVariant,
|
|
1689
|
+
assistantVariant,
|
|
1690
|
+
scale,
|
|
1691
|
+
showAvatars = true,
|
|
1692
|
+
showTimestamp = true,
|
|
1693
|
+
renderMetadata,
|
|
1694
|
+
metadata,
|
|
1528
1695
|
className
|
|
1529
1696
|
}) {
|
|
1530
1697
|
switch (entry.entryType.type) {
|
|
1531
1698
|
case "user_message":
|
|
1532
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1699
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1700
|
+
UserMessage,
|
|
1701
|
+
{
|
|
1702
|
+
entry,
|
|
1703
|
+
variant: userVariant,
|
|
1704
|
+
scale,
|
|
1705
|
+
showAvatar: showAvatars,
|
|
1706
|
+
showTimestamp,
|
|
1707
|
+
renderMetadata,
|
|
1708
|
+
metadata,
|
|
1709
|
+
className
|
|
1710
|
+
}
|
|
1711
|
+
);
|
|
1533
1712
|
case "assistant_message":
|
|
1534
1713
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1535
1714
|
AssistantMessage,
|
|
1536
1715
|
{
|
|
1537
1716
|
entry,
|
|
1717
|
+
variant: assistantVariant,
|
|
1718
|
+
scale,
|
|
1719
|
+
showAvatar: showAvatars,
|
|
1720
|
+
showTimestamp,
|
|
1538
1721
|
onOptionSelect,
|
|
1539
1722
|
richContentRenderers,
|
|
1723
|
+
markdownComponents,
|
|
1724
|
+
renderMetadata,
|
|
1725
|
+
metadata,
|
|
1540
1726
|
className
|
|
1541
1727
|
}
|
|
1542
1728
|
);
|
|
1543
1729
|
case "thinking":
|
|
1544
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ThinkingMessage, { entry, className });
|
|
1730
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ThinkingMessage, { entry, scale, showAvatar: showAvatars, className });
|
|
1545
1731
|
case "tool_call":
|
|
1546
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ToolCallMessage, { entry, defaultExpanded, className });
|
|
1732
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ToolCallMessage, { entry, scale, showAvatar: showAvatars, defaultExpanded, className });
|
|
1547
1733
|
case "error":
|
|
1548
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ErrorMessage, { entry, className });
|
|
1734
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ErrorMessage, { entry, scale, showAvatar: showAvatars, className });
|
|
1549
1735
|
default:
|
|
1550
1736
|
return null;
|
|
1551
1737
|
}
|
|
@@ -2164,6 +2350,13 @@ var DEFAULT_DISPLAY_CONFIG = {
|
|
|
2164
2350
|
defaultExpanded: false,
|
|
2165
2351
|
animationDuration: 300
|
|
2166
2352
|
};
|
|
2353
|
+
var DEFAULT_STYLE_CONFIG = {
|
|
2354
|
+
userVariant: "bubble",
|
|
2355
|
+
assistantVariant: "bubble",
|
|
2356
|
+
scale: "compact",
|
|
2357
|
+
showTimestamp: true,
|
|
2358
|
+
showAvatars: true
|
|
2359
|
+
};
|
|
2167
2360
|
var DisplayModeContext = react.createContext(null);
|
|
2168
2361
|
function DisplayModeProvider({ children, initialConfig }) {
|
|
2169
2362
|
const [config, setConfigState] = react.useState({
|
|
@@ -2217,6 +2410,14 @@ function MessageList({
|
|
|
2217
2410
|
onWidgetAction,
|
|
2218
2411
|
autoScroll = true,
|
|
2219
2412
|
richContentRenderers,
|
|
2413
|
+
userVariant,
|
|
2414
|
+
assistantVariant,
|
|
2415
|
+
scale,
|
|
2416
|
+
showAvatars = true,
|
|
2417
|
+
showTimestamp = true,
|
|
2418
|
+
markdownComponents,
|
|
2419
|
+
renderMetadata,
|
|
2420
|
+
metadata,
|
|
2220
2421
|
className
|
|
2221
2422
|
}) {
|
|
2222
2423
|
const contextConfig = useDisplayConfig();
|
|
@@ -2251,7 +2452,8 @@ function MessageList({
|
|
|
2251
2452
|
}
|
|
2252
2453
|
return groupEntriesForCompactMode(entries, config);
|
|
2253
2454
|
}, [entries, config]);
|
|
2254
|
-
|
|
2455
|
+
const densityClass = scale ? `ash-density-${scale}` : void 0;
|
|
2456
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: cn("flex-1 overflow-y-auto px-3 py-2 space-y-1 ash-scrollbar", densityClass, className), children: [
|
|
2255
2457
|
groupedEntries.map((groupedEntry) => {
|
|
2256
2458
|
if (groupedEntry.type === "single") {
|
|
2257
2459
|
const entry = groupedEntry.entry;
|
|
@@ -2273,15 +2475,23 @@ function MessageList({
|
|
|
2273
2475
|
entry,
|
|
2274
2476
|
onOptionSelect,
|
|
2275
2477
|
defaultExpanded: config.defaultExpanded,
|
|
2276
|
-
richContentRenderers
|
|
2478
|
+
richContentRenderers,
|
|
2479
|
+
markdownComponents,
|
|
2480
|
+
userVariant,
|
|
2481
|
+
assistantVariant,
|
|
2482
|
+
scale,
|
|
2483
|
+
showAvatars,
|
|
2484
|
+
showTimestamp,
|
|
2485
|
+
renderMetadata,
|
|
2486
|
+
metadata
|
|
2277
2487
|
},
|
|
2278
2488
|
entry.id
|
|
2279
2489
|
);
|
|
2280
2490
|
}
|
|
2281
2491
|
const toolCalls = extractToolCallsFromGroup(groupedEntry.entries);
|
|
2282
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex
|
|
2283
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
2284
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: config.mode === "accordion" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2492
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ash-message-row flex ash-animate-fade-in pl-1", style: { gap: "var(--ash-message-gap, 0.5rem)" }, children: [
|
|
2493
|
+
showAvatars && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ash-avatar rounded-md bg-[var(--ash-avatar-assistant-bg)] flex items-center justify-center shrink-0 mt-0.5", style: { width: "var(--ash-avatar-size, 1.25rem)", height: "var(--ash-avatar-size, 1.25rem)" }, children: /* @__PURE__ */ jsxRuntime.jsx(BotIcon, { className: "w-3 h-3 text-[var(--ash-accent)]" }) }),
|
|
2494
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: config.mode === "accordion" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2285
2495
|
StepAccordion,
|
|
2286
2496
|
{
|
|
2287
2497
|
toolCalls,
|
|
@@ -2297,13 +2507,13 @@ function MessageList({
|
|
|
2297
2507
|
) })
|
|
2298
2508
|
] }, groupedEntry.id);
|
|
2299
2509
|
}),
|
|
2300
|
-
streamingContent && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex
|
|
2301
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
2302
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1
|
|
2510
|
+
streamingContent && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ash-message-row flex ash-animate-fade-in pl-1", style: { gap: "var(--ash-message-gap, 0.5rem)" }, children: [
|
|
2511
|
+
showAvatars && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ash-avatar rounded-md bg-[var(--ash-avatar-assistant-bg)] flex items-center justify-center shrink-0 mt-0.5", style: { width: "var(--ash-avatar-size, 1.25rem)", height: "var(--ash-avatar-size, 1.25rem)" }, children: /* @__PURE__ */ jsxRuntime.jsx(BotIcon, { className: "w-3 h-3 text-[var(--ash-accent)]" }) }),
|
|
2512
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ash-message-bubble rounded-lg bg-white/[0.03] text-white/80 leading-relaxed", style: { padding: "var(--ash-message-padding, 0.5rem 0.75rem)", fontSize: "var(--ash-font-size-base, 13px)" }, children: /* @__PURE__ */ jsxRuntime.jsx(StreamingText, { content: streamingContent, isStreaming: true }) }) })
|
|
2303
2513
|
] }),
|
|
2304
|
-
loading && !streamingContent && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex
|
|
2305
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
2306
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-
|
|
2514
|
+
loading && !streamingContent && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ash-message-row flex ash-animate-fade-in pl-1", style: { gap: "var(--ash-message-gap, 0.5rem)" }, children: [
|
|
2515
|
+
showAvatars && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ash-avatar rounded-md bg-[var(--ash-avatar-assistant-bg)] flex items-center justify-center shrink-0 mt-0.5", style: { width: "var(--ash-avatar-size, 1.25rem)", height: "var(--ash-avatar-size, 1.25rem)" }, children: /* @__PURE__ */ jsxRuntime.jsx(BotIcon, { className: "w-3 h-3 text-[var(--ash-accent)]" }) }),
|
|
2516
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg px-3 py-1.5 bg-white/[0.03]", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator, { variant: "dots" }) })
|
|
2307
2517
|
] }),
|
|
2308
2518
|
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: messagesEndRef })
|
|
2309
2519
|
] });
|
|
@@ -3120,6 +3330,21 @@ var typography = {
|
|
|
3120
3330
|
relaxed: "1.75"
|
|
3121
3331
|
}
|
|
3122
3332
|
};
|
|
3333
|
+
var cssVars = {
|
|
3334
|
+
fontSize: {
|
|
3335
|
+
base: "--ash-font-size-base",
|
|
3336
|
+
sm: "--ash-font-size-sm",
|
|
3337
|
+
xs: "--ash-font-size-xs",
|
|
3338
|
+
code: "--ash-font-size-code"
|
|
3339
|
+
},
|
|
3340
|
+
accent: "--ash-accent",
|
|
3341
|
+
accentForeground: "--ash-accent-foreground",
|
|
3342
|
+
surfaceDark: "--ash-surface-dark",
|
|
3343
|
+
surfaceDarker: "--ash-surface-darker",
|
|
3344
|
+
surfaceCard: "--ash-surface-card",
|
|
3345
|
+
surfaceElevated: "--ash-surface-elevated",
|
|
3346
|
+
surfaceBorder: "--ash-surface-border"
|
|
3347
|
+
};
|
|
3123
3348
|
var keyframes = {
|
|
3124
3349
|
slideUp: {
|
|
3125
3350
|
from: { opacity: "0", transform: "translateY(20px)" },
|
|
@@ -3238,6 +3463,10 @@ function tokensToCssVariables(prefix = "ash") {
|
|
|
3238
3463
|
if (key !== "DEFAULT") vars[`--${prefix}-border-${key}`] = value;
|
|
3239
3464
|
else vars[`--${prefix}-border`] = value;
|
|
3240
3465
|
});
|
|
3466
|
+
vars[`--${prefix}-font-size-base`] = "14px";
|
|
3467
|
+
vars[`--${prefix}-font-size-sm`] = "12px";
|
|
3468
|
+
vars[`--${prefix}-font-size-xs`] = "11px";
|
|
3469
|
+
vars[`--${prefix}-font-size-code`] = "13px";
|
|
3241
3470
|
return vars;
|
|
3242
3471
|
}
|
|
3243
3472
|
var inlineStyles = {
|
|
@@ -3493,19 +3722,95 @@ function useFileUpload({
|
|
|
3493
3722
|
openFilePicker
|
|
3494
3723
|
};
|
|
3495
3724
|
}
|
|
3725
|
+
|
|
3726
|
+
// src/hooks/middleware.ts
|
|
3727
|
+
async function applyRequestMiddleware(middlewares, request) {
|
|
3728
|
+
let current = { ...request };
|
|
3729
|
+
for (const mw of middlewares) {
|
|
3730
|
+
if (mw.onRequest) {
|
|
3731
|
+
try {
|
|
3732
|
+
const result = await mw.onRequest(current);
|
|
3733
|
+
if (result?.error) {
|
|
3734
|
+
return { request: current, error: result.error };
|
|
3735
|
+
}
|
|
3736
|
+
if (result) {
|
|
3737
|
+
current = {
|
|
3738
|
+
...current,
|
|
3739
|
+
prompt: result.prompt ?? current.prompt,
|
|
3740
|
+
sessionContext: result.sessionContext ?? current.sessionContext,
|
|
3741
|
+
metadata: {
|
|
3742
|
+
...current.metadata,
|
|
3743
|
+
...result.metadata
|
|
3744
|
+
}
|
|
3745
|
+
};
|
|
3746
|
+
}
|
|
3747
|
+
} catch (err) {
|
|
3748
|
+
const errorMessage = err instanceof Error ? err.message : "Middleware error";
|
|
3749
|
+
return { request: current, error: errorMessage };
|
|
3750
|
+
}
|
|
3751
|
+
}
|
|
3752
|
+
}
|
|
3753
|
+
return { request: current };
|
|
3754
|
+
}
|
|
3755
|
+
async function applyEventMiddleware(middlewares, event) {
|
|
3756
|
+
let current = event;
|
|
3757
|
+
for (const mw of middlewares) {
|
|
3758
|
+
if (!current) break;
|
|
3759
|
+
if (mw.onEvent) {
|
|
3760
|
+
try {
|
|
3761
|
+
current = await mw.onEvent(current);
|
|
3762
|
+
} catch (err) {
|
|
3763
|
+
console.error("[middleware] onEvent error:", err);
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
3766
|
+
}
|
|
3767
|
+
return current;
|
|
3768
|
+
}
|
|
3769
|
+
async function callMiddlewareComplete(middlewares, sessionId) {
|
|
3770
|
+
for (const mw of middlewares) {
|
|
3771
|
+
if (mw.onComplete) {
|
|
3772
|
+
try {
|
|
3773
|
+
await mw.onComplete(sessionId);
|
|
3774
|
+
} catch (err) {
|
|
3775
|
+
console.error("[middleware] onComplete error:", err);
|
|
3776
|
+
}
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3780
|
+
async function callMiddlewareError(middlewares, error) {
|
|
3781
|
+
for (const mw of middlewares) {
|
|
3782
|
+
if (mw.onError) {
|
|
3783
|
+
try {
|
|
3784
|
+
await mw.onError(error);
|
|
3785
|
+
} catch (err) {
|
|
3786
|
+
console.error("[middleware] onError error:", err);
|
|
3787
|
+
}
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3791
|
+
|
|
3792
|
+
// src/hooks/useAgentChat.ts
|
|
3496
3793
|
function useAgentChat(options) {
|
|
3497
3794
|
const {
|
|
3498
3795
|
createStream,
|
|
3796
|
+
subscribeToSession,
|
|
3499
3797
|
initialSessionId,
|
|
3500
3798
|
initialEntries = [],
|
|
3501
3799
|
onSessionStart,
|
|
3502
3800
|
onSessionEnd,
|
|
3503
3801
|
onError,
|
|
3504
|
-
onSandboxLog
|
|
3802
|
+
onSandboxLog,
|
|
3803
|
+
onReconnect,
|
|
3804
|
+
maxReconnectAttempts = 3,
|
|
3805
|
+
reconnectBaseDelay = 1e3,
|
|
3806
|
+
onBeforeSend,
|
|
3807
|
+
onEvent,
|
|
3808
|
+
middleware
|
|
3505
3809
|
} = options;
|
|
3506
3810
|
const [historyEntries, setHistoryEntries] = react.useState(initialEntries);
|
|
3507
3811
|
const [streamingEntries, setStreamingEntries] = react.useState([]);
|
|
3508
3812
|
const [isStreaming, setIsStreaming] = react.useState(false);
|
|
3813
|
+
const [isReconnecting, setIsReconnecting] = react.useState(false);
|
|
3509
3814
|
const [error, setError] = react.useState(null);
|
|
3510
3815
|
const [sessionId, setSessionId] = react.useState(initialSessionId || null);
|
|
3511
3816
|
const abortControllerRef = react.useRef(null);
|
|
@@ -3513,6 +3818,16 @@ function useAgentChat(options) {
|
|
|
3513
3818
|
const currentTextIdRef = react.useRef(null);
|
|
3514
3819
|
const pendingToolCallsRef = react.useRef(/* @__PURE__ */ new Map());
|
|
3515
3820
|
const hadToolCallSinceTextRef = react.useRef(false);
|
|
3821
|
+
const reconnectAttemptsRef = react.useRef(0);
|
|
3822
|
+
const eventCountRef = react.useRef(0);
|
|
3823
|
+
const sessionIdRef = react.useRef(sessionId);
|
|
3824
|
+
const streamingEntriesRef = react.useRef([]);
|
|
3825
|
+
react.useEffect(() => {
|
|
3826
|
+
sessionIdRef.current = sessionId;
|
|
3827
|
+
}, [sessionId]);
|
|
3828
|
+
react.useEffect(() => {
|
|
3829
|
+
streamingEntriesRef.current = streamingEntries;
|
|
3830
|
+
}, [streamingEntries]);
|
|
3516
3831
|
const entries = [...historyEntries, ...streamingEntries];
|
|
3517
3832
|
const emitStreamingEntries = react.useCallback((newEntries) => {
|
|
3518
3833
|
setStreamingEntries([...newEntries]);
|
|
@@ -3627,7 +3942,7 @@ function useAgentChat(options) {
|
|
|
3627
3942
|
setError(event.error);
|
|
3628
3943
|
onError?.(event.error);
|
|
3629
3944
|
newEntries.push({
|
|
3630
|
-
id: `error-${Date.now()}`,
|
|
3945
|
+
id: `error-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
3631
3946
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3632
3947
|
entryType: { type: "error", message: event.error, code: event.code },
|
|
3633
3948
|
content: event.error
|
|
@@ -3646,12 +3961,112 @@ function useAgentChat(options) {
|
|
|
3646
3961
|
}
|
|
3647
3962
|
return newEntries;
|
|
3648
3963
|
}, [sessionId, onSessionStart, onSessionEnd, onError, onSandboxLog, createTextEntry, resetStreamingState]);
|
|
3964
|
+
const attemptReconnect = react.useCallback(async (targetSessionId, currentEntries) => {
|
|
3965
|
+
if (!subscribeToSession) {
|
|
3966
|
+
return false;
|
|
3967
|
+
}
|
|
3968
|
+
const attempt = reconnectAttemptsRef.current + 1;
|
|
3969
|
+
if (attempt > maxReconnectAttempts) {
|
|
3970
|
+
console.warn(`[useAgentChat] Max reconnection attempts (${maxReconnectAttempts}) exceeded`);
|
|
3971
|
+
return false;
|
|
3972
|
+
}
|
|
3973
|
+
reconnectAttemptsRef.current = attempt;
|
|
3974
|
+
setIsReconnecting(true);
|
|
3975
|
+
onReconnect?.(attempt, targetSessionId);
|
|
3976
|
+
const delay = reconnectBaseDelay * Math.pow(2, attempt - 1);
|
|
3977
|
+
console.log(`[useAgentChat] Reconnection attempt ${attempt}/${maxReconnectAttempts} in ${delay}ms`);
|
|
3978
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
3979
|
+
const controller = new AbortController();
|
|
3980
|
+
abortControllerRef.current = controller;
|
|
3981
|
+
try {
|
|
3982
|
+
const stream = subscribeToSession(targetSessionId, controller.signal);
|
|
3983
|
+
let localStreamingEntries = [...currentEntries];
|
|
3984
|
+
for await (const event of stream) {
|
|
3985
|
+
if (controller.signal.aborted) break;
|
|
3986
|
+
eventCountRef.current++;
|
|
3987
|
+
localStreamingEntries = processEvent(event, localStreamingEntries);
|
|
3988
|
+
emitStreamingEntries(localStreamingEntries);
|
|
3989
|
+
if (event.type === "complete" || event.type === "session_end" || event.type === "error") {
|
|
3990
|
+
reconnectAttemptsRef.current = 0;
|
|
3991
|
+
setIsReconnecting(false);
|
|
3992
|
+
if (event.type === "complete" && localStreamingEntries.length > 0) {
|
|
3993
|
+
setHistoryEntries((prev) => [...prev, ...localStreamingEntries]);
|
|
3994
|
+
setStreamingEntries([]);
|
|
3995
|
+
}
|
|
3996
|
+
return true;
|
|
3997
|
+
}
|
|
3998
|
+
}
|
|
3999
|
+
reconnectAttemptsRef.current = 0;
|
|
4000
|
+
setIsReconnecting(false);
|
|
4001
|
+
if (localStreamingEntries.length > 0) {
|
|
4002
|
+
setHistoryEntries((prev) => [...prev, ...localStreamingEntries]);
|
|
4003
|
+
setStreamingEntries([]);
|
|
4004
|
+
}
|
|
4005
|
+
return true;
|
|
4006
|
+
} catch (err) {
|
|
4007
|
+
const isAbort = err.name === "AbortError" || err.message?.includes("aborted") || err.message?.includes("BodyStreamBuffer");
|
|
4008
|
+
if (isAbort && !controller.signal.aborted) {
|
|
4009
|
+
console.log(`[useAgentChat] Reconnection stream interrupted, will retry...`);
|
|
4010
|
+
setIsReconnecting(false);
|
|
4011
|
+
return attemptReconnect(targetSessionId, streamingEntriesRef.current);
|
|
4012
|
+
}
|
|
4013
|
+
setIsReconnecting(false);
|
|
4014
|
+
if (!controller.signal.aborted) {
|
|
4015
|
+
const errorMessage = err instanceof Error ? err.message : "Reconnection failed";
|
|
4016
|
+
console.error(`[useAgentChat] Reconnection failed:`, errorMessage);
|
|
4017
|
+
}
|
|
4018
|
+
return false;
|
|
4019
|
+
}
|
|
4020
|
+
}, [subscribeToSession, maxReconnectAttempts, reconnectBaseDelay, onReconnect, processEvent, emitStreamingEntries]);
|
|
3649
4021
|
const send = react.useCallback(async (prompt) => {
|
|
3650
4022
|
if (isStreaming) return;
|
|
4023
|
+
let finalPrompt = prompt;
|
|
4024
|
+
let additionalMetadata = {};
|
|
4025
|
+
let additionalContext;
|
|
4026
|
+
if (onBeforeSend) {
|
|
4027
|
+
try {
|
|
4028
|
+
const result = await onBeforeSend({
|
|
4029
|
+
prompt,
|
|
4030
|
+
sessionId,
|
|
4031
|
+
entries: [...historyEntries, ...streamingEntries]
|
|
4032
|
+
});
|
|
4033
|
+
if (result?.cancel) {
|
|
4034
|
+
return;
|
|
4035
|
+
}
|
|
4036
|
+
if (result?.prompt !== void 0) finalPrompt = result.prompt;
|
|
4037
|
+
if (result?.metadata) additionalMetadata = result.metadata;
|
|
4038
|
+
if (result?.sessionContext) additionalContext = result.sessionContext;
|
|
4039
|
+
} catch (err) {
|
|
4040
|
+
const errorMessage = err instanceof Error ? err.message : "Send cancelled";
|
|
4041
|
+
setError(errorMessage);
|
|
4042
|
+
onError?.(errorMessage);
|
|
4043
|
+
return;
|
|
4044
|
+
}
|
|
4045
|
+
}
|
|
4046
|
+
if (middleware?.length) {
|
|
4047
|
+
const middlewareRequest = {
|
|
4048
|
+
prompt: finalPrompt,
|
|
4049
|
+
sessionId,
|
|
4050
|
+
metadata: additionalMetadata,
|
|
4051
|
+
sessionContext: additionalContext
|
|
4052
|
+
};
|
|
4053
|
+
const { request, error: middlewareError } = await applyRequestMiddleware(middleware, middlewareRequest);
|
|
4054
|
+
if (middlewareError) {
|
|
4055
|
+
setError(middlewareError);
|
|
4056
|
+
onError?.(middlewareError);
|
|
4057
|
+
await callMiddlewareError(middleware, middlewareError);
|
|
4058
|
+
return;
|
|
4059
|
+
}
|
|
4060
|
+
finalPrompt = request.prompt;
|
|
4061
|
+
additionalMetadata = request.metadata || {};
|
|
4062
|
+
additionalContext = request.sessionContext;
|
|
4063
|
+
}
|
|
3651
4064
|
setIsStreaming(true);
|
|
3652
4065
|
setError(null);
|
|
4066
|
+
reconnectAttemptsRef.current = 0;
|
|
4067
|
+
eventCountRef.current = 0;
|
|
3653
4068
|
const userEntry = {
|
|
3654
|
-
id: `user-${Date.now()}`,
|
|
4069
|
+
id: `user-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
3655
4070
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3656
4071
|
entryType: { type: "user_message" },
|
|
3657
4072
|
content: prompt
|
|
@@ -3661,39 +4076,91 @@ function useAgentChat(options) {
|
|
|
3661
4076
|
const controller = new AbortController();
|
|
3662
4077
|
abortControllerRef.current = controller;
|
|
3663
4078
|
let localStreamingEntries = [];
|
|
4079
|
+
let completedSessionId = null;
|
|
3664
4080
|
try {
|
|
3665
|
-
const stream = createStream(
|
|
4081
|
+
const stream = createStream(finalPrompt, sessionId || void 0, {
|
|
4082
|
+
signal: controller.signal,
|
|
4083
|
+
metadata: Object.keys(additionalMetadata).length > 0 ? additionalMetadata : void 0,
|
|
4084
|
+
sessionContext: additionalContext
|
|
4085
|
+
});
|
|
3666
4086
|
for await (const event of stream) {
|
|
3667
4087
|
if (controller.signal.aborted) break;
|
|
3668
|
-
|
|
4088
|
+
eventCountRef.current++;
|
|
4089
|
+
if (event.type === "session_start" && event.sessionId) {
|
|
4090
|
+
completedSessionId = event.sessionId;
|
|
4091
|
+
}
|
|
4092
|
+
if (onEvent) {
|
|
4093
|
+
try {
|
|
4094
|
+
await onEvent(event);
|
|
4095
|
+
} catch (err) {
|
|
4096
|
+
console.error("[useAgentChat] onEvent error:", err);
|
|
4097
|
+
}
|
|
4098
|
+
}
|
|
4099
|
+
let processedEvent = event;
|
|
4100
|
+
if (middleware?.length) {
|
|
4101
|
+
processedEvent = await applyEventMiddleware(middleware, event);
|
|
4102
|
+
}
|
|
4103
|
+
if (!processedEvent) continue;
|
|
4104
|
+
localStreamingEntries = processEvent(processedEvent, localStreamingEntries);
|
|
3669
4105
|
emitStreamingEntries(localStreamingEntries);
|
|
3670
4106
|
}
|
|
3671
4107
|
if (localStreamingEntries.length > 0) {
|
|
3672
4108
|
setHistoryEntries((prev) => [...prev, ...localStreamingEntries]);
|
|
3673
4109
|
setStreamingEntries([]);
|
|
3674
4110
|
}
|
|
4111
|
+
reconnectAttemptsRef.current = 0;
|
|
4112
|
+
if (middleware?.length && (completedSessionId || sessionIdRef.current)) {
|
|
4113
|
+
await callMiddlewareComplete(middleware, completedSessionId || sessionIdRef.current || "");
|
|
4114
|
+
}
|
|
3675
4115
|
} catch (err) {
|
|
3676
|
-
|
|
4116
|
+
const isAbort = err.name === "AbortError" || err.message?.includes("aborted") || err.message?.includes("BodyStreamBuffer");
|
|
4117
|
+
if (isAbort && !controller.signal.aborted) {
|
|
4118
|
+
const currentSessionId = sessionIdRef.current;
|
|
4119
|
+
const hadEvents = eventCountRef.current > 0;
|
|
4120
|
+
console.log(`[useAgentChat] Stream interrupted. sessionId=${currentSessionId}, events=${eventCountRef.current}`);
|
|
4121
|
+
if (currentSessionId && hadEvents && subscribeToSession) {
|
|
4122
|
+
console.log(`[useAgentChat] Attempting auto-reconnection...`);
|
|
4123
|
+
const reconnected = await attemptReconnect(currentSessionId, streamingEntriesRef.current);
|
|
4124
|
+
if (reconnected) {
|
|
4125
|
+
return;
|
|
4126
|
+
}
|
|
4127
|
+
const errorMsg = "Connection lost. Please try again.";
|
|
4128
|
+
setError(errorMsg);
|
|
4129
|
+
onError?.(errorMsg);
|
|
4130
|
+
if (middleware?.length) {
|
|
4131
|
+
await callMiddlewareError(middleware, errorMsg);
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
4134
|
+
} else if (!isAbort) {
|
|
3677
4135
|
const errorMessage = err instanceof Error ? err.message : "Unknown error";
|
|
3678
4136
|
setError(errorMessage);
|
|
3679
4137
|
onError?.(errorMessage);
|
|
4138
|
+
if (middleware?.length) {
|
|
4139
|
+
await callMiddlewareError(middleware, errorMessage);
|
|
4140
|
+
}
|
|
3680
4141
|
}
|
|
3681
4142
|
} finally {
|
|
3682
4143
|
setIsStreaming(false);
|
|
4144
|
+
setIsReconnecting(false);
|
|
3683
4145
|
abortControllerRef.current = null;
|
|
3684
4146
|
resetStreamingState();
|
|
3685
4147
|
}
|
|
3686
|
-
}, [isStreaming, sessionId, createStream, processEvent, emitStreamingEntries, resetStreamingState, onError]);
|
|
4148
|
+
}, [isStreaming, sessionId, historyEntries, streamingEntries, createStream, subscribeToSession, processEvent, emitStreamingEntries, resetStreamingState, onError, attemptReconnect, onBeforeSend, onEvent, middleware]);
|
|
3687
4149
|
const stop = react.useCallback(() => {
|
|
4150
|
+
reconnectAttemptsRef.current = maxReconnectAttempts + 1;
|
|
4151
|
+
setIsReconnecting(false);
|
|
3688
4152
|
if (abortControllerRef.current) {
|
|
3689
4153
|
abortControllerRef.current.abort();
|
|
3690
4154
|
}
|
|
3691
|
-
}, []);
|
|
4155
|
+
}, [maxReconnectAttempts]);
|
|
3692
4156
|
const clear = react.useCallback(() => {
|
|
3693
4157
|
setHistoryEntries([]);
|
|
3694
4158
|
resetStreamingState();
|
|
3695
4159
|
setSessionId(initialSessionId || null);
|
|
3696
4160
|
setError(null);
|
|
4161
|
+
setIsReconnecting(false);
|
|
4162
|
+
reconnectAttemptsRef.current = 0;
|
|
4163
|
+
eventCountRef.current = 0;
|
|
3697
4164
|
}, [initialSessionId, resetStreamingState]);
|
|
3698
4165
|
const setEntries = react.useCallback((newEntries) => {
|
|
3699
4166
|
resetStreamingState();
|
|
@@ -3709,6 +4176,7 @@ function useAgentChat(options) {
|
|
|
3709
4176
|
return {
|
|
3710
4177
|
entries,
|
|
3711
4178
|
isStreaming,
|
|
4179
|
+
isReconnecting,
|
|
3712
4180
|
error,
|
|
3713
4181
|
sessionId,
|
|
3714
4182
|
send,
|
|
@@ -3794,6 +4262,7 @@ exports.ActionIcon = ActionIcon;
|
|
|
3794
4262
|
exports.AgentToolCard = AgentToolCard;
|
|
3795
4263
|
exports.AlertCircleIcon = AlertCircleIcon;
|
|
3796
4264
|
exports.AlertTriangleIcon = AlertTriangleIcon;
|
|
4265
|
+
exports.ArrowUpIcon = ArrowUpIcon;
|
|
3797
4266
|
exports.AssistantMessage = AssistantMessage;
|
|
3798
4267
|
exports.BotIcon = BotIcon;
|
|
3799
4268
|
exports.BrainIcon = BrainIcon;
|
|
@@ -3813,6 +4282,7 @@ exports.CompactToolRow = CompactToolRow;
|
|
|
3813
4282
|
exports.CompactToolStatusLine = CompactToolStatusLine;
|
|
3814
4283
|
exports.CopyIcon = CopyIcon;
|
|
3815
4284
|
exports.DEFAULT_DISPLAY_CONFIG = DEFAULT_DISPLAY_CONFIG;
|
|
4285
|
+
exports.DEFAULT_STYLE_CONFIG = DEFAULT_STYLE_CONFIG;
|
|
3816
4286
|
exports.DisplayModeProvider = DisplayModeProvider;
|
|
3817
4287
|
exports.DisplayModeToggle = DisplayModeToggle;
|
|
3818
4288
|
exports.EditIcon = EditIcon;
|
|
@@ -3824,6 +4294,7 @@ exports.FileIcon = FileIcon;
|
|
|
3824
4294
|
exports.FilePlusIcon = FilePlusIcon;
|
|
3825
4295
|
exports.FolderSearchIcon = FolderSearchIcon;
|
|
3826
4296
|
exports.GlobeIcon = GlobeIcon;
|
|
4297
|
+
exports.HomeIcon = HomeIcon;
|
|
3827
4298
|
exports.InfoIcon = InfoIcon;
|
|
3828
4299
|
exports.JsonDisplay = JsonDisplay;
|
|
3829
4300
|
exports.LazyMarkdown = LazyMarkdown;
|
|
@@ -3834,6 +4305,7 @@ exports.LogsPanel = LogsPanel;
|
|
|
3834
4305
|
exports.MessageEntry = MessageEntry;
|
|
3835
4306
|
exports.MessageList = MessageList;
|
|
3836
4307
|
exports.MessageSquareIcon = MessageSquareIcon;
|
|
4308
|
+
exports.MicrophoneIcon = MicrophoneIcon;
|
|
3837
4309
|
exports.MoonIcon = MoonIcon;
|
|
3838
4310
|
exports.OptionCards = OptionCards;
|
|
3839
4311
|
exports.PaperclipIcon = PaperclipIcon;
|
|
@@ -3862,10 +4334,15 @@ exports.UserMessage = UserMessage;
|
|
|
3862
4334
|
exports.XCircleIcon = XCircleIcon;
|
|
3863
4335
|
exports.XIcon = XIcon;
|
|
3864
4336
|
exports.allKeyframesCss = allKeyframesCss;
|
|
4337
|
+
exports.applyEventMiddleware = applyEventMiddleware;
|
|
4338
|
+
exports.applyRequestMiddleware = applyRequestMiddleware;
|
|
3865
4339
|
exports.borderRadius = borderRadius;
|
|
4340
|
+
exports.callMiddlewareComplete = callMiddlewareComplete;
|
|
4341
|
+
exports.callMiddlewareError = callMiddlewareError;
|
|
3866
4342
|
exports.cn = cn;
|
|
3867
4343
|
exports.colors = colors;
|
|
3868
4344
|
exports.createToolCall = createToolCall;
|
|
4345
|
+
exports.cssVars = cssVars;
|
|
3869
4346
|
exports.extractTextContent = extractTextContent;
|
|
3870
4347
|
exports.extractToolCallsFromGroup = extractToolCallsFromGroup;
|
|
3871
4348
|
exports.formatElapsedTime = formatElapsedTime;
|