@apteva/apteva-kit 0.1.102 → 0.1.104

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;
@@ -3217,7 +3683,7 @@ ${widgetContext}` : widgetContext;
3217
3683
  contentSegments.push({ type: "tool", id: chunk.tool_id, name: displayName, status: "preparing" });
3218
3684
  toolInputBuffers[chunk.tool_id] = "";
3219
3685
  setChatToolName(displayName);
3220
- _optionalChain([onToolCall, 'optionalCall', _76 => _76(chunk.tool_name, chunk.tool_id)]);
3686
+ _optionalChain([onToolCall, 'optionalCall', _79 => _79(chunk.tool_name, chunk.tool_id)]);
3221
3687
  updateMessage();
3222
3688
  }
3223
3689
  break;
@@ -3277,7 +3743,7 @@ ${widgetContext}` : widgetContext;
3277
3743
  toolSegment.result = chunk.content;
3278
3744
  toolSegment.status = "completed";
3279
3745
  toolSegment.isReceiving = false;
3280
- _optionalChain([onToolResult, 'optionalCall', _77 => _77(toolSegment.name, chunk.content)]);
3746
+ _optionalChain([onToolResult, 'optionalCall', _80 => _80(toolSegment.name, chunk.content)]);
3281
3747
  }
3282
3748
  setChatToolName(null);
3283
3749
  updateMessage();
@@ -3320,7 +3786,7 @@ ${widgetContext}` : widgetContext;
3320
3786
  });
3321
3787
  if (threadId2 && threadId2 !== currentThreadId) {
3322
3788
  setCurrentThreadId(threadId2);
3323
- _optionalChain([onThreadChange, 'optionalCall', _78 => _78(threadId2)]);
3789
+ _optionalChain([onThreadChange, 'optionalCall', _81 => _81(threadId2)]);
3324
3790
  }
3325
3791
  setIsLoading(false);
3326
3792
  setCurrentRequestId(null);
@@ -3344,7 +3810,7 @@ ${widgetContext}` : widgetContext;
3344
3810
  setIsLoading(false);
3345
3811
  setCurrentRequestId(null);
3346
3812
  setChatToolName(null);
3347
- _optionalChain([onError, 'optionalCall', _79 => _79(error)]);
3813
+ _optionalChain([onError, 'optionalCall', _82 => _82(error)]);
3348
3814
  }
3349
3815
  );
3350
3816
  }
@@ -3357,7 +3823,7 @@ ${widgetContext}` : widgetContext;
3357
3823
  metadata: { error: true }
3358
3824
  };
3359
3825
  setMessages((prev) => [...prev, errorMessage]);
3360
- _optionalChain([onError, 'optionalCall', _80 => _80(error instanceof Error ? error : new Error("Unknown error"))]);
3826
+ _optionalChain([onError, 'optionalCall', _83 => _83(error instanceof Error ? error : new Error("Unknown error"))]);
3361
3827
  } finally {
3362
3828
  setIsLoading(false);
3363
3829
  }
@@ -3403,7 +3869,7 @@ ${planningInstruction}` : planningInstruction;
3403
3869
  const error = err instanceof Error ? err : new Error("Failed to generate plan");
3404
3870
  setCommandError(error);
3405
3871
  setCommandState("error");
3406
- _optionalChain([onError, 'optionalCall', _81 => _81(error)]);
3872
+ _optionalChain([onError, 'optionalCall', _84 => _84(error)]);
3407
3873
  }
3408
3874
  }
3409
3875
  return;
@@ -3436,12 +3902,12 @@ ${planningInstruction}` : planningInstruction;
3436
3902
  setCommandResult(result);
3437
3903
  setCommandState("success");
3438
3904
  setProgress(100);
3439
- _optionalChain([onComplete, 'optionalCall', _82 => _82(result)]);
3905
+ _optionalChain([onComplete, 'optionalCall', _85 => _85(result)]);
3440
3906
  },
3441
3907
  (error) => {
3442
3908
  setCommandError(error);
3443
3909
  setCommandState("error");
3444
- _optionalChain([onError, 'optionalCall', _83 => _83(error)]);
3910
+ _optionalChain([onError, 'optionalCall', _86 => _86(error)]);
3445
3911
  }
3446
3912
  );
3447
3913
  } else {
@@ -3454,7 +3920,7 @@ ${planningInstruction}` : planningInstruction;
3454
3920
  setCommandResult(result);
3455
3921
  setCommandState("success");
3456
3922
  setProgress(100);
3457
- _optionalChain([onComplete, 'optionalCall', _84 => _84(result)]);
3923
+ _optionalChain([onComplete, 'optionalCall', _87 => _87(result)]);
3458
3924
  }
3459
3925
  } else {
3460
3926
  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 +3950,16 @@ ${commandInstruction}` : commandInstruction;
3484
3950
  const displayName = chunk.tool_display_name || chunk.tool_name;
3485
3951
  lastToolName = chunk.tool_name;
3486
3952
  setCurrentToolName(displayName);
3487
- _optionalChain([onToolCall, 'optionalCall', _85 => _85(chunk.tool_name, chunk.tool_id || "")]);
3953
+ _optionalChain([onToolCall, 'optionalCall', _88 => _88(chunk.tool_name, chunk.tool_id || "")]);
3488
3954
  accumulatedContent = "";
3489
3955
  setStreamedContent("");
3490
3956
  } else if (chunk.type === "tool_result") {
3491
- _optionalChain([onToolResult, 'optionalCall', _86 => _86(lastToolName, chunk.content)]);
3957
+ _optionalChain([onToolResult, 'optionalCall', _89 => _89(lastToolName, chunk.content)]);
3492
3958
  setCurrentToolName(null);
3493
3959
  } else if (chunk.type === "thread_id" && chunk.thread_id) {
3494
3960
  if (!currentThreadId) {
3495
3961
  setCurrentThreadId(chunk.thread_id);
3496
- _optionalChain([onThreadChange, 'optionalCall', _87 => _87(chunk.thread_id)]);
3962
+ _optionalChain([onThreadChange, 'optionalCall', _90 => _90(chunk.thread_id)]);
3497
3963
  }
3498
3964
  } else if (chunk.type === "request_id" && chunk.request_id) {
3499
3965
  setCurrentRequestId(chunk.request_id);
@@ -3509,13 +3975,13 @@ ${commandInstruction}` : commandInstruction;
3509
3975
  setCommandState("success");
3510
3976
  setProgress(100);
3511
3977
  setCurrentRequestId(null);
3512
- _optionalChain([onComplete, 'optionalCall', _88 => _88(result)]);
3978
+ _optionalChain([onComplete, 'optionalCall', _91 => _91(result)]);
3513
3979
  },
3514
3980
  (error) => {
3515
3981
  setCommandError(error);
3516
3982
  setCommandState("error");
3517
3983
  setCurrentRequestId(null);
3518
- _optionalChain([onError, 'optionalCall', _89 => _89(error)]);
3984
+ _optionalChain([onError, 'optionalCall', _92 => _92(error)]);
3519
3985
  }
3520
3986
  );
3521
3987
  } else {
@@ -3535,14 +4001,14 @@ ${commandInstruction}` : commandInstruction;
3535
4001
  setCommandResult(result);
3536
4002
  setCommandState("success");
3537
4003
  setProgress(100);
3538
- _optionalChain([onComplete, 'optionalCall', _90 => _90(result)]);
4004
+ _optionalChain([onComplete, 'optionalCall', _93 => _93(result)]);
3539
4005
  }
3540
4006
  }
3541
4007
  } catch (err) {
3542
4008
  const error = err instanceof Error ? err : new Error("Unknown error");
3543
4009
  setCommandError(error);
3544
4010
  setCommandState("error");
3545
- _optionalChain([onError, 'optionalCall', _91 => _91(error)]);
4011
+ _optionalChain([onError, 'optionalCall', _94 => _94(error)]);
3546
4012
  }
3547
4013
  };
3548
4014
  const resetCommand = () => {
@@ -3590,12 +4056,15 @@ ${planToExecute}`;
3590
4056
  };
3591
4057
  const isCompact = commandVariant === "compact";
3592
4058
  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" })
4059
+ 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: [
4060
+ 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" }) }) }),
4061
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
4062
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-chat-title", children: headerTitle }),
4063
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn(
4064
+ "apteva-chat-status",
4065
+ isLoading ? chatToolName ? "apteva-chat-status-tool" : "apteva-chat-status-thinking" : "apteva-chat-status-ready"
4066
+ ), children: isLoading ? chatToolName ? `Using ${chatToolName}...` : "Thinking..." : "Ready" })
4067
+ ] })
3599
4068
  ] }) }),
3600
4069
  mode === "chat" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
3601
4070
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -3635,8 +4104,8 @@ ${planToExecute}`;
3635
4104
  executeCommand(text, files);
3636
4105
  },
3637
4106
  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]),
4107
+ response: _optionalChain([commandResult, 'optionalAccess', _95 => _95.data, 'optionalAccess', _96 => _96.summary]) || _optionalChain([commandResult, 'optionalAccess', _97 => _97.message]),
4108
+ error: _optionalChain([commandError, 'optionalAccess', _98 => _98.message]),
3640
4109
  plan,
3641
4110
  streamedContent,
3642
4111
  toolName: currentToolName,
@@ -3804,13 +4273,13 @@ ${planningInstruction}` : planningInstruction;
3804
4273
  const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
3805
4274
  setError(error2);
3806
4275
  setState("error");
3807
- _optionalChain([onError, 'optionalCall', _96 => _96(error2)]);
4276
+ _optionalChain([onError, 'optionalCall', _99 => _99(error2)]);
3808
4277
  });
3809
4278
  } catch (err) {
3810
4279
  const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
3811
4280
  setError(error2);
3812
4281
  setState("error");
3813
- _optionalChain([onError, 'optionalCall', _97 => _97(error2)]);
4282
+ _optionalChain([onError, 'optionalCall', _100 => _100(error2)]);
3814
4283
  }
3815
4284
  }
3816
4285
  return;
@@ -3821,7 +4290,7 @@ ${planningInstruction}` : planningInstruction;
3821
4290
  setStreamedContent("");
3822
4291
  setCommand("");
3823
4292
  setUploadedFiles([]);
3824
- _optionalChain([onStart, 'optionalCall', _98 => _98()]);
4293
+ _optionalChain([onStart, 'optionalCall', _101 => _101()]);
3825
4294
  try {
3826
4295
  if (useMock) {
3827
4296
  if (enableStreaming) {
@@ -3832,16 +4301,16 @@ ${planningInstruction}` : planningInstruction;
3832
4301
  if (chunk.type === "token" && chunk.content) {
3833
4302
  accumulatedContent += chunk.content;
3834
4303
  setStreamedContent(accumulatedContent);
3835
- _optionalChain([onChunk, 'optionalCall', _99 => _99(chunk.content)]);
4304
+ _optionalChain([onChunk, 'optionalCall', _102 => _102(chunk.content)]);
3836
4305
  const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
3837
4306
  setProgress(estimatedProgress);
3838
- _optionalChain([onProgress, 'optionalCall', _100 => _100(estimatedProgress)]);
4307
+ _optionalChain([onProgress, 'optionalCall', _103 => _103(estimatedProgress)]);
3839
4308
  } else if (chunk.type === "widget" && chunk.widget) {
3840
4309
  const widget = chunk.widget;
3841
4310
  setResult((prev) => ({
3842
4311
  success: true,
3843
- data: _optionalChain([prev, 'optionalAccess', _101 => _101.data]) || {},
3844
- widgets: [..._optionalChain([prev, 'optionalAccess', _102 => _102.widgets]) || [], widget],
4312
+ data: _optionalChain([prev, 'optionalAccess', _104 => _104.data]) || {},
4313
+ widgets: [..._optionalChain([prev, 'optionalAccess', _105 => _105.widgets]) || [], widget],
3845
4314
  message: accumulatedContent || "Command executed successfully"
3846
4315
  }));
3847
4316
  }
@@ -3861,19 +4330,19 @@ ${planningInstruction}` : planningInstruction;
3861
4330
  setResult(result2);
3862
4331
  setState("success");
3863
4332
  setProgress(100);
3864
- _optionalChain([onComplete, 'optionalCall', _103 => _103(result2)]);
4333
+ _optionalChain([onComplete, 'optionalCall', _106 => _106(result2)]);
3865
4334
  },
3866
4335
  (error2) => {
3867
4336
  setError(error2);
3868
4337
  setState("error");
3869
- _optionalChain([onError, 'optionalCall', _104 => _104(error2)]);
4338
+ _optionalChain([onError, 'optionalCall', _107 => _107(error2)]);
3870
4339
  }
3871
4340
  );
3872
4341
  } else {
3873
4342
  const progressInterval = setInterval(() => {
3874
4343
  setProgress((prev) => {
3875
4344
  const next = Math.min(prev + 10, 90);
3876
- _optionalChain([onProgress, 'optionalCall', _105 => _105(next)]);
4345
+ _optionalChain([onProgress, 'optionalCall', _108 => _108(next)]);
3877
4346
  return next;
3878
4347
  });
3879
4348
  }, 200);
@@ -3897,7 +4366,7 @@ ${planningInstruction}` : planningInstruction;
3897
4366
  setResult(result2);
3898
4367
  setState("success");
3899
4368
  setProgress(100);
3900
- _optionalChain([onComplete, 'optionalCall', _106 => _106(result2)]);
4369
+ _optionalChain([onComplete, 'optionalCall', _109 => _109(result2)]);
3901
4370
  }
3902
4371
  } else {
3903
4372
  if (enableStreaming) {
@@ -3943,16 +4412,16 @@ ${commandInstruction}` : commandInstruction;
3943
4412
  if (chunk.type === "token" && chunk.content) {
3944
4413
  accumulatedContent += chunk.content;
3945
4414
  setStreamedContent(accumulatedContent);
3946
- _optionalChain([onChunk, 'optionalCall', _107 => _107(chunk.content)]);
4415
+ _optionalChain([onChunk, 'optionalCall', _110 => _110(chunk.content)]);
3947
4416
  const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
3948
4417
  setProgress(estimatedProgress);
3949
- _optionalChain([onProgress, 'optionalCall', _108 => _108(estimatedProgress)]);
4418
+ _optionalChain([onProgress, 'optionalCall', _111 => _111(estimatedProgress)]);
3950
4419
  } else if (chunk.type === "widget" && chunk.widget) {
3951
4420
  const widget = chunk.widget;
3952
4421
  setResult((prev) => ({
3953
4422
  success: true,
3954
- data: _optionalChain([prev, 'optionalAccess', _109 => _109.data]) || {},
3955
- widgets: [..._optionalChain([prev, 'optionalAccess', _110 => _110.widgets]) || [], widget],
4423
+ data: _optionalChain([prev, 'optionalAccess', _112 => _112.data]) || {},
4424
+ widgets: [..._optionalChain([prev, 'optionalAccess', _113 => _113.widgets]) || [], widget],
3956
4425
  message: accumulatedContent || "Command executed successfully"
3957
4426
  }));
3958
4427
  }
@@ -3972,20 +4441,20 @@ ${commandInstruction}` : commandInstruction;
3972
4441
  setResult(result2);
3973
4442
  setState("success");
3974
4443
  setProgress(100);
3975
- _optionalChain([onComplete, 'optionalCall', _111 => _111(result2)]);
4444
+ _optionalChain([onComplete, 'optionalCall', _114 => _114(result2)]);
3976
4445
  },
3977
4446
  (error2) => {
3978
4447
  const err = error2 instanceof Error ? error2 : new Error("Unknown error");
3979
4448
  setError(err);
3980
4449
  setState("error");
3981
- _optionalChain([onError, 'optionalCall', _112 => _112(err)]);
4450
+ _optionalChain([onError, 'optionalCall', _115 => _115(err)]);
3982
4451
  }
3983
4452
  );
3984
4453
  } else {
3985
4454
  const progressInterval = setInterval(() => {
3986
4455
  setProgress((prev) => {
3987
4456
  const next = Math.min(prev + 10, 90);
3988
- _optionalChain([onProgress, 'optionalCall', _113 => _113(next)]);
4457
+ _optionalChain([onProgress, 'optionalCall', _116 => _116(next)]);
3989
4458
  return next;
3990
4459
  });
3991
4460
  }, 200);
@@ -4041,14 +4510,14 @@ ${commandInstruction}` : commandInstruction;
4041
4510
  setResult(result2);
4042
4511
  setState("success");
4043
4512
  setProgress(100);
4044
- _optionalChain([onComplete, 'optionalCall', _114 => _114(result2)]);
4513
+ _optionalChain([onComplete, 'optionalCall', _117 => _117(result2)]);
4045
4514
  }
4046
4515
  }
4047
4516
  } catch (err) {
4048
4517
  const error2 = err instanceof Error ? err : new Error("Unknown error");
4049
4518
  setError(error2);
4050
4519
  setState("error");
4051
- _optionalChain([onError, 'optionalCall', _115 => _115(error2)]);
4520
+ _optionalChain([onError, 'optionalCall', _118 => _118(error2)]);
4052
4521
  }
4053
4522
  };
4054
4523
  const resetCommand = () => {
@@ -4081,14 +4550,14 @@ ${planToExecute}`;
4081
4550
  };
4082
4551
  const handleFileSelect = async (e) => {
4083
4552
  if (e.target.files && e.target.files.length > 0) {
4084
- _optionalChain([onFileUpload, 'optionalCall', _116 => _116(e.target.files)]);
4553
+ _optionalChain([onFileUpload, 'optionalCall', _119 => _119(e.target.files)]);
4085
4554
  const files = [];
4086
4555
  for (let i = 0; i < e.target.files.length; i++) {
4087
4556
  const file = e.target.files[i];
4088
4557
  const reader = new FileReader();
4089
4558
  await new Promise((resolve) => {
4090
4559
  reader.onload = (event) => {
4091
- if (_optionalChain([event, 'access', _117 => _117.target, 'optionalAccess', _118 => _118.result])) {
4560
+ if (_optionalChain([event, 'access', _120 => _120.target, 'optionalAccess', _121 => _121.result])) {
4092
4561
  const fullDataUrl = event.target.result;
4093
4562
  const base64Data = fullDataUrl.split(",")[1];
4094
4563
  if (file.type.startsWith("image/")) {
@@ -4182,7 +4651,7 @@ ${planToExecute}`;
4182
4651
  enableFileUpload && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4183
4652
  "button",
4184
4653
  {
4185
- onClick: () => _optionalChain([fileInputRef, 'access', _119 => _119.current, 'optionalAccess', _120 => _120.click, 'call', _121 => _121()]),
4654
+ onClick: () => _optionalChain([fileInputRef, 'access', _122 => _122.current, 'optionalAccess', _123 => _123.click, 'call', _124 => _124()]),
4186
4655
  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
4656
  title: "Attach file",
4188
4657
  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 +4870,7 @@ ${planToExecute}`;
4401
4870
  /* @__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
4871
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
4403
4872
  /* @__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]) })
4873
+ /* @__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
4874
  ] })
4406
4875
  ] }) }),
4407
4876
  allowInput && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -4429,7 +4898,7 @@ ${planToExecute}`;
4429
4898
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-green-700 dark:text-green-300 text-sm", children: "Command executed successfully" })
4430
4899
  ] })
4431
4900
  ] }),
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 }),
4901
+ _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
4902
  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
4903
  WidgetRenderer,
4435
4904
  {
@@ -4480,7 +4949,7 @@ ${planToExecute}`;
4480
4949
  enableFileUpload && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4481
4950
  "button",
4482
4951
  {
4483
- onClick: () => _optionalChain([fileInputRef, 'access', _125 => _125.current, 'optionalAccess', _126 => _126.click, 'call', _127 => _127()]),
4952
+ onClick: () => _optionalChain([fileInputRef, 'access', _128 => _128.current, 'optionalAccess', _129 => _129.click, 'call', _130 => _130()]),
4484
4953
  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
4954
  title: "Attach file",
4486
4955
  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 +5135,25 @@ function Prompt({
4666
5135
  const newValue = e.target.value;
4667
5136
  if (!maxLength || newValue.length <= maxLength) {
4668
5137
  setValue(newValue);
4669
- _optionalChain([onChange, 'optionalCall', _128 => _128(newValue)]);
5138
+ _optionalChain([onChange, 'optionalCall', _131 => _131(newValue)]);
4670
5139
  }
4671
5140
  };
4672
5141
  const handleSubmit = async () => {
4673
5142
  if (value.length < minLength) return;
4674
- _optionalChain([onSubmit, 'optionalCall', _129 => _129(value)]);
5143
+ _optionalChain([onSubmit, 'optionalCall', _132 => _132(value)]);
4675
5144
  setIsLoading(true);
4676
5145
  try {
4677
5146
  if (useMock) {
4678
5147
  await new Promise((resolve) => setTimeout(resolve, 1500));
4679
5148
  const mockResult = `Enhanced version: ${value} [AI-generated content]`;
4680
- _optionalChain([onResult, 'optionalCall', _130 => _130(mockResult)]);
5149
+ _optionalChain([onResult, 'optionalCall', _133 => _133(mockResult)]);
4681
5150
  setValue("");
4682
5151
  } else {
4683
5152
  const response = await aptevaClient.chat({
4684
5153
  agent_id: agentId,
4685
5154
  message: value
4686
5155
  });
4687
- _optionalChain([onResult, 'optionalCall', _131 => _131(response.message)]);
5156
+ _optionalChain([onResult, 'optionalCall', _134 => _134(response.message)]);
4688
5157
  setValue("");
4689
5158
  }
4690
5159
  } catch (error) {
@@ -4779,7 +5248,7 @@ function Stream({
4779
5248
  }, [autoStart]);
4780
5249
  const startStreaming = async () => {
4781
5250
  setIsStreaming(true);
4782
- _optionalChain([onStart, 'optionalCall', _132 => _132()]);
5251
+ _optionalChain([onStart, 'optionalCall', _135 => _135()]);
4783
5252
  try {
4784
5253
  if (useMock) {
4785
5254
  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 +5256,13 @@ function Stream({
4787
5256
  mockText,
4788
5257
  (chunk) => {
4789
5258
  setText((prev) => prev + chunk);
4790
- _optionalChain([onChunk, 'optionalCall', _133 => _133(chunk)]);
5259
+ _optionalChain([onChunk, 'optionalCall', _136 => _136(chunk)]);
4791
5260
  },
4792
5261
  typingSpeed
4793
5262
  );
4794
5263
  setIsComplete(true);
4795
5264
  setIsStreaming(false);
4796
- _optionalChain([onComplete, 'optionalCall', _134 => _134(text + mockText)]);
5265
+ _optionalChain([onComplete, 'optionalCall', _137 => _137(text + mockText)]);
4797
5266
  } else {
4798
5267
  let accumulatedText = "";
4799
5268
  await aptevaClient.chatStream(
@@ -4806,24 +5275,24 @@ function Stream({
4806
5275
  if (chunk.type === "token" && chunk.content) {
4807
5276
  accumulatedText += chunk.content;
4808
5277
  setText(accumulatedText);
4809
- _optionalChain([onChunk, 'optionalCall', _135 => _135(chunk.content)]);
5278
+ _optionalChain([onChunk, 'optionalCall', _138 => _138(chunk.content)]);
4810
5279
  }
4811
5280
  },
4812
5281
  () => {
4813
5282
  setIsComplete(true);
4814
5283
  setIsStreaming(false);
4815
- _optionalChain([onComplete, 'optionalCall', _136 => _136(accumulatedText)]);
5284
+ _optionalChain([onComplete, 'optionalCall', _139 => _139(accumulatedText)]);
4816
5285
  },
4817
5286
  (error) => {
4818
5287
  const err = error instanceof Error ? error : new Error("Streaming error");
4819
- _optionalChain([onError, 'optionalCall', _137 => _137(err)]);
5288
+ _optionalChain([onError, 'optionalCall', _140 => _140(err)]);
4820
5289
  setIsStreaming(false);
4821
5290
  }
4822
5291
  );
4823
5292
  }
4824
5293
  } catch (error) {
4825
5294
  const err = error instanceof Error ? error : new Error("Streaming error");
4826
- _optionalChain([onError, 'optionalCall', _138 => _138(err)]);
5295
+ _optionalChain([onError, 'optionalCall', _141 => _141(err)]);
4827
5296
  setIsStreaming(false);
4828
5297
  }
4829
5298
  };
@@ -4915,7 +5384,7 @@ function ThreadList({
4915
5384
  }) {
4916
5385
  const [searchQuery, setSearchQuery] = _react.useState.call(void 0, "");
4917
5386
  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())])
5387
+ (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
5388
  );
4920
5389
  const groupedThreads = groupBy === "date" ? groupThreadsByDate(filteredThreads) : { All: filteredThreads };
4921
5390
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col h-full", children: [
@@ -4937,8 +5406,8 @@ function ThreadList({
4937
5406
  {
4938
5407
  thread,
4939
5408
  isActive: thread.id === currentThreadId,
4940
- onSelect: () => _optionalChain([onThreadSelect, 'optionalCall', _144 => _144(thread.id)]),
4941
- onDelete: () => _optionalChain([onThreadDelete, 'optionalCall', _145 => _145(thread.id)])
5409
+ onSelect: () => _optionalChain([onThreadSelect, 'optionalCall', _147 => _147(thread.id)]),
5410
+ onDelete: () => _optionalChain([onThreadDelete, 'optionalCall', _148 => _148(thread.id)])
4942
5411
  },
4943
5412
  thread.id
4944
5413
  ))
@@ -5000,7 +5469,7 @@ function Threads({
5000
5469
  threads.slice(0, 5).map((thread) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5001
5470
  "button",
5002
5471
  {
5003
- onClick: () => _optionalChain([onThreadSelect, 'optionalCall', _146 => _146(thread.id)]),
5472
+ onClick: () => _optionalChain([onThreadSelect, 'optionalCall', _149 => _149(thread.id)]),
5004
5473
  className: cn(
5005
5474
  "px-4 py-2 whitespace-nowrap font-medium transition-colors",
5006
5475
  thread.id === currentThreadId ? "border-b-2 border-apteva-500 text-apteva-500" : "text-neutral-600 hover:text-neutral-900"
@@ -5042,6 +5511,418 @@ function Threads({
5042
5511
  ] });
5043
5512
  }
5044
5513
 
5514
+ // src/components/AutoInterface/AutoInterface.tsx
5515
+
5516
+
5517
+ // src/components/AutoInterface/LayoutRenderer.tsx
5518
+
5519
+
5520
+ var gapClasses = {
5521
+ none: "gap-0",
5522
+ sm: "gap-2",
5523
+ md: "gap-4",
5524
+ lg: "gap-6"
5525
+ };
5526
+ var paddingClasses = {
5527
+ none: "p-0",
5528
+ sm: "p-2",
5529
+ md: "p-4",
5530
+ lg: "p-6"
5531
+ };
5532
+ var maxWidthClasses = {
5533
+ sm: "max-w-2xl",
5534
+ md: "max-w-4xl",
5535
+ lg: "max-w-6xl",
5536
+ xl: "max-w-7xl",
5537
+ full: "max-w-full"
5538
+ };
5539
+ function LayoutRenderer({ node, onAction, renderNode }) {
5540
+ const children = node.children || [];
5541
+ switch (node.layout) {
5542
+ case "page":
5543
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PageLayout, { node, renderNode });
5544
+ case "row":
5545
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RowLayout, { node, renderNode });
5546
+ case "columns":
5547
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ColumnsLayout, { node, renderNode });
5548
+ case "stack":
5549
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, StackLayout, { node, renderNode });
5550
+ case "sidebar":
5551
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SidebarLayout, { node, renderNode });
5552
+ case "tabs":
5553
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabsLayout, { node, renderNode });
5554
+ default:
5555
+ 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)) });
5556
+ }
5557
+ }
5558
+ function PageLayout({ node, renderNode }) {
5559
+ const { title, padding = "md", maxWidth = "xl" } = node.props || {};
5560
+ const children = node.children || [];
5561
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("w-full mx-auto", paddingClasses[padding], maxWidthClasses[maxWidth]), children: [
5562
+ title && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h1", { className: "!text-2xl font-bold !text-neutral-900 dark:!text-white mb-6", children: title }),
5563
+ /* @__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)) })
5564
+ ] });
5565
+ }
5566
+ function RowLayout({ node, renderNode }) {
5567
+ const { columns, gap = "md", align = "stretch" } = node.props || {};
5568
+ const children = node.children || [];
5569
+ const templateColumns = columns ? columns.map((c) => `${c}fr`).join(" ") : `repeat(${children.length}, 1fr)`;
5570
+ const alignClasses = {
5571
+ start: "items-start",
5572
+ center: "items-center",
5573
+ end: "items-end",
5574
+ stretch: "items-stretch"
5575
+ };
5576
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5577
+ "div",
5578
+ {
5579
+ className: cn("grid", gapClasses[gap], alignClasses[align]),
5580
+ style: { gridTemplateColumns: templateColumns },
5581
+ children: children.map((child) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: renderNode(child) }, child.id))
5582
+ }
5583
+ );
5584
+ }
5585
+ function ColumnsLayout({ node, renderNode }) {
5586
+ const { count, gap = "md" } = node.props || {};
5587
+ const children = node.children || [];
5588
+ const colCount = count || children.length;
5589
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5590
+ "div",
5591
+ {
5592
+ className: cn("grid", gapClasses[gap]),
5593
+ style: { gridTemplateColumns: `repeat(${colCount}, 1fr)` },
5594
+ children: children.map((child) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: renderNode(child) }, child.id))
5595
+ }
5596
+ );
5597
+ }
5598
+ function StackLayout({ node, renderNode }) {
5599
+ const { gap = "md", align = "stretch" } = node.props || {};
5600
+ const children = node.children || [];
5601
+ const alignClasses = {
5602
+ left: "items-start",
5603
+ center: "items-center",
5604
+ right: "items-end",
5605
+ stretch: "items-stretch"
5606
+ };
5607
+ 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)) });
5608
+ }
5609
+ function SidebarLayout({ node, renderNode }) {
5610
+ const { side = "left", width = "280px" } = node.props || {};
5611
+ const children = node.children || [];
5612
+ const [sidebarChild, ...mainChildren] = side === "left" ? children : [...children].reverse();
5613
+ if (!sidebarChild) return null;
5614
+ const sidebar = /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5615
+ "div",
5616
+ {
5617
+ className: "flex-shrink-0 overflow-y-auto border-neutral-200 dark:border-neutral-700",
5618
+ style: { width },
5619
+ children: renderNode(sidebarChild)
5620
+ }
5621
+ );
5622
+ 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)) });
5623
+ 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: [
5624
+ sidebar,
5625
+ main
5626
+ ] }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5627
+ main,
5628
+ sidebar
5629
+ ] }) });
5630
+ }
5631
+ function TabsLayout({ node, renderNode }) {
5632
+ const { labels = [], defaultTab = 0 } = node.props || {};
5633
+ const children = node.children || [];
5634
+ const [activeTab, setActiveTab] = _react.useState.call(void 0, defaultTab);
5635
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
5636
+ /* @__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,
5637
+ "button",
5638
+ {
5639
+ onClick: () => setActiveTab(idx),
5640
+ className: cn(
5641
+ "px-4 py-2 !text-sm font-medium transition-colors border-b-2 -mb-px",
5642
+ 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"
5643
+ ),
5644
+ children: label
5645
+ },
5646
+ idx
5647
+ )) }),
5648
+ children[activeTab] && renderNode(children[activeTab])
5649
+ ] });
5650
+ }
5651
+
5652
+ // src/components/AutoInterface/InterfaceRenderer.tsx
5653
+
5654
+ var STRUCTURAL_KEYS = /* @__PURE__ */ new Set(["type", "id", "layout", "props", "children", "actions", "metadata", "isStreaming"]);
5655
+ function normalizeNode(n) {
5656
+ let node = { ...n };
5657
+ if (node.type === "widget" && _optionalChain([node, 'access', _150 => _150.props, 'optionalAccess', _151 => _151.widget])) {
5658
+ node.type = node.props.widget;
5659
+ const { widget: _, ...rest } = node.props;
5660
+ node.props = rest;
5661
+ }
5662
+ const explicit = node.props || {};
5663
+ const extra = {};
5664
+ for (const key of Object.keys(node)) {
5665
+ if (!STRUCTURAL_KEYS.has(key)) {
5666
+ extra[key] = node[key];
5667
+ }
5668
+ }
5669
+ node.props = { ...extra, ...explicit };
5670
+ if (node.props.style && !node.props.variant) {
5671
+ node.props.variant = node.props.style;
5672
+ delete node.props.style;
5673
+ }
5674
+ if (node.children) {
5675
+ node.children = node.children.map(normalizeNode);
5676
+ }
5677
+ return node;
5678
+ }
5679
+ function InterfaceRenderer({ node, onAction }) {
5680
+ const renderNode = (rawNode) => {
5681
+ const n = normalizeNode(rawNode);
5682
+ if (n.type === "layout" && n.layout) {
5683
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5684
+ LayoutRenderer,
5685
+ {
5686
+ node: n,
5687
+ onAction,
5688
+ renderNode
5689
+ },
5690
+ n.id
5691
+ );
5692
+ }
5693
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5694
+ WidgetRenderer,
5695
+ {
5696
+ widget: {
5697
+ type: n.type,
5698
+ id: n.id,
5699
+ props: n.props || {},
5700
+ actions: n.actions,
5701
+ metadata: n.metadata,
5702
+ isStreaming: n.isStreaming
5703
+ },
5704
+ onAction
5705
+ },
5706
+ n.id
5707
+ );
5708
+ };
5709
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: renderNode(node) });
5710
+ }
5711
+
5712
+ // src/components/AutoInterface/InterfaceSkeleton.tsx
5713
+
5714
+ function InterfaceSkeleton({ className }) {
5715
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("animate-pulse space-y-6 p-6", className), children: [
5716
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-7 bg-neutral-200 dark:bg-neutral-700 rounded w-1/3" }),
5717
+ /* @__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: [
5718
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-neutral-200 dark:bg-neutral-700 rounded w-2/3" }),
5719
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-8 bg-neutral-200 dark:bg-neutral-700 rounded w-1/2" })
5720
+ ] }, i)) }),
5721
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "grid grid-cols-3 gap-4", children: [
5722
+ /* @__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: [
5723
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-neutral-200 dark:bg-neutral-700 rounded w-1/4" }),
5724
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-40 bg-neutral-200 dark:bg-neutral-700 rounded" })
5725
+ ] }),
5726
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "border border-neutral-200 dark:border-neutral-700 rounded-xl p-5 space-y-3", children: [
5727
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-neutral-200 dark:bg-neutral-700 rounded w-1/2" }),
5728
+ [1, 2, 3].map((i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-10 bg-neutral-200 dark:bg-neutral-700 rounded" }, i))
5729
+ ] })
5730
+ ] })
5731
+ ] });
5732
+ }
5733
+
5734
+ // src/components/AutoInterface/AutoInterface.tsx
5735
+
5736
+ async function generateInitialInterface(apiUrl, apiKey, agentId, prompt) {
5737
+ const systemContext = generateCompactInterfaceContext();
5738
+ const message = `${systemContext}
5739
+
5740
+ Generate an interface for: ${prompt}`;
5741
+ const headers = { "Content-Type": "application/json" };
5742
+ if (apiKey) headers["X-API-Key"] = apiKey;
5743
+ const response = await fetch(`${apiUrl}/chat`, {
5744
+ method: "POST",
5745
+ headers,
5746
+ body: JSON.stringify({
5747
+ agent_id: agentId,
5748
+ message,
5749
+ stream: false
5750
+ })
5751
+ });
5752
+ if (!response.ok) {
5753
+ const err = await response.json().catch(() => ({ error: "Request failed" }));
5754
+ throw new Error(err.error || `Request failed with status ${response.status}`);
5755
+ }
5756
+ const data = await response.json();
5757
+ const text = data.response || data.message || "";
5758
+ console.log("[AutoInterface] Raw API response:", data);
5759
+ console.log("[AutoInterface] Extracted text (" + text.length + " chars):", text.substring(0, 500));
5760
+ const spec = parseInterfaceFromText(text);
5761
+ console.log("[AutoInterface] Parsed spec:", spec ? "OK" : "null", spec ? JSON.stringify(spec).substring(0, 300) + "..." : "");
5762
+ return { spec, threadId: data.thread_id || null };
5763
+ }
5764
+ function AutoInterface({
5765
+ agentId,
5766
+ threadId,
5767
+ initialPrompt,
5768
+ initialInterface,
5769
+ context,
5770
+ apiUrl,
5771
+ apiKey,
5772
+ onInterfaceChange,
5773
+ onAction,
5774
+ onThreadChange,
5775
+ onError,
5776
+ chatPosition = "right",
5777
+ chatWidth = "380px",
5778
+ chatCollapsible = true,
5779
+ chatPlaceholder = "Ask the AI to generate or update the interface...",
5780
+ chatWelcomeTitle = "Auto Interface",
5781
+ useMock,
5782
+ theme,
5783
+ className
5784
+ }) {
5785
+ const [interfaceSpec, setInterfaceSpec] = _react.useState.call(void 0, initialInterface || null);
5786
+ const [isGenerating, setIsGenerating] = _react.useState.call(void 0, false);
5787
+ const [chatCollapsed, setChatCollapsed] = _react.useState.call(void 0, false);
5788
+ const chatRef = _react.useRef.call(void 0, null);
5789
+ const systemContext = [
5790
+ generateInterfaceContext(),
5791
+ context || ""
5792
+ ].filter(Boolean).join("\n\n");
5793
+ const updateInterface = _react.useCallback.call(void 0, (newSpec) => {
5794
+ setInterfaceSpec(newSpec);
5795
+ _optionalChain([onInterfaceChange, 'optionalCall', _152 => _152(newSpec)]);
5796
+ }, [onInterfaceChange]);
5797
+ const handleAction = _react.useCallback.call(void 0, (action) => {
5798
+ _optionalChain([onAction, 'optionalCall', _153 => _153(action)]);
5799
+ if (chatRef.current) {
5800
+ chatRef.current.sendMessage(
5801
+ `[Action: ${action.type} on widget ${action.widgetId || "unknown"}. Payload: ${JSON.stringify(action.payload)}]`
5802
+ );
5803
+ }
5804
+ }, [onAction]);
5805
+ const handleMessageComplete = _react.useCallback.call(void 0, (result) => {
5806
+ if (!_optionalChain([result, 'optionalAccess', _154 => _154.data])) return;
5807
+ const text = typeof result.data === "string" ? result.data : result.data.message || "";
5808
+ console.log("[AutoInterface] Chat message complete, text (" + text.length + " chars):", text.substring(0, 300));
5809
+ const parsed = parseInterfaceFromText(text);
5810
+ if (parsed) {
5811
+ console.log("[AutoInterface] Parsed full interface from chat");
5812
+ updateInterface(parsed);
5813
+ setIsGenerating(false);
5814
+ return;
5815
+ }
5816
+ const updates = parseUpdatesFromText(text);
5817
+ if (updates.length > 0 && interfaceSpec) {
5818
+ console.log("[AutoInterface] Parsed", updates.length, "updates from chat");
5819
+ const newSpec = applyUpdates(interfaceSpec, updates);
5820
+ updateInterface(newSpec);
5821
+ } else {
5822
+ console.log("[AutoInterface] No interface or updates found in chat message");
5823
+ }
5824
+ setIsGenerating(false);
5825
+ }, [interfaceSpec, updateInterface]);
5826
+ _react.useEffect.call(void 0, () => {
5827
+ if (!initialPrompt || initialInterface || useMock) return;
5828
+ if (!apiUrl) return;
5829
+ let cancelled = false;
5830
+ setIsGenerating(true);
5831
+ console.log("[AutoInterface] Generating initial interface for prompt:", initialPrompt);
5832
+ console.log("[AutoInterface] API URL:", apiUrl, "| Agent:", agentId);
5833
+ generateInitialInterface(apiUrl, apiKey, agentId, initialPrompt).then(({ spec, threadId: threadId2 }) => {
5834
+ if (cancelled) return;
5835
+ console.log("[AutoInterface] Generation complete. Spec:", spec ? "parsed OK" : "null", "| Thread:", threadId2);
5836
+ if (spec) {
5837
+ console.log("[AutoInterface] Setting interface with", JSON.stringify(spec).length, "bytes");
5838
+ updateInterface(spec);
5839
+ } else {
5840
+ console.warn("[AutoInterface] Agent did not return a parseable @interface block");
5841
+ }
5842
+ setIsGenerating(false);
5843
+ }).catch((err) => {
5844
+ if (cancelled) return;
5845
+ console.error("[AutoInterface] Initial generation failed:", err);
5846
+ _optionalChain([onError, 'optionalCall', _155 => _155(err instanceof Error ? err : new Error(String(err)))]);
5847
+ setIsGenerating(false);
5848
+ });
5849
+ return () => {
5850
+ cancelled = true;
5851
+ };
5852
+ }, [initialPrompt]);
5853
+ const hasInterface = interfaceSpec !== null;
5854
+ const showSkeleton = isGenerating && !hasInterface;
5855
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn(
5856
+ "flex h-full bg-neutral-50 dark:bg-black",
5857
+ chatPosition === "bottom" ? "flex-col" : "flex-row",
5858
+ className
5859
+ ), children: [
5860
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn(
5861
+ "flex-1 overflow-y-auto min-w-0",
5862
+ hasInterface || showSkeleton ? "" : "hidden"
5863
+ ), children: [
5864
+ showSkeleton && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InterfaceSkeleton, {}),
5865
+ hasInterface && interfaceSpec && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "p-4", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5866
+ InterfaceRenderer,
5867
+ {
5868
+ node: interfaceSpec.root,
5869
+ onAction: handleAction
5870
+ }
5871
+ ) })
5872
+ ] }),
5873
+ chatCollapsible && hasInterface && chatPosition === "right" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5874
+ "button",
5875
+ {
5876
+ onClick: () => setChatCollapsed(!chatCollapsed),
5877
+ 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",
5878
+ title: chatCollapsed ? "Show chat" : "Hide chat",
5879
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "!text-xs !text-neutral-500 dark:!text-neutral-400", children: chatCollapsed ? "\u25C0" : "\u25B6" })
5880
+ }
5881
+ ),
5882
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5883
+ "div",
5884
+ {
5885
+ className: cn(
5886
+ "flex-shrink-0 border-neutral-200 dark:border-neutral-700",
5887
+ chatPosition === "right" ? "border-l" : "border-t",
5888
+ chatCollapsed && "hidden",
5889
+ // When no interface is generated yet, chat takes full width
5890
+ !hasInterface && !showSkeleton && "flex-1"
5891
+ ),
5892
+ style: hasInterface || showSkeleton ? chatPosition === "right" ? { width: chatWidth } : { height: "300px" } : void 0,
5893
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5894
+ Chat,
5895
+ {
5896
+ ref: chatRef,
5897
+ agentId,
5898
+ threadId,
5899
+ apiUrl,
5900
+ apiKey,
5901
+ useMock,
5902
+ context: systemContext,
5903
+ placeholder: chatPlaceholder,
5904
+ welcomeTitle: chatWelcomeTitle,
5905
+ welcomeSubtitle: "Describe the interface you want to create",
5906
+ enableStreaming: true,
5907
+ enableWidgets: true,
5908
+ showHeader: true,
5909
+ headerTitle: "Chat",
5910
+ onThreadChange,
5911
+ onComplete: handleMessageComplete,
5912
+ onError,
5913
+ className: "h-full",
5914
+ suggestedPrompts: !hasInterface ? [
5915
+ "Show me a sales dashboard",
5916
+ "Create a user management panel",
5917
+ "Build a project overview page"
5918
+ ] : void 0
5919
+ }
5920
+ )
5921
+ }
5922
+ )
5923
+ ] });
5924
+ }
5925
+
5045
5926
  // src/utils/theme-script.ts
5046
5927
  var themeScript = `
5047
5928
  (function() {
@@ -5066,6 +5947,139 @@ function getThemeScript() {
5066
5947
  return themeScript;
5067
5948
  }
5068
5949
 
5950
+ // src/hooks/useInterfaceState.ts
5951
+
5952
+ function useInterfaceState(initialSpec) {
5953
+ const [spec, setSpec] = _react.useState.call(void 0, initialSpec || null);
5954
+ const [isStreaming, setIsStreaming] = _react.useState.call(void 0, false);
5955
+ const setInterface = _react.useCallback.call(void 0, (newSpec) => {
5956
+ setSpec(newSpec);
5957
+ }, []);
5958
+ const clearInterface = _react.useCallback.call(void 0, () => {
5959
+ setSpec(null);
5960
+ }, []);
5961
+ const applyInterfaceUpdate = _react.useCallback.call(void 0, (update) => {
5962
+ setSpec((prev) => {
5963
+ if (!prev) return prev;
5964
+ return applyUpdate(prev, update);
5965
+ });
5966
+ }, []);
5967
+ const applyInterfaceUpdates = _react.useCallback.call(void 0, (updates) => {
5968
+ setSpec((prev) => {
5969
+ if (!prev) return prev;
5970
+ return applyUpdates(prev, updates);
5971
+ });
5972
+ }, []);
5973
+ const getNode = _react.useCallback.call(void 0, (id) => {
5974
+ if (!spec) return null;
5975
+ return findNode(spec.root, id);
5976
+ }, [spec]);
5977
+ return {
5978
+ spec,
5979
+ isStreaming,
5980
+ setInterface,
5981
+ clearInterface,
5982
+ applyInterfaceUpdate,
5983
+ applyInterfaceUpdates,
5984
+ setIsStreaming,
5985
+ getNode
5986
+ };
5987
+ }
5988
+
5989
+ // src/hooks/useInterfaceAI.ts
5990
+
5991
+ function useInterfaceAI({
5992
+ agentId,
5993
+ apiUrl,
5994
+ apiKey,
5995
+ context,
5996
+ onInterface,
5997
+ onUpdates,
5998
+ onError,
5999
+ onStreamStart,
6000
+ onStreamEnd
6001
+ }) {
6002
+ const threadIdRef = _react.useRef.call(void 0, null);
6003
+ const accumulatedTextRef = _react.useRef.call(void 0, "");
6004
+ if (apiUrl || apiKey) {
6005
+ aptevaClient.configure({
6006
+ ...apiUrl && { apiUrl },
6007
+ ...apiKey && { apiKey }
6008
+ });
6009
+ }
6010
+ const sendMessage = _react.useCallback.call(void 0, async (message) => {
6011
+ accumulatedTextRef.current = "";
6012
+ _optionalChain([onStreamStart, 'optionalCall', _156 => _156()]);
6013
+ const systemPrompt = [
6014
+ generateInterfaceContext(),
6015
+ context || ""
6016
+ ].filter(Boolean).join("\n\n");
6017
+ try {
6018
+ await aptevaClient.chatStream(
6019
+ {
6020
+ agent_id: agentId,
6021
+ message,
6022
+ thread_id: threadIdRef.current || void 0,
6023
+ stream: true,
6024
+ system: systemPrompt
6025
+ },
6026
+ // onChunk
6027
+ (chunk) => {
6028
+ if (chunk.thread_id) {
6029
+ threadIdRef.current = chunk.thread_id;
6030
+ }
6031
+ if (chunk.type === "content" || chunk.type === "token") {
6032
+ accumulatedTextRef.current += chunk.content || "";
6033
+ const parsed = parseInterfaceFromText(accumulatedTextRef.current);
6034
+ if (parsed) {
6035
+ _optionalChain([onInterface, 'optionalCall', _157 => _157(parsed)]);
6036
+ }
6037
+ const updates = parseUpdatesFromText(accumulatedTextRef.current);
6038
+ if (updates.length > 0) {
6039
+ _optionalChain([onUpdates, 'optionalCall', _158 => _158(updates)]);
6040
+ }
6041
+ }
6042
+ },
6043
+ // onComplete
6044
+ () => {
6045
+ _optionalChain([onStreamEnd, 'optionalCall', _159 => _159()]);
6046
+ },
6047
+ // onError
6048
+ (error) => {
6049
+ _optionalChain([onError, 'optionalCall', _160 => _160(error)]);
6050
+ _optionalChain([onStreamEnd, 'optionalCall', _161 => _161()]);
6051
+ }
6052
+ );
6053
+ } catch (error) {
6054
+ _optionalChain([onError, 'optionalCall', _162 => _162(error instanceof Error ? error : new Error("Unknown error"))]);
6055
+ _optionalChain([onStreamEnd, 'optionalCall', _163 => _163()]);
6056
+ }
6057
+ }, [agentId, context, onInterface, onUpdates, onError, onStreamStart, onStreamEnd]);
6058
+ return {
6059
+ sendMessage,
6060
+ threadId: threadIdRef.current
6061
+ };
6062
+ }
6063
+
6064
+
6065
+
6066
+
6067
+
6068
+
6069
+
6070
+
6071
+
6072
+
6073
+
6074
+
6075
+
6076
+
6077
+
6078
+
6079
+
6080
+
6081
+
6082
+
5069
6083
 
5070
6084
 
5071
6085
 
@@ -5082,5 +6096,5 @@ function getThemeScript() {
5082
6096
 
5083
6097
 
5084
6098
 
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;
6099
+ 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
6100
  //# sourceMappingURL=index.js.map