@apteva/apteva-kit 0.1.69 → 0.1.71
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.d.mts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +296 -72
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +377 -153
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -23,6 +23,8 @@ interface Widget {
|
|
|
23
23
|
actions?: Action[];
|
|
24
24
|
/** Additional data not displayed but captured via onWidgetRender */
|
|
25
25
|
meta?: Record<string, any>;
|
|
26
|
+
/** Whether the widget is still receiving streaming data */
|
|
27
|
+
isStreaming?: boolean;
|
|
26
28
|
}
|
|
27
29
|
interface CardWidget extends Widget {
|
|
28
30
|
type: 'card';
|
|
@@ -392,7 +394,9 @@ interface CardProps {
|
|
|
392
394
|
declare function Card({ widget, onAction }: CardProps): react_jsx_runtime.JSX.Element;
|
|
393
395
|
|
|
394
396
|
interface ListProps {
|
|
395
|
-
widget: ListWidget
|
|
397
|
+
widget: ListWidget & {
|
|
398
|
+
isStreaming?: boolean;
|
|
399
|
+
};
|
|
396
400
|
onAction?: (action: ActionEvent) => void;
|
|
397
401
|
}
|
|
398
402
|
declare function List({ widget, onAction }: ListProps): react_jsx_runtime.JSX.Element;
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ interface Widget {
|
|
|
23
23
|
actions?: Action[];
|
|
24
24
|
/** Additional data not displayed but captured via onWidgetRender */
|
|
25
25
|
meta?: Record<string, any>;
|
|
26
|
+
/** Whether the widget is still receiving streaming data */
|
|
27
|
+
isStreaming?: boolean;
|
|
26
28
|
}
|
|
27
29
|
interface CardWidget extends Widget {
|
|
28
30
|
type: 'card';
|
|
@@ -392,7 +394,9 @@ interface CardProps {
|
|
|
392
394
|
declare function Card({ widget, onAction }: CardProps): react_jsx_runtime.JSX.Element;
|
|
393
395
|
|
|
394
396
|
interface ListProps {
|
|
395
|
-
widget: ListWidget
|
|
397
|
+
widget: ListWidget & {
|
|
398
|
+
isStreaming?: boolean;
|
|
399
|
+
};
|
|
396
400
|
onAction?: (action: ActionEvent) => void;
|
|
397
401
|
}
|
|
398
402
|
declare function List({ widget, onAction }: ListProps): react_jsx_runtime.JSX.Element;
|
package/dist/index.js
CHANGED
|
@@ -502,6 +502,71 @@ function validateFile(file) {
|
|
|
502
502
|
}
|
|
503
503
|
|
|
504
504
|
// src/utils/widget-parser.ts
|
|
505
|
+
var STREAMABLE_WIDGET_TYPES = ["list", "table"];
|
|
506
|
+
function parsePartialItemsArray(partialJson) {
|
|
507
|
+
const items = [];
|
|
508
|
+
let isStreaming = false;
|
|
509
|
+
const itemsMatch = partialJson.match(/"items"\s*:\s*\[/);
|
|
510
|
+
if (!itemsMatch) {
|
|
511
|
+
return { items, isStreaming: false };
|
|
512
|
+
}
|
|
513
|
+
const arrayStart = partialJson.indexOf("[", itemsMatch.index);
|
|
514
|
+
if (arrayStart === -1) {
|
|
515
|
+
return { items, isStreaming: true };
|
|
516
|
+
}
|
|
517
|
+
let depth = 0;
|
|
518
|
+
let inString = false;
|
|
519
|
+
let escapeNext = false;
|
|
520
|
+
let objectStart = -1;
|
|
521
|
+
for (let i = arrayStart + 1; i < partialJson.length; i++) {
|
|
522
|
+
const char = partialJson[i];
|
|
523
|
+
if (escapeNext) {
|
|
524
|
+
escapeNext = false;
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
if (char === "\\" && inString) {
|
|
528
|
+
escapeNext = true;
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
if (char === '"') {
|
|
532
|
+
inString = !inString;
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
if (inString) continue;
|
|
536
|
+
if (char === "{") {
|
|
537
|
+
if (depth === 0) {
|
|
538
|
+
objectStart = i;
|
|
539
|
+
}
|
|
540
|
+
depth++;
|
|
541
|
+
} else if (char === "}") {
|
|
542
|
+
depth--;
|
|
543
|
+
if (depth === 0 && objectStart !== -1) {
|
|
544
|
+
const objectJson = partialJson.slice(objectStart, i + 1);
|
|
545
|
+
try {
|
|
546
|
+
const item = JSON.parse(objectJson);
|
|
547
|
+
if (!item.id) {
|
|
548
|
+
item.id = `item-${items.length}-${simpleHash(objectJson)}`;
|
|
549
|
+
}
|
|
550
|
+
items.push(item);
|
|
551
|
+
} catch (e) {
|
|
552
|
+
}
|
|
553
|
+
objectStart = -1;
|
|
554
|
+
}
|
|
555
|
+
} else if (char === "]" && depth === 0) {
|
|
556
|
+
isStreaming = false;
|
|
557
|
+
break;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
if (depth > 0 || objectStart !== -1) {
|
|
561
|
+
isStreaming = true;
|
|
562
|
+
}
|
|
563
|
+
const afterItems = partialJson.slice(arrayStart);
|
|
564
|
+
const closingBracket = findMatchingBracket(afterItems, 0);
|
|
565
|
+
if (closingBracket === -1) {
|
|
566
|
+
isStreaming = true;
|
|
567
|
+
}
|
|
568
|
+
return { items, isStreaming };
|
|
569
|
+
}
|
|
505
570
|
function simpleHash(str) {
|
|
506
571
|
let hash = 0;
|
|
507
572
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -563,9 +628,38 @@ function parseWidgetsFromText(text) {
|
|
|
563
628
|
const fullBracketStart = lastWidgetStart + bracketOpenIndex;
|
|
564
629
|
const bracketEnd = findMatchingBracket(text, fullBracketStart);
|
|
565
630
|
if (bracketEnd === -1) {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
631
|
+
if (STREAMABLE_WIDGET_TYPES.includes(widgetType)) {
|
|
632
|
+
const partialContent = text.slice(fullBracketStart + 1);
|
|
633
|
+
const { items, isStreaming } = parsePartialItemsArray(partialContent);
|
|
634
|
+
if (items.length > 0) {
|
|
635
|
+
processText = text.slice(0, lastWidgetStart);
|
|
636
|
+
const widgetId = `widget-${widgetType}-streaming-${simpleHash(partialContent)}`;
|
|
637
|
+
const textBefore = processText.replace(/[\s:;\-–—\.]+$/g, "").trim();
|
|
638
|
+
if (textBefore) {
|
|
639
|
+
segments.push({ type: "text", content: textBefore });
|
|
640
|
+
}
|
|
641
|
+
segments.push({
|
|
642
|
+
type: "widget",
|
|
643
|
+
widget: {
|
|
644
|
+
type: widgetType,
|
|
645
|
+
id: widgetId,
|
|
646
|
+
props: widgetType === "table" ? { rows: items, columns: [] } : { items },
|
|
647
|
+
isStreaming: true
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
hasWidgets = true;
|
|
651
|
+
hasPendingWidget = false;
|
|
652
|
+
processText = "";
|
|
653
|
+
} else {
|
|
654
|
+
processText = text.slice(0, lastWidgetStart);
|
|
655
|
+
pendingWidgetType = widgetType;
|
|
656
|
+
hasPendingWidget = true;
|
|
657
|
+
}
|
|
658
|
+
} else {
|
|
659
|
+
processText = text.slice(0, lastWidgetStart);
|
|
660
|
+
pendingWidgetType = widgetType;
|
|
661
|
+
hasPendingWidget = true;
|
|
662
|
+
}
|
|
569
663
|
}
|
|
570
664
|
}
|
|
571
665
|
}
|
|
@@ -729,38 +823,73 @@ function Card({ widget, onAction }) {
|
|
|
729
823
|
|
|
730
824
|
// src/components/Widgets/widget-library/List.tsx
|
|
731
825
|
|
|
826
|
+
|
|
732
827
|
function List({ widget, onAction }) {
|
|
733
828
|
const { items } = widget.props;
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
829
|
+
const isStreaming = _nullishCoalesce(widget.isStreaming, () => ( false));
|
|
830
|
+
const seenItemsRef = _react.useRef.call(void 0, /* @__PURE__ */ new Set());
|
|
831
|
+
const [newItemIds, setNewItemIds] = _react.useState.call(void 0, /* @__PURE__ */ new Set());
|
|
832
|
+
_react.useEffect.call(void 0, () => {
|
|
833
|
+
const currentIds = new Set(items.map((item) => item.id));
|
|
834
|
+
const newIds = /* @__PURE__ */ new Set();
|
|
835
|
+
items.forEach((item) => {
|
|
836
|
+
if (!seenItemsRef.current.has(item.id)) {
|
|
837
|
+
newIds.add(item.id);
|
|
838
|
+
}
|
|
839
|
+
});
|
|
840
|
+
items.forEach((item) => seenItemsRef.current.add(item.id));
|
|
841
|
+
if (newIds.size > 0) {
|
|
842
|
+
setNewItemIds(newIds);
|
|
843
|
+
const timer = setTimeout(() => {
|
|
844
|
+
setNewItemIds(/* @__PURE__ */ new Set());
|
|
845
|
+
}, 500);
|
|
846
|
+
return () => clearTimeout(timer);
|
|
847
|
+
}
|
|
848
|
+
}, [items]);
|
|
849
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "border border-neutral-200 dark:border-neutral-700 rounded-xl bg-white dark:bg-neutral-900 overflow-hidden", children: [
|
|
850
|
+
items.map((item, index) => {
|
|
851
|
+
const isNew = newItemIds.has(item.id);
|
|
852
|
+
const isLast = index === items.length - 1;
|
|
853
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
854
|
+
"div",
|
|
855
|
+
{
|
|
856
|
+
className: `apteva-list-item flex items-center p-4 transition-colors ${!isLast || isStreaming ? "border-b border-neutral-200 dark:border-neutral-700" : ""} ${!item.backgroundColor ? "hover:bg-neutral-50 dark:hover:bg-neutral-800" : ""} ${isNew ? "apteva-list-item-new" : ""}`,
|
|
857
|
+
style: item.backgroundColor ? { backgroundColor: item.backgroundColor } : void 0,
|
|
858
|
+
children: [
|
|
859
|
+
item.image && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: item.image, alt: item.title, className: "w-16 h-16 rounded object-cover" }),
|
|
860
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: `flex-1 ${item.image ? "ml-4" : ""}`, children: [
|
|
861
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h4", { className: "font-semibold !text-neutral-900 dark:!text-white", children: item.title }),
|
|
862
|
+
item.subtitle && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "!text-sm !text-neutral-600 dark:!text-neutral-400", children: item.subtitle }),
|
|
863
|
+
item.description && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "!text-xs !text-neutral-500 dark:!text-neutral-500 mt-1", children: item.description })
|
|
864
|
+
] }),
|
|
865
|
+
widget.actions && widget.actions.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex gap-2", children: widget.actions.map((action, idx) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
866
|
+
"button",
|
|
867
|
+
{
|
|
868
|
+
onClick: () => _optionalChain([onAction, 'optionalCall', _3 => _3({
|
|
869
|
+
type: action.type,
|
|
870
|
+
payload: item.metadata || item,
|
|
871
|
+
widgetId: widget.id,
|
|
872
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
873
|
+
})]),
|
|
874
|
+
className: "px-3 py-1.5 !text-sm rounded-lg font-medium transition-colors bg-blue-500 !text-white hover:bg-blue-600",
|
|
875
|
+
children: action.label
|
|
876
|
+
},
|
|
877
|
+
idx
|
|
878
|
+
)) })
|
|
879
|
+
]
|
|
880
|
+
},
|
|
881
|
+
item.id
|
|
882
|
+
);
|
|
883
|
+
}),
|
|
884
|
+
isStreaming && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-list-streaming flex items-center gap-3 p-4 text-neutral-500 dark:text-neutral-400", children: [
|
|
885
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-streaming-dots flex gap-1", children: [
|
|
886
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "w-2 h-2 bg-current rounded-full animate-pulse", style: { animationDelay: "0ms" } }),
|
|
887
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "w-2 h-2 bg-current rounded-full animate-pulse", style: { animationDelay: "150ms" } }),
|
|
888
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "w-2 h-2 bg-current rounded-full animate-pulse", style: { animationDelay: "300ms" } })
|
|
889
|
+
] }),
|
|
890
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-sm", children: "Loading more..." })
|
|
891
|
+
] })
|
|
892
|
+
] });
|
|
764
893
|
}
|
|
765
894
|
|
|
766
895
|
// src/components/Widgets/widget-library/Button.tsx
|
|
@@ -840,8 +969,32 @@ function ButtonGroup({ widget, onAction }) {
|
|
|
840
969
|
|
|
841
970
|
// src/components/Widgets/widget-library/Table.tsx
|
|
842
971
|
|
|
972
|
+
|
|
843
973
|
function Table({ widget, onAction }) {
|
|
844
974
|
const { columns, rows, caption, compact = false, striped = false } = widget.props;
|
|
975
|
+
const isStreaming = _nullishCoalesce(widget.isStreaming, () => ( false));
|
|
976
|
+
const seenRowsRef = _react.useRef.call(void 0, /* @__PURE__ */ new Set());
|
|
977
|
+
const [newRowIds, setNewRowIds] = _react.useState.call(void 0, /* @__PURE__ */ new Set());
|
|
978
|
+
_react.useEffect.call(void 0, () => {
|
|
979
|
+
const newIds = /* @__PURE__ */ new Set();
|
|
980
|
+
rows.forEach((row, index) => {
|
|
981
|
+
const rowId = row.id || `row-${index}`;
|
|
982
|
+
if (!seenRowsRef.current.has(rowId)) {
|
|
983
|
+
newIds.add(rowId);
|
|
984
|
+
}
|
|
985
|
+
});
|
|
986
|
+
rows.forEach((row, index) => {
|
|
987
|
+
const rowId = row.id || `row-${index}`;
|
|
988
|
+
seenRowsRef.current.add(rowId);
|
|
989
|
+
});
|
|
990
|
+
if (newIds.size > 0) {
|
|
991
|
+
setNewRowIds(newIds);
|
|
992
|
+
const timer = setTimeout(() => {
|
|
993
|
+
setNewRowIds(/* @__PURE__ */ new Set());
|
|
994
|
+
}, 500);
|
|
995
|
+
return () => clearTimeout(timer);
|
|
996
|
+
}
|
|
997
|
+
}, [rows]);
|
|
845
998
|
const getAlignment = (align) => {
|
|
846
999
|
switch (align) {
|
|
847
1000
|
case "center":
|
|
@@ -868,47 +1021,67 @@ function Table({ widget, onAction }) {
|
|
|
868
1021
|
column.key
|
|
869
1022
|
)) }) }),
|
|
870
1023
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "tbody", { children: [
|
|
871
|
-
rows.map((row, rowIndex) =>
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
{
|
|
893
|
-
className: cn(
|
|
894
|
-
"text-neutral-700 dark:text-neutral-300",
|
|
895
|
-
compact ? "px-3 py-2 text-xs" : "px-4 py-3 text-sm",
|
|
896
|
-
getAlignment(column.align)
|
|
897
|
-
),
|
|
898
|
-
children: _nullishCoalesce(row[column.key], () => ( "\u2014"))
|
|
1024
|
+
rows.map((row, rowIndex) => {
|
|
1025
|
+
const rowId = row.id || `row-${rowIndex}`;
|
|
1026
|
+
const isNew = newRowIds.has(rowId);
|
|
1027
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1028
|
+
"tr",
|
|
1029
|
+
{
|
|
1030
|
+
className: cn(
|
|
1031
|
+
"apteva-table-row border-b border-neutral-200 dark:border-neutral-700 last:border-b-0",
|
|
1032
|
+
"transition-colors hover:bg-neutral-50 dark:hover:bg-neutral-800",
|
|
1033
|
+
striped && rowIndex % 2 === 1 && "bg-neutral-50/50 dark:bg-neutral-800/50",
|
|
1034
|
+
isNew && "apteva-table-row-new"
|
|
1035
|
+
),
|
|
1036
|
+
onClick: () => {
|
|
1037
|
+
if (widget.actions && widget.actions.length > 0) {
|
|
1038
|
+
_optionalChain([onAction, 'optionalCall', _15 => _15({
|
|
1039
|
+
type: widget.actions[0].type,
|
|
1040
|
+
payload: row,
|
|
1041
|
+
widgetId: widget.id,
|
|
1042
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
1043
|
+
})]);
|
|
1044
|
+
}
|
|
899
1045
|
},
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
1046
|
+
style: { cursor: _optionalChain([widget, 'access', _16 => _16.actions, 'optionalAccess', _17 => _17.length]) ? "pointer" : "default" },
|
|
1047
|
+
children: columns.map((column) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1048
|
+
"td",
|
|
1049
|
+
{
|
|
1050
|
+
className: cn(
|
|
1051
|
+
"text-neutral-700 dark:text-neutral-300",
|
|
1052
|
+
compact ? "px-3 py-2 text-xs" : "px-4 py-3 text-sm",
|
|
1053
|
+
getAlignment(column.align)
|
|
1054
|
+
),
|
|
1055
|
+
children: _nullishCoalesce(row[column.key], () => ( "\u2014"))
|
|
1056
|
+
},
|
|
1057
|
+
column.key
|
|
1058
|
+
))
|
|
1059
|
+
},
|
|
1060
|
+
rowId
|
|
1061
|
+
);
|
|
1062
|
+
}),
|
|
1063
|
+
rows.length === 0 && !isStreaming && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tr", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
906
1064
|
"td",
|
|
907
1065
|
{
|
|
908
|
-
colSpan: columns.length,
|
|
1066
|
+
colSpan: columns.length || 1,
|
|
909
1067
|
className: "px-4 py-8 text-center text-sm text-neutral-500 dark:text-neutral-400",
|
|
910
1068
|
children: "No data available"
|
|
911
1069
|
}
|
|
1070
|
+
) }),
|
|
1071
|
+
isStreaming && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tr", { className: "apteva-table-streaming", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1072
|
+
"td",
|
|
1073
|
+
{
|
|
1074
|
+
colSpan: columns.length || 1,
|
|
1075
|
+
className: "px-4 py-3 text-center",
|
|
1076
|
+
children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-center gap-3 text-neutral-500 dark:text-neutral-400", children: [
|
|
1077
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-1", children: [
|
|
1078
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "w-2 h-2 bg-current rounded-full animate-pulse", style: { animationDelay: "0ms" } }),
|
|
1079
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "w-2 h-2 bg-current rounded-full animate-pulse", style: { animationDelay: "150ms" } }),
|
|
1080
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "w-2 h-2 bg-current rounded-full animate-pulse", style: { animationDelay: "300ms" } })
|
|
1081
|
+
] }),
|
|
1082
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-sm", children: "Loading more..." })
|
|
1083
|
+
] })
|
|
1084
|
+
}
|
|
912
1085
|
) })
|
|
913
1086
|
] })
|
|
914
1087
|
] }) }) });
|
|
@@ -1345,14 +1518,39 @@ function MarkdownContent({ content, className = "" }) {
|
|
|
1345
1518
|
|
|
1346
1519
|
// src/components/Chat/ToolCall.tsx
|
|
1347
1520
|
|
|
1348
|
-
function ToolCall({ name, status }) {
|
|
1521
|
+
function ToolCall({ name, status, isReceiving = false }) {
|
|
1522
|
+
if (status === "preparing") {
|
|
1523
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: `apteva-tool-card apteva-tool-card-preparing ${isReceiving ? "apteva-tool-receiving" : ""}`, children: [
|
|
1524
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { className: "apteva-tool-icon apteva-tool-icon-spin", fill: "none", viewBox: "0 0 24 24", children: [
|
|
1525
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { className: "apteva-tool-spinner-track", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
1526
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { className: "apteva-tool-spinner-fill", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
|
|
1527
|
+
] }),
|
|
1528
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "apteva-tool-label", children: [
|
|
1529
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: name }),
|
|
1530
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-tool-status-text", children: " preparing" }),
|
|
1531
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "apteva-tool-dots", children: [
|
|
1532
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "." }),
|
|
1533
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "." }),
|
|
1534
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "." })
|
|
1535
|
+
] })
|
|
1536
|
+
] })
|
|
1537
|
+
] });
|
|
1538
|
+
}
|
|
1349
1539
|
if (status === "running") {
|
|
1350
1540
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-tool-card apteva-tool-card-running", children: [
|
|
1351
1541
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { className: "apteva-tool-icon apteva-tool-icon-spin", fill: "none", viewBox: "0 0 24 24", children: [
|
|
1352
1542
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { className: "apteva-tool-spinner-track", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
1353
1543
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { className: "apteva-tool-spinner-fill", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
|
|
1354
1544
|
] }),
|
|
1355
|
-
/* @__PURE__ */ _jsxruntime.
|
|
1545
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "apteva-tool-label", children: [
|
|
1546
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: name }),
|
|
1547
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-tool-status-text", children: " running" }),
|
|
1548
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "apteva-tool-dots", children: [
|
|
1549
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "." }),
|
|
1550
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "." }),
|
|
1551
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "." })
|
|
1552
|
+
] })
|
|
1553
|
+
] })
|
|
1356
1554
|
] });
|
|
1357
1555
|
}
|
|
1358
1556
|
if (status === "completed") {
|
|
@@ -1566,7 +1764,8 @@ function Message({ message, onAction, enableWidgets, onWidgetRender }) {
|
|
|
1566
1764
|
ToolCall,
|
|
1567
1765
|
{
|
|
1568
1766
|
name: segment.name,
|
|
1569
|
-
status: segment.result !== void 0 ? "completed" : "running"
|
|
1767
|
+
status: segment.status || (segment.result !== void 0 ? "completed" : "running"),
|
|
1768
|
+
isReceiving: segment.isReceiving
|
|
1570
1769
|
}
|
|
1571
1770
|
) }, segment.id)
|
|
1572
1771
|
);
|
|
@@ -2672,6 +2871,7 @@ ${widgetContext}` : widgetContext;
|
|
|
2672
2871
|
let accumulatedWidgets = [];
|
|
2673
2872
|
let responseThreadId = currentThreadId;
|
|
2674
2873
|
let toolInputBuffer = "";
|
|
2874
|
+
let receivingTimeout = null;
|
|
2675
2875
|
const streamingMessageId = `msg-${Date.now()}`;
|
|
2676
2876
|
const updateMessage = () => {
|
|
2677
2877
|
const segments = [...contentSegments];
|
|
@@ -2748,7 +2948,7 @@ ${widgetContext}` : widgetContext;
|
|
|
2748
2948
|
contentSegments.push({ type: "text", content: currentTextBuffer });
|
|
2749
2949
|
currentTextBuffer = "";
|
|
2750
2950
|
}
|
|
2751
|
-
contentSegments.push({ type: "tool", id: chunk.tool_id, name: displayName });
|
|
2951
|
+
contentSegments.push({ type: "tool", id: chunk.tool_id, name: displayName, status: "preparing" });
|
|
2752
2952
|
toolInputBuffer = "";
|
|
2753
2953
|
setChatToolName(displayName);
|
|
2754
2954
|
_optionalChain([onToolCall, 'optionalCall', _72 => _72(chunk.tool_name, chunk.tool_id)]);
|
|
@@ -2758,6 +2958,28 @@ ${widgetContext}` : widgetContext;
|
|
|
2758
2958
|
case "tool_input_delta":
|
|
2759
2959
|
if (chunk.tool_id && chunk.content) {
|
|
2760
2960
|
toolInputBuffer += chunk.content;
|
|
2961
|
+
const toolSegment = contentSegments.find((s) => s.type === "tool" && s.id === chunk.tool_id);
|
|
2962
|
+
if (toolSegment) {
|
|
2963
|
+
toolSegment.isReceiving = true;
|
|
2964
|
+
updateMessage();
|
|
2965
|
+
if (receivingTimeout) clearTimeout(receivingTimeout);
|
|
2966
|
+
receivingTimeout = setTimeout(() => {
|
|
2967
|
+
if (toolSegment.status === "preparing") {
|
|
2968
|
+
toolSegment.isReceiving = false;
|
|
2969
|
+
updateMessage();
|
|
2970
|
+
}
|
|
2971
|
+
}, 150);
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
break;
|
|
2975
|
+
case "tool_use":
|
|
2976
|
+
if (chunk.tool_id) {
|
|
2977
|
+
const toolSegment = contentSegments.find((s) => s.type === "tool" && s.id === chunk.tool_id);
|
|
2978
|
+
if (toolSegment && toolSegment.status === "preparing") {
|
|
2979
|
+
toolSegment.status = "running";
|
|
2980
|
+
toolSegment.isReceiving = false;
|
|
2981
|
+
updateMessage();
|
|
2982
|
+
}
|
|
2761
2983
|
}
|
|
2762
2984
|
break;
|
|
2763
2985
|
case "tool_result":
|
|
@@ -2765,6 +2987,8 @@ ${widgetContext}` : widgetContext;
|
|
|
2765
2987
|
const toolSegment = contentSegments.find((s) => s.type === "tool" && s.id === chunk.tool_id);
|
|
2766
2988
|
if (toolSegment) {
|
|
2767
2989
|
toolSegment.result = chunk.content;
|
|
2990
|
+
toolSegment.status = "completed";
|
|
2991
|
+
toolSegment.isReceiving = false;
|
|
2768
2992
|
_optionalChain([onToolResult, 'optionalCall', _73 => _73(toolSegment.name, chunk.content)]);
|
|
2769
2993
|
}
|
|
2770
2994
|
setChatToolName(null);
|