@apteva/apteva-kit 0.1.68 → 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 +243 -71
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +324 -152
- 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();
|
|
@@ -1975,9 +2148,8 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
|
|
|
1975
2148
|
onKeyDown: handleKeyDown,
|
|
1976
2149
|
placeholder,
|
|
1977
2150
|
disabled,
|
|
1978
|
-
className: "apteva-composer-textarea flex-1 resize-none bg-transparent border-none focus:outline-none !text-neutral-900 dark:!text-neutral-100 placeholder-neutral-400 dark:placeholder-neutral-500 py-1 disabled:opacity-50 disabled:cursor-not-allowed overflow-
|
|
1979
|
-
rows: 1
|
|
1980
|
-
style: { maxHeight: "120px" }
|
|
2151
|
+
className: "apteva-composer-textarea flex-1 resize-none bg-transparent border-none focus:outline-none !text-neutral-900 dark:!text-neutral-100 placeholder-neutral-400 dark:placeholder-neutral-500 py-1 disabled:opacity-50 disabled:cursor-not-allowed overflow-hidden",
|
|
2152
|
+
rows: 1
|
|
1981
2153
|
}
|
|
1982
2154
|
),
|
|
1983
2155
|
isLoading && onStop ? /* @__PURE__ */ jsx15(
|
|
@@ -2014,7 +2186,7 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
|
|
|
2014
2186
|
}
|
|
2015
2187
|
|
|
2016
2188
|
// src/components/Chat/CommandComposer.tsx
|
|
2017
|
-
import { useState as
|
|
2189
|
+
import { useState as useState5, useRef as useRef6 } from "react";
|
|
2018
2190
|
import { Fragment as Fragment2, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2019
2191
|
function CommandComposer({
|
|
2020
2192
|
onExecute,
|
|
@@ -2032,13 +2204,13 @@ function CommandComposer({
|
|
|
2032
2204
|
placeholder = "Enter your command...",
|
|
2033
2205
|
disabled = false
|
|
2034
2206
|
}) {
|
|
2035
|
-
const [input, setInput] =
|
|
2036
|
-
const [pendingFiles, setPendingFiles] =
|
|
2037
|
-
const [fileError, setFileError] =
|
|
2038
|
-
const [showMenu, setShowMenu] =
|
|
2039
|
-
const inputRef =
|
|
2040
|
-
const fileInputRef =
|
|
2041
|
-
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);
|
|
2042
2214
|
const handleSubmit = () => {
|
|
2043
2215
|
const hasText = input.trim();
|
|
2044
2216
|
const hasFiles = pendingFiles.length > 0;
|
|
@@ -2567,25 +2739,25 @@ var Chat = forwardRef(function Chat2({
|
|
|
2567
2739
|
onWidgetRender,
|
|
2568
2740
|
className
|
|
2569
2741
|
}, ref) {
|
|
2570
|
-
const [messages, setMessages] =
|
|
2571
|
-
const [isLoading, setIsLoading] =
|
|
2572
|
-
const [currentThreadId, setCurrentThreadId] =
|
|
2573
|
-
const [mode, setMode] =
|
|
2574
|
-
const [chatToolName, setChatToolName] =
|
|
2575
|
-
const [commandState, setCommandState] =
|
|
2576
|
-
const [commandResult, setCommandResult] =
|
|
2577
|
-
const [commandError, setCommandError] =
|
|
2578
|
-
const [progress, setProgress] =
|
|
2579
|
-
const [commandInput, setCommandInput] =
|
|
2580
|
-
const [streamedContent, setStreamedContent] =
|
|
2581
|
-
const [currentToolName, setCurrentToolName] =
|
|
2582
|
-
const [currentRequestId, setCurrentRequestId] =
|
|
2583
|
-
const [plan, setPlan] =
|
|
2584
|
-
const [pendingCommand, setPendingCommand] =
|
|
2585
|
-
const [internalPlanMode, setInternalPlanMode] =
|
|
2586
|
-
const [showSettingsMenu, setShowSettingsMenu] =
|
|
2587
|
-
const fileInputRef =
|
|
2588
|
-
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);
|
|
2589
2761
|
useImperativeHandle(ref, () => ({
|
|
2590
2762
|
sendMessage: async (text) => {
|
|
2591
2763
|
if (handleSendMessageRef.current) {
|
|
@@ -2606,7 +2778,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
2606
2778
|
return context ? `${context}
|
|
2607
2779
|
${widgetContext}` : widgetContext;
|
|
2608
2780
|
}, [context, enableWidgets, availableWidgets, compactWidgetContext]);
|
|
2609
|
-
|
|
2781
|
+
useEffect6(() => {
|
|
2610
2782
|
if (apiUrl || apiKey) {
|
|
2611
2783
|
aptevaClient.configure({
|
|
2612
2784
|
...apiUrl && { apiUrl },
|
|
@@ -2614,15 +2786,15 @@ ${widgetContext}` : widgetContext;
|
|
|
2614
2786
|
});
|
|
2615
2787
|
}
|
|
2616
2788
|
}, [apiUrl, apiKey]);
|
|
2617
|
-
|
|
2789
|
+
useEffect6(() => {
|
|
2618
2790
|
if (threadId) {
|
|
2619
2791
|
onThreadChange?.(threadId);
|
|
2620
2792
|
}
|
|
2621
2793
|
}, [threadId, onThreadChange]);
|
|
2622
|
-
|
|
2794
|
+
useEffect6(() => {
|
|
2623
2795
|
setInternalPlanMode(planMode);
|
|
2624
2796
|
}, [planMode]);
|
|
2625
|
-
|
|
2797
|
+
useEffect6(() => {
|
|
2626
2798
|
const handleClickOutside = (event) => {
|
|
2627
2799
|
const target = event.target;
|
|
2628
2800
|
if (showSettingsMenu && !target.closest(".settings-menu-container")) {
|
|
@@ -3154,11 +3326,11 @@ ${planToExecute}`;
|
|
|
3154
3326
|
});
|
|
3155
3327
|
|
|
3156
3328
|
// src/components/Chat/CommandOutput.tsx
|
|
3157
|
-
import { useState as
|
|
3329
|
+
import { useState as useState7 } from "react";
|
|
3158
3330
|
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3159
3331
|
|
|
3160
3332
|
// src/components/Command/Command.tsx
|
|
3161
|
-
import React, { useState as
|
|
3333
|
+
import React, { useState as useState8, useEffect as useEffect7 } from "react";
|
|
3162
3334
|
import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3163
3335
|
function Command({
|
|
3164
3336
|
agentId,
|
|
@@ -3186,28 +3358,28 @@ function Command({
|
|
|
3186
3358
|
resultRenderer,
|
|
3187
3359
|
className
|
|
3188
3360
|
}) {
|
|
3189
|
-
const [state, setState] =
|
|
3190
|
-
const [result, setResult] =
|
|
3191
|
-
const [error, setError] =
|
|
3192
|
-
const [progress, setProgress] =
|
|
3193
|
-
const [command, setCommand] =
|
|
3194
|
-
const [streamedContent, setStreamedContent] =
|
|
3195
|
-
const [plan, setPlan] =
|
|
3196
|
-
const [pendingCommand, setPendingCommand] =
|
|
3197
|
-
const [showPlanDetails, setShowPlanDetails] =
|
|
3198
|
-
const [uploadedFiles, setUploadedFiles] =
|
|
3199
|
-
const [showSettingsMenu, setShowSettingsMenu] =
|
|
3200
|
-
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);
|
|
3201
3373
|
const fileInputRef = React.useRef(null);
|
|
3202
|
-
|
|
3374
|
+
useEffect7(() => {
|
|
3203
3375
|
if (autoExecute && state === "idle" && command) {
|
|
3204
3376
|
executeCommand();
|
|
3205
3377
|
}
|
|
3206
3378
|
}, [autoExecute]);
|
|
3207
|
-
|
|
3379
|
+
useEffect7(() => {
|
|
3208
3380
|
setInternalPlanMode(planMode);
|
|
3209
3381
|
}, [planMode]);
|
|
3210
|
-
|
|
3382
|
+
useEffect7(() => {
|
|
3211
3383
|
const handleClickOutside = (event) => {
|
|
3212
3384
|
const target = event.target;
|
|
3213
3385
|
if (showSettingsMenu && !target.closest(".settings-menu-container")) {
|
|
@@ -4129,7 +4301,7 @@ ${planToExecute}`;
|
|
|
4129
4301
|
}
|
|
4130
4302
|
|
|
4131
4303
|
// src/components/Prompt/Prompt.tsx
|
|
4132
|
-
import { useState as
|
|
4304
|
+
import { useState as useState9 } from "react";
|
|
4133
4305
|
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4134
4306
|
function Prompt({
|
|
4135
4307
|
agentId,
|
|
@@ -4147,9 +4319,9 @@ function Prompt({
|
|
|
4147
4319
|
showSuggestions = false,
|
|
4148
4320
|
className
|
|
4149
4321
|
}) {
|
|
4150
|
-
const [value, setValue] =
|
|
4151
|
-
const [isLoading, setIsLoading] =
|
|
4152
|
-
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"]);
|
|
4153
4325
|
const handleChange = (e) => {
|
|
4154
4326
|
const newValue = e.target.value;
|
|
4155
4327
|
if (!maxLength || newValue.length <= maxLength) {
|
|
@@ -4240,7 +4412,7 @@ function Prompt({
|
|
|
4240
4412
|
}
|
|
4241
4413
|
|
|
4242
4414
|
// src/components/Stream/Stream.tsx
|
|
4243
|
-
import { useState as
|
|
4415
|
+
import { useState as useState10, useEffect as useEffect8 } from "react";
|
|
4244
4416
|
import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
4245
4417
|
function Stream({
|
|
4246
4418
|
agentId,
|
|
@@ -4257,10 +4429,10 @@ function Stream({
|
|
|
4257
4429
|
typingSpeed = 30,
|
|
4258
4430
|
className
|
|
4259
4431
|
}) {
|
|
4260
|
-
const [text, setText] =
|
|
4261
|
-
const [isStreaming, setIsStreaming] =
|
|
4262
|
-
const [isComplete, setIsComplete] =
|
|
4263
|
-
|
|
4432
|
+
const [text, setText] = useState10("");
|
|
4433
|
+
const [isStreaming, setIsStreaming] = useState10(false);
|
|
4434
|
+
const [isComplete, setIsComplete] = useState10(false);
|
|
4435
|
+
useEffect8(() => {
|
|
4264
4436
|
if (autoStart && !isStreaming && !isComplete) {
|
|
4265
4437
|
startStreaming();
|
|
4266
4438
|
}
|
|
@@ -4337,7 +4509,7 @@ function Stream({
|
|
|
4337
4509
|
}
|
|
4338
4510
|
|
|
4339
4511
|
// src/components/Threads/ThreadList.tsx
|
|
4340
|
-
import { useState as
|
|
4512
|
+
import { useState as useState11 } from "react";
|
|
4341
4513
|
|
|
4342
4514
|
// src/components/Threads/ThreadItem.tsx
|
|
4343
4515
|
import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
@@ -4401,7 +4573,7 @@ function ThreadList({
|
|
|
4401
4573
|
showSearch = false,
|
|
4402
4574
|
groupBy = "none"
|
|
4403
4575
|
}) {
|
|
4404
|
-
const [searchQuery, setSearchQuery] =
|
|
4576
|
+
const [searchQuery, setSearchQuery] = useState11("");
|
|
4405
4577
|
const filteredThreads = threads.filter(
|
|
4406
4578
|
(thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || thread.preview?.toLowerCase().includes(searchQuery.toLowerCase())
|
|
4407
4579
|
);
|