@apteva/apteva-kit 0.1.102 → 0.1.105

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.js CHANGED
@@ -797,6 +797,347 @@ Widgets: @ui:type[{json}] - MUST use square brackets []. Example: @ui:list[{"ite
797
797
  `;
798
798
  }
799
799
 
800
+ // src/utils/interface-parser.ts
801
+ function findMatchingBracket2(text, startIndex) {
802
+ const openChar = text[startIndex];
803
+ const closeChar = openChar === "[" ? "]" : "}";
804
+ let depth = 0;
805
+ let inString = false;
806
+ let escapeNext = false;
807
+ for (let i = startIndex; i < text.length; i++) {
808
+ const char = text[i];
809
+ if (escapeNext) {
810
+ escapeNext = false;
811
+ continue;
812
+ }
813
+ if (char === "\\" && inString) {
814
+ escapeNext = true;
815
+ continue;
816
+ }
817
+ if (char === '"') {
818
+ inString = !inString;
819
+ continue;
820
+ }
821
+ if (inString) continue;
822
+ if (char === openChar || char === (openChar === "[" ? "{" : "[")) {
823
+ if (char === openChar) depth++;
824
+ } else if (char === closeChar || char === (closeChar === "]" ? "}" : "]")) {
825
+ if (char === closeChar) {
826
+ depth--;
827
+ if (depth === 0) return i;
828
+ }
829
+ }
830
+ }
831
+ return -1;
832
+ }
833
+ function parseInterfaceFromText(text) {
834
+ const marker = "@interface[";
835
+ const idx = text.indexOf(marker);
836
+ if (idx === -1) return null;
837
+ const bracketStart = idx + marker.length - 1;
838
+ const bracketEnd = findMatchingBracket2(text, bracketStart);
839
+ if (bracketEnd === -1) return null;
840
+ const jsonContent = text.slice(bracketStart + 1, bracketEnd);
841
+ try {
842
+ const parsed = JSON.parse(jsonContent);
843
+ if (!parsed.root || !parsed.root.id) return null;
844
+ return {
845
+ version: parsed.version || 1,
846
+ root: parsed.root
847
+ };
848
+ } catch (e2) {
849
+ return null;
850
+ }
851
+ }
852
+ function parseUpdatesFromText(text) {
853
+ const updates = [];
854
+ const marker = "@update[";
855
+ let searchFrom = 0;
856
+ while (true) {
857
+ const idx = text.indexOf(marker, searchFrom);
858
+ if (idx === -1) break;
859
+ const bracketStart = idx + marker.length - 1;
860
+ const bracketEnd = findMatchingBracket2(text, bracketStart);
861
+ if (bracketEnd === -1) break;
862
+ const jsonContent = text.slice(bracketStart + 1, bracketEnd);
863
+ try {
864
+ const parsed = JSON.parse(jsonContent);
865
+ if (Array.isArray(parsed)) {
866
+ updates.push(...parsed);
867
+ } else if (parsed.op && parsed.target) {
868
+ updates.push(parsed);
869
+ }
870
+ } catch (e3) {
871
+ }
872
+ searchFrom = bracketEnd + 1;
873
+ }
874
+ return updates;
875
+ }
876
+ function containsInterface(text) {
877
+ return text.includes("@interface[") || text.includes("@update[");
878
+ }
879
+ function stripInterface(text) {
880
+ let result = text;
881
+ const ifacePattern = /@interface\[/g;
882
+ let match;
883
+ while ((match = ifacePattern.exec(result)) !== null) {
884
+ const bracketStart = match.index + match[0].length - 1;
885
+ const bracketEnd = findMatchingBracket2(result, bracketStart);
886
+ if (bracketEnd === -1) break;
887
+ result = result.slice(0, match.index) + result.slice(bracketEnd + 1);
888
+ ifacePattern.lastIndex = match.index;
889
+ }
890
+ const updatePattern = /@update\[/g;
891
+ while ((match = updatePattern.exec(result)) !== null) {
892
+ const bracketStart = match.index + match[0].length - 1;
893
+ const bracketEnd = findMatchingBracket2(result, bracketStart);
894
+ if (bracketEnd === -1) break;
895
+ result = result.slice(0, match.index) + result.slice(bracketEnd + 1);
896
+ updatePattern.lastIndex = match.index;
897
+ }
898
+ return result.replace(/\s+/g, " ").trim();
899
+ }
900
+
901
+ // src/utils/interface-context.ts
902
+ function generateInterfaceContext() {
903
+ return `## Auto Interface Mode
904
+
905
+ You generate full page interfaces as JSON. When asked for a dashboard, form, or any UI, respond with an @interface block.
906
+
907
+ ### CRITICAL FORMAT RULES
908
+ 1. Wrap your JSON in: @interface[{...}]
909
+ 2. Every node MUST have: "type", "id", and "props" (an object)
910
+ 3. Widget properties go INSIDE "props", NOT at the top level
911
+ 4. The "type" field is the ACTUAL widget name (e.g. "form", "kpi", "table") \u2014 NEVER use "widget" as a type
912
+ 5. Layout nodes use type: "layout" with a "layout" field for the layout kind
913
+
914
+ ### Node structure
915
+
916
+ Layout node:
917
+ {"type": "layout", "id": "unique-id", "layout": "page|row|stack|columns|sidebar|tabs", "props": {...}, "children": [...]}
918
+
919
+ Widget node:
920
+ {"type": "kpi|text_block|form|table|chart|list|card|spacer|button_group|image", "id": "unique-id", "props": {...}}
921
+
922
+ ### Layout types and their props
923
+ - page: { title?, padding?: "none"|"sm"|"md"|"lg", maxWidth?: "sm"|"md"|"lg"|"xl"|"full" }
924
+ - row: { columns?: number[] (e.g. [1,2] for 1/3+2/3), gap?: "none"|"sm"|"md"|"lg" }
925
+ - stack: { gap?: "none"|"sm"|"md"|"lg", align?: "left"|"center"|"right"|"stretch" }
926
+ - columns: { count?: number, gap?: "none"|"sm"|"md"|"lg" }
927
+ - sidebar: { side?: "left"|"right", width?: string }
928
+ - tabs: { labels: string[], defaultTab?: number }
929
+
930
+ ### Widget types and their props
931
+ - kpi: { label: string, value: string, change?: string, trend?: "up"|"down"|"flat" }
932
+ - text_block: { content: string (markdown), variant?: "heading"|"body"|"caption" }
933
+ - spacer: { height?: "sm"|"md"|"lg", variant?: "line"|"space" }
934
+ - card: { title: string, description?: string, image?: string, footer?: string }
935
+ - list: { items: [{ id: string, title: string, subtitle?: string }] }
936
+ - table: { columns: [{ key: string, label: string }], rows: [{ key: value, ... }], striped?: boolean, compact?: boolean }
937
+ - chart: { chartType: "line"|"bar"|"pie", title?: string, data: { labels: string[], datasets: [{ label: string, data: number[] }] } }
938
+ - form: { title?: string, fields: [{ name: string, type: "text"|"email"|"select"|"textarea"|"checkbox", label: string, required?: boolean, placeholder?: string, options?: [{ label: string, value: string }] }] }
939
+ - button_group: { buttons: [{ id: string, label: string, variant?: string }] }
940
+ - image: { src: string, alt: string, caption?: string }
941
+
942
+ ### CORRECT example
943
+
944
+ @interface[{"version":1,"root":{"type":"layout","id":"root","layout":"page","props":{"title":"My Form"},"children":[{"type":"text_block","id":"t1","props":{"content":"Fill out the form below","variant":"body"}},{"type":"form","id":"f1","props":{"fields":[{"name":"name","type":"text","label":"Name","required":true},{"name":"email","type":"email","label":"Email"}]}},{"type":"button_group","id":"b1","props":{"buttons":[{"id":"submit","label":"Submit"}]}}]}}]
945
+
946
+ ### WRONG (do NOT do these)
947
+ - {"type": "widget", "props": {"widget": "form"}} \u2014 WRONG, type must be "form" directly
948
+ - {"type": "text_block", "content": "hello"} \u2014 WRONG, content must be inside props
949
+ - {"type": "text_block", "props": {"style": "heading"}} \u2014 WRONG, use "variant" not "style"
950
+
951
+ ### Guidelines
952
+ - Always use unique IDs for every node
953
+ - Organize content logically: KPIs in a row, charts with supporting lists, etc.
954
+ - Use text_block for descriptions and headings within layouts
955
+ - Use spacer with variant "line" to separate sections
956
+ - You can include normal text before/after the @interface block
957
+ - For updates use: @update[{"op": "update", "target": "widget-id", "props": {"key": "new-value"}}]`;
958
+ }
959
+ function generateCompactInterfaceContext() {
960
+ return `Generate a UI interface as JSON wrapped in @interface[{...}].
961
+
962
+ STRICT FORMAT \u2014 every node needs "type", "id", and "props" (object):
963
+ - Layout: {"type":"layout","id":"x","layout":"page|row|stack|tabs","props":{...},"children":[...]}
964
+ - Widget: {"type":"kpi|text_block|form|table|chart|list|card|spacer|button_group|image","id":"x","props":{...}}
965
+
966
+ NEVER use type:"widget". The type IS the widget name. All widget properties go INSIDE "props".
967
+
968
+ Widget props:
969
+ - kpi: {label,value,change?,trend?}
970
+ - text_block: {content,variant?:"heading"|"body"|"caption"}
971
+ - form: {fields:[{name,type,label,required?,placeholder?}]}
972
+ - table: {columns:[{key,label}],rows:[{...}]}
973
+ - chart: {chartType:"line"|"bar"|"pie",data:{labels,datasets:[{label,data}]}}
974
+ - list: {items:[{id,title,subtitle?}]}
975
+ - button_group: {buttons:[{id,label}]}
976
+
977
+ Row props: {columns:[1,2]} means 1/3+2/3. Page props: {title:"..."}.
978
+
979
+ Example: @interface[{"version":1,"root":{"type":"layout","id":"root","layout":"page","props":{"title":"Form"},"children":[{"type":"form","id":"f1","props":{"fields":[{"name":"name","type":"text","label":"Name"}]}}]}}]`;
980
+ }
981
+
982
+ // src/utils/interface-operations.ts
983
+ function findNode(root, id) {
984
+ if (root.id === id) return root;
985
+ if (root.children) {
986
+ for (const child of root.children) {
987
+ const found = findNode(child, id);
988
+ if (found) return found;
989
+ }
990
+ }
991
+ return null;
992
+ }
993
+ function replaceNode(root, targetId, newNode) {
994
+ if (root.id === targetId) return newNode;
995
+ if (!root.children) return root;
996
+ const newChildren = root.children.map((child) => replaceNode(child, targetId, newNode));
997
+ if (newChildren.every((child, i) => child === root.children[i])) return root;
998
+ return { ...root, children: newChildren };
999
+ }
1000
+ function updateNodeProps(root, targetId, props) {
1001
+ if (root.id === targetId) {
1002
+ return { ...root, props: { ...root.props, ...props } };
1003
+ }
1004
+ if (!root.children) return root;
1005
+ const newChildren = root.children.map((child) => updateNodeProps(child, targetId, props));
1006
+ if (newChildren.every((child, i) => child === root.children[i])) return root;
1007
+ return { ...root, children: newChildren };
1008
+ }
1009
+ function removeNode(root, targetId) {
1010
+ if (root.id === targetId) return null;
1011
+ if (!root.children) return root;
1012
+ const newChildren = root.children.map((child) => removeNode(child, targetId)).filter((child) => child !== null);
1013
+ if (newChildren.length === root.children.length && newChildren.every((child, i) => child === root.children[i])) return root;
1014
+ return { ...root, children: newChildren };
1015
+ }
1016
+ function appendNode(root, targetId, newNode) {
1017
+ if (root.id === targetId) {
1018
+ return { ...root, children: [...root.children || [], newNode] };
1019
+ }
1020
+ if (!root.children) return root;
1021
+ const newChildren = root.children.map((child) => appendNode(child, targetId, newNode));
1022
+ if (newChildren.every((child, i) => child === root.children[i])) return root;
1023
+ return { ...root, children: newChildren };
1024
+ }
1025
+ function prependNode(root, targetId, newNode) {
1026
+ if (root.id === targetId) {
1027
+ return { ...root, children: [newNode, ...root.children || []] };
1028
+ }
1029
+ if (!root.children) return root;
1030
+ const newChildren = root.children.map((child) => prependNode(child, targetId, newNode));
1031
+ if (newChildren.every((child, i) => child === root.children[i])) return root;
1032
+ return { ...root, children: newChildren };
1033
+ }
1034
+ function applyUpdate(spec, update) {
1035
+ let newRoot = spec.root;
1036
+ switch (update.op) {
1037
+ case "replace":
1038
+ if (!update.node) return spec;
1039
+ newRoot = replaceNode(spec.root, update.target, update.node);
1040
+ break;
1041
+ case "update":
1042
+ if (!update.props) return spec;
1043
+ newRoot = updateNodeProps(spec.root, update.target, update.props);
1044
+ break;
1045
+ case "remove":
1046
+ newRoot = removeNode(spec.root, update.target);
1047
+ if (!newRoot) return spec;
1048
+ break;
1049
+ case "append":
1050
+ if (!update.node) return spec;
1051
+ newRoot = appendNode(spec.root, update.target, update.node);
1052
+ break;
1053
+ case "prepend":
1054
+ if (!update.node) return spec;
1055
+ newRoot = prependNode(spec.root, update.target, update.node);
1056
+ break;
1057
+ default:
1058
+ return spec;
1059
+ }
1060
+ if (newRoot === spec.root) return spec;
1061
+ return { ...spec, root: newRoot };
1062
+ }
1063
+ function applyUpdates(spec, updates) {
1064
+ return updates.reduce((s, update) => applyUpdate(s, update), spec);
1065
+ }
1066
+
1067
+ // src/utils/message-converter.ts
1068
+ function convertApiMessages(apiMessages) {
1069
+ const result = [];
1070
+ let lastAssistantSegments = null;
1071
+ for (let i = 0; i < apiMessages.length; i++) {
1072
+ const msg = apiMessages[i];
1073
+ const timestamp = msg.created_at || msg.timestamp ? new Date(msg.created_at || msg.timestamp) : /* @__PURE__ */ new Date();
1074
+ if (typeof msg.content === "string") {
1075
+ const message = {
1076
+ id: msg.id || `thread-msg-${i}`,
1077
+ role: msg.role,
1078
+ content: msg.content,
1079
+ timestamp
1080
+ };
1081
+ result.push(message);
1082
+ lastAssistantSegments = null;
1083
+ } else if (Array.isArray(msg.content)) {
1084
+ if (msg.role === "assistant") {
1085
+ const segments = [];
1086
+ let textContent = "";
1087
+ for (const block of msg.content) {
1088
+ if (block.type === "text" && block.text) {
1089
+ segments.push({ type: "text", content: block.text });
1090
+ textContent += block.text;
1091
+ } else if (block.type === "tool_use") {
1092
+ segments.push({
1093
+ type: "tool",
1094
+ id: block.id || `tool-${i}-${segments.length}`,
1095
+ name: block.name || "unknown",
1096
+ status: "completed"
1097
+ });
1098
+ }
1099
+ }
1100
+ const message = {
1101
+ id: msg.id || `thread-msg-${i}`,
1102
+ role: "assistant",
1103
+ content: textContent,
1104
+ timestamp,
1105
+ metadata: segments.length > 0 ? { content_segments: segments } : void 0
1106
+ };
1107
+ result.push(message);
1108
+ lastAssistantSegments = segments;
1109
+ } else if (msg.role === "user") {
1110
+ const hasToolResults = msg.content.some((b) => b.type === "tool_result");
1111
+ if (hasToolResults && lastAssistantSegments) {
1112
+ for (const block of msg.content) {
1113
+ if (block.type === "tool_result" && block.tool_use_id) {
1114
+ const toolSegment = lastAssistantSegments.find(
1115
+ (s) => s.type === "tool" && s.id === block.tool_use_id
1116
+ );
1117
+ if (toolSegment && toolSegment.type === "tool") {
1118
+ toolSegment.result = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.map((c) => c.text || "").join("") : void 0;
1119
+ toolSegment.status = block.is_error ? "error" : "completed";
1120
+ }
1121
+ }
1122
+ }
1123
+ } else {
1124
+ const textContent = msg.content.filter((b) => b.type === "text").map((b) => b.text || "").join("");
1125
+ if (textContent) {
1126
+ result.push({
1127
+ id: msg.id || `thread-msg-${i}`,
1128
+ role: "user",
1129
+ content: textContent,
1130
+ timestamp
1131
+ });
1132
+ }
1133
+ lastAssistantSegments = null;
1134
+ }
1135
+ }
1136
+ }
1137
+ }
1138
+ return result;
1139
+ }
1140
+
800
1141
  // src/components/Widgets/Widgets.tsx
801
1142
 
802
1143
 
@@ -1436,6 +1777,141 @@ function Flow({ widget }) {
1436
1777
  ] });
1437
1778
  }
1438
1779
 
1780
+ // src/components/Widgets/widget-library/Kpi.tsx
1781
+
1782
+ var trendIcons = {
1783
+ up: { symbol: "\u2191", color: "text-emerald-500" },
1784
+ down: { symbol: "\u2193", color: "text-red-500" },
1785
+ flat: { symbol: "\u2192", color: "text-neutral-400" }
1786
+ };
1787
+ function Kpi({ widget, onAction }) {
1788
+ const { label = "", value = "", change, trend } = widget.props || {};
1789
+ const trendInfo = trend ? trendIcons[trend] : null;
1790
+ 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 p-5", children: [
1791
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "!text-sm font-medium !text-neutral-500 dark:!text-neutral-400 mb-1", children: label }),
1792
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-end gap-2", children: [
1793
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "!text-2xl font-bold !text-neutral-900 dark:!text-white", children: value }),
1794
+ change && trendInfo && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: `flex items-center gap-0.5 !text-sm font-medium ${trendInfo.color} mb-0.5`, children: [
1795
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: trendInfo.symbol }),
1796
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: change })
1797
+ ] }),
1798
+ change && !trendInfo && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "!text-sm font-medium !text-neutral-400 mb-0.5", children: change })
1799
+ ] }),
1800
+ widget.actions && widget.actions.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex gap-2 mt-3 pt-3 border-t border-neutral-200 dark:border-neutral-700", children: widget.actions.map((action, idx) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1801
+ "button",
1802
+ {
1803
+ onClick: () => _optionalChain([onAction, 'optionalCall', _32 => _32({
1804
+ type: action.type,
1805
+ payload: action.payload,
1806
+ widgetId: widget.id,
1807
+ timestamp: /* @__PURE__ */ new Date()
1808
+ })]),
1809
+ className: "px-2 py-1 !text-xs rounded font-medium transition-colors bg-neutral-100 dark:bg-neutral-800 !text-neutral-600 dark:!text-neutral-300 hover:bg-neutral-200 dark:hover:bg-neutral-700",
1810
+ children: action.label
1811
+ },
1812
+ idx
1813
+ )) })
1814
+ ] });
1815
+ }
1816
+
1817
+ // src/components/Widgets/widget-library/TextBlock.tsx
1818
+
1819
+ function TextBlock({ widget }) {
1820
+ const { content = "", variant = "body" } = widget.props || {};
1821
+ const variantClasses = {
1822
+ heading: "!text-xl font-bold !text-neutral-900 dark:!text-white",
1823
+ body: "!text-sm !text-neutral-700 dark:!text-neutral-300 leading-relaxed",
1824
+ caption: "!text-xs !text-neutral-500 dark:!text-neutral-400"
1825
+ };
1826
+ const renderMarkdown = (text) => {
1827
+ const lines = text.split("\n");
1828
+ const elements = [];
1829
+ let i = 0;
1830
+ while (i < lines.length) {
1831
+ const line = lines[i];
1832
+ if (line.startsWith("### ")) {
1833
+ elements.push(
1834
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "!text-base font-semibold !text-neutral-900 dark:!text-white mt-3 mb-1", children: renderInline(line.slice(4)) }, i)
1835
+ );
1836
+ } else if (line.startsWith("## ")) {
1837
+ elements.push(
1838
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "!text-lg font-bold !text-neutral-900 dark:!text-white mt-4 mb-1", children: renderInline(line.slice(3)) }, i)
1839
+ );
1840
+ } else if (/^[-*+]\s/.test(line)) {
1841
+ const listItems = [];
1842
+ while (i < lines.length && /^[-*+]\s/.test(lines[i])) {
1843
+ listItems.push(
1844
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "li", { className: "ml-4 list-disc", children: renderInline(lines[i].slice(2)) }, i)
1845
+ );
1846
+ i++;
1847
+ }
1848
+ elements.push(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "ul", { className: "my-1 space-y-0.5", children: listItems }, `list-${i}`));
1849
+ continue;
1850
+ } else if (line.trim() === "") {
1851
+ elements.push(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-2" }, i));
1852
+ } else {
1853
+ elements.push(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "my-0.5", children: renderInline(line) }, i));
1854
+ }
1855
+ i++;
1856
+ }
1857
+ return elements;
1858
+ };
1859
+ const renderInline = (text) => {
1860
+ const parts = [];
1861
+ let remaining = text;
1862
+ let key = 0;
1863
+ while (remaining.length > 0) {
1864
+ const boldMatch = remaining.match(/\*\*(.+?)\*\*/);
1865
+ const codeMatch = remaining.match(/`(.+?)`/);
1866
+ const linkMatch = remaining.match(/\[(.+?)\]\((.+?)\)/);
1867
+ const matches = [
1868
+ boldMatch ? { type: "bold", index: boldMatch.index, match: boldMatch } : null,
1869
+ codeMatch ? { type: "code", index: codeMatch.index, match: codeMatch } : null,
1870
+ linkMatch ? { type: "link", index: linkMatch.index, match: linkMatch } : null
1871
+ ].filter(Boolean).sort((a, b) => a.index - b.index);
1872
+ if (matches.length === 0) {
1873
+ parts.push(remaining);
1874
+ break;
1875
+ }
1876
+ const first = matches[0];
1877
+ if (first.index > 0) {
1878
+ parts.push(remaining.slice(0, first.index));
1879
+ }
1880
+ if (first.type === "bold") {
1881
+ parts.push(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { className: "font-semibold", children: first.match[1] }, key++));
1882
+ remaining = remaining.slice(first.index + first.match[0].length);
1883
+ } else if (first.type === "code") {
1884
+ parts.push(
1885
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "code", { className: "px-1 py-0.5 bg-neutral-100 dark:bg-neutral-800 rounded text-xs font-mono", children: first.match[1] }, key++)
1886
+ );
1887
+ remaining = remaining.slice(first.index + first.match[0].length);
1888
+ } else if (first.type === "link") {
1889
+ parts.push(
1890
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { href: first.match[2], className: "text-blue-500 hover:underline", target: "_blank", rel: "noopener noreferrer", children: first.match[1] }, key++)
1891
+ );
1892
+ remaining = remaining.slice(first.index + first.match[0].length);
1893
+ }
1894
+ }
1895
+ return parts.length === 1 ? parts[0] : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: parts });
1896
+ };
1897
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: variantClasses[variant] || variantClasses.body, children: renderMarkdown(content) });
1898
+ }
1899
+
1900
+ // src/components/Widgets/widget-library/Spacer.tsx
1901
+
1902
+ var heightClasses = {
1903
+ sm: "h-2",
1904
+ md: "h-4",
1905
+ lg: "h-8"
1906
+ };
1907
+ function Spacer({ widget }) {
1908
+ const { height = "md", variant = "space" } = widget.props || {};
1909
+ if (variant === "line") {
1910
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: heightClasses[height] || heightClasses.md + " flex items-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "hr", { className: "w-full border-neutral-200 dark:border-neutral-700" }) });
1911
+ }
1912
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: heightClasses[height] || heightClasses.md });
1913
+ }
1914
+
1439
1915
  // src/components/Widgets/WidgetRenderer.tsx
1440
1916
 
1441
1917
  function WidgetRenderer({ widget, onAction }) {
@@ -1457,6 +1933,12 @@ function WidgetRenderer({ widget, onAction }) {
1457
1933
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Image, { widget });
1458
1934
  case "flow":
1459
1935
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Flow, { widget });
1936
+ case "kpi":
1937
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Kpi, { widget, onAction });
1938
+ case "text_block":
1939
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TextBlock, { widget });
1940
+ case "spacer":
1941
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spacer, { widget });
1460
1942
  default:
1461
1943
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "p-4 border border-yellow-300 bg-yellow-50 rounded-lg", children: [
1462
1944
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "text-sm text-yellow-800", children: [
@@ -1483,7 +1965,7 @@ function Widgets({
1483
1965
  }) {
1484
1966
  _react.useEffect.call(void 0, () => {
1485
1967
  widgets.forEach((widget) => {
1486
- _optionalChain([onWidgetMount, 'optionalCall', _32 => _32(widget.id)]);
1968
+ _optionalChain([onWidgetMount, 'optionalCall', _33 => _33(widget.id)]);
1487
1969
  });
1488
1970
  }, [widgets, onWidgetMount]);
1489
1971
  const layoutClasses = {
@@ -1809,8 +2291,8 @@ function ToolCall({ name, status, isReceiving = false, inputLength = 0, streamOu
1809
2291
 
1810
2292
  function Message({ message, onAction, enableWidgets, onWidgetRender }) {
1811
2293
  const isUser = message.role === "user";
1812
- const contentSegments = _optionalChain([message, 'access', _33 => _33.metadata, 'optionalAccess', _34 => _34.content_segments]);
1813
- const isStreaming = _optionalChain([message, 'access', _35 => _35.metadata, 'optionalAccess', _36 => _36.isStreaming]) === true;
2294
+ const contentSegments = _optionalChain([message, 'access', _34 => _34.metadata, 'optionalAccess', _35 => _35.content_segments]);
2295
+ const isStreaming = _optionalChain([message, 'access', _36 => _36.metadata, 'optionalAccess', _37 => _37.isStreaming]) === true;
1814
2296
  const hasContent = message.content || contentSegments && contentSegments.length > 0;
1815
2297
  const reportedWidgetsRef = _react.useRef.call(void 0, /* @__PURE__ */ new Set());
1816
2298
  const parsedWidgets = _react.useMemo.call(void 0, () => {
@@ -1890,7 +2372,7 @@ function Message({ message, onAction, enableWidgets, onWidgetRender }) {
1890
2372
  }
1891
2373
  return elements.length > 0 ? elements : null;
1892
2374
  };
1893
- const attachments = _optionalChain([message, 'access', _37 => _37.metadata, 'optionalAccess', _38 => _38.attachments]) || [];
2375
+ const attachments = _optionalChain([message, 'access', _38 => _38.metadata, 'optionalAccess', _39 => _39.attachments]) || [];
1894
2376
  const hasAttachments = attachments.length > 0;
1895
2377
  const renderAttachments = () => {
1896
2378
  if (!hasAttachments) return null;
@@ -2311,7 +2793,7 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
2311
2793
  setFileError(errors.join(", "));
2312
2794
  setTimeout(() => setFileError(null), 5e3);
2313
2795
  }
2314
- _optionalChain([onFileUpload, 'optionalCall', _39 => _39(e.target.files)]);
2796
+ _optionalChain([onFileUpload, 'optionalCall', _40 => _40(e.target.files)]);
2315
2797
  setShowMenu(false);
2316
2798
  e.target.value = "";
2317
2799
  }
@@ -2335,33 +2817,26 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
2335
2817
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) });
2336
2818
  };
2337
2819
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "px-4 py-3 relative", children: [
2338
- fileError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute bottom-full left-4 right-4 mb-2 p-3 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg z-20", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 !text-red-700 dark:!text-red-300 text-sm", children: [
2339
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-4 h-4 flex-shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
2820
+ fileError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-file-error", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-file-error-content", children: [
2821
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
2340
2822
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: fileError })
2341
2823
  ] }) }),
2342
- pendingFiles.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mb-2 flex flex-wrap gap-2", children: pendingFiles.map((pf, index) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2343
- "div",
2344
- {
2345
- className: "relative group flex items-center gap-2 px-3 py-2 bg-neutral-100 dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-700 rounded-lg",
2346
- children: [
2347
- pf.preview ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: pf.preview, alt: pf.file.name, className: "w-8 h-8 object-cover rounded" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-8 h-8 flex items-center justify-center bg-neutral-200 dark:bg-neutral-700 rounded !text-neutral-500 dark:!text-neutral-400", children: getFileIcon(pf.file.type) }),
2348
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col min-w-0", children: [
2349
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-xs font-medium !text-neutral-700 dark:!text-neutral-300 truncate max-w-[120px]", children: pf.file.name }),
2350
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-xs !text-neutral-500 dark:!text-neutral-400", children: formatFileSize(pf.file.size) })
2351
- ] }),
2352
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2353
- "button",
2354
- {
2355
- onClick: () => removeFile(index),
2356
- className: "absolute -top-1.5 -right-1.5 w-5 h-5 bg-neutral-500 hover:bg-red-500 text-white rounded-full flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity",
2357
- title: "Remove file",
2358
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
2359
- }
2360
- )
2361
- ]
2362
- },
2363
- index
2364
- )) }),
2824
+ pendingFiles.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-file-preview", children: pendingFiles.map((pf, index) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-file-item", children: [
2825
+ pf.preview ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: pf.preview, alt: pf.file.name, className: "apteva-file-thumb" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-file-icon", children: getFileIcon(pf.file.type) }),
2826
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-file-info", children: [
2827
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-file-name", children: pf.file.name }),
2828
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-file-size", children: formatFileSize(pf.file.size) })
2829
+ ] }),
2830
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2831
+ "button",
2832
+ {
2833
+ onClick: () => removeFile(index),
2834
+ className: "apteva-file-remove",
2835
+ title: "Remove file",
2836
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
2837
+ }
2838
+ )
2839
+ ] }, index)) }),
2365
2840
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2366
2841
  "div",
2367
2842
  {
@@ -2390,15 +2865,15 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
2390
2865
  {
2391
2866
  className: "apteva-composer-menu fixed bg-neutral-800 dark:bg-neutral-800 rounded-xl shadow-lg overflow-hidden z-[9999] min-w-[200px]",
2392
2867
  style: {
2393
- left: _nullishCoalesce(_optionalChain([menuButtonRef, 'access', _40 => _40.current, 'optionalAccess', _41 => _41.getBoundingClientRect, 'call', _42 => _42(), 'access', _43 => _43.left]), () => ( 0)),
2394
- bottom: window.innerHeight - (_nullishCoalesce(_optionalChain([menuButtonRef, 'access', _44 => _44.current, 'optionalAccess', _45 => _45.getBoundingClientRect, 'call', _46 => _46(), 'access', _47 => _47.top]), () => ( 0))) + 8
2868
+ left: _nullishCoalesce(_optionalChain([menuButtonRef, 'access', _41 => _41.current, 'optionalAccess', _42 => _42.getBoundingClientRect, 'call', _43 => _43(), 'access', _44 => _44.left]), () => ( 0)),
2869
+ bottom: window.innerHeight - (_nullishCoalesce(_optionalChain([menuButtonRef, 'access', _45 => _45.current, 'optionalAccess', _46 => _46.getBoundingClientRect, 'call', _47 => _47(), 'access', _48 => _48.top]), () => ( 0))) + 8
2395
2870
  },
2396
2871
  children: [
2397
2872
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2398
2873
  "button",
2399
2874
  {
2400
2875
  onClick: () => {
2401
- _optionalChain([fileInputRef, 'access', _48 => _48.current, 'optionalAccess', _49 => _49.click, 'call', _50 => _50()]);
2876
+ _optionalChain([fileInputRef, 'access', _49 => _49.current, 'optionalAccess', _50 => _50.click, 'call', _51 => _51()]);
2402
2877
  setShowMenu(false);
2403
2878
  },
2404
2879
  className: "w-full flex items-center gap-3 px-4 py-3 hover:bg-neutral-700 dark:hover:bg-neutral-700 transition-colors !text-white text-left",
@@ -2519,8 +2994,8 @@ function CommandComposer({
2519
2994
  }
2520
2995
  };
2521
2996
  const handleNewCommand = () => {
2522
- _optionalChain([onReset, 'optionalCall', _51 => _51()]);
2523
- _optionalChain([inputRef, 'access', _52 => _52.current, 'optionalAccess', _53 => _53.focus, 'call', _54 => _54()]);
2997
+ _optionalChain([onReset, 'optionalCall', _52 => _52()]);
2998
+ _optionalChain([inputRef, 'access', _53 => _53.current, 'optionalAccess', _54 => _54.focus, 'call', _55 => _55()]);
2524
2999
  };
2525
3000
  const handleInputChange = (value) => {
2526
3001
  setInput(value);
@@ -2599,8 +3074,8 @@ function CommandComposer({
2599
3074
  const isShowingResult = state !== "idle";
2600
3075
  const { text: displayContent, isToolCall } = getDisplayContent();
2601
3076
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "w-full relative", children: [
2602
- fileError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute -top-12 left-0 right-0 mx-3 p-2 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg z-30", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 !text-red-700 dark:!text-red-300 text-xs", children: [
2603
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-3 h-3 flex-shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
3077
+ fileError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-file-error", style: { top: "-3rem", bottom: "auto" }, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-file-error-content", children: [
3078
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
2604
3079
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: fileError })
2605
3080
  ] }) }),
2606
3081
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
@@ -2634,15 +3109,15 @@ function CommandComposer({
2634
3109
  {
2635
3110
  className: "apteva-composer-menu fixed bg-neutral-800 dark:bg-neutral-800 rounded-xl shadow-lg overflow-hidden z-[9999] min-w-[200px]",
2636
3111
  style: {
2637
- left: _nullishCoalesce(_optionalChain([menuButtonRef, 'access', _55 => _55.current, 'optionalAccess', _56 => _56.getBoundingClientRect, 'call', _57 => _57(), 'access', _58 => _58.left]), () => ( 0)),
2638
- top: (_nullishCoalesce(_optionalChain([menuButtonRef, 'access', _59 => _59.current, 'optionalAccess', _60 => _60.getBoundingClientRect, 'call', _61 => _61(), 'access', _62 => _62.bottom]), () => ( 0))) + 8
3112
+ left: _nullishCoalesce(_optionalChain([menuButtonRef, 'access', _56 => _56.current, 'optionalAccess', _57 => _57.getBoundingClientRect, 'call', _58 => _58(), 'access', _59 => _59.left]), () => ( 0)),
3113
+ top: (_nullishCoalesce(_optionalChain([menuButtonRef, 'access', _60 => _60.current, 'optionalAccess', _61 => _61.getBoundingClientRect, 'call', _62 => _62(), 'access', _63 => _63.bottom]), () => ( 0))) + 8
2639
3114
  },
2640
3115
  children: [
2641
3116
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2642
3117
  "button",
2643
3118
  {
2644
3119
  onClick: () => {
2645
- _optionalChain([fileInputRef, 'access', _63 => _63.current, 'optionalAccess', _64 => _64.click, 'call', _65 => _65()]);
3120
+ _optionalChain([fileInputRef, 'access', _64 => _64.current, 'optionalAccess', _65 => _65.click, 'call', _66 => _66()]);
2646
3121
  setShowMenu(false);
2647
3122
  },
2648
3123
  className: "w-full flex items-center gap-3 px-4 py-3 hover:bg-neutral-700 dark:hover:bg-neutral-700 transition-colors !text-white text-left",
@@ -2674,26 +3149,18 @@ function CommandComposer({
2674
3149
  state === "loading" && !toolName && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-4 h-4 border-2 border-blue-200 border-t-blue-500 rounded-full animate-spin" }),
2675
3150
  state === "loading" && toolName && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-2 h-2 rounded-full bg-blue-500 animate-pulse" })
2676
3151
  ] }),
2677
- pendingFiles.length > 0 && state === "idle" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center gap-1 flex-shrink-0", children: pendingFiles.map((pf, index) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2678
- "div",
2679
- {
2680
- className: "relative group flex items-center justify-center w-6 h-6 bg-neutral-100 dark:bg-neutral-800 rounded overflow-hidden",
2681
- title: pf.file.name,
2682
- children: [
2683
- pf.preview ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: pf.preview, alt: pf.file.name, className: "w-6 h-6 object-cover" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-xs !text-neutral-500 dark:!text-neutral-400", children: getFileIcon(pf.file.type) }),
2684
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2685
- "button",
2686
- {
2687
- onClick: () => removeFile(index),
2688
- className: "absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 flex items-center justify-center transition-opacity",
2689
- title: "Remove",
2690
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-3 h-3 text-white", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
2691
- }
2692
- )
2693
- ]
2694
- },
2695
- index
2696
- )) }),
3152
+ pendingFiles.length > 0 && state === "idle" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-file-badges", children: pendingFiles.map((pf, index) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-file-badge", title: pf.file.name, children: [
3153
+ pf.preview ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: pf.preview, alt: pf.file.name, className: "apteva-file-badge-img" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-file-badge-icon", children: getFileIcon(pf.file.type) }),
3154
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3155
+ "button",
3156
+ {
3157
+ onClick: () => removeFile(index),
3158
+ className: "apteva-file-badge-remove",
3159
+ title: "Remove",
3160
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
3161
+ }
3162
+ )
3163
+ ] }, index)) }),
2697
3164
  state === "idle" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2698
3165
  "textarea",
2699
3166
  {
@@ -2799,22 +3266,20 @@ function CommandComposer({
2799
3266
  }
2800
3267
 
2801
3268
  // src/lib/apteva-client.ts
2802
- var DEFAULT_API_URL = "http://91.99.200.48:3000/agents";
2803
- var DEFAULT_API_KEY = "agt_894abd5966bc9f1e9f8f17f2a6f6b5e0";
2804
3269
  var AptevaClient = class {
2805
- constructor() {
3270
+ constructor(config) {
2806
3271
  __publicField(this, "config");
2807
3272
  this.config = {
2808
- apiUrl: DEFAULT_API_URL,
2809
- apiKey: DEFAULT_API_KEY
3273
+ apiUrl: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _67 => _67.apiUrl]), () => ( "")),
3274
+ apiKey: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _68 => _68.apiKey]), () => ( ""))
2810
3275
  };
2811
3276
  }
2812
3277
  /**
2813
3278
  * Update client configuration (optional - users can override defaults)
2814
3279
  */
2815
3280
  configure(config) {
2816
- if (config.apiUrl) this.config.apiUrl = config.apiUrl;
2817
- if (config.apiKey) this.config.apiKey = config.apiKey;
3281
+ if (config.apiUrl !== void 0) this.config.apiUrl = config.apiUrl;
3282
+ if (config.apiKey !== void 0) this.config.apiKey = config.apiKey;
2818
3283
  }
2819
3284
  /**
2820
3285
  * Get current configuration
@@ -2883,7 +3348,7 @@ var AptevaClient = class {
2883
3348
  const error = await response.json().catch(() => ({ error: "Request failed" }));
2884
3349
  throw new Error(error.error || `Request failed with status ${response.status}`);
2885
3350
  }
2886
- const reader = _optionalChain([response, 'access', _66 => _66.body, 'optionalAccess', _67 => _67.getReader, 'call', _68 => _68()]);
3351
+ const reader = _optionalChain([response, 'access', _69 => _69.body, 'optionalAccess', _70 => _70.getReader, 'call', _71 => _71()]);
2887
3352
  if (!reader) {
2888
3353
  throw new Error("Response body is not readable");
2889
3354
  }
@@ -2901,7 +3366,7 @@ var AptevaClient = class {
2901
3366
  if (line.startsWith("data: ")) {
2902
3367
  const data = line.slice(6);
2903
3368
  if (data === "[DONE]") {
2904
- _optionalChain([onComplete, 'optionalCall', _69 => _69(threadId)]);
3369
+ _optionalChain([onComplete, 'optionalCall', _72 => _72(threadId)]);
2905
3370
  return;
2906
3371
  }
2907
3372
  try {
@@ -2916,10 +3381,10 @@ var AptevaClient = class {
2916
3381
  }
2917
3382
  }
2918
3383
  }
2919
- _optionalChain([onComplete, 'optionalCall', _70 => _70(threadId)]);
3384
+ _optionalChain([onComplete, 'optionalCall', _73 => _73(threadId)]);
2920
3385
  } catch (error) {
2921
3386
  const err = error instanceof Error ? error : new Error("Unknown error");
2922
- _optionalChain([onError, 'optionalCall', _71 => _71(err)]);
3387
+ _optionalChain([onError, 'optionalCall', _74 => _74(err)]);
2923
3388
  throw err;
2924
3389
  }
2925
3390
  }
@@ -3024,6 +3489,7 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
3024
3489
  placeholder,
3025
3490
  showHeader = true,
3026
3491
  headerTitle = "Chat",
3492
+ onHeaderBack,
3027
3493
  // Widget detection
3028
3494
  enableWidgets = false,
3029
3495
  availableWidgets,
@@ -3080,7 +3546,7 @@ ${widgetContext}` : widgetContext;
3080
3546
  }, [apiUrl, apiKey]);
3081
3547
  _react.useEffect.call(void 0, () => {
3082
3548
  if (threadId) {
3083
- _optionalChain([onThreadChange, 'optionalCall', _72 => _72(threadId)]);
3549
+ _optionalChain([onThreadChange, 'optionalCall', _75 => _75(threadId)]);
3084
3550
  }
3085
3551
  }, [threadId, onThreadChange]);
3086
3552
  _react.useEffect.call(void 0, () => {
@@ -3098,7 +3564,7 @@ ${widgetContext}` : widgetContext;
3098
3564
  }, [showSettingsMenu]);
3099
3565
  const handleModeChange = (newMode) => {
3100
3566
  setMode(newMode);
3101
- _optionalChain([onModeChange, 'optionalCall', _73 => _73(newMode)]);
3567
+ _optionalChain([onModeChange, 'optionalCall', _76 => _76(newMode)]);
3102
3568
  if (newMode === "command") {
3103
3569
  setCommandState("idle");
3104
3570
  setCommandResult(null);
@@ -3123,7 +3589,7 @@ ${widgetContext}` : widgetContext;
3123
3589
  metadata: hasFiles ? { attachments } : void 0
3124
3590
  };
3125
3591
  setMessages((prev) => [...prev, userMessage]);
3126
- _optionalChain([onMessageSent, 'optionalCall', _74 => _74(userMessage)]);
3592
+ _optionalChain([onMessageSent, 'optionalCall', _77 => _77(userMessage)]);
3127
3593
  }
3128
3594
  setIsLoading(true);
3129
3595
  try {
@@ -3138,7 +3604,7 @@ ${widgetContext}` : widgetContext;
3138
3604
  let responseThreadId = currentThreadId;
3139
3605
  const toolInputBuffers = {};
3140
3606
  const receivingTimeouts = {};
3141
- const streamingMessageId = `msg-${Date.now()}`;
3607
+ const streamingMessageId = `msg-${Date.now()}-res`;
3142
3608
  const updateMessage = () => {
3143
3609
  const segments = [...contentSegments];
3144
3610
  if (currentTextBuffer) {
@@ -3191,7 +3657,7 @@ ${widgetContext}` : widgetContext;
3191
3657
  responseThreadId = chunk.thread_id;
3192
3658
  if (!currentThreadId) {
3193
3659
  setCurrentThreadId(chunk.thread_id);
3194
- _optionalChain([onThreadChange, 'optionalCall', _75 => _75(chunk.thread_id)]);
3660
+ _optionalChain([onThreadChange, 'optionalCall', _78 => _78(chunk.thread_id)]);
3195
3661
  }
3196
3662
  }
3197
3663
  break;
@@ -3203,21 +3669,27 @@ ${widgetContext}` : widgetContext;
3203
3669
  case "content":
3204
3670
  case "token":
3205
3671
  if (chunk.content) {
3206
- currentTextBuffer += chunk.content;
3207
- updateMessage();
3672
+ if (!currentTextBuffer) {
3673
+ currentTextBuffer = chunk.content.trimStart();
3674
+ } else {
3675
+ currentTextBuffer += chunk.content;
3676
+ }
3677
+ if (currentTextBuffer) {
3678
+ updateMessage();
3679
+ }
3208
3680
  }
3209
3681
  break;
3210
3682
  case "tool_call":
3211
3683
  if (chunk.tool_id && chunk.tool_name) {
3212
3684
  const displayName = chunk.tool_display_name || chunk.tool_name;
3213
3685
  if (currentTextBuffer) {
3214
- contentSegments.push({ type: "text", content: currentTextBuffer });
3686
+ contentSegments.push({ type: "text", content: currentTextBuffer.trimEnd() });
3215
3687
  currentTextBuffer = "";
3216
3688
  }
3217
3689
  contentSegments.push({ type: "tool", id: chunk.tool_id, name: displayName, status: "preparing" });
3218
3690
  toolInputBuffers[chunk.tool_id] = "";
3219
3691
  setChatToolName(displayName);
3220
- _optionalChain([onToolCall, 'optionalCall', _76 => _76(chunk.tool_name, chunk.tool_id)]);
3692
+ _optionalChain([onToolCall, 'optionalCall', _79 => _79(chunk.tool_name, chunk.tool_id)]);
3221
3693
  updateMessage();
3222
3694
  }
3223
3695
  break;
@@ -3277,7 +3749,7 @@ ${widgetContext}` : widgetContext;
3277
3749
  toolSegment.result = chunk.content;
3278
3750
  toolSegment.status = "completed";
3279
3751
  toolSegment.isReceiving = false;
3280
- _optionalChain([onToolResult, 'optionalCall', _77 => _77(toolSegment.name, chunk.content)]);
3752
+ _optionalChain([onToolResult, 'optionalCall', _80 => _80(toolSegment.name, chunk.content)]);
3281
3753
  }
3282
3754
  setChatToolName(null);
3283
3755
  updateMessage();
@@ -3294,6 +3766,7 @@ ${widgetContext}` : widgetContext;
3294
3766
  }
3295
3767
  },
3296
3768
  (threadId2) => {
3769
+ currentTextBuffer = currentTextBuffer.trimEnd();
3297
3770
  if (currentTextBuffer) {
3298
3771
  const lastSegment = contentSegments[contentSegments.length - 1];
3299
3772
  if (lastSegment && lastSegment.type === "text") {
@@ -3320,7 +3793,7 @@ ${widgetContext}` : widgetContext;
3320
3793
  });
3321
3794
  if (threadId2 && threadId2 !== currentThreadId) {
3322
3795
  setCurrentThreadId(threadId2);
3323
- _optionalChain([onThreadChange, 'optionalCall', _78 => _78(threadId2)]);
3796
+ _optionalChain([onThreadChange, 'optionalCall', _81 => _81(threadId2)]);
3324
3797
  }
3325
3798
  setIsLoading(false);
3326
3799
  setCurrentRequestId(null);
@@ -3344,7 +3817,7 @@ ${widgetContext}` : widgetContext;
3344
3817
  setIsLoading(false);
3345
3818
  setCurrentRequestId(null);
3346
3819
  setChatToolName(null);
3347
- _optionalChain([onError, 'optionalCall', _79 => _79(error)]);
3820
+ _optionalChain([onError, 'optionalCall', _82 => _82(error)]);
3348
3821
  }
3349
3822
  );
3350
3823
  }
@@ -3357,7 +3830,7 @@ ${widgetContext}` : widgetContext;
3357
3830
  metadata: { error: true }
3358
3831
  };
3359
3832
  setMessages((prev) => [...prev, errorMessage]);
3360
- _optionalChain([onError, 'optionalCall', _80 => _80(error instanceof Error ? error : new Error("Unknown error"))]);
3833
+ _optionalChain([onError, 'optionalCall', _83 => _83(error instanceof Error ? error : new Error("Unknown error"))]);
3361
3834
  } finally {
3362
3835
  setIsLoading(false);
3363
3836
  }
@@ -3403,7 +3876,7 @@ ${planningInstruction}` : planningInstruction;
3403
3876
  const error = err instanceof Error ? err : new Error("Failed to generate plan");
3404
3877
  setCommandError(error);
3405
3878
  setCommandState("error");
3406
- _optionalChain([onError, 'optionalCall', _81 => _81(error)]);
3879
+ _optionalChain([onError, 'optionalCall', _84 => _84(error)]);
3407
3880
  }
3408
3881
  }
3409
3882
  return;
@@ -3436,12 +3909,12 @@ ${planningInstruction}` : planningInstruction;
3436
3909
  setCommandResult(result);
3437
3910
  setCommandState("success");
3438
3911
  setProgress(100);
3439
- _optionalChain([onComplete, 'optionalCall', _82 => _82(result)]);
3912
+ _optionalChain([onComplete, 'optionalCall', _85 => _85(result)]);
3440
3913
  },
3441
3914
  (error) => {
3442
3915
  setCommandError(error);
3443
3916
  setCommandState("error");
3444
- _optionalChain([onError, 'optionalCall', _83 => _83(error)]);
3917
+ _optionalChain([onError, 'optionalCall', _86 => _86(error)]);
3445
3918
  }
3446
3919
  );
3447
3920
  } else {
@@ -3454,7 +3927,7 @@ ${planningInstruction}` : planningInstruction;
3454
3927
  setCommandResult(result);
3455
3928
  setCommandState("success");
3456
3929
  setProgress(100);
3457
- _optionalChain([onComplete, 'optionalCall', _84 => _84(result)]);
3930
+ _optionalChain([onComplete, 'optionalCall', _87 => _87(result)]);
3458
3931
  }
3459
3932
  } else {
3460
3933
  const commandInstruction = `CRITICAL COMMAND MODE: Maximum 10 words per response. Execute the command immediately. Make reasonable assumptions based on context. Use sensible defaults for missing details. DO NOT ask questions unless something is truly impossible without user input (e.g., missing required password). State what you're doing or the result. Examples: "Analyzing customer data from last quarter..." or "Created 5 new database entries successfully" or "Search complete: found 12 matching results". NO greetings, NO filler words, NO clarification requests. Action/result only.`;
@@ -3484,16 +3957,16 @@ ${commandInstruction}` : commandInstruction;
3484
3957
  const displayName = chunk.tool_display_name || chunk.tool_name;
3485
3958
  lastToolName = chunk.tool_name;
3486
3959
  setCurrentToolName(displayName);
3487
- _optionalChain([onToolCall, 'optionalCall', _85 => _85(chunk.tool_name, chunk.tool_id || "")]);
3960
+ _optionalChain([onToolCall, 'optionalCall', _88 => _88(chunk.tool_name, chunk.tool_id || "")]);
3488
3961
  accumulatedContent = "";
3489
3962
  setStreamedContent("");
3490
3963
  } else if (chunk.type === "tool_result") {
3491
- _optionalChain([onToolResult, 'optionalCall', _86 => _86(lastToolName, chunk.content)]);
3964
+ _optionalChain([onToolResult, 'optionalCall', _89 => _89(lastToolName, chunk.content)]);
3492
3965
  setCurrentToolName(null);
3493
3966
  } else if (chunk.type === "thread_id" && chunk.thread_id) {
3494
3967
  if (!currentThreadId) {
3495
3968
  setCurrentThreadId(chunk.thread_id);
3496
- _optionalChain([onThreadChange, 'optionalCall', _87 => _87(chunk.thread_id)]);
3969
+ _optionalChain([onThreadChange, 'optionalCall', _90 => _90(chunk.thread_id)]);
3497
3970
  }
3498
3971
  } else if (chunk.type === "request_id" && chunk.request_id) {
3499
3972
  setCurrentRequestId(chunk.request_id);
@@ -3509,13 +3982,13 @@ ${commandInstruction}` : commandInstruction;
3509
3982
  setCommandState("success");
3510
3983
  setProgress(100);
3511
3984
  setCurrentRequestId(null);
3512
- _optionalChain([onComplete, 'optionalCall', _88 => _88(result)]);
3985
+ _optionalChain([onComplete, 'optionalCall', _91 => _91(result)]);
3513
3986
  },
3514
3987
  (error) => {
3515
3988
  setCommandError(error);
3516
3989
  setCommandState("error");
3517
3990
  setCurrentRequestId(null);
3518
- _optionalChain([onError, 'optionalCall', _89 => _89(error)]);
3991
+ _optionalChain([onError, 'optionalCall', _92 => _92(error)]);
3519
3992
  }
3520
3993
  );
3521
3994
  } else {
@@ -3535,14 +4008,14 @@ ${commandInstruction}` : commandInstruction;
3535
4008
  setCommandResult(result);
3536
4009
  setCommandState("success");
3537
4010
  setProgress(100);
3538
- _optionalChain([onComplete, 'optionalCall', _90 => _90(result)]);
4011
+ _optionalChain([onComplete, 'optionalCall', _93 => _93(result)]);
3539
4012
  }
3540
4013
  }
3541
4014
  } catch (err) {
3542
4015
  const error = err instanceof Error ? err : new Error("Unknown error");
3543
4016
  setCommandError(error);
3544
4017
  setCommandState("error");
3545
- _optionalChain([onError, 'optionalCall', _91 => _91(error)]);
4018
+ _optionalChain([onError, 'optionalCall', _94 => _94(error)]);
3546
4019
  }
3547
4020
  };
3548
4021
  const resetCommand = () => {
@@ -3590,12 +4063,15 @@ ${planToExecute}`;
3590
4063
  };
3591
4064
  const isCompact = commandVariant === "compact";
3592
4065
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("apteva-chat flex flex-col h-full", variant !== "default" && `apteva-chat-${variant}`, className), children: [
3593
- showHeader && mode === "chat" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-chat-header px-4 py-3 flex items-center justify-between", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
3594
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-chat-title", children: headerTitle }),
3595
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn(
3596
- "apteva-chat-status",
3597
- isLoading ? chatToolName ? "apteva-chat-status-tool" : "apteva-chat-status-thinking" : "apteva-chat-status-ready"
3598
- ), children: isLoading ? chatToolName ? `Using ${chatToolName}...` : "Thinking..." : "Ready" })
4066
+ showHeader && mode === "chat" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-chat-header px-4 py-3", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
4067
+ onHeaderBack && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: onHeaderBack, className: "apteva-chat-back", style: { flexShrink: 0 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 12L6 8l4-4" }) }) }),
4068
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
4069
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-chat-title", children: headerTitle }),
4070
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn(
4071
+ "apteva-chat-status",
4072
+ isLoading ? chatToolName ? "apteva-chat-status-tool" : "apteva-chat-status-thinking" : "apteva-chat-status-ready"
4073
+ ), children: isLoading ? chatToolName ? `Using ${chatToolName}...` : "Thinking..." : "Ready" })
4074
+ ] })
3599
4075
  ] }) }),
3600
4076
  mode === "chat" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
3601
4077
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -3635,8 +4111,8 @@ ${planToExecute}`;
3635
4111
  executeCommand(text, files);
3636
4112
  },
3637
4113
  state: commandState,
3638
- response: _optionalChain([commandResult, 'optionalAccess', _92 => _92.data, 'optionalAccess', _93 => _93.summary]) || _optionalChain([commandResult, 'optionalAccess', _94 => _94.message]),
3639
- error: _optionalChain([commandError, 'optionalAccess', _95 => _95.message]),
4114
+ response: _optionalChain([commandResult, 'optionalAccess', _95 => _95.data, 'optionalAccess', _96 => _96.summary]) || _optionalChain([commandResult, 'optionalAccess', _97 => _97.message]),
4115
+ error: _optionalChain([commandError, 'optionalAccess', _98 => _98.message]),
3640
4116
  plan,
3641
4117
  streamedContent,
3642
4118
  toolName: currentToolName,
@@ -3804,13 +4280,13 @@ ${planningInstruction}` : planningInstruction;
3804
4280
  const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
3805
4281
  setError(error2);
3806
4282
  setState("error");
3807
- _optionalChain([onError, 'optionalCall', _96 => _96(error2)]);
4283
+ _optionalChain([onError, 'optionalCall', _99 => _99(error2)]);
3808
4284
  });
3809
4285
  } catch (err) {
3810
4286
  const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
3811
4287
  setError(error2);
3812
4288
  setState("error");
3813
- _optionalChain([onError, 'optionalCall', _97 => _97(error2)]);
4289
+ _optionalChain([onError, 'optionalCall', _100 => _100(error2)]);
3814
4290
  }
3815
4291
  }
3816
4292
  return;
@@ -3821,7 +4297,7 @@ ${planningInstruction}` : planningInstruction;
3821
4297
  setStreamedContent("");
3822
4298
  setCommand("");
3823
4299
  setUploadedFiles([]);
3824
- _optionalChain([onStart, 'optionalCall', _98 => _98()]);
4300
+ _optionalChain([onStart, 'optionalCall', _101 => _101()]);
3825
4301
  try {
3826
4302
  if (useMock) {
3827
4303
  if (enableStreaming) {
@@ -3832,16 +4308,16 @@ ${planningInstruction}` : planningInstruction;
3832
4308
  if (chunk.type === "token" && chunk.content) {
3833
4309
  accumulatedContent += chunk.content;
3834
4310
  setStreamedContent(accumulatedContent);
3835
- _optionalChain([onChunk, 'optionalCall', _99 => _99(chunk.content)]);
4311
+ _optionalChain([onChunk, 'optionalCall', _102 => _102(chunk.content)]);
3836
4312
  const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
3837
4313
  setProgress(estimatedProgress);
3838
- _optionalChain([onProgress, 'optionalCall', _100 => _100(estimatedProgress)]);
4314
+ _optionalChain([onProgress, 'optionalCall', _103 => _103(estimatedProgress)]);
3839
4315
  } else if (chunk.type === "widget" && chunk.widget) {
3840
4316
  const widget = chunk.widget;
3841
4317
  setResult((prev) => ({
3842
4318
  success: true,
3843
- data: _optionalChain([prev, 'optionalAccess', _101 => _101.data]) || {},
3844
- widgets: [..._optionalChain([prev, 'optionalAccess', _102 => _102.widgets]) || [], widget],
4319
+ data: _optionalChain([prev, 'optionalAccess', _104 => _104.data]) || {},
4320
+ widgets: [..._optionalChain([prev, 'optionalAccess', _105 => _105.widgets]) || [], widget],
3845
4321
  message: accumulatedContent || "Command executed successfully"
3846
4322
  }));
3847
4323
  }
@@ -3861,19 +4337,19 @@ ${planningInstruction}` : planningInstruction;
3861
4337
  setResult(result2);
3862
4338
  setState("success");
3863
4339
  setProgress(100);
3864
- _optionalChain([onComplete, 'optionalCall', _103 => _103(result2)]);
4340
+ _optionalChain([onComplete, 'optionalCall', _106 => _106(result2)]);
3865
4341
  },
3866
4342
  (error2) => {
3867
4343
  setError(error2);
3868
4344
  setState("error");
3869
- _optionalChain([onError, 'optionalCall', _104 => _104(error2)]);
4345
+ _optionalChain([onError, 'optionalCall', _107 => _107(error2)]);
3870
4346
  }
3871
4347
  );
3872
4348
  } else {
3873
4349
  const progressInterval = setInterval(() => {
3874
4350
  setProgress((prev) => {
3875
4351
  const next = Math.min(prev + 10, 90);
3876
- _optionalChain([onProgress, 'optionalCall', _105 => _105(next)]);
4352
+ _optionalChain([onProgress, 'optionalCall', _108 => _108(next)]);
3877
4353
  return next;
3878
4354
  });
3879
4355
  }, 200);
@@ -3897,7 +4373,7 @@ ${planningInstruction}` : planningInstruction;
3897
4373
  setResult(result2);
3898
4374
  setState("success");
3899
4375
  setProgress(100);
3900
- _optionalChain([onComplete, 'optionalCall', _106 => _106(result2)]);
4376
+ _optionalChain([onComplete, 'optionalCall', _109 => _109(result2)]);
3901
4377
  }
3902
4378
  } else {
3903
4379
  if (enableStreaming) {
@@ -3943,16 +4419,16 @@ ${commandInstruction}` : commandInstruction;
3943
4419
  if (chunk.type === "token" && chunk.content) {
3944
4420
  accumulatedContent += chunk.content;
3945
4421
  setStreamedContent(accumulatedContent);
3946
- _optionalChain([onChunk, 'optionalCall', _107 => _107(chunk.content)]);
4422
+ _optionalChain([onChunk, 'optionalCall', _110 => _110(chunk.content)]);
3947
4423
  const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
3948
4424
  setProgress(estimatedProgress);
3949
- _optionalChain([onProgress, 'optionalCall', _108 => _108(estimatedProgress)]);
4425
+ _optionalChain([onProgress, 'optionalCall', _111 => _111(estimatedProgress)]);
3950
4426
  } else if (chunk.type === "widget" && chunk.widget) {
3951
4427
  const widget = chunk.widget;
3952
4428
  setResult((prev) => ({
3953
4429
  success: true,
3954
- data: _optionalChain([prev, 'optionalAccess', _109 => _109.data]) || {},
3955
- widgets: [..._optionalChain([prev, 'optionalAccess', _110 => _110.widgets]) || [], widget],
4430
+ data: _optionalChain([prev, 'optionalAccess', _112 => _112.data]) || {},
4431
+ widgets: [..._optionalChain([prev, 'optionalAccess', _113 => _113.widgets]) || [], widget],
3956
4432
  message: accumulatedContent || "Command executed successfully"
3957
4433
  }));
3958
4434
  }
@@ -3972,20 +4448,20 @@ ${commandInstruction}` : commandInstruction;
3972
4448
  setResult(result2);
3973
4449
  setState("success");
3974
4450
  setProgress(100);
3975
- _optionalChain([onComplete, 'optionalCall', _111 => _111(result2)]);
4451
+ _optionalChain([onComplete, 'optionalCall', _114 => _114(result2)]);
3976
4452
  },
3977
4453
  (error2) => {
3978
4454
  const err = error2 instanceof Error ? error2 : new Error("Unknown error");
3979
4455
  setError(err);
3980
4456
  setState("error");
3981
- _optionalChain([onError, 'optionalCall', _112 => _112(err)]);
4457
+ _optionalChain([onError, 'optionalCall', _115 => _115(err)]);
3982
4458
  }
3983
4459
  );
3984
4460
  } else {
3985
4461
  const progressInterval = setInterval(() => {
3986
4462
  setProgress((prev) => {
3987
4463
  const next = Math.min(prev + 10, 90);
3988
- _optionalChain([onProgress, 'optionalCall', _113 => _113(next)]);
4464
+ _optionalChain([onProgress, 'optionalCall', _116 => _116(next)]);
3989
4465
  return next;
3990
4466
  });
3991
4467
  }, 200);
@@ -4041,14 +4517,14 @@ ${commandInstruction}` : commandInstruction;
4041
4517
  setResult(result2);
4042
4518
  setState("success");
4043
4519
  setProgress(100);
4044
- _optionalChain([onComplete, 'optionalCall', _114 => _114(result2)]);
4520
+ _optionalChain([onComplete, 'optionalCall', _117 => _117(result2)]);
4045
4521
  }
4046
4522
  }
4047
4523
  } catch (err) {
4048
4524
  const error2 = err instanceof Error ? err : new Error("Unknown error");
4049
4525
  setError(error2);
4050
4526
  setState("error");
4051
- _optionalChain([onError, 'optionalCall', _115 => _115(error2)]);
4527
+ _optionalChain([onError, 'optionalCall', _118 => _118(error2)]);
4052
4528
  }
4053
4529
  };
4054
4530
  const resetCommand = () => {
@@ -4081,14 +4557,14 @@ ${planToExecute}`;
4081
4557
  };
4082
4558
  const handleFileSelect = async (e) => {
4083
4559
  if (e.target.files && e.target.files.length > 0) {
4084
- _optionalChain([onFileUpload, 'optionalCall', _116 => _116(e.target.files)]);
4560
+ _optionalChain([onFileUpload, 'optionalCall', _119 => _119(e.target.files)]);
4085
4561
  const files = [];
4086
4562
  for (let i = 0; i < e.target.files.length; i++) {
4087
4563
  const file = e.target.files[i];
4088
4564
  const reader = new FileReader();
4089
4565
  await new Promise((resolve) => {
4090
4566
  reader.onload = (event) => {
4091
- if (_optionalChain([event, 'access', _117 => _117.target, 'optionalAccess', _118 => _118.result])) {
4567
+ if (_optionalChain([event, 'access', _120 => _120.target, 'optionalAccess', _121 => _121.result])) {
4092
4568
  const fullDataUrl = event.target.result;
4093
4569
  const base64Data = fullDataUrl.split(",")[1];
4094
4570
  if (file.type.startsWith("image/")) {
@@ -4182,7 +4658,7 @@ ${planToExecute}`;
4182
4658
  enableFileUpload && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4183
4659
  "button",
4184
4660
  {
4185
- onClick: () => _optionalChain([fileInputRef, 'access', _119 => _119.current, 'optionalAccess', _120 => _120.click, 'call', _121 => _121()]),
4661
+ onClick: () => _optionalChain([fileInputRef, 'access', _122 => _122.current, 'optionalAccess', _123 => _123.click, 'call', _124 => _124()]),
4186
4662
  className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0 !text-neutral-500 dark:!text-neutral-500 hover:bg-neutral-100 dark:hover:bg-neutral-800",
4187
4663
  title: "Attach file",
4188
4664
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M8.4 2.8L4.4 6.8C3.736 7.464 3.736 8.536 4.4 9.2C5.064 9.864 6.136 9.864 6.8 9.2L11.6 4.4C12.704 3.296 12.704 1.504 11.6 0.4C10.496 -0.704 8.704 -0.704 7.6 0.4L2.8 5.2C1.256 6.744 1.256 9.256 2.8 10.8C4.344 12.344 6.856 12.344 8.4 10.8L12.4 6.8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round", transform: "translate(1.6, 2.4)" }) })
@@ -4401,7 +4877,7 @@ ${planToExecute}`;
4401
4877
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-5 h-5 text-red-600 mt-0.5 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
4402
4878
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
4403
4879
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-sm font-semibold text-red-800 dark:text-red-400", children: "Error" }),
4404
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-red-700 dark:text-red-300 text-sm mt-1", children: _optionalChain([error, 'optionalAccess', _122 => _122.message]) })
4880
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-red-700 dark:text-red-300 text-sm mt-1", children: _optionalChain([error, 'optionalAccess', _125 => _125.message]) })
4405
4881
  ] })
4406
4882
  ] }) }),
4407
4883
  allowInput && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -4429,7 +4905,7 @@ ${planToExecute}`;
4429
4905
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-green-700 dark:text-green-300 text-sm", children: "Command executed successfully" })
4430
4906
  ] })
4431
4907
  ] }),
4432
- _optionalChain([result, 'access', _123 => _123.data, 'optionalAccess', _124 => _124.summary]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-neutral-700 dark:text-neutral-300 text-sm leading-relaxed whitespace-pre-line", children: result.data.summary }),
4908
+ _optionalChain([result, 'access', _126 => _126.data, 'optionalAccess', _127 => _127.summary]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-neutral-700 dark:text-neutral-300 text-sm leading-relaxed whitespace-pre-line", children: result.data.summary }),
4433
4909
  result.widgets && result.widgets.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "space-y-3", children: result.widgets.map((widget) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4434
4910
  WidgetRenderer,
4435
4911
  {
@@ -4480,7 +4956,7 @@ ${planToExecute}`;
4480
4956
  enableFileUpload && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4481
4957
  "button",
4482
4958
  {
4483
- onClick: () => _optionalChain([fileInputRef, 'access', _125 => _125.current, 'optionalAccess', _126 => _126.click, 'call', _127 => _127()]),
4959
+ onClick: () => _optionalChain([fileInputRef, 'access', _128 => _128.current, 'optionalAccess', _129 => _129.click, 'call', _130 => _130()]),
4484
4960
  className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0 !text-neutral-500 dark:!text-neutral-500 hover:bg-neutral-100 dark:hover:bg-neutral-800",
4485
4961
  title: "Attach file",
4486
4962
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M8.4 2.8L4.4 6.8C3.736 7.464 3.736 8.536 4.4 9.2C5.064 9.864 6.136 9.864 6.8 9.2L11.6 4.4C12.704 3.296 12.704 1.504 11.6 0.4C10.496 -0.704 8.704 -0.704 7.6 0.4L2.8 5.2C1.256 6.744 1.256 9.256 2.8 10.8C4.344 12.344 6.856 12.344 8.4 10.8L12.4 6.8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round", transform: "translate(1.6, 2.4)" }) })
@@ -4666,25 +5142,25 @@ function Prompt({
4666
5142
  const newValue = e.target.value;
4667
5143
  if (!maxLength || newValue.length <= maxLength) {
4668
5144
  setValue(newValue);
4669
- _optionalChain([onChange, 'optionalCall', _128 => _128(newValue)]);
5145
+ _optionalChain([onChange, 'optionalCall', _131 => _131(newValue)]);
4670
5146
  }
4671
5147
  };
4672
5148
  const handleSubmit = async () => {
4673
5149
  if (value.length < minLength) return;
4674
- _optionalChain([onSubmit, 'optionalCall', _129 => _129(value)]);
5150
+ _optionalChain([onSubmit, 'optionalCall', _132 => _132(value)]);
4675
5151
  setIsLoading(true);
4676
5152
  try {
4677
5153
  if (useMock) {
4678
5154
  await new Promise((resolve) => setTimeout(resolve, 1500));
4679
5155
  const mockResult = `Enhanced version: ${value} [AI-generated content]`;
4680
- _optionalChain([onResult, 'optionalCall', _130 => _130(mockResult)]);
5156
+ _optionalChain([onResult, 'optionalCall', _133 => _133(mockResult)]);
4681
5157
  setValue("");
4682
5158
  } else {
4683
5159
  const response = await aptevaClient.chat({
4684
5160
  agent_id: agentId,
4685
5161
  message: value
4686
5162
  });
4687
- _optionalChain([onResult, 'optionalCall', _131 => _131(response.message)]);
5163
+ _optionalChain([onResult, 'optionalCall', _134 => _134(response.message)]);
4688
5164
  setValue("");
4689
5165
  }
4690
5166
  } catch (error) {
@@ -4779,7 +5255,7 @@ function Stream({
4779
5255
  }, [autoStart]);
4780
5256
  const startStreaming = async () => {
4781
5257
  setIsStreaming(true);
4782
- _optionalChain([onStart, 'optionalCall', _132 => _132()]);
5258
+ _optionalChain([onStart, 'optionalCall', _135 => _135()]);
4783
5259
  try {
4784
5260
  if (useMock) {
4785
5261
  const mockText = "This is a simulated streaming response from the AI agent. In a real implementation, this would stream data from your backend API. The text appears word by word to simulate the streaming effect. You can customize the typing speed and styling based on your needs.";
@@ -4787,13 +5263,13 @@ function Stream({
4787
5263
  mockText,
4788
5264
  (chunk) => {
4789
5265
  setText((prev) => prev + chunk);
4790
- _optionalChain([onChunk, 'optionalCall', _133 => _133(chunk)]);
5266
+ _optionalChain([onChunk, 'optionalCall', _136 => _136(chunk)]);
4791
5267
  },
4792
5268
  typingSpeed
4793
5269
  );
4794
5270
  setIsComplete(true);
4795
5271
  setIsStreaming(false);
4796
- _optionalChain([onComplete, 'optionalCall', _134 => _134(text + mockText)]);
5272
+ _optionalChain([onComplete, 'optionalCall', _137 => _137(text + mockText)]);
4797
5273
  } else {
4798
5274
  let accumulatedText = "";
4799
5275
  await aptevaClient.chatStream(
@@ -4806,24 +5282,24 @@ function Stream({
4806
5282
  if (chunk.type === "token" && chunk.content) {
4807
5283
  accumulatedText += chunk.content;
4808
5284
  setText(accumulatedText);
4809
- _optionalChain([onChunk, 'optionalCall', _135 => _135(chunk.content)]);
5285
+ _optionalChain([onChunk, 'optionalCall', _138 => _138(chunk.content)]);
4810
5286
  }
4811
5287
  },
4812
5288
  () => {
4813
5289
  setIsComplete(true);
4814
5290
  setIsStreaming(false);
4815
- _optionalChain([onComplete, 'optionalCall', _136 => _136(accumulatedText)]);
5291
+ _optionalChain([onComplete, 'optionalCall', _139 => _139(accumulatedText)]);
4816
5292
  },
4817
5293
  (error) => {
4818
5294
  const err = error instanceof Error ? error : new Error("Streaming error");
4819
- _optionalChain([onError, 'optionalCall', _137 => _137(err)]);
5295
+ _optionalChain([onError, 'optionalCall', _140 => _140(err)]);
4820
5296
  setIsStreaming(false);
4821
5297
  }
4822
5298
  );
4823
5299
  }
4824
5300
  } catch (error) {
4825
5301
  const err = error instanceof Error ? error : new Error("Streaming error");
4826
- _optionalChain([onError, 'optionalCall', _138 => _138(err)]);
5302
+ _optionalChain([onError, 'optionalCall', _141 => _141(err)]);
4827
5303
  setIsStreaming(false);
4828
5304
  }
4829
5305
  };
@@ -4915,7 +5391,7 @@ function ThreadList({
4915
5391
  }) {
4916
5392
  const [searchQuery, setSearchQuery] = _react.useState.call(void 0, "");
4917
5393
  const filteredThreads = threads.filter(
4918
- (thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || _optionalChain([thread, 'access', _139 => _139.preview, 'optionalAccess', _140 => _140.toLowerCase, 'call', _141 => _141(), 'access', _142 => _142.includes, 'call', _143 => _143(searchQuery.toLowerCase())])
5394
+ (thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || _optionalChain([thread, 'access', _142 => _142.preview, 'optionalAccess', _143 => _143.toLowerCase, 'call', _144 => _144(), 'access', _145 => _145.includes, 'call', _146 => _146(searchQuery.toLowerCase())])
4919
5395
  );
4920
5396
  const groupedThreads = groupBy === "date" ? groupThreadsByDate(filteredThreads) : { All: filteredThreads };
4921
5397
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col h-full", children: [
@@ -4937,8 +5413,8 @@ function ThreadList({
4937
5413
  {
4938
5414
  thread,
4939
5415
  isActive: thread.id === currentThreadId,
4940
- onSelect: () => _optionalChain([onThreadSelect, 'optionalCall', _144 => _144(thread.id)]),
4941
- onDelete: () => _optionalChain([onThreadDelete, 'optionalCall', _145 => _145(thread.id)])
5416
+ onSelect: () => _optionalChain([onThreadSelect, 'optionalCall', _147 => _147(thread.id)]),
5417
+ onDelete: () => _optionalChain([onThreadDelete, 'optionalCall', _148 => _148(thread.id)])
4942
5418
  },
4943
5419
  thread.id
4944
5420
  ))
@@ -5000,7 +5476,7 @@ function Threads({
5000
5476
  threads.slice(0, 5).map((thread) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5001
5477
  "button",
5002
5478
  {
5003
- onClick: () => _optionalChain([onThreadSelect, 'optionalCall', _146 => _146(thread.id)]),
5479
+ onClick: () => _optionalChain([onThreadSelect, 'optionalCall', _149 => _149(thread.id)]),
5004
5480
  className: cn(
5005
5481
  "px-4 py-2 whitespace-nowrap font-medium transition-colors",
5006
5482
  thread.id === currentThreadId ? "border-b-2 border-apteva-500 text-apteva-500" : "text-neutral-600 hover:text-neutral-900"
@@ -5042,6 +5518,418 @@ function Threads({
5042
5518
  ] });
5043
5519
  }
5044
5520
 
5521
+ // src/components/AutoInterface/AutoInterface.tsx
5522
+
5523
+
5524
+ // src/components/AutoInterface/LayoutRenderer.tsx
5525
+
5526
+
5527
+ var gapClasses = {
5528
+ none: "gap-0",
5529
+ sm: "gap-2",
5530
+ md: "gap-4",
5531
+ lg: "gap-6"
5532
+ };
5533
+ var paddingClasses = {
5534
+ none: "p-0",
5535
+ sm: "p-2",
5536
+ md: "p-4",
5537
+ lg: "p-6"
5538
+ };
5539
+ var maxWidthClasses = {
5540
+ sm: "max-w-2xl",
5541
+ md: "max-w-4xl",
5542
+ lg: "max-w-6xl",
5543
+ xl: "max-w-7xl",
5544
+ full: "max-w-full"
5545
+ };
5546
+ function LayoutRenderer({ node, onAction, renderNode }) {
5547
+ const children = node.children || [];
5548
+ switch (node.layout) {
5549
+ case "page":
5550
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PageLayout, { node, renderNode });
5551
+ case "row":
5552
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RowLayout, { node, renderNode });
5553
+ case "columns":
5554
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ColumnsLayout, { node, renderNode });
5555
+ case "stack":
5556
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, StackLayout, { node, renderNode });
5557
+ case "sidebar":
5558
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SidebarLayout, { node, renderNode });
5559
+ case "tabs":
5560
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabsLayout, { node, renderNode });
5561
+ default:
5562
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "space-y-4", children: children.map((child) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: renderNode(child) }, child.id)) });
5563
+ }
5564
+ }
5565
+ function PageLayout({ node, renderNode }) {
5566
+ const { title, padding = "md", maxWidth = "xl" } = node.props || {};
5567
+ const children = node.children || [];
5568
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("w-full mx-auto", paddingClasses[padding], maxWidthClasses[maxWidth]), children: [
5569
+ title && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h1", { className: "!text-2xl font-bold !text-neutral-900 dark:!text-white mb-6", children: title }),
5570
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "space-y-6", children: children.map((child) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: renderNode(child) }, child.id)) })
5571
+ ] });
5572
+ }
5573
+ function RowLayout({ node, renderNode }) {
5574
+ const { columns, gap = "md", align = "stretch" } = node.props || {};
5575
+ const children = node.children || [];
5576
+ const templateColumns = columns ? columns.map((c) => `${c}fr`).join(" ") : `repeat(${children.length}, 1fr)`;
5577
+ const alignClasses = {
5578
+ start: "items-start",
5579
+ center: "items-center",
5580
+ end: "items-end",
5581
+ stretch: "items-stretch"
5582
+ };
5583
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5584
+ "div",
5585
+ {
5586
+ className: cn("grid", gapClasses[gap], alignClasses[align]),
5587
+ style: { gridTemplateColumns: templateColumns },
5588
+ children: children.map((child) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: renderNode(child) }, child.id))
5589
+ }
5590
+ );
5591
+ }
5592
+ function ColumnsLayout({ node, renderNode }) {
5593
+ const { count, gap = "md" } = node.props || {};
5594
+ const children = node.children || [];
5595
+ const colCount = count || children.length;
5596
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5597
+ "div",
5598
+ {
5599
+ className: cn("grid", gapClasses[gap]),
5600
+ style: { gridTemplateColumns: `repeat(${colCount}, 1fr)` },
5601
+ children: children.map((child) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: renderNode(child) }, child.id))
5602
+ }
5603
+ );
5604
+ }
5605
+ function StackLayout({ node, renderNode }) {
5606
+ const { gap = "md", align = "stretch" } = node.props || {};
5607
+ const children = node.children || [];
5608
+ const alignClasses = {
5609
+ left: "items-start",
5610
+ center: "items-center",
5611
+ right: "items-end",
5612
+ stretch: "items-stretch"
5613
+ };
5614
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("flex flex-col", gapClasses[gap], alignClasses[align]), children: children.map((child) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: renderNode(child) }, child.id)) });
5615
+ }
5616
+ function SidebarLayout({ node, renderNode }) {
5617
+ const { side = "left", width = "280px" } = node.props || {};
5618
+ const children = node.children || [];
5619
+ const [sidebarChild, ...mainChildren] = side === "left" ? children : [...children].reverse();
5620
+ if (!sidebarChild) return null;
5621
+ const sidebar = /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5622
+ "div",
5623
+ {
5624
+ className: "flex-shrink-0 overflow-y-auto border-neutral-200 dark:border-neutral-700",
5625
+ style: { width },
5626
+ children: renderNode(sidebarChild)
5627
+ }
5628
+ );
5629
+ const main = /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 overflow-y-auto min-w-0", children: mainChildren.map((child) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: renderNode(child) }, child.id)) });
5630
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full gap-4", children: side === "left" ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5631
+ sidebar,
5632
+ main
5633
+ ] }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5634
+ main,
5635
+ sidebar
5636
+ ] }) });
5637
+ }
5638
+ function TabsLayout({ node, renderNode }) {
5639
+ const { labels = [], defaultTab = 0 } = node.props || {};
5640
+ const children = node.children || [];
5641
+ const [activeTab, setActiveTab] = _react.useState.call(void 0, defaultTab);
5642
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
5643
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex border-b border-neutral-200 dark:border-neutral-700 mb-4", children: labels.map((label, idx) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5644
+ "button",
5645
+ {
5646
+ onClick: () => setActiveTab(idx),
5647
+ className: cn(
5648
+ "px-4 py-2 !text-sm font-medium transition-colors border-b-2 -mb-px",
5649
+ activeTab === idx ? "border-blue-500 !text-blue-600 dark:!text-blue-400" : "border-transparent !text-neutral-500 hover:!text-neutral-700 dark:hover:!text-neutral-300"
5650
+ ),
5651
+ children: label
5652
+ },
5653
+ idx
5654
+ )) }),
5655
+ children[activeTab] && renderNode(children[activeTab])
5656
+ ] });
5657
+ }
5658
+
5659
+ // src/components/AutoInterface/InterfaceRenderer.tsx
5660
+
5661
+ var STRUCTURAL_KEYS = /* @__PURE__ */ new Set(["type", "id", "layout", "props", "children", "actions", "metadata", "isStreaming"]);
5662
+ function normalizeNode(n) {
5663
+ let node = { ...n };
5664
+ if (node.type === "widget" && _optionalChain([node, 'access', _150 => _150.props, 'optionalAccess', _151 => _151.widget])) {
5665
+ node.type = node.props.widget;
5666
+ const { widget: _, ...rest } = node.props;
5667
+ node.props = rest;
5668
+ }
5669
+ const explicit = node.props || {};
5670
+ const extra = {};
5671
+ for (const key of Object.keys(node)) {
5672
+ if (!STRUCTURAL_KEYS.has(key)) {
5673
+ extra[key] = node[key];
5674
+ }
5675
+ }
5676
+ node.props = { ...extra, ...explicit };
5677
+ if (node.props.style && !node.props.variant) {
5678
+ node.props.variant = node.props.style;
5679
+ delete node.props.style;
5680
+ }
5681
+ if (node.children) {
5682
+ node.children = node.children.map(normalizeNode);
5683
+ }
5684
+ return node;
5685
+ }
5686
+ function InterfaceRenderer({ node, onAction }) {
5687
+ const renderNode = (rawNode) => {
5688
+ const n = normalizeNode(rawNode);
5689
+ if (n.type === "layout" && n.layout) {
5690
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5691
+ LayoutRenderer,
5692
+ {
5693
+ node: n,
5694
+ onAction,
5695
+ renderNode
5696
+ },
5697
+ n.id
5698
+ );
5699
+ }
5700
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5701
+ WidgetRenderer,
5702
+ {
5703
+ widget: {
5704
+ type: n.type,
5705
+ id: n.id,
5706
+ props: n.props || {},
5707
+ actions: n.actions,
5708
+ metadata: n.metadata,
5709
+ isStreaming: n.isStreaming
5710
+ },
5711
+ onAction
5712
+ },
5713
+ n.id
5714
+ );
5715
+ };
5716
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: renderNode(node) });
5717
+ }
5718
+
5719
+ // src/components/AutoInterface/InterfaceSkeleton.tsx
5720
+
5721
+ function InterfaceSkeleton({ className }) {
5722
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("animate-pulse space-y-6 p-6", className), children: [
5723
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-7 bg-neutral-200 dark:bg-neutral-700 rounded w-1/3" }),
5724
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "grid grid-cols-4 gap-4", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "border border-neutral-200 dark:border-neutral-700 rounded-xl p-5 space-y-2", children: [
5725
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-neutral-200 dark:bg-neutral-700 rounded w-2/3" }),
5726
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-8 bg-neutral-200 dark:bg-neutral-700 rounded w-1/2" })
5727
+ ] }, i)) }),
5728
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "grid grid-cols-3 gap-4", children: [
5729
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "col-span-2 border border-neutral-200 dark:border-neutral-700 rounded-xl p-5 space-y-3", children: [
5730
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-neutral-200 dark:bg-neutral-700 rounded w-1/4" }),
5731
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-40 bg-neutral-200 dark:bg-neutral-700 rounded" })
5732
+ ] }),
5733
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "border border-neutral-200 dark:border-neutral-700 rounded-xl p-5 space-y-3", children: [
5734
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-neutral-200 dark:bg-neutral-700 rounded w-1/2" }),
5735
+ [1, 2, 3].map((i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-10 bg-neutral-200 dark:bg-neutral-700 rounded" }, i))
5736
+ ] })
5737
+ ] })
5738
+ ] });
5739
+ }
5740
+
5741
+ // src/components/AutoInterface/AutoInterface.tsx
5742
+
5743
+ async function generateInitialInterface(apiUrl, apiKey, agentId, prompt) {
5744
+ const systemContext = generateCompactInterfaceContext();
5745
+ const message = `${systemContext}
5746
+
5747
+ Generate an interface for: ${prompt}`;
5748
+ const headers = { "Content-Type": "application/json" };
5749
+ if (apiKey) headers["X-API-Key"] = apiKey;
5750
+ const response = await fetch(`${apiUrl}/chat`, {
5751
+ method: "POST",
5752
+ headers,
5753
+ body: JSON.stringify({
5754
+ agent_id: agentId,
5755
+ message,
5756
+ stream: false
5757
+ })
5758
+ });
5759
+ if (!response.ok) {
5760
+ const err = await response.json().catch(() => ({ error: "Request failed" }));
5761
+ throw new Error(err.error || `Request failed with status ${response.status}`);
5762
+ }
5763
+ const data = await response.json();
5764
+ const text = data.response || data.message || "";
5765
+ console.log("[AutoInterface] Raw API response:", data);
5766
+ console.log("[AutoInterface] Extracted text (" + text.length + " chars):", text.substring(0, 500));
5767
+ const spec = parseInterfaceFromText(text);
5768
+ console.log("[AutoInterface] Parsed spec:", spec ? "OK" : "null", spec ? JSON.stringify(spec).substring(0, 300) + "..." : "");
5769
+ return { spec, threadId: data.thread_id || null };
5770
+ }
5771
+ function AutoInterface({
5772
+ agentId,
5773
+ threadId,
5774
+ initialPrompt,
5775
+ initialInterface,
5776
+ context,
5777
+ apiUrl,
5778
+ apiKey,
5779
+ onInterfaceChange,
5780
+ onAction,
5781
+ onThreadChange,
5782
+ onError,
5783
+ chatPosition = "right",
5784
+ chatWidth = "380px",
5785
+ chatCollapsible = true,
5786
+ chatPlaceholder = "Ask the AI to generate or update the interface...",
5787
+ chatWelcomeTitle = "Auto Interface",
5788
+ useMock,
5789
+ theme,
5790
+ className
5791
+ }) {
5792
+ const [interfaceSpec, setInterfaceSpec] = _react.useState.call(void 0, initialInterface || null);
5793
+ const [isGenerating, setIsGenerating] = _react.useState.call(void 0, false);
5794
+ const [chatCollapsed, setChatCollapsed] = _react.useState.call(void 0, false);
5795
+ const chatRef = _react.useRef.call(void 0, null);
5796
+ const systemContext = [
5797
+ generateInterfaceContext(),
5798
+ context || ""
5799
+ ].filter(Boolean).join("\n\n");
5800
+ const updateInterface = _react.useCallback.call(void 0, (newSpec) => {
5801
+ setInterfaceSpec(newSpec);
5802
+ _optionalChain([onInterfaceChange, 'optionalCall', _152 => _152(newSpec)]);
5803
+ }, [onInterfaceChange]);
5804
+ const handleAction = _react.useCallback.call(void 0, (action) => {
5805
+ _optionalChain([onAction, 'optionalCall', _153 => _153(action)]);
5806
+ if (chatRef.current) {
5807
+ chatRef.current.sendMessage(
5808
+ `[Action: ${action.type} on widget ${action.widgetId || "unknown"}. Payload: ${JSON.stringify(action.payload)}]`
5809
+ );
5810
+ }
5811
+ }, [onAction]);
5812
+ const handleMessageComplete = _react.useCallback.call(void 0, (result) => {
5813
+ if (!_optionalChain([result, 'optionalAccess', _154 => _154.data])) return;
5814
+ const text = typeof result.data === "string" ? result.data : result.data.message || "";
5815
+ console.log("[AutoInterface] Chat message complete, text (" + text.length + " chars):", text.substring(0, 300));
5816
+ const parsed = parseInterfaceFromText(text);
5817
+ if (parsed) {
5818
+ console.log("[AutoInterface] Parsed full interface from chat");
5819
+ updateInterface(parsed);
5820
+ setIsGenerating(false);
5821
+ return;
5822
+ }
5823
+ const updates = parseUpdatesFromText(text);
5824
+ if (updates.length > 0 && interfaceSpec) {
5825
+ console.log("[AutoInterface] Parsed", updates.length, "updates from chat");
5826
+ const newSpec = applyUpdates(interfaceSpec, updates);
5827
+ updateInterface(newSpec);
5828
+ } else {
5829
+ console.log("[AutoInterface] No interface or updates found in chat message");
5830
+ }
5831
+ setIsGenerating(false);
5832
+ }, [interfaceSpec, updateInterface]);
5833
+ _react.useEffect.call(void 0, () => {
5834
+ if (!initialPrompt || initialInterface || useMock) return;
5835
+ if (!apiUrl) return;
5836
+ let cancelled = false;
5837
+ setIsGenerating(true);
5838
+ console.log("[AutoInterface] Generating initial interface for prompt:", initialPrompt);
5839
+ console.log("[AutoInterface] API URL:", apiUrl, "| Agent:", agentId);
5840
+ generateInitialInterface(apiUrl, apiKey, agentId, initialPrompt).then(({ spec, threadId: threadId2 }) => {
5841
+ if (cancelled) return;
5842
+ console.log("[AutoInterface] Generation complete. Spec:", spec ? "parsed OK" : "null", "| Thread:", threadId2);
5843
+ if (spec) {
5844
+ console.log("[AutoInterface] Setting interface with", JSON.stringify(spec).length, "bytes");
5845
+ updateInterface(spec);
5846
+ } else {
5847
+ console.warn("[AutoInterface] Agent did not return a parseable @interface block");
5848
+ }
5849
+ setIsGenerating(false);
5850
+ }).catch((err) => {
5851
+ if (cancelled) return;
5852
+ console.error("[AutoInterface] Initial generation failed:", err);
5853
+ _optionalChain([onError, 'optionalCall', _155 => _155(err instanceof Error ? err : new Error(String(err)))]);
5854
+ setIsGenerating(false);
5855
+ });
5856
+ return () => {
5857
+ cancelled = true;
5858
+ };
5859
+ }, [initialPrompt]);
5860
+ const hasInterface = interfaceSpec !== null;
5861
+ const showSkeleton = isGenerating && !hasInterface;
5862
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn(
5863
+ "flex h-full bg-neutral-50 dark:bg-black",
5864
+ chatPosition === "bottom" ? "flex-col" : "flex-row",
5865
+ className
5866
+ ), children: [
5867
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn(
5868
+ "flex-1 overflow-y-auto min-w-0",
5869
+ hasInterface || showSkeleton ? "" : "hidden"
5870
+ ), children: [
5871
+ showSkeleton && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InterfaceSkeleton, {}),
5872
+ hasInterface && interfaceSpec && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "p-4", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5873
+ InterfaceRenderer,
5874
+ {
5875
+ node: interfaceSpec.root,
5876
+ onAction: handleAction
5877
+ }
5878
+ ) })
5879
+ ] }),
5880
+ chatCollapsible && hasInterface && chatPosition === "right" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5881
+ "button",
5882
+ {
5883
+ onClick: () => setChatCollapsed(!chatCollapsed),
5884
+ className: "flex-shrink-0 w-6 flex items-center justify-center border-l border-neutral-200 dark:border-neutral-700 bg-neutral-100 dark:bg-neutral-800 hover:bg-neutral-200 dark:hover:bg-neutral-700 transition-colors",
5885
+ title: chatCollapsed ? "Show chat" : "Hide chat",
5886
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "!text-xs !text-neutral-500 dark:!text-neutral-400", children: chatCollapsed ? "\u25C0" : "\u25B6" })
5887
+ }
5888
+ ),
5889
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5890
+ "div",
5891
+ {
5892
+ className: cn(
5893
+ "flex-shrink-0 border-neutral-200 dark:border-neutral-700",
5894
+ chatPosition === "right" ? "border-l" : "border-t",
5895
+ chatCollapsed && "hidden",
5896
+ // When no interface is generated yet, chat takes full width
5897
+ !hasInterface && !showSkeleton && "flex-1"
5898
+ ),
5899
+ style: hasInterface || showSkeleton ? chatPosition === "right" ? { width: chatWidth } : { height: "300px" } : void 0,
5900
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5901
+ Chat,
5902
+ {
5903
+ ref: chatRef,
5904
+ agentId,
5905
+ threadId,
5906
+ apiUrl,
5907
+ apiKey,
5908
+ useMock,
5909
+ context: systemContext,
5910
+ placeholder: chatPlaceholder,
5911
+ welcomeTitle: chatWelcomeTitle,
5912
+ welcomeSubtitle: "Describe the interface you want to create",
5913
+ enableStreaming: true,
5914
+ enableWidgets: true,
5915
+ showHeader: true,
5916
+ headerTitle: "Chat",
5917
+ onThreadChange,
5918
+ onComplete: handleMessageComplete,
5919
+ onError,
5920
+ className: "h-full",
5921
+ suggestedPrompts: !hasInterface ? [
5922
+ "Show me a sales dashboard",
5923
+ "Create a user management panel",
5924
+ "Build a project overview page"
5925
+ ] : void 0
5926
+ }
5927
+ )
5928
+ }
5929
+ )
5930
+ ] });
5931
+ }
5932
+
5045
5933
  // src/utils/theme-script.ts
5046
5934
  var themeScript = `
5047
5935
  (function() {
@@ -5066,6 +5954,139 @@ function getThemeScript() {
5066
5954
  return themeScript;
5067
5955
  }
5068
5956
 
5957
+ // src/hooks/useInterfaceState.ts
5958
+
5959
+ function useInterfaceState(initialSpec) {
5960
+ const [spec, setSpec] = _react.useState.call(void 0, initialSpec || null);
5961
+ const [isStreaming, setIsStreaming] = _react.useState.call(void 0, false);
5962
+ const setInterface = _react.useCallback.call(void 0, (newSpec) => {
5963
+ setSpec(newSpec);
5964
+ }, []);
5965
+ const clearInterface = _react.useCallback.call(void 0, () => {
5966
+ setSpec(null);
5967
+ }, []);
5968
+ const applyInterfaceUpdate = _react.useCallback.call(void 0, (update) => {
5969
+ setSpec((prev) => {
5970
+ if (!prev) return prev;
5971
+ return applyUpdate(prev, update);
5972
+ });
5973
+ }, []);
5974
+ const applyInterfaceUpdates = _react.useCallback.call(void 0, (updates) => {
5975
+ setSpec((prev) => {
5976
+ if (!prev) return prev;
5977
+ return applyUpdates(prev, updates);
5978
+ });
5979
+ }, []);
5980
+ const getNode = _react.useCallback.call(void 0, (id) => {
5981
+ if (!spec) return null;
5982
+ return findNode(spec.root, id);
5983
+ }, [spec]);
5984
+ return {
5985
+ spec,
5986
+ isStreaming,
5987
+ setInterface,
5988
+ clearInterface,
5989
+ applyInterfaceUpdate,
5990
+ applyInterfaceUpdates,
5991
+ setIsStreaming,
5992
+ getNode
5993
+ };
5994
+ }
5995
+
5996
+ // src/hooks/useInterfaceAI.ts
5997
+
5998
+ function useInterfaceAI({
5999
+ agentId,
6000
+ apiUrl,
6001
+ apiKey,
6002
+ context,
6003
+ onInterface,
6004
+ onUpdates,
6005
+ onError,
6006
+ onStreamStart,
6007
+ onStreamEnd
6008
+ }) {
6009
+ const threadIdRef = _react.useRef.call(void 0, null);
6010
+ const accumulatedTextRef = _react.useRef.call(void 0, "");
6011
+ if (apiUrl || apiKey) {
6012
+ aptevaClient.configure({
6013
+ ...apiUrl && { apiUrl },
6014
+ ...apiKey && { apiKey }
6015
+ });
6016
+ }
6017
+ const sendMessage = _react.useCallback.call(void 0, async (message) => {
6018
+ accumulatedTextRef.current = "";
6019
+ _optionalChain([onStreamStart, 'optionalCall', _156 => _156()]);
6020
+ const systemPrompt = [
6021
+ generateInterfaceContext(),
6022
+ context || ""
6023
+ ].filter(Boolean).join("\n\n");
6024
+ try {
6025
+ await aptevaClient.chatStream(
6026
+ {
6027
+ agent_id: agentId,
6028
+ message,
6029
+ thread_id: threadIdRef.current || void 0,
6030
+ stream: true,
6031
+ system: systemPrompt
6032
+ },
6033
+ // onChunk
6034
+ (chunk) => {
6035
+ if (chunk.thread_id) {
6036
+ threadIdRef.current = chunk.thread_id;
6037
+ }
6038
+ if (chunk.type === "content" || chunk.type === "token") {
6039
+ accumulatedTextRef.current += chunk.content || "";
6040
+ const parsed = parseInterfaceFromText(accumulatedTextRef.current);
6041
+ if (parsed) {
6042
+ _optionalChain([onInterface, 'optionalCall', _157 => _157(parsed)]);
6043
+ }
6044
+ const updates = parseUpdatesFromText(accumulatedTextRef.current);
6045
+ if (updates.length > 0) {
6046
+ _optionalChain([onUpdates, 'optionalCall', _158 => _158(updates)]);
6047
+ }
6048
+ }
6049
+ },
6050
+ // onComplete
6051
+ () => {
6052
+ _optionalChain([onStreamEnd, 'optionalCall', _159 => _159()]);
6053
+ },
6054
+ // onError
6055
+ (error) => {
6056
+ _optionalChain([onError, 'optionalCall', _160 => _160(error)]);
6057
+ _optionalChain([onStreamEnd, 'optionalCall', _161 => _161()]);
6058
+ }
6059
+ );
6060
+ } catch (error) {
6061
+ _optionalChain([onError, 'optionalCall', _162 => _162(error instanceof Error ? error : new Error("Unknown error"))]);
6062
+ _optionalChain([onStreamEnd, 'optionalCall', _163 => _163()]);
6063
+ }
6064
+ }, [agentId, context, onInterface, onUpdates, onError, onStreamStart, onStreamEnd]);
6065
+ return {
6066
+ sendMessage,
6067
+ threadId: threadIdRef.current
6068
+ };
6069
+ }
6070
+
6071
+
6072
+
6073
+
6074
+
6075
+
6076
+
6077
+
6078
+
6079
+
6080
+
6081
+
6082
+
6083
+
6084
+
6085
+
6086
+
6087
+
6088
+
6089
+
5069
6090
 
5070
6091
 
5071
6092
 
@@ -5082,5 +6103,5 @@ function getThemeScript() {
5082
6103
 
5083
6104
 
5084
6105
 
5085
- exports.AptevaClient = AptevaClient; exports.Button = Button; exports.Card = Card; exports.Chat = Chat; exports.Command = Command; exports.List = List; exports.Prompt = Prompt; exports.Stream = Stream; exports.Threads = Threads; exports.Widgets = Widgets; exports.aptevaClient = aptevaClient; exports.cn = cn; exports.getThemeScript = getThemeScript; exports.mockMessages = mockMessages; exports.mockThreads = mockThreads; exports.mockWidgets = mockWidgets;
6106
+ exports.AptevaClient = AptevaClient; exports.AutoInterface = AutoInterface; exports.Button = Button; exports.Card = Card; exports.Chat = Chat; exports.Command = Command; exports.InterfaceRenderer = InterfaceRenderer; exports.InterfaceSkeleton = InterfaceSkeleton; exports.Kpi = Kpi; exports.LayoutRenderer = LayoutRenderer; exports.List = List; exports.Prompt = Prompt; exports.Spacer = Spacer; exports.Stream = Stream; exports.TextBlock = TextBlock; exports.Threads = Threads; exports.Widgets = Widgets; exports.applyUpdate = applyUpdate; exports.applyUpdates = applyUpdates; exports.aptevaClient = aptevaClient; exports.cn = cn; exports.containsInterface = containsInterface; exports.convertApiMessages = convertApiMessages; exports.findNode = findNode; exports.generateCompactInterfaceContext = generateCompactInterfaceContext; exports.generateInterfaceContext = generateInterfaceContext; exports.getThemeScript = getThemeScript; exports.mockMessages = mockMessages; exports.mockThreads = mockThreads; exports.mockWidgets = mockWidgets; exports.parseInterfaceFromText = parseInterfaceFromText; exports.parseUpdatesFromText = parseUpdatesFromText; exports.stripInterface = stripInterface; exports.useInterfaceAI = useInterfaceAI; exports.useInterfaceState = useInterfaceState;
5086
6107
  //# sourceMappingURL=index.js.map