@apteva/apteva-kit 0.1.69 → 0.1.70
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 +241 -68
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +322 -149
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -4,13 +4,13 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
|
|
6
6
|
// src/components/Chat/Chat.tsx
|
|
7
|
-
import { useState as
|
|
7
|
+
import { useState as useState6, useEffect as useEffect6, useRef as useRef7, useMemo as useMemo2, forwardRef, useImperativeHandle } from "react";
|
|
8
8
|
|
|
9
9
|
// src/components/Chat/MessageList.tsx
|
|
10
|
-
import { useEffect as
|
|
10
|
+
import { useEffect as useEffect5, useRef as useRef4 } from "react";
|
|
11
11
|
|
|
12
12
|
// src/components/Chat/Message.tsx
|
|
13
|
-
import { useEffect as
|
|
13
|
+
import { useEffect as useEffect4, useRef as useRef3, useMemo } from "react";
|
|
14
14
|
|
|
15
15
|
// src/utils/cn.ts
|
|
16
16
|
import { clsx } from "clsx";
|
|
@@ -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
|
}
|
|
@@ -695,7 +789,7 @@ Widgets: @ui:type[{props}]. Types: ${widgets.join(", ")}. Add "meta" at root (no
|
|
|
695
789
|
}
|
|
696
790
|
|
|
697
791
|
// src/components/Widgets/Widgets.tsx
|
|
698
|
-
import { useEffect } from "react";
|
|
792
|
+
import { useEffect as useEffect3 } from "react";
|
|
699
793
|
|
|
700
794
|
// src/components/Widgets/widget-library/Card.tsx
|
|
701
795
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -728,39 +822,74 @@ function Card({ widget, onAction }) {
|
|
|
728
822
|
}
|
|
729
823
|
|
|
730
824
|
// src/components/Widgets/widget-library/List.tsx
|
|
825
|
+
import { useEffect, useRef, useState } from "react";
|
|
731
826
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
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 = widget.isStreaming ?? false;
|
|
830
|
+
const seenItemsRef = useRef(/* @__PURE__ */ new Set());
|
|
831
|
+
const [newItemIds, setNewItemIds] = useState(/* @__PURE__ */ new Set());
|
|
832
|
+
useEffect(() => {
|
|
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__ */ jsxs2("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__ */ jsxs2(
|
|
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__ */ jsx2("img", { src: item.image, alt: item.title, className: "w-16 h-16 rounded object-cover" }),
|
|
860
|
+
/* @__PURE__ */ jsxs2("div", { className: `flex-1 ${item.image ? "ml-4" : ""}`, children: [
|
|
861
|
+
/* @__PURE__ */ jsx2("h4", { className: "font-semibold !text-neutral-900 dark:!text-white", children: item.title }),
|
|
862
|
+
item.subtitle && /* @__PURE__ */ jsx2("p", { className: "!text-sm !text-neutral-600 dark:!text-neutral-400", children: item.subtitle }),
|
|
863
|
+
item.description && /* @__PURE__ */ jsx2("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__ */ jsx2("div", { className: "flex gap-2", children: widget.actions.map((action, idx) => /* @__PURE__ */ jsx2(
|
|
866
|
+
"button",
|
|
867
|
+
{
|
|
868
|
+
onClick: () => onAction?.({
|
|
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__ */ jsxs2("div", { className: "apteva-list-streaming flex items-center gap-3 p-4 text-neutral-500 dark:text-neutral-400", children: [
|
|
885
|
+
/* @__PURE__ */ jsxs2("div", { className: "apteva-streaming-dots flex gap-1", children: [
|
|
886
|
+
/* @__PURE__ */ jsx2("span", { className: "w-2 h-2 bg-current rounded-full animate-pulse", style: { animationDelay: "0ms" } }),
|
|
887
|
+
/* @__PURE__ */ jsx2("span", { className: "w-2 h-2 bg-current rounded-full animate-pulse", style: { animationDelay: "150ms" } }),
|
|
888
|
+
/* @__PURE__ */ jsx2("span", { className: "w-2 h-2 bg-current rounded-full animate-pulse", style: { animationDelay: "300ms" } })
|
|
889
|
+
] }),
|
|
890
|
+
/* @__PURE__ */ jsx2("span", { className: "text-sm", children: "Loading more..." })
|
|
891
|
+
] })
|
|
892
|
+
] });
|
|
764
893
|
}
|
|
765
894
|
|
|
766
895
|
// src/components/Widgets/widget-library/Button.tsx
|
|
@@ -839,9 +968,33 @@ function ButtonGroup({ widget, onAction }) {
|
|
|
839
968
|
}
|
|
840
969
|
|
|
841
970
|
// src/components/Widgets/widget-library/Table.tsx
|
|
971
|
+
import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
842
972
|
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
843
973
|
function Table({ widget, onAction }) {
|
|
844
974
|
const { columns, rows, caption, compact = false, striped = false } = widget.props;
|
|
975
|
+
const isStreaming = widget.isStreaming ?? false;
|
|
976
|
+
const seenRowsRef = useRef2(/* @__PURE__ */ new Set());
|
|
977
|
+
const [newRowIds, setNewRowIds] = useState2(/* @__PURE__ */ new Set());
|
|
978
|
+
useEffect2(() => {
|
|
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,58 +1021,78 @@ function Table({ widget, onAction }) {
|
|
|
868
1021
|
column.key
|
|
869
1022
|
)) }) }),
|
|
870
1023
|
/* @__PURE__ */ jsxs3("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: 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__ */ jsx5(
|
|
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
|
+
onAction?.({
|
|
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: widget.actions?.length ? "pointer" : "default" },
|
|
1047
|
+
children: columns.map((column) => /* @__PURE__ */ jsx5(
|
|
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: row[column.key] ?? "\u2014"
|
|
1056
|
+
},
|
|
1057
|
+
column.key
|
|
1058
|
+
))
|
|
1059
|
+
},
|
|
1060
|
+
rowId
|
|
1061
|
+
);
|
|
1062
|
+
}),
|
|
1063
|
+
rows.length === 0 && !isStreaming && /* @__PURE__ */ jsx5("tr", { children: /* @__PURE__ */ jsx5(
|
|
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__ */ jsx5("tr", { className: "apteva-table-streaming", children: /* @__PURE__ */ jsx5(
|
|
1072
|
+
"td",
|
|
1073
|
+
{
|
|
1074
|
+
colSpan: columns.length || 1,
|
|
1075
|
+
className: "px-4 py-3 text-center",
|
|
1076
|
+
children: /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-center gap-3 text-neutral-500 dark:text-neutral-400", children: [
|
|
1077
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex gap-1", children: [
|
|
1078
|
+
/* @__PURE__ */ jsx5("span", { className: "w-2 h-2 bg-current rounded-full animate-pulse", style: { animationDelay: "0ms" } }),
|
|
1079
|
+
/* @__PURE__ */ jsx5("span", { className: "w-2 h-2 bg-current rounded-full animate-pulse", style: { animationDelay: "150ms" } }),
|
|
1080
|
+
/* @__PURE__ */ jsx5("span", { className: "w-2 h-2 bg-current rounded-full animate-pulse", style: { animationDelay: "300ms" } })
|
|
1081
|
+
] }),
|
|
1082
|
+
/* @__PURE__ */ jsx5("span", { className: "text-sm", children: "Loading more..." })
|
|
1083
|
+
] })
|
|
1084
|
+
}
|
|
912
1085
|
) })
|
|
913
1086
|
] })
|
|
914
1087
|
] }) }) });
|
|
915
1088
|
}
|
|
916
1089
|
|
|
917
1090
|
// src/components/Widgets/widget-library/Form.tsx
|
|
918
|
-
import { useState } from "react";
|
|
1091
|
+
import { useState as useState3 } from "react";
|
|
919
1092
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
920
1093
|
function Form({ widget, onAction }) {
|
|
921
1094
|
const { title, fields } = widget.props;
|
|
922
|
-
const [formData, setFormData] =
|
|
1095
|
+
const [formData, setFormData] = useState3(() => {
|
|
923
1096
|
const initial = {};
|
|
924
1097
|
fields.forEach((field) => {
|
|
925
1098
|
initial[field.name] = field.defaultValue ?? (field.type === "checkbox" ? false : "");
|
|
@@ -1069,7 +1242,7 @@ function Widgets({
|
|
|
1069
1242
|
columns = 3,
|
|
1070
1243
|
className
|
|
1071
1244
|
}) {
|
|
1072
|
-
|
|
1245
|
+
useEffect3(() => {
|
|
1073
1246
|
widgets.forEach((widget) => {
|
|
1074
1247
|
onWidgetMount?.(widget.id);
|
|
1075
1248
|
});
|
|
@@ -1377,7 +1550,7 @@ function Message({ message, onAction, enableWidgets, onWidgetRender }) {
|
|
|
1377
1550
|
const contentSegments = message.metadata?.content_segments;
|
|
1378
1551
|
const isStreaming = message.metadata?.isStreaming === true;
|
|
1379
1552
|
const hasContent = message.content || contentSegments && contentSegments.length > 0;
|
|
1380
|
-
const reportedWidgetsRef =
|
|
1553
|
+
const reportedWidgetsRef = useRef3(/* @__PURE__ */ new Set());
|
|
1381
1554
|
const parsedWidgets = useMemo(() => {
|
|
1382
1555
|
if (!enableWidgets || isUser || !message.content) {
|
|
1383
1556
|
return [];
|
|
@@ -1385,7 +1558,7 @@ function Message({ message, onAction, enableWidgets, onWidgetRender }) {
|
|
|
1385
1558
|
const parsed = parseWidgetsFromText(message.content);
|
|
1386
1559
|
return parsed.segments.filter((seg) => seg.type === "widget" && !!seg.widget).map((seg) => seg.widget);
|
|
1387
1560
|
}, [enableWidgets, isUser, message.content]);
|
|
1388
|
-
|
|
1561
|
+
useEffect4(() => {
|
|
1389
1562
|
if (onWidgetRender && message.widgets) {
|
|
1390
1563
|
for (const widget of message.widgets) {
|
|
1391
1564
|
if (!reportedWidgetsRef.current.has(widget.id)) {
|
|
@@ -1395,7 +1568,7 @@ function Message({ message, onAction, enableWidgets, onWidgetRender }) {
|
|
|
1395
1568
|
}
|
|
1396
1569
|
}
|
|
1397
1570
|
}, [message.widgets, onWidgetRender]);
|
|
1398
|
-
|
|
1571
|
+
useEffect4(() => {
|
|
1399
1572
|
if (onWidgetRender && parsedWidgets.length > 0) {
|
|
1400
1573
|
for (const widget of parsedWidgets) {
|
|
1401
1574
|
if (!reportedWidgetsRef.current.has(widget.id)) {
|
|
@@ -1767,16 +1940,16 @@ function MessageList({
|
|
|
1767
1940
|
enableWidgets,
|
|
1768
1941
|
onWidgetRender
|
|
1769
1942
|
}) {
|
|
1770
|
-
const listRef =
|
|
1771
|
-
const isNearBottomRef =
|
|
1772
|
-
const lastScrollHeightRef =
|
|
1943
|
+
const listRef = useRef4(null);
|
|
1944
|
+
const isNearBottomRef = useRef4(true);
|
|
1945
|
+
const lastScrollHeightRef = useRef4(0);
|
|
1773
1946
|
const handleScroll = () => {
|
|
1774
1947
|
if (listRef.current) {
|
|
1775
1948
|
const { scrollTop, scrollHeight, clientHeight } = listRef.current;
|
|
1776
1949
|
isNearBottomRef.current = scrollHeight - scrollTop - clientHeight < 100;
|
|
1777
1950
|
}
|
|
1778
1951
|
};
|
|
1779
|
-
|
|
1952
|
+
useEffect5(() => {
|
|
1780
1953
|
if (listRef.current && isNearBottomRef.current) {
|
|
1781
1954
|
const currentScrollHeight = listRef.current.scrollHeight;
|
|
1782
1955
|
if (currentScrollHeight !== lastScrollHeightRef.current) {
|
|
@@ -1800,16 +1973,16 @@ function MessageList({
|
|
|
1800
1973
|
}
|
|
1801
1974
|
|
|
1802
1975
|
// src/components/Chat/Composer.tsx
|
|
1803
|
-
import { useState as
|
|
1976
|
+
import { useState as useState4, useRef as useRef5 } from "react";
|
|
1804
1977
|
import { Fragment, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1805
1978
|
function Composer({ onSendMessage, placeholder = "Type a message...", disabled = false, isLoading = false, onStop, onFileUpload, onSwitchMode }) {
|
|
1806
|
-
const [text, setText] =
|
|
1807
|
-
const [showMenu, setShowMenu] =
|
|
1808
|
-
const [pendingFiles, setPendingFiles] =
|
|
1809
|
-
const [fileError, setFileError] =
|
|
1810
|
-
const textareaRef =
|
|
1811
|
-
const fileInputRef =
|
|
1812
|
-
const menuButtonRef =
|
|
1979
|
+
const [text, setText] = useState4("");
|
|
1980
|
+
const [showMenu, setShowMenu] = useState4(false);
|
|
1981
|
+
const [pendingFiles, setPendingFiles] = useState4([]);
|
|
1982
|
+
const [fileError, setFileError] = useState4(null);
|
|
1983
|
+
const textareaRef = useRef5(null);
|
|
1984
|
+
const fileInputRef = useRef5(null);
|
|
1985
|
+
const menuButtonRef = useRef5(null);
|
|
1813
1986
|
const handleKeyDown = (e) => {
|
|
1814
1987
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
1815
1988
|
e.preventDefault();
|
|
@@ -2013,7 +2186,7 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
|
|
|
2013
2186
|
}
|
|
2014
2187
|
|
|
2015
2188
|
// src/components/Chat/CommandComposer.tsx
|
|
2016
|
-
import { useState as
|
|
2189
|
+
import { useState as useState5, useRef as useRef6 } from "react";
|
|
2017
2190
|
import { Fragment as Fragment2, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2018
2191
|
function CommandComposer({
|
|
2019
2192
|
onExecute,
|
|
@@ -2031,13 +2204,13 @@ function CommandComposer({
|
|
|
2031
2204
|
placeholder = "Enter your command...",
|
|
2032
2205
|
disabled = false
|
|
2033
2206
|
}) {
|
|
2034
|
-
const [input, setInput] =
|
|
2035
|
-
const [pendingFiles, setPendingFiles] =
|
|
2036
|
-
const [fileError, setFileError] =
|
|
2037
|
-
const [showMenu, setShowMenu] =
|
|
2038
|
-
const inputRef =
|
|
2039
|
-
const fileInputRef =
|
|
2040
|
-
const menuButtonRef =
|
|
2207
|
+
const [input, setInput] = useState5("");
|
|
2208
|
+
const [pendingFiles, setPendingFiles] = useState5([]);
|
|
2209
|
+
const [fileError, setFileError] = useState5(null);
|
|
2210
|
+
const [showMenu, setShowMenu] = useState5(false);
|
|
2211
|
+
const inputRef = useRef6(null);
|
|
2212
|
+
const fileInputRef = useRef6(null);
|
|
2213
|
+
const menuButtonRef = useRef6(null);
|
|
2041
2214
|
const handleSubmit = () => {
|
|
2042
2215
|
const hasText = input.trim();
|
|
2043
2216
|
const hasFiles = pendingFiles.length > 0;
|
|
@@ -2566,25 +2739,25 @@ var Chat = forwardRef(function Chat2({
|
|
|
2566
2739
|
onWidgetRender,
|
|
2567
2740
|
className
|
|
2568
2741
|
}, ref) {
|
|
2569
|
-
const [messages, setMessages] =
|
|
2570
|
-
const [isLoading, setIsLoading] =
|
|
2571
|
-
const [currentThreadId, setCurrentThreadId] =
|
|
2572
|
-
const [mode, setMode] =
|
|
2573
|
-
const [chatToolName, setChatToolName] =
|
|
2574
|
-
const [commandState, setCommandState] =
|
|
2575
|
-
const [commandResult, setCommandResult] =
|
|
2576
|
-
const [commandError, setCommandError] =
|
|
2577
|
-
const [progress, setProgress] =
|
|
2578
|
-
const [commandInput, setCommandInput] =
|
|
2579
|
-
const [streamedContent, setStreamedContent] =
|
|
2580
|
-
const [currentToolName, setCurrentToolName] =
|
|
2581
|
-
const [currentRequestId, setCurrentRequestId] =
|
|
2582
|
-
const [plan, setPlan] =
|
|
2583
|
-
const [pendingCommand, setPendingCommand] =
|
|
2584
|
-
const [internalPlanMode, setInternalPlanMode] =
|
|
2585
|
-
const [showSettingsMenu, setShowSettingsMenu] =
|
|
2586
|
-
const fileInputRef =
|
|
2587
|
-
const handleSendMessageRef =
|
|
2742
|
+
const [messages, setMessages] = useState6(initialMessages);
|
|
2743
|
+
const [isLoading, setIsLoading] = useState6(false);
|
|
2744
|
+
const [currentThreadId, setCurrentThreadId] = useState6(threadId || null);
|
|
2745
|
+
const [mode, setMode] = useState6(initialMode);
|
|
2746
|
+
const [chatToolName, setChatToolName] = useState6(null);
|
|
2747
|
+
const [commandState, setCommandState] = useState6("idle");
|
|
2748
|
+
const [commandResult, setCommandResult] = useState6(null);
|
|
2749
|
+
const [commandError, setCommandError] = useState6(null);
|
|
2750
|
+
const [progress, setProgress] = useState6(0);
|
|
2751
|
+
const [commandInput, setCommandInput] = useState6("");
|
|
2752
|
+
const [streamedContent, setStreamedContent] = useState6("");
|
|
2753
|
+
const [currentToolName, setCurrentToolName] = useState6(null);
|
|
2754
|
+
const [currentRequestId, setCurrentRequestId] = useState6(null);
|
|
2755
|
+
const [plan, setPlan] = useState6("");
|
|
2756
|
+
const [pendingCommand, setPendingCommand] = useState6("");
|
|
2757
|
+
const [internalPlanMode, setInternalPlanMode] = useState6(planMode);
|
|
2758
|
+
const [showSettingsMenu, setShowSettingsMenu] = useState6(false);
|
|
2759
|
+
const fileInputRef = useRef7(null);
|
|
2760
|
+
const handleSendMessageRef = useRef7(null);
|
|
2588
2761
|
useImperativeHandle(ref, () => ({
|
|
2589
2762
|
sendMessage: async (text) => {
|
|
2590
2763
|
if (handleSendMessageRef.current) {
|
|
@@ -2605,7 +2778,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
2605
2778
|
return context ? `${context}
|
|
2606
2779
|
${widgetContext}` : widgetContext;
|
|
2607
2780
|
}, [context, enableWidgets, availableWidgets, compactWidgetContext]);
|
|
2608
|
-
|
|
2781
|
+
useEffect6(() => {
|
|
2609
2782
|
if (apiUrl || apiKey) {
|
|
2610
2783
|
aptevaClient.configure({
|
|
2611
2784
|
...apiUrl && { apiUrl },
|
|
@@ -2613,15 +2786,15 @@ ${widgetContext}` : widgetContext;
|
|
|
2613
2786
|
});
|
|
2614
2787
|
}
|
|
2615
2788
|
}, [apiUrl, apiKey]);
|
|
2616
|
-
|
|
2789
|
+
useEffect6(() => {
|
|
2617
2790
|
if (threadId) {
|
|
2618
2791
|
onThreadChange?.(threadId);
|
|
2619
2792
|
}
|
|
2620
2793
|
}, [threadId, onThreadChange]);
|
|
2621
|
-
|
|
2794
|
+
useEffect6(() => {
|
|
2622
2795
|
setInternalPlanMode(planMode);
|
|
2623
2796
|
}, [planMode]);
|
|
2624
|
-
|
|
2797
|
+
useEffect6(() => {
|
|
2625
2798
|
const handleClickOutside = (event) => {
|
|
2626
2799
|
const target = event.target;
|
|
2627
2800
|
if (showSettingsMenu && !target.closest(".settings-menu-container")) {
|
|
@@ -3153,11 +3326,11 @@ ${planToExecute}`;
|
|
|
3153
3326
|
});
|
|
3154
3327
|
|
|
3155
3328
|
// src/components/Chat/CommandOutput.tsx
|
|
3156
|
-
import { useState as
|
|
3329
|
+
import { useState as useState7 } from "react";
|
|
3157
3330
|
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3158
3331
|
|
|
3159
3332
|
// src/components/Command/Command.tsx
|
|
3160
|
-
import React, { useState as
|
|
3333
|
+
import React, { useState as useState8, useEffect as useEffect7 } from "react";
|
|
3161
3334
|
import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3162
3335
|
function Command({
|
|
3163
3336
|
agentId,
|
|
@@ -3185,28 +3358,28 @@ function Command({
|
|
|
3185
3358
|
resultRenderer,
|
|
3186
3359
|
className
|
|
3187
3360
|
}) {
|
|
3188
|
-
const [state, setState] =
|
|
3189
|
-
const [result, setResult] =
|
|
3190
|
-
const [error, setError] =
|
|
3191
|
-
const [progress, setProgress] =
|
|
3192
|
-
const [command, setCommand] =
|
|
3193
|
-
const [streamedContent, setStreamedContent] =
|
|
3194
|
-
const [plan, setPlan] =
|
|
3195
|
-
const [pendingCommand, setPendingCommand] =
|
|
3196
|
-
const [showPlanDetails, setShowPlanDetails] =
|
|
3197
|
-
const [uploadedFiles, setUploadedFiles] =
|
|
3198
|
-
const [showSettingsMenu, setShowSettingsMenu] =
|
|
3199
|
-
const [internalPlanMode, setInternalPlanMode] =
|
|
3361
|
+
const [state, setState] = useState8("idle");
|
|
3362
|
+
const [result, setResult] = useState8(null);
|
|
3363
|
+
const [error, setError] = useState8(null);
|
|
3364
|
+
const [progress, setProgress] = useState8(0);
|
|
3365
|
+
const [command, setCommand] = useState8(initialCommand || "");
|
|
3366
|
+
const [streamedContent, setStreamedContent] = useState8("");
|
|
3367
|
+
const [plan, setPlan] = useState8("");
|
|
3368
|
+
const [pendingCommand, setPendingCommand] = useState8("");
|
|
3369
|
+
const [showPlanDetails, setShowPlanDetails] = useState8(false);
|
|
3370
|
+
const [uploadedFiles, setUploadedFiles] = useState8([]);
|
|
3371
|
+
const [showSettingsMenu, setShowSettingsMenu] = useState8(false);
|
|
3372
|
+
const [internalPlanMode, setInternalPlanMode] = useState8(planMode);
|
|
3200
3373
|
const fileInputRef = React.useRef(null);
|
|
3201
|
-
|
|
3374
|
+
useEffect7(() => {
|
|
3202
3375
|
if (autoExecute && state === "idle" && command) {
|
|
3203
3376
|
executeCommand();
|
|
3204
3377
|
}
|
|
3205
3378
|
}, [autoExecute]);
|
|
3206
|
-
|
|
3379
|
+
useEffect7(() => {
|
|
3207
3380
|
setInternalPlanMode(planMode);
|
|
3208
3381
|
}, [planMode]);
|
|
3209
|
-
|
|
3382
|
+
useEffect7(() => {
|
|
3210
3383
|
const handleClickOutside = (event) => {
|
|
3211
3384
|
const target = event.target;
|
|
3212
3385
|
if (showSettingsMenu && !target.closest(".settings-menu-container")) {
|
|
@@ -4128,7 +4301,7 @@ ${planToExecute}`;
|
|
|
4128
4301
|
}
|
|
4129
4302
|
|
|
4130
4303
|
// src/components/Prompt/Prompt.tsx
|
|
4131
|
-
import { useState as
|
|
4304
|
+
import { useState as useState9 } from "react";
|
|
4132
4305
|
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4133
4306
|
function Prompt({
|
|
4134
4307
|
agentId,
|
|
@@ -4146,9 +4319,9 @@ function Prompt({
|
|
|
4146
4319
|
showSuggestions = false,
|
|
4147
4320
|
className
|
|
4148
4321
|
}) {
|
|
4149
|
-
const [value, setValue] =
|
|
4150
|
-
const [isLoading, setIsLoading] =
|
|
4151
|
-
const [suggestions] =
|
|
4322
|
+
const [value, setValue] = useState9(initialValue);
|
|
4323
|
+
const [isLoading, setIsLoading] = useState9(false);
|
|
4324
|
+
const [suggestions] = useState9(["Plan a trip", "Write a description", "Analyze data"]);
|
|
4152
4325
|
const handleChange = (e) => {
|
|
4153
4326
|
const newValue = e.target.value;
|
|
4154
4327
|
if (!maxLength || newValue.length <= maxLength) {
|
|
@@ -4239,7 +4412,7 @@ function Prompt({
|
|
|
4239
4412
|
}
|
|
4240
4413
|
|
|
4241
4414
|
// src/components/Stream/Stream.tsx
|
|
4242
|
-
import { useState as
|
|
4415
|
+
import { useState as useState10, useEffect as useEffect8 } from "react";
|
|
4243
4416
|
import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
4244
4417
|
function Stream({
|
|
4245
4418
|
agentId,
|
|
@@ -4256,10 +4429,10 @@ function Stream({
|
|
|
4256
4429
|
typingSpeed = 30,
|
|
4257
4430
|
className
|
|
4258
4431
|
}) {
|
|
4259
|
-
const [text, setText] =
|
|
4260
|
-
const [isStreaming, setIsStreaming] =
|
|
4261
|
-
const [isComplete, setIsComplete] =
|
|
4262
|
-
|
|
4432
|
+
const [text, setText] = useState10("");
|
|
4433
|
+
const [isStreaming, setIsStreaming] = useState10(false);
|
|
4434
|
+
const [isComplete, setIsComplete] = useState10(false);
|
|
4435
|
+
useEffect8(() => {
|
|
4263
4436
|
if (autoStart && !isStreaming && !isComplete) {
|
|
4264
4437
|
startStreaming();
|
|
4265
4438
|
}
|
|
@@ -4336,7 +4509,7 @@ function Stream({
|
|
|
4336
4509
|
}
|
|
4337
4510
|
|
|
4338
4511
|
// src/components/Threads/ThreadList.tsx
|
|
4339
|
-
import { useState as
|
|
4512
|
+
import { useState as useState11 } from "react";
|
|
4340
4513
|
|
|
4341
4514
|
// src/components/Threads/ThreadItem.tsx
|
|
4342
4515
|
import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
@@ -4400,7 +4573,7 @@ function ThreadList({
|
|
|
4400
4573
|
showSearch = false,
|
|
4401
4574
|
groupBy = "none"
|
|
4402
4575
|
}) {
|
|
4403
|
-
const [searchQuery, setSearchQuery] =
|
|
4576
|
+
const [searchQuery, setSearchQuery] = useState11("");
|
|
4404
4577
|
const filteredThreads = threads.filter(
|
|
4405
4578
|
(thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || thread.preview?.toLowerCase().includes(searchQuery.toLowerCase())
|
|
4406
4579
|
);
|