@apteva/apteva-kit 0.1.16 → 0.1.18

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
@@ -498,6 +498,237 @@ function validateFile(file) {
498
498
  return { valid: true };
499
499
  }
500
500
 
501
+ // src/utils/widget-parser.ts
502
+ function findMatchingBracket(text, startIndex) {
503
+ let depth = 0;
504
+ let inString = false;
505
+ let escapeNext = false;
506
+ for (let i = startIndex; i < text.length; i++) {
507
+ const char = text[i];
508
+ if (escapeNext) {
509
+ escapeNext = false;
510
+ continue;
511
+ }
512
+ if (char === "\\" && inString) {
513
+ escapeNext = true;
514
+ continue;
515
+ }
516
+ if (char === '"') {
517
+ inString = !inString;
518
+ continue;
519
+ }
520
+ if (inString) continue;
521
+ if (char === "[" || char === "{") {
522
+ depth++;
523
+ } else if (char === "]" || char === "}") {
524
+ depth--;
525
+ if (depth === 0) {
526
+ return i;
527
+ }
528
+ }
529
+ }
530
+ return -1;
531
+ }
532
+ function parseWidgetsFromText(text) {
533
+ const segments = [];
534
+ let hasWidgets = false;
535
+ let hasPendingWidget = false;
536
+ let currentIndex = 0;
537
+ let pendingWidgetType = null;
538
+ let processText = text;
539
+ const lastWidgetStart = text.lastIndexOf("@ui:");
540
+ if (lastWidgetStart !== -1) {
541
+ const afterStart = text.slice(lastWidgetStart);
542
+ const typeMatch = afterStart.match(/^@ui:(\w+)/);
543
+ if (typeMatch) {
544
+ const widgetType = typeMatch[1];
545
+ const bracketOpenIndex = afterStart.indexOf("[");
546
+ if (bracketOpenIndex === -1) {
547
+ processText = text.slice(0, lastWidgetStart);
548
+ pendingWidgetType = widgetType;
549
+ hasPendingWidget = true;
550
+ } else {
551
+ const fullBracketStart = lastWidgetStart + bracketOpenIndex;
552
+ const bracketEnd = findMatchingBracket(text, fullBracketStart);
553
+ if (bracketEnd === -1) {
554
+ processText = text.slice(0, lastWidgetStart);
555
+ pendingWidgetType = widgetType;
556
+ hasPendingWidget = true;
557
+ }
558
+ }
559
+ }
560
+ }
561
+ if (hasPendingWidget) {
562
+ processText = processText.replace(/[\s:;\-–—\.]+$/g, "");
563
+ }
564
+ const startPattern = /@ui:(\w+)\[/g;
565
+ let match;
566
+ while ((match = startPattern.exec(processText)) !== null) {
567
+ const widgetType = match[1];
568
+ const bracketStart = match.index + match[0].length - 1;
569
+ const bracketEnd = findMatchingBracket(processText, bracketStart);
570
+ if (bracketEnd === -1) {
571
+ continue;
572
+ }
573
+ const jsonContent = processText.slice(bracketStart + 1, bracketEnd);
574
+ if (match.index > currentIndex) {
575
+ const textContent = processText.slice(currentIndex, match.index).trim();
576
+ if (textContent) {
577
+ segments.push({
578
+ type: "text",
579
+ content: textContent
580
+ });
581
+ }
582
+ }
583
+ try {
584
+ const trimmedJson = jsonContent.trim();
585
+ const props = JSON.parse(trimmedJson);
586
+ const widgetId = `widget-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
587
+ segments.push({
588
+ type: "widget",
589
+ widget: {
590
+ type: widgetType,
591
+ id: widgetId,
592
+ props
593
+ }
594
+ });
595
+ hasWidgets = true;
596
+ } catch (e) {
597
+ }
598
+ currentIndex = bracketEnd + 1;
599
+ startPattern.lastIndex = currentIndex;
600
+ }
601
+ if (currentIndex < processText.length) {
602
+ const remainingText = processText.slice(currentIndex).trim();
603
+ if (remainingText) {
604
+ segments.push({
605
+ type: "text",
606
+ content: remainingText
607
+ });
608
+ }
609
+ }
610
+ if (segments.length === 0 && processText.trim()) {
611
+ segments.push({
612
+ type: "text",
613
+ content: processText.trim()
614
+ });
615
+ }
616
+ if (pendingWidgetType) {
617
+ segments.push({
618
+ type: "widget_pending",
619
+ pendingType: pendingWidgetType
620
+ });
621
+ }
622
+ return { segments, hasWidgets, hasPendingWidget };
623
+ }
624
+
625
+ // src/utils/widget-context.ts
626
+ var WIDGET_DEFINITIONS = {
627
+ card: {
628
+ description: "Displays a card with title and optional description, image, footer",
629
+ schema: '{"title": "string", "description?": "string", "image?": "url", "footer?": "string"}',
630
+ example: '@ui:card[{"title": "Summary", "description": "Key findings from the analysis"}]'
631
+ },
632
+ list: {
633
+ description: "Displays a list of items with title, subtitle, and optional description",
634
+ schema: '{"items": [{"id": "string", "title": "string", "subtitle?": "string", "description?": "string", "image?": "url"}]}',
635
+ example: '@ui:list[{"items": [{"id": "1", "title": "First item", "subtitle": "Details"}]}]'
636
+ },
637
+ button_group: {
638
+ description: "Displays action buttons. User clicks are sent back to you with the button id",
639
+ schema: '{"buttons": [{"id": "string", "label": "string", "variant?": "primary|secondary|outline"}], "layout?": "horizontal|vertical"}',
640
+ example: '@ui:button_group[{"buttons": [{"id": "confirm", "label": "Confirm", "variant": "primary"}, {"id": "cancel", "label": "Cancel"}]}]'
641
+ },
642
+ form: {
643
+ description: "Displays an input form. Submitted data is sent back to you",
644
+ schema: '{"title?": "string", "fields": [{"name": "string", "type": "text|number|select|checkbox|textarea|date", "label": "string", "required?": boolean, "placeholder?": "string", "options?": [{"label": "string", "value": "string"}]}]}',
645
+ example: '@ui:form[{"title": "Contact", "fields": [{"name": "email", "type": "text", "label": "Email", "required": true}]}]'
646
+ },
647
+ image: {
648
+ description: "Displays a single image with optional caption",
649
+ schema: '{"src": "url", "alt": "string", "caption?": "string"}',
650
+ example: '@ui:image[{"src": "https://example.com/img.png", "alt": "Description", "caption": "Figure 1"}]'
651
+ },
652
+ gallery: {
653
+ description: "Displays multiple images in a grid or carousel layout",
654
+ schema: '{"images": [{"id": "string", "src": "url", "alt": "string", "caption?": "string"}], "layout?": "grid|carousel"}',
655
+ example: '@ui:gallery[{"images": [{"id": "1", "src": "https://example.com/1.png", "alt": "Image 1"}], "layout": "grid"}]'
656
+ },
657
+ chart: {
658
+ description: "Displays a chart visualization (line, bar, pie, doughnut)",
659
+ schema: '{"chartType": "line|bar|pie|doughnut", "title?": "string", "data": {"labels": ["string"], "datasets": [{"label": "string", "data": [number], "backgroundColor?": "string|string[]"}]}}',
660
+ example: '@ui:chart[{"chartType": "bar", "title": "Sales", "data": {"labels": ["Q1", "Q2"], "datasets": [{"label": "Revenue", "data": [100, 150]}]}}]'
661
+ },
662
+ map: {
663
+ description: "Displays an interactive map with optional markers",
664
+ schema: '{"center": {"lat": number, "lng": number}, "zoom?": number, "markers?": [{"id": "string", "position": {"lat": number, "lng": number}, "title": "string"}]}',
665
+ example: '@ui:map[{"center": {"lat": 40.7128, "lng": -74.0060}, "zoom": 12, "markers": [{"id": "1", "position": {"lat": 40.7128, "lng": -74.0060}, "title": "NYC"}]}]'
666
+ },
667
+ table: {
668
+ description: "Displays structured data in rows and columns",
669
+ schema: '{"columns": [{"key": "string", "label": "string", "align?": "left|center|right"}], "rows": [{"id?": "string", ...}], "caption?": "string", "compact?": boolean, "striped?": boolean}',
670
+ example: '@ui:table[{"columns": [{"key": "name", "label": "Name"}, {"key": "status", "label": "Status"}], "rows": [{"name": "Item 1", "status": "Active"}, {"name": "Item 2", "status": "Pending"}]}]'
671
+ }
672
+ };
673
+ var ALL_WIDGET_TYPES = Object.keys(WIDGET_DEFINITIONS);
674
+ function generateWidgetContext(enabledWidgets) {
675
+ const widgets = enabledWidgets || ALL_WIDGET_TYPES;
676
+ let context = `
677
+ ## Available UI Widgets
678
+
679
+ `;
680
+ context += `You can render rich UI components in your responses using this syntax: @ui:type[{json_props}]
681
+
682
+ `;
683
+ context += `The widget syntax will be automatically converted to interactive UI. Users see the rendered widget, not the raw syntax.
684
+
685
+ `;
686
+ context += `### Available widgets:
687
+
688
+ `;
689
+ for (const type of widgets) {
690
+ const def = WIDGET_DEFINITIONS[type];
691
+ if (!def) continue;
692
+ context += `**${type}** - ${def.description}
693
+ `;
694
+ context += `Schema: \`${def.schema}\`
695
+ `;
696
+ context += `Example: \`${def.example}\`
697
+
698
+ `;
699
+ }
700
+ context += `### Important notes:
701
+ `;
702
+ context += `- JSON must be valid (use double quotes for strings)
703
+ `;
704
+ context += `- Widget actions (button clicks, form submissions) are sent back to you
705
+ `;
706
+ context += `- You can include multiple widgets in a single response
707
+ `;
708
+ context += `- Combine widgets with regular text for context
709
+ `;
710
+ return context;
711
+ }
712
+ function generateCompactWidgetContext(enabledWidgets) {
713
+ const widgets = enabledWidgets || ALL_WIDGET_TYPES;
714
+ let context = `
715
+ UI Widgets: Use @ui:type[{props}] syntax.
716
+ `;
717
+ context += `Available: ${widgets.join(", ")}
718
+ `;
719
+ context += `Examples:
720
+ `;
721
+ const examples = ["card", "list", "button_group"].filter((w) => widgets.includes(w));
722
+ for (const type of examples) {
723
+ const def = WIDGET_DEFINITIONS[type];
724
+ if (def) {
725
+ context += `${def.example}
726
+ `;
727
+ }
728
+ }
729
+ return context;
730
+ }
731
+
501
732
  // src/components/Widgets/Widgets.tsx
502
733
 
503
734
 
@@ -642,6 +873,82 @@ function ButtonGroup({ widget, onAction }) {
642
873
  );
643
874
  }
644
875
 
876
+ // src/components/Widgets/widget-library/Table.tsx
877
+
878
+ function Table({ widget, onAction }) {
879
+ const { columns, rows, caption, compact = false, striped = false } = widget.props;
880
+ const getAlignment = (align) => {
881
+ switch (align) {
882
+ case "center":
883
+ return "text-center";
884
+ case "right":
885
+ return "text-right";
886
+ default:
887
+ return "text-left";
888
+ }
889
+ };
890
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "border border-gray-200 dark:border-gray-700 rounded-xl bg-white dark:bg-gray-900 overflow-hidden", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "overflow-x-auto", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "table", { className: "w-full", children: [
891
+ caption && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "caption", { className: "px-4 py-2 text-sm text-gray-600 dark:text-gray-400 text-left bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700", children: caption }),
892
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "thead", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tr", { className: "bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700", children: columns.map((column) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
893
+ "th",
894
+ {
895
+ className: cn(
896
+ "font-semibold text-gray-900 dark:text-white",
897
+ compact ? "px-3 py-2 text-xs" : "px-4 py-3 text-sm",
898
+ getAlignment(column.align)
899
+ ),
900
+ style: column.width ? { width: column.width } : void 0,
901
+ children: column.label
902
+ },
903
+ column.key
904
+ )) }) }),
905
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "tbody", { children: [
906
+ rows.map((row, rowIndex) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
907
+ "tr",
908
+ {
909
+ className: cn(
910
+ "border-b border-gray-200 dark:border-gray-700 last:border-b-0",
911
+ "transition-colors hover:bg-gray-50 dark:hover:bg-gray-800",
912
+ striped && rowIndex % 2 === 1 && "bg-gray-50/50 dark:bg-gray-800/50"
913
+ ),
914
+ onClick: () => {
915
+ if (widget.actions && widget.actions.length > 0) {
916
+ _optionalChain([onAction, 'optionalCall', _15 => _15({
917
+ type: widget.actions[0].type,
918
+ payload: row,
919
+ widgetId: widget.id,
920
+ timestamp: /* @__PURE__ */ new Date()
921
+ })]);
922
+ }
923
+ },
924
+ style: { cursor: _optionalChain([widget, 'access', _16 => _16.actions, 'optionalAccess', _17 => _17.length]) ? "pointer" : "default" },
925
+ children: columns.map((column) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
926
+ "td",
927
+ {
928
+ className: cn(
929
+ "text-gray-700 dark:text-gray-300",
930
+ compact ? "px-3 py-2 text-xs" : "px-4 py-3 text-sm",
931
+ getAlignment(column.align)
932
+ ),
933
+ children: _nullishCoalesce(row[column.key], () => ( "\u2014"))
934
+ },
935
+ column.key
936
+ ))
937
+ },
938
+ row.id || rowIndex
939
+ )),
940
+ rows.length === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tr", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
941
+ "td",
942
+ {
943
+ colSpan: columns.length,
944
+ className: "px-4 py-8 text-center text-sm text-gray-500 dark:text-gray-400",
945
+ children: "No data available"
946
+ }
947
+ ) })
948
+ ] })
949
+ ] }) }) });
950
+ }
951
+
645
952
  // src/components/Widgets/WidgetRenderer.tsx
646
953
 
647
954
  function WidgetRenderer({ widget, onAction }) {
@@ -654,6 +961,8 @@ function WidgetRenderer({ widget, onAction }) {
654
961
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { widget, onAction });
655
962
  case "button_group":
656
963
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ButtonGroup, { widget, onAction });
964
+ case "table":
965
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Table, { widget, onAction });
657
966
  default:
658
967
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "p-4 border border-yellow-300 bg-yellow-50 rounded-lg", children: [
659
968
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "text-sm text-yellow-800", children: [
@@ -678,7 +987,7 @@ function Widgets({
678
987
  }) {
679
988
  _react.useEffect.call(void 0, () => {
680
989
  widgets.forEach((widget) => {
681
- _optionalChain([onWidgetMount, 'optionalCall', _15 => _15(widget.id)]);
990
+ _optionalChain([onWidgetMount, 'optionalCall', _18 => _18(widget.id)]);
682
991
  });
683
992
  }, [widgets, onWidgetMount]);
684
993
  const layoutClasses = {
@@ -694,6 +1003,80 @@ function Widgets({
694
1003
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn(layoutClasses[layout], spacingClasses[spacing], className), children: widgets.map((widget) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, WidgetRenderer, { widget, onAction }, widget.id)) });
695
1004
  }
696
1005
 
1006
+ // src/components/Widgets/WidgetSkeleton.tsx
1007
+
1008
+ function WidgetSkeleton({ type, className }) {
1009
+ switch (type) {
1010
+ case "card":
1011
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("animate-pulse rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden", className), children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "p-4 space-y-3", children: [
1012
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-3/4" }),
1013
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-200 dark:bg-gray-700 rounded w-full" }),
1014
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-200 dark:bg-gray-700 rounded w-5/6" })
1015
+ ] }) });
1016
+ case "list":
1017
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("animate-pulse space-y-2", className), children: [1, 2, 3].map((i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3 p-3 rounded-lg border border-gray-200 dark:border-gray-700", children: [
1018
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-10 h-10 bg-gray-200 dark:bg-gray-700 rounded-full flex-shrink-0" }),
1019
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 space-y-2", children: [
1020
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-200 dark:bg-gray-700 rounded w-1/2" }),
1021
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-2 bg-gray-200 dark:bg-gray-700 rounded w-3/4" })
1022
+ ] })
1023
+ ] }, i)) });
1024
+ case "button_group":
1025
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("animate-pulse flex gap-2", className), children: [
1026
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-9 bg-gray-200 dark:bg-gray-700 rounded-lg w-20" }),
1027
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-9 bg-gray-200 dark:bg-gray-700 rounded-lg w-20" }),
1028
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-9 bg-gray-200 dark:bg-gray-700 rounded-lg w-20" })
1029
+ ] });
1030
+ case "form":
1031
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("animate-pulse rounded-lg border border-gray-200 dark:border-gray-700 p-4 space-y-4", className), children: [
1032
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-1/3" }),
1033
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-3", children: [
1034
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" }),
1035
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
1036
+ ] }),
1037
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-9 bg-gray-200 dark:bg-gray-700 rounded w-24" })
1038
+ ] });
1039
+ case "chart":
1040
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("animate-pulse rounded-lg border border-gray-200 dark:border-gray-700 p-4", className), children: [
1041
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-1/4 mb-4" }),
1042
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-end gap-2 h-32", children: [
1043
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 bg-gray-200 dark:bg-gray-700 rounded-t h-1/2" }),
1044
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 bg-gray-200 dark:bg-gray-700 rounded-t h-3/4" }),
1045
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 bg-gray-200 dark:bg-gray-700 rounded-t h-1/3" }),
1046
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 bg-gray-200 dark:bg-gray-700 rounded-t h-full" }),
1047
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 bg-gray-200 dark:bg-gray-700 rounded-t h-2/3" })
1048
+ ] })
1049
+ ] });
1050
+ case "image":
1051
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("animate-pulse", className), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "aspect-video bg-gray-200 dark:bg-gray-700 rounded-lg" }) });
1052
+ case "gallery":
1053
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("animate-pulse grid grid-cols-3 gap-2", className), children: [1, 2, 3].map((i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "aspect-square bg-gray-200 dark:bg-gray-700 rounded-lg" }, i)) });
1054
+ case "map":
1055
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("animate-pulse", className), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-48 bg-gray-200 dark:bg-gray-700 rounded-lg flex items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { className: "w-8 h-8 text-gray-300 dark:text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: [
1056
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" }),
1057
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M15 11a3 3 0 11-6 0 3 3 0 016 0z" })
1058
+ ] }) }) });
1059
+ case "table":
1060
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("animate-pulse rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden", className), children: [
1061
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex bg-gray-100 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700", children: [
1062
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 px-4 py-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-300 dark:bg-gray-600 rounded w-16" }) }),
1063
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 px-4 py-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-300 dark:bg-gray-600 rounded w-20" }) }),
1064
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 px-4 py-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-300 dark:bg-gray-600 rounded w-14" }) })
1065
+ ] }),
1066
+ [1, 2, 3].map((i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex border-b border-gray-200 dark:border-gray-700 last:border-b-0", children: [
1067
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 px-4 py-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-200 dark:bg-gray-700 rounded w-24" }) }),
1068
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 px-4 py-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-200 dark:bg-gray-700 rounded w-16" }) }),
1069
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 px-4 py-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-200 dark:bg-gray-700 rounded w-20" }) })
1070
+ ] }, i))
1071
+ ] });
1072
+ default:
1073
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("animate-pulse rounded-lg border border-gray-200 dark:border-gray-700 p-4", className), children: [
1074
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-1/2 mb-2" }),
1075
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-200 dark:bg-gray-700 rounded w-full" })
1076
+ ] });
1077
+ }
1078
+ }
1079
+
697
1080
  // src/components/Chat/MarkdownContent.tsx
698
1081
 
699
1082
  function parseInlineMarkdown(text, keyPrefix = "") {
@@ -838,9 +1221,30 @@ function ToolCall({ name, status }) {
838
1221
 
839
1222
  // src/components/Chat/Message.tsx
840
1223
 
841
- function Message({ message, onAction }) {
1224
+ function Message({ message, onAction, enableWidgets }) {
842
1225
  const isUser = message.role === "user";
843
- const contentSegments = _optionalChain([message, 'access', _16 => _16.metadata, 'optionalAccess', _17 => _17.content_segments]);
1226
+ const contentSegments = _optionalChain([message, 'access', _19 => _19.metadata, 'optionalAccess', _20 => _20.content_segments]);
1227
+ const renderTextContent = (text) => {
1228
+ if (!enableWidgets || isUser) {
1229
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MarkdownContent, { content: text });
1230
+ }
1231
+ const parsed = parseWidgetsFromText(text);
1232
+ if (parsed.segments.length === 0) {
1233
+ return null;
1234
+ }
1235
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: parsed.segments.map((segment, index) => {
1236
+ if (segment.type === "text" && segment.content) {
1237
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MarkdownContent, { content: segment.content }, `text-${index}`);
1238
+ }
1239
+ if (segment.type === "widget" && segment.widget) {
1240
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "my-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, WidgetRenderer, { widget: segment.widget, onAction }) }, `widget-${index}`);
1241
+ }
1242
+ if (segment.type === "widget_pending" && segment.pendingType) {
1243
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "my-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, WidgetSkeleton, { type: segment.pendingType }) }, `pending-${index}`);
1244
+ }
1245
+ return null;
1246
+ }) });
1247
+ };
844
1248
  const renderContent = () => {
845
1249
  if (isUser) {
846
1250
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "whitespace-pre-wrap !text-sm leading-relaxed", children: message.content });
@@ -848,7 +1252,7 @@ function Message({ message, onAction }) {
848
1252
  if (contentSegments && contentSegments.length > 0) {
849
1253
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: contentSegments.map((segment, index) => {
850
1254
  if (segment.type === "text") {
851
- return segment.content ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MarkdownContent, { content: segment.content }, `text-${index}`) : null;
1255
+ return segment.content ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: renderTextContent(segment.content) }, `text-${index}`) : null;
852
1256
  } else if (segment.type === "tool") {
853
1257
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "my-2", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
854
1258
  ToolCall,
@@ -861,7 +1265,7 @@ function Message({ message, onAction }) {
861
1265
  return null;
862
1266
  }) });
863
1267
  }
864
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MarkdownContent, { content: message.content });
1268
+ return renderTextContent(message.content);
865
1269
  };
866
1270
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
867
1271
  "div",
@@ -1030,7 +1434,8 @@ function MessageList({
1030
1434
  welcomeIcon,
1031
1435
  suggestedPrompts,
1032
1436
  welcomeVariant,
1033
- onPromptClick
1437
+ onPromptClick,
1438
+ enableWidgets
1034
1439
  }) {
1035
1440
  const listRef = _react.useRef.call(void 0, null);
1036
1441
  _react.useEffect.call(void 0, () => {
@@ -1049,13 +1454,13 @@ function MessageList({
1049
1454
  onPromptClick: onPromptClick || (() => {
1050
1455
  })
1051
1456
  }
1052
- ) : messages.map((message) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Message, { message, onAction }, message.id)) });
1457
+ ) : messages.map((message) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Message, { message, onAction, enableWidgets }, message.id)) });
1053
1458
  }
1054
1459
 
1055
1460
  // src/components/Chat/Composer.tsx
1056
1461
 
1057
1462
 
1058
- function Composer({ onSendMessage, placeholder = "Type a message...", disabled = false, onFileUpload, onSwitchMode }) {
1463
+ function Composer({ onSendMessage, placeholder = "Type a message...", disabled = false, isLoading = false, onStop, onFileUpload, onSwitchMode }) {
1059
1464
  const [text, setText] = _react.useState.call(void 0, "");
1060
1465
  const [showMenu, setShowMenu] = _react.useState.call(void 0, false);
1061
1466
  const [pendingFiles, setPendingFiles] = _react.useState.call(void 0, []);
@@ -1112,7 +1517,7 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
1112
1517
  setFileError(errors.join(", "));
1113
1518
  setTimeout(() => setFileError(null), 5e3);
1114
1519
  }
1115
- _optionalChain([onFileUpload, 'optionalCall', _18 => _18(e.target.files)]);
1520
+ _optionalChain([onFileUpload, 'optionalCall', _21 => _21(e.target.files)]);
1116
1521
  setShowMenu(false);
1117
1522
  e.target.value = "";
1118
1523
  }
@@ -1182,15 +1587,15 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
1182
1587
  {
1183
1588
  className: "fixed bg-gray-800 dark:bg-gray-700 rounded-xl shadow-lg overflow-hidden z-[9999] min-w-[200px]",
1184
1589
  style: {
1185
- left: _nullishCoalesce(_optionalChain([menuButtonRef, 'access', _19 => _19.current, 'optionalAccess', _20 => _20.getBoundingClientRect, 'call', _21 => _21(), 'access', _22 => _22.left]), () => ( 0)),
1186
- top: (_nullishCoalesce(_optionalChain([menuButtonRef, 'access', _23 => _23.current, 'optionalAccess', _24 => _24.getBoundingClientRect, 'call', _25 => _25(), 'access', _26 => _26.bottom]), () => ( 0))) + 8
1590
+ left: _nullishCoalesce(_optionalChain([menuButtonRef, 'access', _22 => _22.current, 'optionalAccess', _23 => _23.getBoundingClientRect, 'call', _24 => _24(), 'access', _25 => _25.left]), () => ( 0)),
1591
+ top: (_nullishCoalesce(_optionalChain([menuButtonRef, 'access', _26 => _26.current, 'optionalAccess', _27 => _27.getBoundingClientRect, 'call', _28 => _28(), 'access', _29 => _29.bottom]), () => ( 0))) + 8
1187
1592
  },
1188
1593
  children: [
1189
1594
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1190
1595
  "button",
1191
1596
  {
1192
1597
  onClick: () => {
1193
- _optionalChain([fileInputRef, 'access', _27 => _27.current, 'optionalAccess', _28 => _28.click, 'call', _29 => _29()]);
1598
+ _optionalChain([fileInputRef, 'access', _30 => _30.current, 'optionalAccess', _31 => _31.click, 'call', _32 => _32()]);
1194
1599
  setShowMenu(false);
1195
1600
  },
1196
1601
  className: "w-full flex items-center gap-3 px-4 py-3 hover:bg-gray-700 dark:hover:bg-gray-600 transition-colors !text-white text-left",
@@ -1233,7 +1638,15 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
1233
1638
  style: { maxHeight: "120px" }
1234
1639
  }
1235
1640
  ),
1236
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1641
+ isLoading && onStop ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1642
+ "button",
1643
+ {
1644
+ onClick: onStop,
1645
+ className: "w-8 h-8 rounded-lg flex items-center justify-center font-bold transition-all flex-shrink-0 border border-red-400 dark:border-red-500 bg-red-50 dark:bg-red-900/30 !text-red-600 dark:!text-red-400 hover:bg-red-100 dark:hover:bg-red-900/50",
1646
+ title: "Stop generation",
1647
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "2", y: "2", width: "10", height: "10", rx: "1", fill: "currentColor" }) })
1648
+ }
1649
+ ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1237
1650
  "button",
1238
1651
  {
1239
1652
  onClick: handleSend,
@@ -1272,6 +1685,7 @@ function CommandComposer({
1272
1685
  onApprove,
1273
1686
  onReject,
1274
1687
  onReset,
1688
+ onStop,
1275
1689
  onExpand,
1276
1690
  placeholder = "Enter your command...",
1277
1691
  disabled = false
@@ -1300,8 +1714,8 @@ function CommandComposer({
1300
1714
  }
1301
1715
  };
1302
1716
  const handleNewCommand = () => {
1303
- _optionalChain([onReset, 'optionalCall', _30 => _30()]);
1304
- _optionalChain([inputRef, 'access', _31 => _31.current, 'optionalAccess', _32 => _32.focus, 'call', _33 => _33()]);
1717
+ _optionalChain([onReset, 'optionalCall', _33 => _33()]);
1718
+ _optionalChain([inputRef, 'access', _34 => _34.current, 'optionalAccess', _35 => _35.focus, 'call', _36 => _36()]);
1305
1719
  };
1306
1720
  const handleInputChange = (value) => {
1307
1721
  setInput(value);
@@ -1384,26 +1798,6 @@ function CommandComposer({
1384
1798
  /* @__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" }) }),
1385
1799
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: fileError })
1386
1800
  ] }) }),
1387
- pendingFiles.length > 0 && state === "idle" && /* @__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,
1388
- "div",
1389
- {
1390
- className: "relative group flex items-center gap-2 px-2 py-1.5 bg-gray-100 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg",
1391
- children: [
1392
- pf.preview ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: pf.preview, alt: pf.file.name, className: "w-6 h-6 object-cover rounded" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-6 h-6 flex items-center justify-center bg-gray-200 dark:bg-gray-700 rounded !text-gray-500 dark:!text-gray-400", children: getFileIcon(pf.file.type) }),
1393
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-xs font-medium !text-gray-700 dark:!text-gray-300 truncate max-w-[100px]", children: pf.file.name }),
1394
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1395
- "button",
1396
- {
1397
- onClick: () => removeFile(index),
1398
- className: "w-4 h-4 bg-gray-500 hover:bg-red-500 text-white rounded-full flex items-center justify-center",
1399
- title: "Remove file",
1400
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-2.5 h-2.5", 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" }) })
1401
- }
1402
- )
1403
- ]
1404
- },
1405
- index
1406
- )) }),
1407
1801
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1408
1802
  "div",
1409
1803
  {
@@ -1435,15 +1829,15 @@ function CommandComposer({
1435
1829
  {
1436
1830
  className: "fixed bg-gray-800 dark:bg-gray-700 rounded-xl shadow-lg overflow-hidden z-[9999] min-w-[200px]",
1437
1831
  style: {
1438
- left: _nullishCoalesce(_optionalChain([menuButtonRef, 'access', _34 => _34.current, 'optionalAccess', _35 => _35.getBoundingClientRect, 'call', _36 => _36(), 'access', _37 => _37.left]), () => ( 0)),
1439
- top: (_nullishCoalesce(_optionalChain([menuButtonRef, 'access', _38 => _38.current, 'optionalAccess', _39 => _39.getBoundingClientRect, 'call', _40 => _40(), 'access', _41 => _41.bottom]), () => ( 0))) + 8
1832
+ left: _nullishCoalesce(_optionalChain([menuButtonRef, 'access', _37 => _37.current, 'optionalAccess', _38 => _38.getBoundingClientRect, 'call', _39 => _39(), 'access', _40 => _40.left]), () => ( 0)),
1833
+ top: (_nullishCoalesce(_optionalChain([menuButtonRef, 'access', _41 => _41.current, 'optionalAccess', _42 => _42.getBoundingClientRect, 'call', _43 => _43(), 'access', _44 => _44.bottom]), () => ( 0))) + 8
1440
1834
  },
1441
1835
  children: [
1442
1836
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1443
1837
  "button",
1444
1838
  {
1445
1839
  onClick: () => {
1446
- _optionalChain([fileInputRef, 'access', _42 => _42.current, 'optionalAccess', _43 => _43.click, 'call', _44 => _44()]);
1840
+ _optionalChain([fileInputRef, 'access', _45 => _45.current, 'optionalAccess', _46 => _46.click, 'call', _47 => _47()]);
1447
1841
  setShowMenu(false);
1448
1842
  },
1449
1843
  className: "w-full flex items-center gap-3 px-4 py-3 hover:bg-gray-700 dark:hover:bg-gray-600 transition-colors !text-white text-left",
@@ -1475,6 +1869,26 @@ function CommandComposer({
1475
1869
  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" }),
1476
1870
  state === "loading" && toolName && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-2 h-2 rounded-full bg-blue-500 animate-pulse" })
1477
1871
  ] }),
1872
+ 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,
1873
+ "div",
1874
+ {
1875
+ className: "relative group flex items-center justify-center w-6 h-6 bg-gray-100 dark:bg-gray-800 rounded overflow-hidden",
1876
+ title: pf.file.name,
1877
+ children: [
1878
+ 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-gray-500 dark:!text-gray-400", children: getFileIcon(pf.file.type) }),
1879
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1880
+ "button",
1881
+ {
1882
+ onClick: () => removeFile(index),
1883
+ className: "absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 flex items-center justify-center transition-opacity",
1884
+ title: "Remove",
1885
+ 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" }) })
1886
+ }
1887
+ )
1888
+ ]
1889
+ },
1890
+ index
1891
+ )) }),
1478
1892
  state === "idle" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1479
1893
  "textarea",
1480
1894
  {
@@ -1482,7 +1896,7 @@ function CommandComposer({
1482
1896
  value: input,
1483
1897
  onChange: (e) => handleInputChange(e.target.value),
1484
1898
  onKeyDown: handleKeyDown,
1485
- placeholder,
1899
+ placeholder: pendingFiles.length > 0 ? "Add a message..." : placeholder,
1486
1900
  disabled,
1487
1901
  rows: 1,
1488
1902
  className: cn(
@@ -1528,6 +1942,15 @@ function CommandComposer({
1528
1942
  }
1529
1943
  )
1530
1944
  ] }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1945
+ state === "loading" && onStop && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1946
+ "button",
1947
+ {
1948
+ onClick: onStop,
1949
+ className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all border border-red-400 dark:border-red-500 bg-red-50 dark:bg-red-900/30 !text-red-600 dark:!text-red-400 hover:bg-red-100 dark:hover:bg-red-900/50",
1950
+ title: "Stop generation",
1951
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "2", y: "2", width: "10", height: "10", rx: "1", fill: "currentColor" }) })
1952
+ }
1953
+ ),
1531
1954
  (state === "success" || state === "error") && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1532
1955
  "button",
1533
1956
  {
@@ -1655,7 +2078,7 @@ var AptevaClient = class {
1655
2078
  const error = await response.json().catch(() => ({ error: "Request failed" }));
1656
2079
  throw new Error(error.error || `Request failed with status ${response.status}`);
1657
2080
  }
1658
- const reader = _optionalChain([response, 'access', _45 => _45.body, 'optionalAccess', _46 => _46.getReader, 'call', _47 => _47()]);
2081
+ const reader = _optionalChain([response, 'access', _48 => _48.body, 'optionalAccess', _49 => _49.getReader, 'call', _50 => _50()]);
1659
2082
  if (!reader) {
1660
2083
  throw new Error("Response body is not readable");
1661
2084
  }
@@ -1673,7 +2096,7 @@ var AptevaClient = class {
1673
2096
  if (line.startsWith("data: ")) {
1674
2097
  const data = line.slice(6);
1675
2098
  if (data === "[DONE]") {
1676
- _optionalChain([onComplete, 'optionalCall', _48 => _48(threadId)]);
2099
+ _optionalChain([onComplete, 'optionalCall', _51 => _51(threadId)]);
1677
2100
  return;
1678
2101
  }
1679
2102
  try {
@@ -1688,10 +2111,10 @@ var AptevaClient = class {
1688
2111
  }
1689
2112
  }
1690
2113
  }
1691
- _optionalChain([onComplete, 'optionalCall', _49 => _49(threadId)]);
2114
+ _optionalChain([onComplete, 'optionalCall', _52 => _52(threadId)]);
1692
2115
  } catch (error) {
1693
2116
  const err = error instanceof Error ? error : new Error("Unknown error");
1694
- _optionalChain([onError, 'optionalCall', _50 => _50(err)]);
2117
+ _optionalChain([onError, 'optionalCall', _53 => _53(err)]);
1695
2118
  throw err;
1696
2119
  }
1697
2120
  }
@@ -1731,6 +2154,27 @@ var AptevaClient = class {
1731
2154
  const data = await response.json();
1732
2155
  return data.messages;
1733
2156
  }
2157
+ /**
2158
+ * Cancel an in-progress request
2159
+ */
2160
+ async cancelRequest(agentId, requestId) {
2161
+ try {
2162
+ const response = await fetch(`${this.config.apiUrl}/agents/${agentId}/requests/${requestId}/cancel`, {
2163
+ method: "POST",
2164
+ headers: {
2165
+ "Content-Type": "application/json",
2166
+ "X-API-Key": this.config.apiKey
2167
+ }
2168
+ });
2169
+ if (!response.ok) {
2170
+ const error = await response.json().catch(() => ({ error: "Cancel request failed" }));
2171
+ throw new Error(error.error || `Cancel request failed with status ${response.status}`);
2172
+ }
2173
+ } catch (error) {
2174
+ console.error("[AptevaClient] Cancel request error:", error);
2175
+ throw error;
2176
+ }
2177
+ }
1734
2178
  };
1735
2179
  var aptevaClient = new AptevaClient();
1736
2180
 
@@ -1768,10 +2212,16 @@ function Chat({
1768
2212
  onFileUpload,
1769
2213
  onComplete,
1770
2214
  onError,
2215
+ onToolResult,
1771
2216
  // UI
1772
2217
  placeholder,
1773
2218
  showHeader = true,
1774
2219
  headerTitle = "Chat",
2220
+ // Widget detection
2221
+ enableWidgets = false,
2222
+ availableWidgets,
2223
+ compactWidgetContext = false,
2224
+ onWidgetRender,
1775
2225
  className
1776
2226
  }) {
1777
2227
  const [messages, setMessages] = _react.useState.call(void 0, initialMessages);
@@ -1785,11 +2235,18 @@ function Chat({
1785
2235
  const [commandInput, setCommandInput] = _react.useState.call(void 0, "");
1786
2236
  const [streamedContent, setStreamedContent] = _react.useState.call(void 0, "");
1787
2237
  const [currentToolName, setCurrentToolName] = _react.useState.call(void 0, null);
2238
+ const [currentRequestId, setCurrentRequestId] = _react.useState.call(void 0, null);
1788
2239
  const [plan, setPlan] = _react.useState.call(void 0, "");
1789
2240
  const [pendingCommand, setPendingCommand] = _react.useState.call(void 0, "");
1790
2241
  const [internalPlanMode, setInternalPlanMode] = _react.useState.call(void 0, planMode);
1791
2242
  const [showSettingsMenu, setShowSettingsMenu] = _react.useState.call(void 0, false);
1792
2243
  const fileInputRef = _react.useRef.call(void 0, null);
2244
+ const effectiveContext = _react.useMemo.call(void 0, () => {
2245
+ if (!enableWidgets) return context;
2246
+ const widgetContext = compactWidgetContext ? generateCompactWidgetContext(availableWidgets) : generateWidgetContext(availableWidgets);
2247
+ return context ? `${context}
2248
+ ${widgetContext}` : widgetContext;
2249
+ }, [context, enableWidgets, availableWidgets, compactWidgetContext]);
1793
2250
  _react.useEffect.call(void 0, () => {
1794
2251
  if (apiUrl || apiKey) {
1795
2252
  aptevaClient.configure({
@@ -1800,7 +2257,7 @@ function Chat({
1800
2257
  }, [apiUrl, apiKey]);
1801
2258
  _react.useEffect.call(void 0, () => {
1802
2259
  if (threadId) {
1803
- _optionalChain([onThreadChange, 'optionalCall', _51 => _51(threadId)]);
2260
+ _optionalChain([onThreadChange, 'optionalCall', _54 => _54(threadId)]);
1804
2261
  }
1805
2262
  }, [threadId, onThreadChange]);
1806
2263
  _react.useEffect.call(void 0, () => {
@@ -1818,7 +2275,7 @@ function Chat({
1818
2275
  }, [showSettingsMenu]);
1819
2276
  const handleModeChange = (newMode) => {
1820
2277
  setMode(newMode);
1821
- _optionalChain([onModeChange, 'optionalCall', _52 => _52(newMode)]);
2278
+ _optionalChain([onModeChange, 'optionalCall', _55 => _55(newMode)]);
1822
2279
  if (newMode === "command") {
1823
2280
  setCommandState("idle");
1824
2281
  setCommandResult(null);
@@ -1838,7 +2295,7 @@ function Chat({
1838
2295
  metadata: hasFiles ? { attachments: fileNames } : void 0
1839
2296
  };
1840
2297
  setMessages((prev) => [...prev, userMessage]);
1841
- _optionalChain([onMessageSent, 'optionalCall', _53 => _53(userMessage)]);
2298
+ _optionalChain([onMessageSent, 'optionalCall', _56 => _56(userMessage)]);
1842
2299
  setIsLoading(true);
1843
2300
  try {
1844
2301
  const messagePayload = await buildMessageWithAttachments(text, files);
@@ -1894,7 +2351,7 @@ function Chat({
1894
2351
  message: messagePayload,
1895
2352
  stream: true,
1896
2353
  ...currentThreadId && { thread_id: currentThreadId },
1897
- ...context && { system: context }
2354
+ ...effectiveContext && { system: effectiveContext }
1898
2355
  },
1899
2356
  (chunk) => {
1900
2357
  switch (chunk.type) {
@@ -1903,10 +2360,15 @@ function Chat({
1903
2360
  responseThreadId = chunk.thread_id;
1904
2361
  if (!currentThreadId) {
1905
2362
  setCurrentThreadId(chunk.thread_id);
1906
- _optionalChain([onThreadChange, 'optionalCall', _54 => _54(chunk.thread_id)]);
2363
+ _optionalChain([onThreadChange, 'optionalCall', _57 => _57(chunk.thread_id)]);
1907
2364
  }
1908
2365
  }
1909
2366
  break;
2367
+ case "request_id":
2368
+ if (chunk.request_id) {
2369
+ setCurrentRequestId(chunk.request_id);
2370
+ }
2371
+ break;
1910
2372
  case "content":
1911
2373
  case "token":
1912
2374
  if (chunk.content) {
@@ -1935,6 +2397,7 @@ function Chat({
1935
2397
  const toolSegment = contentSegments.find((s) => s.type === "tool" && s.id === chunk.tool_id);
1936
2398
  if (toolSegment) {
1937
2399
  toolSegment.result = chunk.content;
2400
+ _optionalChain([onToolResult, 'optionalCall', _58 => _58(toolSegment.name, chunk.content)]);
1938
2401
  }
1939
2402
  updateMessage();
1940
2403
  }
@@ -1976,9 +2439,10 @@ function Chat({
1976
2439
  });
1977
2440
  if (threadId2 && threadId2 !== currentThreadId) {
1978
2441
  setCurrentThreadId(threadId2);
1979
- _optionalChain([onThreadChange, 'optionalCall', _55 => _55(threadId2)]);
2442
+ _optionalChain([onThreadChange, 'optionalCall', _59 => _59(threadId2)]);
1980
2443
  }
1981
2444
  setIsLoading(false);
2445
+ setCurrentRequestId(null);
1982
2446
  },
1983
2447
  (error) => {
1984
2448
  const errorMessage = {
@@ -1996,7 +2460,8 @@ function Chat({
1996
2460
  return [...prev, errorMessage];
1997
2461
  });
1998
2462
  setIsLoading(false);
1999
- _optionalChain([onError, 'optionalCall', _56 => _56(error)]);
2463
+ setCurrentRequestId(null);
2464
+ _optionalChain([onError, 'optionalCall', _60 => _60(error)]);
2000
2465
  }
2001
2466
  );
2002
2467
  }
@@ -2009,7 +2474,7 @@ function Chat({
2009
2474
  metadata: { error: true }
2010
2475
  };
2011
2476
  setMessages((prev) => [...prev, errorMessage]);
2012
- _optionalChain([onError, 'optionalCall', _57 => _57(error instanceof Error ? error : new Error("Unknown error"))]);
2477
+ _optionalChain([onError, 'optionalCall', _61 => _61(error instanceof Error ? error : new Error("Unknown error"))]);
2013
2478
  } finally {
2014
2479
  setIsLoading(false);
2015
2480
  }
@@ -2038,7 +2503,7 @@ function Chat({
2038
2503
  } else {
2039
2504
  try {
2040
2505
  const planningInstruction = `CRITICAL PLANNING MODE: You are ONLY creating a plan. Write a numbered list of steps describing what WOULD be done. DO NOT execute anything.`;
2041
- const systemMessage = context ? `${context}
2506
+ const systemMessage = effectiveContext ? `${effectiveContext}
2042
2507
 
2043
2508
  ${planningInstruction}` : planningInstruction;
2044
2509
  const response = await aptevaClient.chat({
@@ -2054,7 +2519,7 @@ ${planningInstruction}` : planningInstruction;
2054
2519
  const error = err instanceof Error ? err : new Error("Failed to generate plan");
2055
2520
  setCommandError(error);
2056
2521
  setCommandState("error");
2057
- _optionalChain([onError, 'optionalCall', _58 => _58(error)]);
2522
+ _optionalChain([onError, 'optionalCall', _62 => _62(error)]);
2058
2523
  }
2059
2524
  }
2060
2525
  return;
@@ -2087,12 +2552,12 @@ ${planningInstruction}` : planningInstruction;
2087
2552
  setCommandResult(result);
2088
2553
  setCommandState("success");
2089
2554
  setProgress(100);
2090
- _optionalChain([onComplete, 'optionalCall', _59 => _59(result)]);
2555
+ _optionalChain([onComplete, 'optionalCall', _63 => _63(result)]);
2091
2556
  },
2092
2557
  (error) => {
2093
2558
  setCommandError(error);
2094
2559
  setCommandState("error");
2095
- _optionalChain([onError, 'optionalCall', _60 => _60(error)]);
2560
+ _optionalChain([onError, 'optionalCall', _64 => _64(error)]);
2096
2561
  }
2097
2562
  );
2098
2563
  } else {
@@ -2105,16 +2570,17 @@ ${planningInstruction}` : planningInstruction;
2105
2570
  setCommandResult(result);
2106
2571
  setCommandState("success");
2107
2572
  setProgress(100);
2108
- _optionalChain([onComplete, 'optionalCall', _61 => _61(result)]);
2573
+ _optionalChain([onComplete, 'optionalCall', _65 => _65(result)]);
2109
2574
  }
2110
2575
  } else {
2111
2576
  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.`;
2112
- const systemMessage = context ? `${context}
2577
+ const systemMessage = effectiveContext ? `${effectiveContext}
2113
2578
 
2114
2579
  ${commandInstruction}` : commandInstruction;
2115
2580
  const messagePayload = files && files.length > 0 ? await buildMessageWithAttachments(currentCommand, files) : currentCommand;
2116
2581
  if (enableStreaming) {
2117
2582
  let accumulatedContent = "";
2583
+ let lastToolName = "";
2118
2584
  await aptevaClient.chatStream(
2119
2585
  {
2120
2586
  agent_id: agentId,
@@ -2131,16 +2597,20 @@ ${commandInstruction}` : commandInstruction;
2131
2597
  const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
2132
2598
  setProgress(estimatedProgress);
2133
2599
  } else if (chunk.type === "tool_call" && chunk.tool_name) {
2600
+ lastToolName = chunk.tool_name;
2134
2601
  setCurrentToolName(chunk.tool_name);
2135
2602
  accumulatedContent = "";
2136
2603
  setStreamedContent("");
2137
2604
  } else if (chunk.type === "tool_result") {
2605
+ _optionalChain([onToolResult, 'optionalCall', _66 => _66(lastToolName, chunk.content)]);
2138
2606
  setCurrentToolName(null);
2139
2607
  } else if (chunk.type === "thread_id" && chunk.thread_id) {
2140
2608
  if (!currentThreadId) {
2141
2609
  setCurrentThreadId(chunk.thread_id);
2142
- _optionalChain([onThreadChange, 'optionalCall', _62 => _62(chunk.thread_id)]);
2610
+ _optionalChain([onThreadChange, 'optionalCall', _67 => _67(chunk.thread_id)]);
2143
2611
  }
2612
+ } else if (chunk.type === "request_id" && chunk.request_id) {
2613
+ setCurrentRequestId(chunk.request_id);
2144
2614
  }
2145
2615
  },
2146
2616
  (threadId2) => {
@@ -2152,12 +2622,14 @@ ${commandInstruction}` : commandInstruction;
2152
2622
  setCommandResult(result);
2153
2623
  setCommandState("success");
2154
2624
  setProgress(100);
2155
- _optionalChain([onComplete, 'optionalCall', _63 => _63(result)]);
2625
+ setCurrentRequestId(null);
2626
+ _optionalChain([onComplete, 'optionalCall', _68 => _68(result)]);
2156
2627
  },
2157
2628
  (error) => {
2158
2629
  setCommandError(error);
2159
2630
  setCommandState("error");
2160
- _optionalChain([onError, 'optionalCall', _64 => _64(error)]);
2631
+ setCurrentRequestId(null);
2632
+ _optionalChain([onError, 'optionalCall', _69 => _69(error)]);
2161
2633
  }
2162
2634
  );
2163
2635
  } else {
@@ -2177,14 +2649,14 @@ ${commandInstruction}` : commandInstruction;
2177
2649
  setCommandResult(result);
2178
2650
  setCommandState("success");
2179
2651
  setProgress(100);
2180
- _optionalChain([onComplete, 'optionalCall', _65 => _65(result)]);
2652
+ _optionalChain([onComplete, 'optionalCall', _70 => _70(result)]);
2181
2653
  }
2182
2654
  }
2183
2655
  } catch (err) {
2184
2656
  const error = err instanceof Error ? err : new Error("Unknown error");
2185
2657
  setCommandError(error);
2186
2658
  setCommandState("error");
2187
- _optionalChain([onError, 'optionalCall', _66 => _66(error)]);
2659
+ _optionalChain([onError, 'optionalCall', _71 => _71(error)]);
2188
2660
  }
2189
2661
  };
2190
2662
  const resetCommand = () => {
@@ -2213,6 +2685,23 @@ ${planToExecute}`;
2213
2685
  setPendingCommand("");
2214
2686
  setCommandState("idle");
2215
2687
  };
2688
+ const handleStop = async () => {
2689
+ if (currentRequestId && agentId) {
2690
+ try {
2691
+ await aptevaClient.cancelRequest(agentId, currentRequestId);
2692
+ } catch (error) {
2693
+ console.error("Failed to cancel request:", error);
2694
+ }
2695
+ }
2696
+ setIsLoading(false);
2697
+ if (commandState === "loading") {
2698
+ setCommandState("idle");
2699
+ setStreamedContent("");
2700
+ setCurrentToolName(null);
2701
+ setProgress(0);
2702
+ }
2703
+ setCurrentRequestId(null);
2704
+ };
2216
2705
  const isCompact = commandVariant === "compact";
2217
2706
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("flex flex-col h-full", className), children: [
2218
2707
  showHeader && mode === "chat" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "px-4 py-3 flex items-center justify-between", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "!text-lg font-semibold !text-gray-900 dark:!text-white", children: headerTitle }) }),
@@ -2227,7 +2716,8 @@ ${planToExecute}`;
2227
2716
  welcomeIcon,
2228
2717
  suggestedPrompts,
2229
2718
  welcomeVariant,
2230
- onPromptClick: (prompt) => handleSendMessage(prompt)
2719
+ onPromptClick: (prompt) => handleSendMessage(prompt),
2720
+ enableWidgets
2231
2721
  }
2232
2722
  ),
2233
2723
  isLoading && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "px-4 py-2 !text-sm !text-gray-500 dark:!text-gray-400 italic", children: "AI is thinking..." }),
@@ -2237,6 +2727,8 @@ ${planToExecute}`;
2237
2727
  onSendMessage: handleSendMessage,
2238
2728
  placeholder: placeholder || defaultPlaceholder,
2239
2729
  disabled: isLoading,
2730
+ isLoading,
2731
+ onStop: handleStop,
2240
2732
  onFileUpload,
2241
2733
  onSwitchMode: showModeToggle ? () => handleModeChange("command") : void 0
2242
2734
  }
@@ -2250,14 +2742,15 @@ ${planToExecute}`;
2250
2742
  executeCommand(text, files);
2251
2743
  },
2252
2744
  state: commandState,
2253
- response: _optionalChain([commandResult, 'optionalAccess', _67 => _67.data, 'optionalAccess', _68 => _68.summary]) || _optionalChain([commandResult, 'optionalAccess', _69 => _69.message]),
2254
- error: _optionalChain([commandError, 'optionalAccess', _70 => _70.message]),
2745
+ response: _optionalChain([commandResult, 'optionalAccess', _72 => _72.data, 'optionalAccess', _73 => _73.summary]) || _optionalChain([commandResult, 'optionalAccess', _74 => _74.message]),
2746
+ error: _optionalChain([commandError, 'optionalAccess', _75 => _75.message]),
2255
2747
  plan,
2256
2748
  streamedContent,
2257
2749
  toolName: currentToolName,
2258
2750
  onApprove: approvePlan,
2259
2751
  onReject: rejectPlan,
2260
2752
  onReset: resetCommand,
2753
+ onStop: handleStop,
2261
2754
  onExpand: showModeToggle ? () => handleModeChange("chat") : void 0,
2262
2755
  placeholder: placeholder || "Enter your command..."
2263
2756
  }
@@ -2418,13 +2911,13 @@ ${planningInstruction}` : planningInstruction;
2418
2911
  const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
2419
2912
  setError(error2);
2420
2913
  setState("error");
2421
- _optionalChain([onError, 'optionalCall', _71 => _71(error2)]);
2914
+ _optionalChain([onError, 'optionalCall', _76 => _76(error2)]);
2422
2915
  });
2423
2916
  } catch (err) {
2424
2917
  const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
2425
2918
  setError(error2);
2426
2919
  setState("error");
2427
- _optionalChain([onError, 'optionalCall', _72 => _72(error2)]);
2920
+ _optionalChain([onError, 'optionalCall', _77 => _77(error2)]);
2428
2921
  }
2429
2922
  }
2430
2923
  return;
@@ -2435,7 +2928,7 @@ ${planningInstruction}` : planningInstruction;
2435
2928
  setStreamedContent("");
2436
2929
  setCommand("");
2437
2930
  setUploadedFiles([]);
2438
- _optionalChain([onStart, 'optionalCall', _73 => _73()]);
2931
+ _optionalChain([onStart, 'optionalCall', _78 => _78()]);
2439
2932
  try {
2440
2933
  if (useMock) {
2441
2934
  if (enableStreaming) {
@@ -2446,16 +2939,16 @@ ${planningInstruction}` : planningInstruction;
2446
2939
  if (chunk.type === "token" && chunk.content) {
2447
2940
  accumulatedContent += chunk.content;
2448
2941
  setStreamedContent(accumulatedContent);
2449
- _optionalChain([onChunk, 'optionalCall', _74 => _74(chunk.content)]);
2942
+ _optionalChain([onChunk, 'optionalCall', _79 => _79(chunk.content)]);
2450
2943
  const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
2451
2944
  setProgress(estimatedProgress);
2452
- _optionalChain([onProgress, 'optionalCall', _75 => _75(estimatedProgress)]);
2945
+ _optionalChain([onProgress, 'optionalCall', _80 => _80(estimatedProgress)]);
2453
2946
  } else if (chunk.type === "widget" && chunk.widget) {
2454
2947
  const widget = chunk.widget;
2455
2948
  setResult((prev) => ({
2456
2949
  success: true,
2457
- data: _optionalChain([prev, 'optionalAccess', _76 => _76.data]) || {},
2458
- widgets: [..._optionalChain([prev, 'optionalAccess', _77 => _77.widgets]) || [], widget],
2950
+ data: _optionalChain([prev, 'optionalAccess', _81 => _81.data]) || {},
2951
+ widgets: [..._optionalChain([prev, 'optionalAccess', _82 => _82.widgets]) || [], widget],
2459
2952
  message: accumulatedContent || "Command executed successfully"
2460
2953
  }));
2461
2954
  }
@@ -2475,19 +2968,19 @@ ${planningInstruction}` : planningInstruction;
2475
2968
  setResult(result2);
2476
2969
  setState("success");
2477
2970
  setProgress(100);
2478
- _optionalChain([onComplete, 'optionalCall', _78 => _78(result2)]);
2971
+ _optionalChain([onComplete, 'optionalCall', _83 => _83(result2)]);
2479
2972
  },
2480
2973
  (error2) => {
2481
2974
  setError(error2);
2482
2975
  setState("error");
2483
- _optionalChain([onError, 'optionalCall', _79 => _79(error2)]);
2976
+ _optionalChain([onError, 'optionalCall', _84 => _84(error2)]);
2484
2977
  }
2485
2978
  );
2486
2979
  } else {
2487
2980
  const progressInterval = setInterval(() => {
2488
2981
  setProgress((prev) => {
2489
2982
  const next = Math.min(prev + 10, 90);
2490
- _optionalChain([onProgress, 'optionalCall', _80 => _80(next)]);
2983
+ _optionalChain([onProgress, 'optionalCall', _85 => _85(next)]);
2491
2984
  return next;
2492
2985
  });
2493
2986
  }, 200);
@@ -2511,7 +3004,7 @@ ${planningInstruction}` : planningInstruction;
2511
3004
  setResult(result2);
2512
3005
  setState("success");
2513
3006
  setProgress(100);
2514
- _optionalChain([onComplete, 'optionalCall', _81 => _81(result2)]);
3007
+ _optionalChain([onComplete, 'optionalCall', _86 => _86(result2)]);
2515
3008
  }
2516
3009
  } else {
2517
3010
  if (enableStreaming) {
@@ -2557,16 +3050,16 @@ ${commandInstruction}` : commandInstruction;
2557
3050
  if (chunk.type === "token" && chunk.content) {
2558
3051
  accumulatedContent += chunk.content;
2559
3052
  setStreamedContent(accumulatedContent);
2560
- _optionalChain([onChunk, 'optionalCall', _82 => _82(chunk.content)]);
3053
+ _optionalChain([onChunk, 'optionalCall', _87 => _87(chunk.content)]);
2561
3054
  const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
2562
3055
  setProgress(estimatedProgress);
2563
- _optionalChain([onProgress, 'optionalCall', _83 => _83(estimatedProgress)]);
3056
+ _optionalChain([onProgress, 'optionalCall', _88 => _88(estimatedProgress)]);
2564
3057
  } else if (chunk.type === "widget" && chunk.widget) {
2565
3058
  const widget = chunk.widget;
2566
3059
  setResult((prev) => ({
2567
3060
  success: true,
2568
- data: _optionalChain([prev, 'optionalAccess', _84 => _84.data]) || {},
2569
- widgets: [..._optionalChain([prev, 'optionalAccess', _85 => _85.widgets]) || [], widget],
3061
+ data: _optionalChain([prev, 'optionalAccess', _89 => _89.data]) || {},
3062
+ widgets: [..._optionalChain([prev, 'optionalAccess', _90 => _90.widgets]) || [], widget],
2570
3063
  message: accumulatedContent || "Command executed successfully"
2571
3064
  }));
2572
3065
  }
@@ -2586,20 +3079,20 @@ ${commandInstruction}` : commandInstruction;
2586
3079
  setResult(result2);
2587
3080
  setState("success");
2588
3081
  setProgress(100);
2589
- _optionalChain([onComplete, 'optionalCall', _86 => _86(result2)]);
3082
+ _optionalChain([onComplete, 'optionalCall', _91 => _91(result2)]);
2590
3083
  },
2591
3084
  (error2) => {
2592
3085
  const err = error2 instanceof Error ? error2 : new Error("Unknown error");
2593
3086
  setError(err);
2594
3087
  setState("error");
2595
- _optionalChain([onError, 'optionalCall', _87 => _87(err)]);
3088
+ _optionalChain([onError, 'optionalCall', _92 => _92(err)]);
2596
3089
  }
2597
3090
  );
2598
3091
  } else {
2599
3092
  const progressInterval = setInterval(() => {
2600
3093
  setProgress((prev) => {
2601
3094
  const next = Math.min(prev + 10, 90);
2602
- _optionalChain([onProgress, 'optionalCall', _88 => _88(next)]);
3095
+ _optionalChain([onProgress, 'optionalCall', _93 => _93(next)]);
2603
3096
  return next;
2604
3097
  });
2605
3098
  }, 200);
@@ -2655,14 +3148,14 @@ ${commandInstruction}` : commandInstruction;
2655
3148
  setResult(result2);
2656
3149
  setState("success");
2657
3150
  setProgress(100);
2658
- _optionalChain([onComplete, 'optionalCall', _89 => _89(result2)]);
3151
+ _optionalChain([onComplete, 'optionalCall', _94 => _94(result2)]);
2659
3152
  }
2660
3153
  }
2661
3154
  } catch (err) {
2662
3155
  const error2 = err instanceof Error ? err : new Error("Unknown error");
2663
3156
  setError(error2);
2664
3157
  setState("error");
2665
- _optionalChain([onError, 'optionalCall', _90 => _90(error2)]);
3158
+ _optionalChain([onError, 'optionalCall', _95 => _95(error2)]);
2666
3159
  }
2667
3160
  };
2668
3161
  const resetCommand = () => {
@@ -2695,14 +3188,14 @@ ${planToExecute}`;
2695
3188
  };
2696
3189
  const handleFileSelect = async (e) => {
2697
3190
  if (e.target.files && e.target.files.length > 0) {
2698
- _optionalChain([onFileUpload, 'optionalCall', _91 => _91(e.target.files)]);
3191
+ _optionalChain([onFileUpload, 'optionalCall', _96 => _96(e.target.files)]);
2699
3192
  const files = [];
2700
3193
  for (let i = 0; i < e.target.files.length; i++) {
2701
3194
  const file = e.target.files[i];
2702
3195
  const reader = new FileReader();
2703
3196
  await new Promise((resolve) => {
2704
3197
  reader.onload = (event) => {
2705
- if (_optionalChain([event, 'access', _92 => _92.target, 'optionalAccess', _93 => _93.result])) {
3198
+ if (_optionalChain([event, 'access', _97 => _97.target, 'optionalAccess', _98 => _98.result])) {
2706
3199
  const fullDataUrl = event.target.result;
2707
3200
  const base64Data = fullDataUrl.split(",")[1];
2708
3201
  if (file.type.startsWith("image/")) {
@@ -2796,7 +3289,7 @@ ${planToExecute}`;
2796
3289
  enableFileUpload && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2797
3290
  "button",
2798
3291
  {
2799
- onClick: () => _optionalChain([fileInputRef, 'access', _94 => _94.current, 'optionalAccess', _95 => _95.click, 'call', _96 => _96()]),
3292
+ onClick: () => _optionalChain([fileInputRef, 'access', _99 => _99.current, 'optionalAccess', _100 => _100.click, 'call', _101 => _101()]),
2800
3293
  className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0 !text-gray-500 dark:!text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800",
2801
3294
  title: "Attach file",
2802
3295
  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)" }) })
@@ -3015,7 +3508,7 @@ ${planToExecute}`;
3015
3508
  /* @__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" }) }),
3016
3509
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
3017
3510
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-sm font-semibold text-red-800 dark:text-red-400", children: "Error" }),
3018
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-red-700 dark:text-red-300 text-sm mt-1", children: _optionalChain([error, 'optionalAccess', _97 => _97.message]) })
3511
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-red-700 dark:text-red-300 text-sm mt-1", children: _optionalChain([error, 'optionalAccess', _102 => _102.message]) })
3019
3512
  ] })
3020
3513
  ] }) }),
3021
3514
  allowInput && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -3043,7 +3536,7 @@ ${planToExecute}`;
3043
3536
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-green-700 dark:text-green-300 text-sm", children: "Command executed successfully" })
3044
3537
  ] })
3045
3538
  ] }),
3046
- _optionalChain([result, 'access', _98 => _98.data, 'optionalAccess', _99 => _99.summary]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-gray-700 dark:text-gray-300 text-sm leading-relaxed whitespace-pre-line", children: result.data.summary }),
3539
+ _optionalChain([result, 'access', _103 => _103.data, 'optionalAccess', _104 => _104.summary]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-gray-700 dark:text-gray-300 text-sm leading-relaxed whitespace-pre-line", children: result.data.summary }),
3047
3540
  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,
3048
3541
  WidgetRenderer,
3049
3542
  {
@@ -3094,7 +3587,7 @@ ${planToExecute}`;
3094
3587
  enableFileUpload && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3095
3588
  "button",
3096
3589
  {
3097
- onClick: () => _optionalChain([fileInputRef, 'access', _100 => _100.current, 'optionalAccess', _101 => _101.click, 'call', _102 => _102()]),
3590
+ onClick: () => _optionalChain([fileInputRef, 'access', _105 => _105.current, 'optionalAccess', _106 => _106.click, 'call', _107 => _107()]),
3098
3591
  className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0 !text-gray-500 dark:!text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800",
3099
3592
  title: "Attach file",
3100
3593
  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)" }) })
@@ -3280,25 +3773,25 @@ function Prompt({
3280
3773
  const newValue = e.target.value;
3281
3774
  if (!maxLength || newValue.length <= maxLength) {
3282
3775
  setValue(newValue);
3283
- _optionalChain([onChange, 'optionalCall', _103 => _103(newValue)]);
3776
+ _optionalChain([onChange, 'optionalCall', _108 => _108(newValue)]);
3284
3777
  }
3285
3778
  };
3286
3779
  const handleSubmit = async () => {
3287
3780
  if (value.length < minLength) return;
3288
- _optionalChain([onSubmit, 'optionalCall', _104 => _104(value)]);
3781
+ _optionalChain([onSubmit, 'optionalCall', _109 => _109(value)]);
3289
3782
  setIsLoading(true);
3290
3783
  try {
3291
3784
  if (useMock) {
3292
3785
  await new Promise((resolve) => setTimeout(resolve, 1500));
3293
3786
  const mockResult = `Enhanced version: ${value} [AI-generated content]`;
3294
- _optionalChain([onResult, 'optionalCall', _105 => _105(mockResult)]);
3787
+ _optionalChain([onResult, 'optionalCall', _110 => _110(mockResult)]);
3295
3788
  setValue("");
3296
3789
  } else {
3297
3790
  const response = await aptevaClient.chat({
3298
3791
  agent_id: agentId,
3299
3792
  message: value
3300
3793
  });
3301
- _optionalChain([onResult, 'optionalCall', _106 => _106(response.message)]);
3794
+ _optionalChain([onResult, 'optionalCall', _111 => _111(response.message)]);
3302
3795
  setValue("");
3303
3796
  }
3304
3797
  } catch (error) {
@@ -3393,7 +3886,7 @@ function Stream({
3393
3886
  }, [autoStart]);
3394
3887
  const startStreaming = async () => {
3395
3888
  setIsStreaming(true);
3396
- _optionalChain([onStart, 'optionalCall', _107 => _107()]);
3889
+ _optionalChain([onStart, 'optionalCall', _112 => _112()]);
3397
3890
  try {
3398
3891
  if (useMock) {
3399
3892
  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.";
@@ -3401,13 +3894,13 @@ function Stream({
3401
3894
  mockText,
3402
3895
  (chunk) => {
3403
3896
  setText((prev) => prev + chunk);
3404
- _optionalChain([onChunk, 'optionalCall', _108 => _108(chunk)]);
3897
+ _optionalChain([onChunk, 'optionalCall', _113 => _113(chunk)]);
3405
3898
  },
3406
3899
  typingSpeed
3407
3900
  );
3408
3901
  setIsComplete(true);
3409
3902
  setIsStreaming(false);
3410
- _optionalChain([onComplete, 'optionalCall', _109 => _109(text + mockText)]);
3903
+ _optionalChain([onComplete, 'optionalCall', _114 => _114(text + mockText)]);
3411
3904
  } else {
3412
3905
  let accumulatedText = "";
3413
3906
  await aptevaClient.chatStream(
@@ -3420,24 +3913,24 @@ function Stream({
3420
3913
  if (chunk.type === "token" && chunk.content) {
3421
3914
  accumulatedText += chunk.content;
3422
3915
  setText(accumulatedText);
3423
- _optionalChain([onChunk, 'optionalCall', _110 => _110(chunk.content)]);
3916
+ _optionalChain([onChunk, 'optionalCall', _115 => _115(chunk.content)]);
3424
3917
  }
3425
3918
  },
3426
3919
  () => {
3427
3920
  setIsComplete(true);
3428
3921
  setIsStreaming(false);
3429
- _optionalChain([onComplete, 'optionalCall', _111 => _111(accumulatedText)]);
3922
+ _optionalChain([onComplete, 'optionalCall', _116 => _116(accumulatedText)]);
3430
3923
  },
3431
3924
  (error) => {
3432
3925
  const err = error instanceof Error ? error : new Error("Streaming error");
3433
- _optionalChain([onError, 'optionalCall', _112 => _112(err)]);
3926
+ _optionalChain([onError, 'optionalCall', _117 => _117(err)]);
3434
3927
  setIsStreaming(false);
3435
3928
  }
3436
3929
  );
3437
3930
  }
3438
3931
  } catch (error) {
3439
3932
  const err = error instanceof Error ? error : new Error("Streaming error");
3440
- _optionalChain([onError, 'optionalCall', _113 => _113(err)]);
3933
+ _optionalChain([onError, 'optionalCall', _118 => _118(err)]);
3441
3934
  setIsStreaming(false);
3442
3935
  }
3443
3936
  };
@@ -3529,7 +4022,7 @@ function ThreadList({
3529
4022
  }) {
3530
4023
  const [searchQuery, setSearchQuery] = _react.useState.call(void 0, "");
3531
4024
  const filteredThreads = threads.filter(
3532
- (thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || _optionalChain([thread, 'access', _114 => _114.preview, 'optionalAccess', _115 => _115.toLowerCase, 'call', _116 => _116(), 'access', _117 => _117.includes, 'call', _118 => _118(searchQuery.toLowerCase())])
4025
+ (thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || _optionalChain([thread, 'access', _119 => _119.preview, 'optionalAccess', _120 => _120.toLowerCase, 'call', _121 => _121(), 'access', _122 => _122.includes, 'call', _123 => _123(searchQuery.toLowerCase())])
3533
4026
  );
3534
4027
  const groupedThreads = groupBy === "date" ? groupThreadsByDate(filteredThreads) : { All: filteredThreads };
3535
4028
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col h-full", children: [
@@ -3551,8 +4044,8 @@ function ThreadList({
3551
4044
  {
3552
4045
  thread,
3553
4046
  isActive: thread.id === currentThreadId,
3554
- onSelect: () => _optionalChain([onThreadSelect, 'optionalCall', _119 => _119(thread.id)]),
3555
- onDelete: () => _optionalChain([onThreadDelete, 'optionalCall', _120 => _120(thread.id)])
4047
+ onSelect: () => _optionalChain([onThreadSelect, 'optionalCall', _124 => _124(thread.id)]),
4048
+ onDelete: () => _optionalChain([onThreadDelete, 'optionalCall', _125 => _125(thread.id)])
3556
4049
  },
3557
4050
  thread.id
3558
4051
  ))
@@ -3614,7 +4107,7 @@ function Threads({
3614
4107
  threads.slice(0, 5).map((thread) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3615
4108
  "button",
3616
4109
  {
3617
- onClick: () => _optionalChain([onThreadSelect, 'optionalCall', _121 => _121(thread.id)]),
4110
+ onClick: () => _optionalChain([onThreadSelect, 'optionalCall', _126 => _126(thread.id)]),
3618
4111
  className: cn(
3619
4112
  "px-4 py-2 whitespace-nowrap font-medium transition-colors",
3620
4113
  thread.id === currentThreadId ? "border-b-2 border-apteva-500 text-apteva-500" : "text-gray-600 hover:text-gray-900"