@ash-cloud/ash-ui 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +839 -338
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +330 -17
- package/dist/index.d.ts +330 -17
- package/dist/index.js +837 -340
- package/dist/index.js.map +1 -1
- package/dist/styles-full.css +1 -0
- package/dist/styles.css +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +8 -0
- package/dist/types.d.ts +8 -0
- package/dist/types.js.map +1 -1
- package/dist/utils.cjs +22 -8
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.js +22 -8
- package/dist/utils.js.map +1 -1
- package/package.json +6 -3
package/dist/index.cjs
CHANGED
|
@@ -41,27 +41,41 @@ function mapToolToActionType(toolName, input) {
|
|
|
41
41
|
command: inputObj.command || "",
|
|
42
42
|
description: inputObj.description
|
|
43
43
|
};
|
|
44
|
-
case "Read":
|
|
44
|
+
case "Read": {
|
|
45
|
+
const limit = inputObj.limit;
|
|
45
46
|
return {
|
|
46
47
|
action: "file_read",
|
|
47
48
|
path: inputObj.file_path || "",
|
|
48
49
|
offset: inputObj.offset,
|
|
49
|
-
limit
|
|
50
|
+
limit,
|
|
51
|
+
linesRead: limit
|
|
52
|
+
// Use limit as approximate lines read if specified
|
|
50
53
|
};
|
|
51
|
-
|
|
54
|
+
}
|
|
55
|
+
case "Edit": {
|
|
56
|
+
const oldStr = inputObj.old_string;
|
|
57
|
+
const newStr = inputObj.new_string;
|
|
58
|
+
const oldLines = oldStr ? oldStr.split("\n").length : 0;
|
|
59
|
+
const newLines = newStr ? newStr.split("\n").length : 0;
|
|
52
60
|
return {
|
|
53
61
|
action: "file_edit",
|
|
54
62
|
path: inputObj.file_path || "",
|
|
55
|
-
oldString:
|
|
56
|
-
newString:
|
|
57
|
-
replaceAll: inputObj.replace_all
|
|
63
|
+
oldString: oldStr,
|
|
64
|
+
newString: newStr,
|
|
65
|
+
replaceAll: inputObj.replace_all,
|
|
66
|
+
linesAdded: newLines,
|
|
67
|
+
linesRemoved: oldLines
|
|
58
68
|
};
|
|
59
|
-
|
|
69
|
+
}
|
|
70
|
+
case "Write": {
|
|
71
|
+
const content = inputObj.content;
|
|
60
72
|
return {
|
|
61
73
|
action: "file_write",
|
|
62
74
|
path: inputObj.file_path || "",
|
|
63
|
-
content
|
|
75
|
+
content,
|
|
76
|
+
linesWritten: content ? content.split("\n").length : void 0
|
|
64
77
|
};
|
|
78
|
+
}
|
|
65
79
|
case "Grep":
|
|
66
80
|
return {
|
|
67
81
|
action: "search",
|
|
@@ -1310,275 +1324,422 @@ function StreamingText({
|
|
|
1310
1324
|
isStreaming && /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator, { variant: "cursor", size: "sm", className: "inline-block ml-0.5" })
|
|
1311
1325
|
] }) });
|
|
1312
1326
|
}
|
|
1313
|
-
function
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1327
|
+
function getFilePath(actionType) {
|
|
1328
|
+
switch (actionType.action) {
|
|
1329
|
+
case "file_read":
|
|
1330
|
+
case "file_edit":
|
|
1331
|
+
case "file_write":
|
|
1332
|
+
return actionType.path;
|
|
1333
|
+
default:
|
|
1334
|
+
return null;
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
function getFileName(path) {
|
|
1338
|
+
const parts = path.split("/");
|
|
1339
|
+
return parts[parts.length - 1] || path;
|
|
1340
|
+
}
|
|
1341
|
+
function getFileExtension(path) {
|
|
1342
|
+
const fileName = getFileName(path);
|
|
1343
|
+
const dotIndex = fileName.lastIndexOf(".");
|
|
1344
|
+
if (dotIndex === -1) return null;
|
|
1345
|
+
return fileName.slice(dotIndex + 1).toLowerCase();
|
|
1346
|
+
}
|
|
1347
|
+
function getDiffStats(actionType) {
|
|
1348
|
+
switch (actionType.action) {
|
|
1349
|
+
case "file_edit": {
|
|
1350
|
+
const edit = actionType;
|
|
1351
|
+
if (edit.linesAdded !== void 0 || edit.linesRemoved !== void 0) {
|
|
1352
|
+
return { added: edit.linesAdded, removed: edit.linesRemoved };
|
|
1338
1353
|
}
|
|
1339
|
-
|
|
1340
|
-
setDisplayedToolCall(toolCall);
|
|
1354
|
+
return null;
|
|
1341
1355
|
}
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1356
|
+
case "file_read": {
|
|
1357
|
+
const read = actionType;
|
|
1358
|
+
if (read.linesRead !== void 0) {
|
|
1359
|
+
return { read: read.linesRead };
|
|
1360
|
+
}
|
|
1361
|
+
return null;
|
|
1362
|
+
}
|
|
1363
|
+
case "file_write": {
|
|
1364
|
+
const write = actionType;
|
|
1365
|
+
if (write.linesWritten !== void 0) {
|
|
1366
|
+
return { written: write.linesWritten };
|
|
1367
|
+
}
|
|
1368
|
+
return null;
|
|
1369
|
+
}
|
|
1370
|
+
default:
|
|
1371
|
+
return null;
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
function getFileTypeColor(ext) {
|
|
1375
|
+
switch (ext) {
|
|
1376
|
+
case "ts":
|
|
1377
|
+
case "tsx":
|
|
1378
|
+
return "text-blue-400";
|
|
1379
|
+
case "js":
|
|
1380
|
+
case "jsx":
|
|
1381
|
+
return "text-yellow-400";
|
|
1382
|
+
case "md":
|
|
1383
|
+
return "text-white/60";
|
|
1384
|
+
case "json":
|
|
1385
|
+
return "text-orange-400";
|
|
1386
|
+
case "sh":
|
|
1387
|
+
return "text-green-400";
|
|
1388
|
+
case "css":
|
|
1389
|
+
case "scss":
|
|
1390
|
+
return "text-pink-400";
|
|
1391
|
+
case "py":
|
|
1392
|
+
return "text-blue-300";
|
|
1393
|
+
default:
|
|
1394
|
+
return "text-white/70";
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
function CompactToolRow({ toolCall, showFullPath = false, className }) {
|
|
1398
|
+
const { actionType, status, summary } = toolCall;
|
|
1399
|
+
const label = getActionLabel(actionType);
|
|
1400
|
+
const filePath = getFilePath(actionType);
|
|
1401
|
+
const diffStats = getDiffStats(actionType);
|
|
1402
|
+
const displayPath = filePath ? showFullPath ? filePath : getFileName(filePath) : null;
|
|
1403
|
+
const ext = filePath ? getFileExtension(filePath) : null;
|
|
1404
|
+
const fileColor = getFileTypeColor(ext);
|
|
1405
|
+
const showSummary = !filePath && summary;
|
|
1406
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1350
1407
|
"div",
|
|
1351
1408
|
{
|
|
1352
1409
|
className: cn(
|
|
1353
|
-
"flex items-center gap-
|
|
1354
|
-
|
|
1410
|
+
"flex items-center gap-2 py-1.5 text-sm min-w-0",
|
|
1411
|
+
className
|
|
1355
1412
|
),
|
|
1356
|
-
style: {
|
|
1357
|
-
animationDuration: `${animationDuration}ms`
|
|
1358
|
-
},
|
|
1359
1413
|
children: [
|
|
1360
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1381
|
-
|
|
1414
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 shrink-0", children: [
|
|
1415
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1416
|
+
ActionIcon,
|
|
1417
|
+
{
|
|
1418
|
+
actionType,
|
|
1419
|
+
className: cn(
|
|
1420
|
+
"w-3.5 h-3.5",
|
|
1421
|
+
status === "pending" ? "text-yellow-400" : status === "failed" ? "text-red-400" : "text-white/50"
|
|
1422
|
+
)
|
|
1423
|
+
}
|
|
1424
|
+
),
|
|
1425
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
1426
|
+
"font-medium",
|
|
1427
|
+
status === "pending" ? "text-white/90" : status === "failed" ? "text-red-400" : "text-white/60"
|
|
1428
|
+
), children: label })
|
|
1429
|
+
] }),
|
|
1430
|
+
displayPath && /* @__PURE__ */ jsxRuntime.jsx("code", { className: cn(
|
|
1431
|
+
"px-1.5 py-0.5 rounded bg-white/5 font-mono text-xs truncate max-w-[200px]",
|
|
1432
|
+
fileColor
|
|
1433
|
+
), children: displayPath }),
|
|
1434
|
+
diffStats && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-xs shrink-0 font-mono", children: [
|
|
1435
|
+
diffStats.added !== void 0 && diffStats.added > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-emerald-400", children: [
|
|
1436
|
+
"+",
|
|
1437
|
+
diffStats.added
|
|
1438
|
+
] }),
|
|
1439
|
+
diffStats.removed !== void 0 && diffStats.removed > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-red-400", children: [
|
|
1440
|
+
"-",
|
|
1441
|
+
diffStats.removed
|
|
1442
|
+
] }),
|
|
1443
|
+
diffStats.read !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-white/40", children: [
|
|
1444
|
+
diffStats.read,
|
|
1445
|
+
" lines"
|
|
1446
|
+
] }),
|
|
1447
|
+
diffStats.written !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-emerald-400", children: [
|
|
1448
|
+
"+",
|
|
1449
|
+
diffStats.written
|
|
1450
|
+
] })
|
|
1451
|
+
] }),
|
|
1452
|
+
showSummary && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-white/40 truncate min-w-0 text-xs", children: summary })
|
|
1382
1453
|
]
|
|
1383
1454
|
}
|
|
1384
1455
|
);
|
|
1456
|
+
}
|
|
1457
|
+
function getFileExtension2(path) {
|
|
1458
|
+
const fileName = path.split("/").pop() || path;
|
|
1459
|
+
const dotIndex = fileName.lastIndexOf(".");
|
|
1460
|
+
if (dotIndex === -1) return null;
|
|
1461
|
+
return fileName.slice(dotIndex + 1).toLowerCase();
|
|
1462
|
+
}
|
|
1463
|
+
function getFileIcon(ext) {
|
|
1464
|
+
switch (ext) {
|
|
1465
|
+
case "ts":
|
|
1466
|
+
case "tsx":
|
|
1467
|
+
return "TS";
|
|
1468
|
+
case "js":
|
|
1469
|
+
case "jsx":
|
|
1470
|
+
return "JS";
|
|
1471
|
+
case "md":
|
|
1472
|
+
return "MD";
|
|
1473
|
+
case "json":
|
|
1474
|
+
return "{}";
|
|
1475
|
+
case "sh":
|
|
1476
|
+
return "$";
|
|
1477
|
+
case "css":
|
|
1478
|
+
case "scss":
|
|
1479
|
+
return "#";
|
|
1480
|
+
case "py":
|
|
1481
|
+
return "PY";
|
|
1482
|
+
default:
|
|
1483
|
+
return "";
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
function getFileBgColor(ext) {
|
|
1487
|
+
switch (ext) {
|
|
1488
|
+
case "ts":
|
|
1489
|
+
case "tsx":
|
|
1490
|
+
return "bg-blue-500/20";
|
|
1491
|
+
case "js":
|
|
1492
|
+
case "jsx":
|
|
1493
|
+
return "bg-yellow-500/20";
|
|
1494
|
+
case "md":
|
|
1495
|
+
return "bg-white/10";
|
|
1496
|
+
case "json":
|
|
1497
|
+
return "bg-orange-500/20";
|
|
1498
|
+
case "sh":
|
|
1499
|
+
return "bg-green-500/20";
|
|
1500
|
+
case "css":
|
|
1501
|
+
case "scss":
|
|
1502
|
+
return "bg-pink-500/20";
|
|
1503
|
+
case "py":
|
|
1504
|
+
return "bg-blue-400/20";
|
|
1505
|
+
default:
|
|
1506
|
+
return "bg-white/10";
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
function FileBadge({
|
|
1510
|
+
path,
|
|
1511
|
+
linesAdded,
|
|
1512
|
+
linesRemoved,
|
|
1513
|
+
showOnlyFilename = true,
|
|
1514
|
+
className
|
|
1515
|
+
}) {
|
|
1516
|
+
const fileName = showOnlyFilename ? path.split("/").pop() || path : path;
|
|
1517
|
+
const ext = getFileExtension2(path);
|
|
1518
|
+
const icon = getFileIcon(ext);
|
|
1519
|
+
const bgColor = getFileBgColor(ext);
|
|
1520
|
+
const hasDiff = linesAdded !== void 0 && linesAdded > 0 || linesRemoved !== void 0 && linesRemoved > 0;
|
|
1385
1521
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1386
|
-
"
|
|
1522
|
+
"span",
|
|
1387
1523
|
{
|
|
1388
1524
|
className: cn(
|
|
1389
|
-
"
|
|
1390
|
-
|
|
1391
|
-
displayedToolCall.status === "pending" && "ash-tool-status-pending",
|
|
1525
|
+
"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md text-xs font-mono",
|
|
1526
|
+
bgColor,
|
|
1392
1527
|
className
|
|
1393
1528
|
),
|
|
1394
1529
|
children: [
|
|
1395
|
-
|
|
1396
|
-
|
|
1530
|
+
icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] opacity-60 font-semibold", children: icon }),
|
|
1531
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-white/80 truncate max-w-[120px]", children: fileName }),
|
|
1532
|
+
hasDiff && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-0.5", children: [
|
|
1533
|
+
linesAdded !== void 0 && linesAdded > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-emerald-400", children: [
|
|
1534
|
+
"+",
|
|
1535
|
+
linesAdded
|
|
1536
|
+
] }),
|
|
1537
|
+
linesRemoved !== void 0 && linesRemoved > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-red-400", children: [
|
|
1538
|
+
"-",
|
|
1539
|
+
linesRemoved
|
|
1540
|
+
] })
|
|
1541
|
+
] })
|
|
1397
1542
|
]
|
|
1398
1543
|
}
|
|
1399
1544
|
);
|
|
1400
1545
|
}
|
|
1401
|
-
function
|
|
1402
|
-
const
|
|
1403
|
-
const
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1546
|
+
function extractFileChanges(toolCalls) {
|
|
1547
|
+
const fileMap = /* @__PURE__ */ new Map();
|
|
1548
|
+
for (const tc of toolCalls) {
|
|
1549
|
+
const { actionType } = tc;
|
|
1550
|
+
if (actionType.action === "file_edit") {
|
|
1551
|
+
const edit = actionType;
|
|
1552
|
+
const existing = fileMap.get(edit.path);
|
|
1553
|
+
if (existing) {
|
|
1554
|
+
existing.linesAdded = (existing.linesAdded || 0) + (edit.linesAdded || 0);
|
|
1555
|
+
existing.linesRemoved = (existing.linesRemoved || 0) + (edit.linesRemoved || 0);
|
|
1556
|
+
} else {
|
|
1557
|
+
fileMap.set(edit.path, {
|
|
1558
|
+
path: edit.path,
|
|
1559
|
+
linesAdded: edit.linesAdded,
|
|
1560
|
+
linesRemoved: edit.linesRemoved
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1563
|
+
} else if (actionType.action === "file_write") {
|
|
1564
|
+
const write = actionType;
|
|
1565
|
+
if (!fileMap.has(write.path)) {
|
|
1566
|
+
fileMap.set(write.path, {
|
|
1567
|
+
path: write.path,
|
|
1568
|
+
linesAdded: write.linesWritten
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
return Array.from(fileMap.values());
|
|
1574
|
+
}
|
|
1575
|
+
function countActionTypes(toolCalls) {
|
|
1576
|
+
const counts = {};
|
|
1577
|
+
for (const tc of toolCalls) {
|
|
1578
|
+
const action = tc.actionType.action;
|
|
1579
|
+
counts[action] = (counts[action] || 0) + 1;
|
|
1580
|
+
}
|
|
1581
|
+
return counts;
|
|
1582
|
+
}
|
|
1583
|
+
function getActionIconComponent(action) {
|
|
1584
|
+
switch (action) {
|
|
1585
|
+
case "file_read":
|
|
1586
|
+
return FileIcon;
|
|
1587
|
+
case "file_edit":
|
|
1588
|
+
case "file_write":
|
|
1589
|
+
return EditIcon;
|
|
1590
|
+
case "command_run":
|
|
1591
|
+
return TerminalIcon;
|
|
1592
|
+
case "search":
|
|
1593
|
+
case "glob":
|
|
1594
|
+
return SearchIcon;
|
|
1595
|
+
default:
|
|
1596
|
+
return null;
|
|
1597
|
+
}
|
|
1409
1598
|
}
|
|
1410
1599
|
function ToolExecutionGroup({
|
|
1411
1600
|
toolCalls,
|
|
1412
1601
|
defaultExpanded = false,
|
|
1413
|
-
animationDuration = 300,
|
|
1414
1602
|
className
|
|
1415
1603
|
}) {
|
|
1416
1604
|
const [expanded, setExpanded] = react.useState(defaultExpanded);
|
|
1417
|
-
const
|
|
1418
|
-
const
|
|
1419
|
-
const
|
|
1420
|
-
const
|
|
1421
|
-
|
|
1605
|
+
const [expandedCardId, setExpandedCardId] = react.useState(null);
|
|
1606
|
+
const fileChanges = react.useMemo(() => extractFileChanges(toolCalls), [toolCalls]);
|
|
1607
|
+
const actionCounts = react.useMemo(() => countActionTypes(toolCalls), [toolCalls]);
|
|
1608
|
+
const displayActions = react.useMemo(() => {
|
|
1609
|
+
return Object.entries(actionCounts).sort((a, b) => b[1] - a[1]).slice(0, 3).map(([action]) => action);
|
|
1610
|
+
}, [actionCounts]);
|
|
1422
1611
|
const totalCount = toolCalls.length;
|
|
1423
|
-
if (
|
|
1612
|
+
if (toolCalls.length === 0) {
|
|
1424
1613
|
return null;
|
|
1425
1614
|
}
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
className: cn(
|
|
1436
|
-
"rounded-xl border bg-[var(--ash-surface-dark,#0a0a0a)] overflow-hidden ash-animate-fade-in",
|
|
1437
|
-
borderClasses[groupStatus],
|
|
1438
|
-
groupStatus === "pending" && "ash-tool-status-pending",
|
|
1439
|
-
className
|
|
1440
|
-
),
|
|
1441
|
-
children: [
|
|
1442
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1443
|
-
"button",
|
|
1444
|
-
{
|
|
1445
|
-
onClick: () => setExpanded(!expanded),
|
|
1446
|
-
className: cn(
|
|
1447
|
-
"w-full transition-colors hover:bg-white/5 cursor-pointer"
|
|
1448
|
-
),
|
|
1449
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
1450
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1451
|
-
CompactToolStatusLine,
|
|
1452
|
-
{
|
|
1453
|
-
toolCall: activeToolCall,
|
|
1454
|
-
previousToolCall,
|
|
1455
|
-
animationDuration,
|
|
1456
|
-
className: "border-0 rounded-none"
|
|
1457
|
-
}
|
|
1458
|
-
),
|
|
1459
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-2", children: [
|
|
1460
|
-
totalCount > 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1461
|
-
"div",
|
|
1462
|
-
{
|
|
1463
|
-
className: cn(
|
|
1464
|
-
"flex items-center gap-1.5 px-2 py-0.5 rounded-full text-xs font-medium",
|
|
1465
|
-
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"
|
|
1466
|
-
),
|
|
1467
|
-
children: groupStatus === "pending" ? /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1468
|
-
completedCount,
|
|
1469
|
-
"/",
|
|
1470
|
-
totalCount
|
|
1471
|
-
] }) : failedCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1472
|
-
completedCount,
|
|
1473
|
-
" ok, ",
|
|
1474
|
-
failedCount,
|
|
1475
|
-
" failed"
|
|
1476
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1477
|
-
totalCount,
|
|
1478
|
-
" tools"
|
|
1479
|
-
] })
|
|
1480
|
-
}
|
|
1481
|
-
),
|
|
1482
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1483
|
-
ChevronDownIcon,
|
|
1484
|
-
{
|
|
1485
|
-
className: cn(
|
|
1486
|
-
"w-4 h-4 text-white/40 transition-transform duration-200",
|
|
1487
|
-
expanded && "rotate-180"
|
|
1488
|
-
)
|
|
1489
|
-
}
|
|
1490
|
-
)
|
|
1491
|
-
] })
|
|
1492
|
-
] })
|
|
1493
|
-
}
|
|
1494
|
-
),
|
|
1495
|
-
expanded && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-white/5 bg-black/20", children: [
|
|
1496
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3 space-y-2", children: toolCalls.map((toolCall, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
1497
|
-
index < toolCalls.length - 1 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-[19px] top-10 bottom-0 w-px bg-white/10" }),
|
|
1498
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1499
|
-
ToolCallCard,
|
|
1500
|
-
{
|
|
1501
|
-
toolCall,
|
|
1502
|
-
defaultExpanded: false,
|
|
1503
|
-
className: "relative z-10"
|
|
1504
|
-
}
|
|
1505
|
-
)
|
|
1506
|
-
] }, toolCall.id)) }),
|
|
1507
|
-
groupStatus !== "pending" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1508
|
-
"div",
|
|
1615
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("ash-animate-fade-in", className), children: [
|
|
1616
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1617
|
+
"button",
|
|
1618
|
+
{
|
|
1619
|
+
onClick: () => setExpanded(!expanded),
|
|
1620
|
+
className: "w-full flex items-center gap-2 py-1 text-left group",
|
|
1621
|
+
children: [
|
|
1622
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1623
|
+
ChevronRightIcon,
|
|
1509
1624
|
{
|
|
1510
1625
|
className: cn(
|
|
1511
|
-
"
|
|
1512
|
-
|
|
1513
|
-
)
|
|
1514
|
-
children: groupStatus === "success" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1515
|
-
/* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "w-4 h-4 text-[var(--ash-accent)]" }),
|
|
1516
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-[var(--ash-accent)] font-medium", children: [
|
|
1517
|
-
"All ",
|
|
1518
|
-
totalCount,
|
|
1519
|
-
" tool",
|
|
1520
|
-
totalCount !== 1 ? "s" : "",
|
|
1521
|
-
" completed successfully"
|
|
1522
|
-
] })
|
|
1523
|
-
] }) : groupStatus === "failed" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1524
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatusIndicator, { status: "failed", size: "sm" }),
|
|
1525
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-red-400 font-medium", children: [
|
|
1526
|
-
failedCount,
|
|
1527
|
-
" tool",
|
|
1528
|
-
failedCount !== 1 ? "s" : "",
|
|
1529
|
-
" failed"
|
|
1530
|
-
] })
|
|
1531
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1532
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatusIndicator, { status: "failed", size: "sm" }),
|
|
1533
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-orange-400 font-medium", children: [
|
|
1534
|
-
completedCount,
|
|
1535
|
-
" succeeded, ",
|
|
1536
|
-
failedCount,
|
|
1537
|
-
" failed"
|
|
1538
|
-
] })
|
|
1539
|
-
] })
|
|
1626
|
+
"w-3.5 h-3.5 text-white/40 transition-transform duration-200 shrink-0",
|
|
1627
|
+
expanded && "rotate-90"
|
|
1628
|
+
)
|
|
1540
1629
|
}
|
|
1541
|
-
)
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
}
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1630
|
+
),
|
|
1631
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-white/60", children: [
|
|
1632
|
+
totalCount,
|
|
1633
|
+
" tool call",
|
|
1634
|
+
totalCount !== 1 ? "s" : ""
|
|
1635
|
+
] }),
|
|
1636
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: displayActions.map((action) => {
|
|
1637
|
+
const IconComponent = getActionIconComponent(action);
|
|
1638
|
+
if (!IconComponent) return null;
|
|
1639
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1640
|
+
IconComponent,
|
|
1641
|
+
{
|
|
1642
|
+
className: "w-3.5 h-3.5 text-white/30"
|
|
1643
|
+
},
|
|
1644
|
+
action
|
|
1645
|
+
);
|
|
1646
|
+
}) }),
|
|
1647
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
|
|
1648
|
+
!expanded && fileChanges.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 flex-wrap justify-end", children: [
|
|
1649
|
+
fileChanges.slice(0, 4).map((fc) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1650
|
+
FileBadge,
|
|
1651
|
+
{
|
|
1652
|
+
path: fc.path,
|
|
1653
|
+
linesAdded: fc.linesAdded,
|
|
1654
|
+
linesRemoved: fc.linesRemoved
|
|
1655
|
+
},
|
|
1656
|
+
fc.path
|
|
1657
|
+
)),
|
|
1658
|
+
fileChanges.length > 4 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-white/40", children: [
|
|
1659
|
+
"+",
|
|
1660
|
+
fileChanges.length - 4,
|
|
1661
|
+
" more"
|
|
1662
|
+
] })
|
|
1663
|
+
] })
|
|
1664
|
+
]
|
|
1665
|
+
}
|
|
1666
|
+
),
|
|
1667
|
+
expanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pl-5 border-l border-white/10 ml-1.5 mt-1 space-y-0.5", children: toolCalls.map((toolCall) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: expandedCardId === toolCall.id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-1", children: [
|
|
1668
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1669
|
+
ToolCallCard,
|
|
1670
|
+
{
|
|
1671
|
+
toolCall,
|
|
1672
|
+
defaultExpanded: true
|
|
1673
|
+
}
|
|
1674
|
+
),
|
|
1675
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1676
|
+
"button",
|
|
1677
|
+
{
|
|
1678
|
+
onClick: () => setExpandedCardId(null),
|
|
1679
|
+
className: "text-xs text-white/40 hover:text-white/60 mt-1 pl-1",
|
|
1680
|
+
children: "Collapse"
|
|
1681
|
+
}
|
|
1682
|
+
)
|
|
1683
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1684
|
+
"button",
|
|
1685
|
+
{
|
|
1686
|
+
onClick: () => setExpandedCardId(toolCall.id),
|
|
1687
|
+
className: "w-full text-left hover:bg-white/5 rounded px-1 -mx-1 transition-colors",
|
|
1688
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(CompactToolRow, { toolCall })
|
|
1689
|
+
}
|
|
1690
|
+
) }, toolCall.id)) })
|
|
1691
|
+
] });
|
|
1551
1692
|
}
|
|
1552
|
-
function
|
|
1553
|
-
|
|
1554
|
-
|
|
1693
|
+
function extractFileChanges2(toolCalls) {
|
|
1694
|
+
const fileMap = /* @__PURE__ */ new Map();
|
|
1695
|
+
for (const tc of toolCalls) {
|
|
1696
|
+
const { actionType } = tc;
|
|
1697
|
+
if (actionType.action === "file_edit") {
|
|
1698
|
+
const edit = actionType;
|
|
1699
|
+
const existing = fileMap.get(edit.path);
|
|
1700
|
+
if (existing) {
|
|
1701
|
+
existing.linesAdded = (existing.linesAdded || 0) + (edit.linesAdded || 0);
|
|
1702
|
+
existing.linesRemoved = (existing.linesRemoved || 0) + (edit.linesRemoved || 0);
|
|
1703
|
+
} else {
|
|
1704
|
+
fileMap.set(edit.path, {
|
|
1705
|
+
path: edit.path,
|
|
1706
|
+
linesAdded: edit.linesAdded,
|
|
1707
|
+
linesRemoved: edit.linesRemoved
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
} else if (actionType.action === "file_write") {
|
|
1711
|
+
if (!fileMap.has(actionType.path)) {
|
|
1712
|
+
fileMap.set(actionType.path, {
|
|
1713
|
+
path: actionType.path,
|
|
1714
|
+
linesAdded: actionType.linesWritten
|
|
1715
|
+
});
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1555
1718
|
}
|
|
1556
|
-
|
|
1557
|
-
return cleaned.charAt(0).toUpperCase() + cleaned.slice(1);
|
|
1719
|
+
return Array.from(fileMap.values());
|
|
1558
1720
|
}
|
|
1559
|
-
function
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
return "success";
|
|
1565
|
-
case "failed":
|
|
1566
|
-
return "error";
|
|
1567
|
-
default:
|
|
1568
|
-
return "pending";
|
|
1721
|
+
function countActionTypes2(toolCalls) {
|
|
1722
|
+
const counts = {};
|
|
1723
|
+
for (const tc of toolCalls) {
|
|
1724
|
+
const action = tc.actionType.action;
|
|
1725
|
+
counts[action] = (counts[action] || 0) + 1;
|
|
1569
1726
|
}
|
|
1727
|
+
return counts;
|
|
1570
1728
|
}
|
|
1571
|
-
function
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
case "
|
|
1577
|
-
return
|
|
1578
|
-
case "
|
|
1579
|
-
return
|
|
1729
|
+
function getActionIconComponent2(action) {
|
|
1730
|
+
switch (action) {
|
|
1731
|
+
case "file_read":
|
|
1732
|
+
return FileIcon;
|
|
1733
|
+
case "file_edit":
|
|
1734
|
+
case "file_write":
|
|
1735
|
+
return EditIcon;
|
|
1736
|
+
case "command_run":
|
|
1737
|
+
return TerminalIcon;
|
|
1738
|
+
case "search":
|
|
1739
|
+
case "glob":
|
|
1740
|
+
return SearchIcon;
|
|
1580
1741
|
default:
|
|
1581
|
-
return
|
|
1742
|
+
return null;
|
|
1582
1743
|
}
|
|
1583
1744
|
}
|
|
1584
1745
|
function StepAccordion({
|
|
@@ -1597,109 +1758,70 @@ function StepAccordion({
|
|
|
1597
1758
|
setInternalExpanded((prev) => !prev);
|
|
1598
1759
|
}
|
|
1599
1760
|
}, [onToggle]);
|
|
1761
|
+
const fileChanges = react.useMemo(() => extractFileChanges2(toolCalls), [toolCalls]);
|
|
1762
|
+
const actionCounts = react.useMemo(() => countActionTypes2(toolCalls), [toolCalls]);
|
|
1763
|
+
const displayActions = react.useMemo(() => {
|
|
1764
|
+
return Object.entries(actionCounts).sort((a, b) => b[1] - a[1]).slice(0, 3).map(([action]) => action);
|
|
1765
|
+
}, [actionCounts]);
|
|
1600
1766
|
if (toolCalls.length === 0) {
|
|
1601
1767
|
return null;
|
|
1602
1768
|
}
|
|
1603
|
-
const
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
),
|
|
1615
|
-
children: [
|
|
1616
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1617
|
-
"button",
|
|
1618
|
-
{
|
|
1619
|
-
type: "button",
|
|
1620
|
-
onClick: handleToggle,
|
|
1621
|
-
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",
|
|
1622
|
-
children: [
|
|
1623
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1624
|
-
ChevronDownIcon,
|
|
1625
|
-
{
|
|
1626
|
-
className: cn(
|
|
1627
|
-
"w-4 h-4 text-white/40 transition-transform duration-200 flex-shrink-0",
|
|
1628
|
-
!isExpanded && "-rotate-90"
|
|
1629
|
-
)
|
|
1630
|
-
}
|
|
1631
|
-
),
|
|
1632
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0 flex items-center gap-2", children: runningStep ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1633
|
-
/* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, { className: "w-3.5 h-3.5 animate-spin text-[var(--ash-accent)] flex-shrink-0" }),
|
|
1634
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-white/80 truncate", children: getToolLabel(runningStep.toolName, runningStep.summary) })
|
|
1635
|
-
] }) : hasError ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1636
|
-
/* @__PURE__ */ jsxRuntime.jsx(ErrorIcon, { className: "w-3.5 h-3.5 text-red-500 flex-shrink-0" }),
|
|
1637
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-red-400 truncate", children: "Completed with errors" })
|
|
1638
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1639
|
-
/* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "w-3.5 h-3.5 text-[var(--ash-accent)] flex-shrink-0" }),
|
|
1640
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-white/70 truncate", children: [
|
|
1641
|
-
completedSteps,
|
|
1642
|
-
" step",
|
|
1643
|
-
completedSteps !== 1 ? "s" : "",
|
|
1644
|
-
" completed"
|
|
1645
|
-
] })
|
|
1646
|
-
] }) }),
|
|
1647
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs px-1.5 py-0.5 rounded-full bg-white/10 text-white/50 flex-shrink-0", children: [
|
|
1648
|
-
completedSteps,
|
|
1649
|
-
"/",
|
|
1650
|
-
toolCalls.length
|
|
1651
|
-
] })
|
|
1652
|
-
]
|
|
1653
|
-
}
|
|
1654
|
-
),
|
|
1655
|
-
isExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-white/10 ash-accordion-content", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-white/5", children: toolCalls.map((toolCall, index) => {
|
|
1656
|
-
const stepStatus = toStepStatus(toolCall.status);
|
|
1657
|
-
const startTime = toolCall.startedAt ? new Date(toolCall.startedAt).getTime() : 0;
|
|
1658
|
-
const endTime = toolCall.completedAt ? new Date(toolCall.completedAt).getTime() : 0;
|
|
1659
|
-
const hasDuration = startTime > 0 && endTime > 0;
|
|
1660
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1661
|
-
"div",
|
|
1769
|
+
const totalCount = toolCalls.length;
|
|
1770
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("ash-animate-fade-in", className), children: [
|
|
1771
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1772
|
+
"button",
|
|
1773
|
+
{
|
|
1774
|
+
type: "button",
|
|
1775
|
+
onClick: handleToggle,
|
|
1776
|
+
className: "w-full flex items-center gap-2 py-1 text-left group",
|
|
1777
|
+
children: [
|
|
1778
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1779
|
+
ChevronRightIcon,
|
|
1662
1780
|
{
|
|
1663
1781
|
className: cn(
|
|
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
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1782
|
+
"w-3.5 h-3.5 text-white/40 transition-transform duration-200 shrink-0",
|
|
1783
|
+
isExpanded && "rotate-90"
|
|
1784
|
+
)
|
|
1785
|
+
}
|
|
1786
|
+
),
|
|
1787
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-white/60", children: [
|
|
1788
|
+
totalCount,
|
|
1789
|
+
" tool call",
|
|
1790
|
+
totalCount !== 1 ? "s" : ""
|
|
1791
|
+
] }),
|
|
1792
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: displayActions.map((action) => {
|
|
1793
|
+
const IconComponent = getActionIconComponent2(action);
|
|
1794
|
+
if (!IconComponent) return null;
|
|
1795
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1796
|
+
IconComponent,
|
|
1797
|
+
{
|
|
1798
|
+
className: "w-3.5 h-3.5 text-white/30"
|
|
1799
|
+
},
|
|
1800
|
+
action
|
|
1801
|
+
);
|
|
1802
|
+
}) }),
|
|
1803
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
|
|
1804
|
+
!isExpanded && fileChanges.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 flex-wrap justify-end", children: [
|
|
1805
|
+
fileChanges.slice(0, 4).map((fc) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1806
|
+
FileBadge,
|
|
1807
|
+
{
|
|
1808
|
+
path: fc.path,
|
|
1809
|
+
linesAdded: fc.linesAdded,
|
|
1810
|
+
linesRemoved: fc.linesRemoved
|
|
1811
|
+
},
|
|
1812
|
+
fc.path
|
|
1813
|
+
)),
|
|
1814
|
+
fileChanges.length > 4 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-white/40", children: [
|
|
1815
|
+
"+",
|
|
1816
|
+
fileChanges.length - 4,
|
|
1817
|
+
" more"
|
|
1818
|
+
] })
|
|
1819
|
+
] })
|
|
1820
|
+
]
|
|
1821
|
+
}
|
|
1822
|
+
),
|
|
1823
|
+
isExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pl-5 border-l border-white/10 ml-1.5 mt-1 space-y-0.5", children: toolCalls.map((toolCall) => /* @__PURE__ */ jsxRuntime.jsx(CompactToolRow, { toolCall }, toolCall.id)) })
|
|
1824
|
+
] });
|
|
1703
1825
|
}
|
|
1704
1826
|
|
|
1705
1827
|
// src/types.ts
|
|
@@ -1802,10 +1924,18 @@ function MessageList({
|
|
|
1802
1924
|
onOptionSelect,
|
|
1803
1925
|
renderWidget,
|
|
1804
1926
|
onWidgetAction,
|
|
1927
|
+
autoScroll = true,
|
|
1805
1928
|
className
|
|
1806
1929
|
}) {
|
|
1807
1930
|
const contextConfig = useDisplayConfig();
|
|
1808
1931
|
const config = displayConfigProp || contextConfig;
|
|
1932
|
+
const containerRef = react.useRef(null);
|
|
1933
|
+
const messagesEndRef = react.useRef(null);
|
|
1934
|
+
react.useEffect(() => {
|
|
1935
|
+
if (autoScroll && messagesEndRef.current && containerRef.current) {
|
|
1936
|
+
messagesEndRef.current.scrollIntoView({ behavior: "smooth", block: "end" });
|
|
1937
|
+
}
|
|
1938
|
+
}, [entries, streamingContent, loading, autoScroll]);
|
|
1809
1939
|
const createWidgetActionHandler = react.useCallback(
|
|
1810
1940
|
(entryId, widgetType) => {
|
|
1811
1941
|
if (!onWidgetAction) return void 0;
|
|
@@ -1829,7 +1959,7 @@ function MessageList({
|
|
|
1829
1959
|
}
|
|
1830
1960
|
return groupEntriesForCompactMode(entries, config);
|
|
1831
1961
|
}, [entries, config]);
|
|
1832
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex-1 overflow-y-auto p-4 space-y-4 ash-scrollbar", className), children: [
|
|
1962
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: cn("flex-1 overflow-y-auto p-4 space-y-4 ash-scrollbar", className), children: [
|
|
1833
1963
|
groupedEntries.map((groupedEntry) => {
|
|
1834
1964
|
if (groupedEntry.type === "single") {
|
|
1835
1965
|
const entry = groupedEntry.entry;
|
|
@@ -1873,7 +2003,8 @@ function MessageList({
|
|
|
1873
2003
|
loading && !streamingContent && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3 ash-animate-fade-in", children: [
|
|
1874
2004
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-7 h-7 rounded-full bg-[var(--ash-accent)]/20 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(BotIcon, { className: "w-4 h-4 text-[var(--ash-accent)]" }) }),
|
|
1875
2005
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl p-3 bg-white/5", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator, { variant: "dots" }) })
|
|
1876
|
-
] })
|
|
2006
|
+
] }),
|
|
2007
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: messagesEndRef })
|
|
1877
2008
|
] });
|
|
1878
2009
|
}
|
|
1879
2010
|
function getLevelIcon(level) {
|
|
@@ -2020,6 +2151,94 @@ function LogsPanel({
|
|
|
2020
2151
|
}
|
|
2021
2152
|
);
|
|
2022
2153
|
}
|
|
2154
|
+
function CompactToolStatusLine({
|
|
2155
|
+
toolCall,
|
|
2156
|
+
previousToolCall,
|
|
2157
|
+
animationDuration = 300,
|
|
2158
|
+
className
|
|
2159
|
+
}) {
|
|
2160
|
+
const [isAnimating, setIsAnimating] = react.useState(false);
|
|
2161
|
+
const [displayedToolCall, setDisplayedToolCall] = react.useState(toolCall);
|
|
2162
|
+
const [exitingToolCall, setExitingToolCall] = react.useState(null);
|
|
2163
|
+
const prevToolCallRef = react.useRef(null);
|
|
2164
|
+
react.useEffect(() => {
|
|
2165
|
+
if (toolCall.id !== prevToolCallRef.current) {
|
|
2166
|
+
if (prevToolCallRef.current !== null && previousToolCall) {
|
|
2167
|
+
setExitingToolCall(previousToolCall);
|
|
2168
|
+
setIsAnimating(true);
|
|
2169
|
+
const timer = setTimeout(() => {
|
|
2170
|
+
setDisplayedToolCall(toolCall);
|
|
2171
|
+
setExitingToolCall(null);
|
|
2172
|
+
setIsAnimating(false);
|
|
2173
|
+
}, animationDuration);
|
|
2174
|
+
prevToolCallRef.current = toolCall.id;
|
|
2175
|
+
return () => clearTimeout(timer);
|
|
2176
|
+
} else {
|
|
2177
|
+
setDisplayedToolCall(toolCall);
|
|
2178
|
+
prevToolCallRef.current = toolCall.id;
|
|
2179
|
+
}
|
|
2180
|
+
} else {
|
|
2181
|
+
setDisplayedToolCall(toolCall);
|
|
2182
|
+
}
|
|
2183
|
+
return void 0;
|
|
2184
|
+
}, [toolCall, previousToolCall, animationDuration]);
|
|
2185
|
+
const statusClasses = {
|
|
2186
|
+
pending: "border-yellow-500/30",
|
|
2187
|
+
success: "border-[var(--ash-accent)]/30",
|
|
2188
|
+
failed: "border-red-500/30"
|
|
2189
|
+
};
|
|
2190
|
+
const renderToolCallContent = (tc, isExiting) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2191
|
+
"div",
|
|
2192
|
+
{
|
|
2193
|
+
className: cn(
|
|
2194
|
+
"flex items-center gap-3 px-4 py-2.5",
|
|
2195
|
+
isExiting ? "ash-status-line-exit" : isAnimating ? "ash-status-line-enter" : ""
|
|
2196
|
+
),
|
|
2197
|
+
style: {
|
|
2198
|
+
animationDuration: `${animationDuration}ms`
|
|
2199
|
+
},
|
|
2200
|
+
children: [
|
|
2201
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2202
|
+
"div",
|
|
2203
|
+
{
|
|
2204
|
+
className: cn(
|
|
2205
|
+
"w-6 h-6 rounded-lg flex items-center justify-center shrink-0",
|
|
2206
|
+
tc.status === "pending" ? "bg-yellow-500/20" : tc.status === "failed" ? "bg-red-500/20" : "bg-[var(--ash-accent)]/20"
|
|
2207
|
+
),
|
|
2208
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2209
|
+
ActionIcon,
|
|
2210
|
+
{
|
|
2211
|
+
actionType: tc.actionType,
|
|
2212
|
+
className: cn(
|
|
2213
|
+
"w-3.5 h-3.5",
|
|
2214
|
+
tc.status === "pending" ? "text-yellow-400" : tc.status === "failed" ? "text-red-400" : "text-[var(--ash-accent)]"
|
|
2215
|
+
)
|
|
2216
|
+
}
|
|
2217
|
+
)
|
|
2218
|
+
}
|
|
2219
|
+
),
|
|
2220
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-white shrink-0", children: getActionLabel(tc.actionType) }),
|
|
2221
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-sm truncate text-white/60 flex-1 min-w-0", children: tc.summary }),
|
|
2222
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusIndicator, { status: tc.status, size: "sm" })
|
|
2223
|
+
]
|
|
2224
|
+
}
|
|
2225
|
+
);
|
|
2226
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2227
|
+
"div",
|
|
2228
|
+
{
|
|
2229
|
+
className: cn(
|
|
2230
|
+
"relative rounded-xl border bg-[var(--ash-surface-dark,#0a0a0a)] overflow-hidden",
|
|
2231
|
+
statusClasses[displayedToolCall.status],
|
|
2232
|
+
displayedToolCall.status === "pending" && "ash-tool-status-pending",
|
|
2233
|
+
className
|
|
2234
|
+
),
|
|
2235
|
+
children: [
|
|
2236
|
+
exitingToolCall && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0", children: renderToolCallContent(exitingToolCall, true) }),
|
|
2237
|
+
renderToolCallContent(displayedToolCall, false)
|
|
2238
|
+
]
|
|
2239
|
+
}
|
|
2240
|
+
);
|
|
2241
|
+
}
|
|
2023
2242
|
function TodoStatusIcon({ status, className = "w-4 h-4" }) {
|
|
2024
2243
|
switch (status) {
|
|
2025
2244
|
case "completed":
|
|
@@ -2973,6 +3192,284 @@ function useFileUpload({
|
|
|
2973
3192
|
openFilePicker
|
|
2974
3193
|
};
|
|
2975
3194
|
}
|
|
3195
|
+
function useAgentChat(options) {
|
|
3196
|
+
const {
|
|
3197
|
+
createStream,
|
|
3198
|
+
initialSessionId,
|
|
3199
|
+
initialEntries = [],
|
|
3200
|
+
onSessionStart,
|
|
3201
|
+
onSessionEnd,
|
|
3202
|
+
onError,
|
|
3203
|
+
onSandboxLog
|
|
3204
|
+
} = options;
|
|
3205
|
+
const [historyEntries, setHistoryEntries] = react.useState(initialEntries);
|
|
3206
|
+
const [streamingEntries, setStreamingEntries] = react.useState([]);
|
|
3207
|
+
const [isStreaming, setIsStreaming] = react.useState(false);
|
|
3208
|
+
const [error, setError] = react.useState(null);
|
|
3209
|
+
const [sessionId, setSessionId] = react.useState(initialSessionId || null);
|
|
3210
|
+
const abortControllerRef = react.useRef(null);
|
|
3211
|
+
const currentTextRef = react.useRef("");
|
|
3212
|
+
const currentTextIdRef = react.useRef(null);
|
|
3213
|
+
const pendingToolCallsRef = react.useRef(/* @__PURE__ */ new Map());
|
|
3214
|
+
const hadToolCallSinceTextRef = react.useRef(false);
|
|
3215
|
+
const entries = [...historyEntries, ...streamingEntries];
|
|
3216
|
+
const emitStreamingEntries = react.useCallback((newEntries) => {
|
|
3217
|
+
setStreamingEntries([...newEntries]);
|
|
3218
|
+
}, []);
|
|
3219
|
+
const createTextEntry = react.useCallback((id, content) => ({
|
|
3220
|
+
id,
|
|
3221
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3222
|
+
entryType: { type: "assistant_message" },
|
|
3223
|
+
content
|
|
3224
|
+
}), []);
|
|
3225
|
+
const resetStreamingState = react.useCallback(() => {
|
|
3226
|
+
currentTextRef.current = "";
|
|
3227
|
+
currentTextIdRef.current = null;
|
|
3228
|
+
pendingToolCallsRef.current.clear();
|
|
3229
|
+
hadToolCallSinceTextRef.current = false;
|
|
3230
|
+
setStreamingEntries([]);
|
|
3231
|
+
}, []);
|
|
3232
|
+
const processEvent = react.useCallback((event, streamEntries) => {
|
|
3233
|
+
const newEntries = [...streamEntries];
|
|
3234
|
+
switch (event.type) {
|
|
3235
|
+
case "session_start":
|
|
3236
|
+
if (event.sessionId) {
|
|
3237
|
+
setSessionId(event.sessionId);
|
|
3238
|
+
onSessionStart?.(event.sessionId);
|
|
3239
|
+
}
|
|
3240
|
+
break;
|
|
3241
|
+
case "text_delta":
|
|
3242
|
+
if (event.delta) {
|
|
3243
|
+
if (hadToolCallSinceTextRef.current && currentTextIdRef.current) {
|
|
3244
|
+
currentTextRef.current = "";
|
|
3245
|
+
currentTextIdRef.current = null;
|
|
3246
|
+
hadToolCallSinceTextRef.current = false;
|
|
3247
|
+
}
|
|
3248
|
+
currentTextRef.current += event.delta;
|
|
3249
|
+
if (!currentTextIdRef.current) {
|
|
3250
|
+
currentTextIdRef.current = `text-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
3251
|
+
newEntries.push(createTextEntry(currentTextIdRef.current, currentTextRef.current));
|
|
3252
|
+
} else {
|
|
3253
|
+
const entryIndex = newEntries.findIndex((e) => e.id === currentTextIdRef.current);
|
|
3254
|
+
if (entryIndex !== -1) {
|
|
3255
|
+
newEntries[entryIndex] = createTextEntry(currentTextIdRef.current, currentTextRef.current);
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
}
|
|
3259
|
+
break;
|
|
3260
|
+
case "tool_use":
|
|
3261
|
+
if (event.toolId && event.toolName) {
|
|
3262
|
+
currentTextRef.current = "";
|
|
3263
|
+
currentTextIdRef.current = null;
|
|
3264
|
+
hadToolCallSinceTextRef.current = true;
|
|
3265
|
+
const toolCall = createToolCall({
|
|
3266
|
+
id: event.toolId,
|
|
3267
|
+
name: event.toolName,
|
|
3268
|
+
input: event.input
|
|
3269
|
+
});
|
|
3270
|
+
const entry = {
|
|
3271
|
+
id: event.toolId,
|
|
3272
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3273
|
+
entryType: { type: "tool_call", toolCall },
|
|
3274
|
+
content: toolCall.summary
|
|
3275
|
+
};
|
|
3276
|
+
const entryIndex = newEntries.length;
|
|
3277
|
+
newEntries.push(entry);
|
|
3278
|
+
pendingToolCallsRef.current.set(event.toolId, { entryIndex, toolCall });
|
|
3279
|
+
}
|
|
3280
|
+
break;
|
|
3281
|
+
case "tool_result":
|
|
3282
|
+
if (event.toolId) {
|
|
3283
|
+
const pending = pendingToolCallsRef.current.get(event.toolId);
|
|
3284
|
+
if (pending) {
|
|
3285
|
+
const updatedToolCall = updateToolCallWithResult(
|
|
3286
|
+
pending.toolCall,
|
|
3287
|
+
event.toolResult,
|
|
3288
|
+
event.isError
|
|
3289
|
+
);
|
|
3290
|
+
const existingEntry = newEntries[pending.entryIndex];
|
|
3291
|
+
if (existingEntry && existingEntry.entryType.type === "tool_call") {
|
|
3292
|
+
newEntries[pending.entryIndex] = {
|
|
3293
|
+
...existingEntry,
|
|
3294
|
+
entryType: { type: "tool_call", toolCall: updatedToolCall }
|
|
3295
|
+
};
|
|
3296
|
+
}
|
|
3297
|
+
pendingToolCallsRef.current.delete(event.toolId);
|
|
3298
|
+
}
|
|
3299
|
+
}
|
|
3300
|
+
break;
|
|
3301
|
+
case "sandbox_log":
|
|
3302
|
+
if (event.entry) {
|
|
3303
|
+
onSandboxLog?.(event.entry);
|
|
3304
|
+
}
|
|
3305
|
+
break;
|
|
3306
|
+
case "error":
|
|
3307
|
+
if (event.error) {
|
|
3308
|
+
setError(event.error);
|
|
3309
|
+
onError?.(event.error);
|
|
3310
|
+
newEntries.push({
|
|
3311
|
+
id: `error-${Date.now()}`,
|
|
3312
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3313
|
+
entryType: { type: "error", message: event.error, code: event.code },
|
|
3314
|
+
content: event.error
|
|
3315
|
+
});
|
|
3316
|
+
}
|
|
3317
|
+
break;
|
|
3318
|
+
case "session_end":
|
|
3319
|
+
onSessionEnd?.(event.sessionId || sessionId || "", event.status || "completed");
|
|
3320
|
+
break;
|
|
3321
|
+
case "complete":
|
|
3322
|
+
if (newEntries.length > 0) {
|
|
3323
|
+
setHistoryEntries((prev) => [...prev, ...newEntries]);
|
|
3324
|
+
}
|
|
3325
|
+
resetStreamingState();
|
|
3326
|
+
return [];
|
|
3327
|
+
}
|
|
3328
|
+
return newEntries;
|
|
3329
|
+
}, [sessionId, onSessionStart, onSessionEnd, onError, onSandboxLog, createTextEntry, resetStreamingState]);
|
|
3330
|
+
const send = react.useCallback(async (prompt) => {
|
|
3331
|
+
if (isStreaming) return;
|
|
3332
|
+
setIsStreaming(true);
|
|
3333
|
+
setError(null);
|
|
3334
|
+
const userEntry = {
|
|
3335
|
+
id: `user-${Date.now()}`,
|
|
3336
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3337
|
+
entryType: { type: "user_message" },
|
|
3338
|
+
content: prompt
|
|
3339
|
+
};
|
|
3340
|
+
setHistoryEntries((prev) => [...prev, userEntry]);
|
|
3341
|
+
resetStreamingState();
|
|
3342
|
+
const controller = new AbortController();
|
|
3343
|
+
abortControllerRef.current = controller;
|
|
3344
|
+
let localStreamingEntries = [];
|
|
3345
|
+
try {
|
|
3346
|
+
const stream = createStream(prompt, sessionId || void 0);
|
|
3347
|
+
for await (const event of stream) {
|
|
3348
|
+
if (controller.signal.aborted) break;
|
|
3349
|
+
localStreamingEntries = processEvent(event, localStreamingEntries);
|
|
3350
|
+
emitStreamingEntries(localStreamingEntries);
|
|
3351
|
+
}
|
|
3352
|
+
if (localStreamingEntries.length > 0) {
|
|
3353
|
+
setHistoryEntries((prev) => [...prev, ...localStreamingEntries]);
|
|
3354
|
+
setStreamingEntries([]);
|
|
3355
|
+
}
|
|
3356
|
+
} catch (err) {
|
|
3357
|
+
if (err.name !== "AbortError") {
|
|
3358
|
+
const errorMessage = err instanceof Error ? err.message : "Unknown error";
|
|
3359
|
+
setError(errorMessage);
|
|
3360
|
+
onError?.(errorMessage);
|
|
3361
|
+
}
|
|
3362
|
+
} finally {
|
|
3363
|
+
setIsStreaming(false);
|
|
3364
|
+
abortControllerRef.current = null;
|
|
3365
|
+
resetStreamingState();
|
|
3366
|
+
}
|
|
3367
|
+
}, [isStreaming, sessionId, createStream, processEvent, emitStreamingEntries, resetStreamingState, onError]);
|
|
3368
|
+
const stop = react.useCallback(() => {
|
|
3369
|
+
if (abortControllerRef.current) {
|
|
3370
|
+
abortControllerRef.current.abort();
|
|
3371
|
+
}
|
|
3372
|
+
}, []);
|
|
3373
|
+
const clear = react.useCallback(() => {
|
|
3374
|
+
setHistoryEntries([]);
|
|
3375
|
+
resetStreamingState();
|
|
3376
|
+
setSessionId(initialSessionId || null);
|
|
3377
|
+
setError(null);
|
|
3378
|
+
}, [initialSessionId, resetStreamingState]);
|
|
3379
|
+
const setEntries = react.useCallback((newEntries) => {
|
|
3380
|
+
resetStreamingState();
|
|
3381
|
+
setHistoryEntries(newEntries);
|
|
3382
|
+
}, [resetStreamingState]);
|
|
3383
|
+
react.useEffect(() => {
|
|
3384
|
+
return () => {
|
|
3385
|
+
if (abortControllerRef.current) {
|
|
3386
|
+
abortControllerRef.current.abort();
|
|
3387
|
+
}
|
|
3388
|
+
};
|
|
3389
|
+
}, []);
|
|
3390
|
+
return {
|
|
3391
|
+
entries,
|
|
3392
|
+
isStreaming,
|
|
3393
|
+
error,
|
|
3394
|
+
sessionId,
|
|
3395
|
+
send,
|
|
3396
|
+
stop,
|
|
3397
|
+
clear,
|
|
3398
|
+
setEntries
|
|
3399
|
+
};
|
|
3400
|
+
}
|
|
3401
|
+
function textToBase64(text) {
|
|
3402
|
+
const encoder = new TextEncoder();
|
|
3403
|
+
const bytes = encoder.encode(text);
|
|
3404
|
+
let binary = "";
|
|
3405
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
3406
|
+
const byte = bytes[i];
|
|
3407
|
+
if (byte !== void 0) {
|
|
3408
|
+
binary += String.fromCharCode(byte);
|
|
3409
|
+
}
|
|
3410
|
+
}
|
|
3411
|
+
return btoa(binary);
|
|
3412
|
+
}
|
|
3413
|
+
function generateFilename(template) {
|
|
3414
|
+
const timestamp = Date.now();
|
|
3415
|
+
const date = new Date(timestamp);
|
|
3416
|
+
const dateStr = date.toISOString().split("T")[0] ?? "unknown-date";
|
|
3417
|
+
const timeStr = (date.toTimeString().split(" ")[0] ?? "00-00-00").replace(/:/g, "-");
|
|
3418
|
+
return template.replace("{timestamp}", String(timestamp)).replace("{date}", dateStr).replace("{time}", timeStr);
|
|
3419
|
+
}
|
|
3420
|
+
function useLongTextConversion({
|
|
3421
|
+
threshold = 5e3,
|
|
3422
|
+
filenameTemplate = "pasted-text-{timestamp}.txt",
|
|
3423
|
+
onConversion
|
|
3424
|
+
} = {}) {
|
|
3425
|
+
const [lastConversion, setLastConversion] = react.useState(null);
|
|
3426
|
+
const processText = react.useCallback((text) => {
|
|
3427
|
+
if (text.length <= threshold) {
|
|
3428
|
+
return { text };
|
|
3429
|
+
}
|
|
3430
|
+
const filename = generateFilename(filenameTemplate);
|
|
3431
|
+
const content = textToBase64(text);
|
|
3432
|
+
const encoder = new TextEncoder();
|
|
3433
|
+
const size = encoder.encode(text).length;
|
|
3434
|
+
const lineCount = text.split("\n").length;
|
|
3435
|
+
const attachment = {
|
|
3436
|
+
filename,
|
|
3437
|
+
content,
|
|
3438
|
+
mimeType: "text/plain",
|
|
3439
|
+
size
|
|
3440
|
+
};
|
|
3441
|
+
const preview = text.slice(0, 100) + (text.length > 100 ? "..." : "");
|
|
3442
|
+
const conversionInfo = {
|
|
3443
|
+
originalLength: text.length,
|
|
3444
|
+
filename,
|
|
3445
|
+
preview,
|
|
3446
|
+
lineCount
|
|
3447
|
+
};
|
|
3448
|
+
setLastConversion(conversionInfo);
|
|
3449
|
+
onConversion?.(conversionInfo);
|
|
3450
|
+
return { text: "", attachment };
|
|
3451
|
+
}, [threshold, filenameTemplate, onConversion]);
|
|
3452
|
+
const handlePaste = react.useCallback((event, _currentValue, _setValue, addAttachment) => {
|
|
3453
|
+
const pastedText = event.clipboardData.getData("text/plain");
|
|
3454
|
+
if (pastedText.length > threshold) {
|
|
3455
|
+
event.preventDefault();
|
|
3456
|
+
const result = processText(pastedText);
|
|
3457
|
+
if (result.attachment) {
|
|
3458
|
+
addAttachment(result.attachment);
|
|
3459
|
+
}
|
|
3460
|
+
}
|
|
3461
|
+
}, [threshold, processText]);
|
|
3462
|
+
const clearLastConversion = react.useCallback(() => {
|
|
3463
|
+
setLastConversion(null);
|
|
3464
|
+
}, []);
|
|
3465
|
+
return {
|
|
3466
|
+
processText,
|
|
3467
|
+
handlePaste,
|
|
3468
|
+
lastConversion,
|
|
3469
|
+
clearLastConversion,
|
|
3470
|
+
threshold
|
|
3471
|
+
};
|
|
3472
|
+
}
|
|
2976
3473
|
|
|
2977
3474
|
exports.ActionIcon = ActionIcon;
|
|
2978
3475
|
exports.AlertCircleIcon = AlertCircleIcon;
|
|
@@ -2991,6 +3488,7 @@ exports.CircleIcon = CircleIcon;
|
|
|
2991
3488
|
exports.ClipboardListIcon = ClipboardListIcon;
|
|
2992
3489
|
exports.CodeBlock = CodeBlock;
|
|
2993
3490
|
exports.CodeIcon = CodeIcon;
|
|
3491
|
+
exports.CompactToolRow = CompactToolRow;
|
|
2994
3492
|
exports.CompactToolStatusLine = CompactToolStatusLine;
|
|
2995
3493
|
exports.CopyIcon = CopyIcon;
|
|
2996
3494
|
exports.DEFAULT_DISPLAY_CONFIG = DEFAULT_DISPLAY_CONFIG;
|
|
@@ -3000,6 +3498,7 @@ exports.EditIcon = EditIcon;
|
|
|
3000
3498
|
exports.EnvVarsPanel = EnvVarsPanel;
|
|
3001
3499
|
exports.ErrorIcon = ErrorIcon;
|
|
3002
3500
|
exports.ErrorMessage = ErrorMessage;
|
|
3501
|
+
exports.FileBadge = FileBadge;
|
|
3003
3502
|
exports.FileIcon = FileIcon;
|
|
3004
3503
|
exports.FilePlusIcon = FilePlusIcon;
|
|
3005
3504
|
exports.FolderSearchIcon = FolderSearchIcon;
|
|
@@ -3082,9 +3581,11 @@ exports.transitions = transitions;
|
|
|
3082
3581
|
exports.truncate = truncate;
|
|
3083
3582
|
exports.typography = typography;
|
|
3084
3583
|
exports.updateToolCallWithResult = updateToolCallWithResult;
|
|
3584
|
+
exports.useAgentChat = useAgentChat;
|
|
3085
3585
|
exports.useDisplayConfig = useDisplayConfig;
|
|
3086
3586
|
exports.useDisplayMode = useDisplayMode;
|
|
3087
3587
|
exports.useFileUpload = useFileUpload;
|
|
3588
|
+
exports.useLongTextConversion = useLongTextConversion;
|
|
3088
3589
|
exports.useMessageQueue = useMessageQueue;
|
|
3089
3590
|
exports.useStopExecution = useStopExecution;
|
|
3090
3591
|
exports.useTheme = useTheme;
|