@apteva/apteva-kit 0.1.17 → 0.1.22

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
@@ -9,6 +9,9 @@ var _react = require('react'); var _react2 = _interopRequireDefault(_react);
9
9
  // src/components/Chat/MessageList.tsx
10
10
 
11
11
 
12
+ // src/components/Chat/Message.tsx
13
+
14
+
12
15
  // src/utils/cn.ts
13
16
  var _clsx = require('clsx');
14
17
  var _tailwindmerge = require('tailwind-merge');
@@ -498,6 +501,246 @@ function validateFile(file) {
498
501
  return { valid: true };
499
502
  }
500
503
 
504
+ // src/utils/widget-parser.ts
505
+ function simpleHash(str) {
506
+ let hash = 0;
507
+ for (let i = 0; i < str.length; i++) {
508
+ const char = str.charCodeAt(i);
509
+ hash = (hash << 5) - hash + char;
510
+ hash = hash & hash;
511
+ }
512
+ return Math.abs(hash).toString(36);
513
+ }
514
+ function findMatchingBracket(text, startIndex) {
515
+ let depth = 0;
516
+ let inString = false;
517
+ let escapeNext = false;
518
+ for (let i = startIndex; i < text.length; i++) {
519
+ const char = text[i];
520
+ if (escapeNext) {
521
+ escapeNext = false;
522
+ continue;
523
+ }
524
+ if (char === "\\" && inString) {
525
+ escapeNext = true;
526
+ continue;
527
+ }
528
+ if (char === '"') {
529
+ inString = !inString;
530
+ continue;
531
+ }
532
+ if (inString) continue;
533
+ if (char === "[" || char === "{") {
534
+ depth++;
535
+ } else if (char === "]" || char === "}") {
536
+ depth--;
537
+ if (depth === 0) {
538
+ return i;
539
+ }
540
+ }
541
+ }
542
+ return -1;
543
+ }
544
+ function parseWidgetsFromText(text) {
545
+ const segments = [];
546
+ let hasWidgets = false;
547
+ let hasPendingWidget = false;
548
+ let currentIndex = 0;
549
+ let pendingWidgetType = null;
550
+ let processText = text;
551
+ const lastWidgetStart = text.lastIndexOf("@ui:");
552
+ if (lastWidgetStart !== -1) {
553
+ const afterStart = text.slice(lastWidgetStart);
554
+ const typeMatch = afterStart.match(/^@ui:(\w+)/);
555
+ if (typeMatch) {
556
+ const widgetType = typeMatch[1];
557
+ const bracketOpenIndex = afterStart.indexOf("[");
558
+ if (bracketOpenIndex === -1) {
559
+ processText = text.slice(0, lastWidgetStart);
560
+ pendingWidgetType = widgetType;
561
+ hasPendingWidget = true;
562
+ } else {
563
+ const fullBracketStart = lastWidgetStart + bracketOpenIndex;
564
+ const bracketEnd = findMatchingBracket(text, fullBracketStart);
565
+ if (bracketEnd === -1) {
566
+ processText = text.slice(0, lastWidgetStart);
567
+ pendingWidgetType = widgetType;
568
+ hasPendingWidget = true;
569
+ }
570
+ }
571
+ }
572
+ }
573
+ if (hasPendingWidget) {
574
+ processText = processText.replace(/[\s:;\-–—\.]+$/g, "");
575
+ }
576
+ const startPattern = /@ui:(\w+)\[/g;
577
+ let match;
578
+ while ((match = startPattern.exec(processText)) !== null) {
579
+ const widgetType = match[1];
580
+ const bracketStart = match.index + match[0].length - 1;
581
+ const bracketEnd = findMatchingBracket(processText, bracketStart);
582
+ if (bracketEnd === -1) {
583
+ continue;
584
+ }
585
+ const jsonContent = processText.slice(bracketStart + 1, bracketEnd);
586
+ if (match.index > currentIndex) {
587
+ const textContent = processText.slice(currentIndex, match.index).trim();
588
+ if (textContent) {
589
+ segments.push({
590
+ type: "text",
591
+ content: textContent
592
+ });
593
+ }
594
+ }
595
+ try {
596
+ const trimmedJson = jsonContent.trim();
597
+ const props = JSON.parse(trimmedJson);
598
+ const widgetId = `widget-${widgetType}-${simpleHash(trimmedJson)}`;
599
+ segments.push({
600
+ type: "widget",
601
+ widget: {
602
+ type: widgetType,
603
+ id: widgetId,
604
+ props
605
+ }
606
+ });
607
+ hasWidgets = true;
608
+ } catch (e) {
609
+ }
610
+ currentIndex = bracketEnd + 1;
611
+ startPattern.lastIndex = currentIndex;
612
+ }
613
+ if (currentIndex < processText.length) {
614
+ const remainingText = processText.slice(currentIndex).trim();
615
+ if (remainingText) {
616
+ segments.push({
617
+ type: "text",
618
+ content: remainingText
619
+ });
620
+ }
621
+ }
622
+ if (segments.length === 0 && processText.trim()) {
623
+ segments.push({
624
+ type: "text",
625
+ content: processText.trim()
626
+ });
627
+ }
628
+ if (pendingWidgetType) {
629
+ segments.push({
630
+ type: "widget_pending",
631
+ pendingType: pendingWidgetType
632
+ });
633
+ }
634
+ return { segments, hasWidgets, hasPendingWidget };
635
+ }
636
+
637
+ // src/utils/widget-context.ts
638
+ var WIDGET_DEFINITIONS = {
639
+ card: {
640
+ description: "Displays a card with title and optional description, image, footer",
641
+ schema: '{"title": "string", "description?": "string", "image?": "url", "footer?": "string"}',
642
+ example: '@ui:card[{"title": "Summary", "description": "Key findings from the analysis"}]'
643
+ },
644
+ list: {
645
+ description: "Displays a list of items with title, subtitle, and optional description",
646
+ schema: '{"items": [{"id": "string", "title": "string", "subtitle?": "string", "description?": "string", "image?": "url"}]}',
647
+ example: '@ui:list[{"items": [{"id": "1", "title": "First item", "subtitle": "Details"}]}]'
648
+ },
649
+ button_group: {
650
+ description: "Displays action buttons. User clicks are sent back to you with the button id",
651
+ schema: '{"buttons": [{"id": "string", "label": "string", "variant?": "primary|secondary|outline"}], "layout?": "horizontal|vertical"}',
652
+ example: '@ui:button_group[{"buttons": [{"id": "confirm", "label": "Confirm", "variant": "primary"}, {"id": "cancel", "label": "Cancel"}]}]'
653
+ },
654
+ form: {
655
+ description: "Displays an input form. Submitted data is sent back to you",
656
+ schema: '{"title?": "string", "fields": [{"name": "string", "type": "text|number|select|checkbox|textarea|date", "label": "string", "required?": boolean, "placeholder?": "string", "options?": [{"label": "string", "value": "string"}]}]}',
657
+ example: '@ui:form[{"title": "Contact", "fields": [{"name": "email", "type": "text", "label": "Email", "required": true}]}]'
658
+ },
659
+ image: {
660
+ description: "Displays a single image with optional caption",
661
+ schema: '{"src": "url", "alt": "string", "caption?": "string"}',
662
+ example: '@ui:image[{"src": "https://example.com/img.png", "alt": "Description", "caption": "Figure 1"}]'
663
+ },
664
+ gallery: {
665
+ description: "Displays multiple images in a grid or carousel layout",
666
+ schema: '{"images": [{"id": "string", "src": "url", "alt": "string", "caption?": "string"}], "layout?": "grid|carousel"}',
667
+ example: '@ui:gallery[{"images": [{"id": "1", "src": "https://example.com/1.png", "alt": "Image 1"}], "layout": "grid"}]'
668
+ },
669
+ chart: {
670
+ description: "Displays a chart visualization (line, bar, pie, doughnut)",
671
+ schema: '{"chartType": "line|bar|pie|doughnut", "title?": "string", "data": {"labels": ["string"], "datasets": [{"label": "string", "data": [number], "backgroundColor?": "string|string[]"}]}}',
672
+ example: '@ui:chart[{"chartType": "bar", "title": "Sales", "data": {"labels": ["Q1", "Q2"], "datasets": [{"label": "Revenue", "data": [100, 150]}]}}]'
673
+ },
674
+ map: {
675
+ description: "Displays an interactive map with optional markers",
676
+ schema: '{"center": {"lat": number, "lng": number}, "zoom?": number, "markers?": [{"id": "string", "position": {"lat": number, "lng": number}, "title": "string"}]}',
677
+ example: '@ui:map[{"center": {"lat": 40.7128, "lng": -74.0060}, "zoom": 12, "markers": [{"id": "1", "position": {"lat": 40.7128, "lng": -74.0060}, "title": "NYC"}]}]'
678
+ },
679
+ table: {
680
+ description: "Displays structured data in rows and columns",
681
+ schema: '{"columns": [{"key": "string", "label": "string", "align?": "left|center|right"}], "rows": [{"id?": "string", ...}], "caption?": "string", "compact?": boolean, "striped?": boolean}',
682
+ example: '@ui:table[{"columns": [{"key": "name", "label": "Name"}, {"key": "status", "label": "Status"}], "rows": [{"name": "Item 1", "status": "Active"}, {"name": "Item 2", "status": "Pending"}]}]'
683
+ }
684
+ };
685
+ var ALL_WIDGET_TYPES = Object.keys(WIDGET_DEFINITIONS);
686
+ function generateWidgetContext(enabledWidgets) {
687
+ const widgets = enabledWidgets || ALL_WIDGET_TYPES;
688
+ let context = `
689
+ ## Available UI Widgets
690
+
691
+ `;
692
+ context += `You can render rich UI components in your responses using this syntax: @ui:type[{json_props}]
693
+
694
+ `;
695
+ context += `The widget syntax will be automatically converted to interactive UI. Users see the rendered widget, not the raw syntax.
696
+
697
+ `;
698
+ context += `### Available widgets:
699
+
700
+ `;
701
+ for (const type of widgets) {
702
+ const def = WIDGET_DEFINITIONS[type];
703
+ if (!def) continue;
704
+ context += `**${type}** - ${def.description}
705
+ `;
706
+ context += `Schema: \`${def.schema}\`
707
+ `;
708
+ context += `Example: \`${def.example}\`
709
+
710
+ `;
711
+ }
712
+ context += `### Important notes:
713
+ `;
714
+ context += `- JSON must be valid (use double quotes for strings)
715
+ `;
716
+ context += `- Widget actions (button clicks, form submissions) are sent back to you
717
+ `;
718
+ context += `- You can include multiple widgets in a single response
719
+ `;
720
+ context += `- Combine widgets with regular text for context
721
+ `;
722
+ return context;
723
+ }
724
+ function generateCompactWidgetContext(enabledWidgets) {
725
+ const widgets = enabledWidgets || ALL_WIDGET_TYPES;
726
+ let context = `
727
+ UI Widgets: Use @ui:type[{props}] syntax.
728
+ `;
729
+ context += `Available: ${widgets.join(", ")}
730
+ `;
731
+ context += `Examples:
732
+ `;
733
+ const examples = ["card", "list", "button_group"].filter((w) => widgets.includes(w));
734
+ for (const type of examples) {
735
+ const def = WIDGET_DEFINITIONS[type];
736
+ if (def) {
737
+ context += `${def.example}
738
+ `;
739
+ }
740
+ }
741
+ return context;
742
+ }
743
+
501
744
  // src/components/Widgets/Widgets.tsx
502
745
 
503
746
 
@@ -642,6 +885,82 @@ function ButtonGroup({ widget, onAction }) {
642
885
  );
643
886
  }
644
887
 
888
+ // src/components/Widgets/widget-library/Table.tsx
889
+
890
+ function Table({ widget, onAction }) {
891
+ const { columns, rows, caption, compact = false, striped = false } = widget.props;
892
+ const getAlignment = (align) => {
893
+ switch (align) {
894
+ case "center":
895
+ return "text-center";
896
+ case "right":
897
+ return "text-right";
898
+ default:
899
+ return "text-left";
900
+ }
901
+ };
902
+ 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: [
903
+ 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 }),
904
+ /* @__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,
905
+ "th",
906
+ {
907
+ className: cn(
908
+ "font-semibold text-gray-900 dark:text-white",
909
+ compact ? "px-3 py-2 text-xs" : "px-4 py-3 text-sm",
910
+ getAlignment(column.align)
911
+ ),
912
+ style: column.width ? { width: column.width } : void 0,
913
+ children: column.label
914
+ },
915
+ column.key
916
+ )) }) }),
917
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "tbody", { children: [
918
+ rows.map((row, rowIndex) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
919
+ "tr",
920
+ {
921
+ className: cn(
922
+ "border-b border-gray-200 dark:border-gray-700 last:border-b-0",
923
+ "transition-colors hover:bg-gray-50 dark:hover:bg-gray-800",
924
+ striped && rowIndex % 2 === 1 && "bg-gray-50/50 dark:bg-gray-800/50"
925
+ ),
926
+ onClick: () => {
927
+ if (widget.actions && widget.actions.length > 0) {
928
+ _optionalChain([onAction, 'optionalCall', _15 => _15({
929
+ type: widget.actions[0].type,
930
+ payload: row,
931
+ widgetId: widget.id,
932
+ timestamp: /* @__PURE__ */ new Date()
933
+ })]);
934
+ }
935
+ },
936
+ style: { cursor: _optionalChain([widget, 'access', _16 => _16.actions, 'optionalAccess', _17 => _17.length]) ? "pointer" : "default" },
937
+ children: columns.map((column) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
938
+ "td",
939
+ {
940
+ className: cn(
941
+ "text-gray-700 dark:text-gray-300",
942
+ compact ? "px-3 py-2 text-xs" : "px-4 py-3 text-sm",
943
+ getAlignment(column.align)
944
+ ),
945
+ children: _nullishCoalesce(row[column.key], () => ( "\u2014"))
946
+ },
947
+ column.key
948
+ ))
949
+ },
950
+ row.id || rowIndex
951
+ )),
952
+ rows.length === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tr", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
953
+ "td",
954
+ {
955
+ colSpan: columns.length,
956
+ className: "px-4 py-8 text-center text-sm text-gray-500 dark:text-gray-400",
957
+ children: "No data available"
958
+ }
959
+ ) })
960
+ ] })
961
+ ] }) }) });
962
+ }
963
+
645
964
  // src/components/Widgets/WidgetRenderer.tsx
646
965
 
647
966
  function WidgetRenderer({ widget, onAction }) {
@@ -654,6 +973,8 @@ function WidgetRenderer({ widget, onAction }) {
654
973
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { widget, onAction });
655
974
  case "button_group":
656
975
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ButtonGroup, { widget, onAction });
976
+ case "table":
977
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Table, { widget, onAction });
657
978
  default:
658
979
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "p-4 border border-yellow-300 bg-yellow-50 rounded-lg", children: [
659
980
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "text-sm text-yellow-800", children: [
@@ -678,7 +999,7 @@ function Widgets({
678
999
  }) {
679
1000
  _react.useEffect.call(void 0, () => {
680
1001
  widgets.forEach((widget) => {
681
- _optionalChain([onWidgetMount, 'optionalCall', _15 => _15(widget.id)]);
1002
+ _optionalChain([onWidgetMount, 'optionalCall', _18 => _18(widget.id)]);
682
1003
  });
683
1004
  }, [widgets, onWidgetMount]);
684
1005
  const layoutClasses = {
@@ -694,19 +1015,147 @@ function Widgets({
694
1015
  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
1016
  }
696
1017
 
1018
+ // src/components/Widgets/WidgetSkeleton.tsx
1019
+
1020
+ function WidgetSkeleton({ type, className }) {
1021
+ switch (type) {
1022
+ case "card":
1023
+ 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: [
1024
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-3/4" }),
1025
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-200 dark:bg-gray-700 rounded w-full" }),
1026
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-200 dark:bg-gray-700 rounded w-5/6" })
1027
+ ] }) });
1028
+ case "list":
1029
+ 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: [
1030
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-10 h-10 bg-gray-200 dark:bg-gray-700 rounded-full flex-shrink-0" }),
1031
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 space-y-2", children: [
1032
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-200 dark:bg-gray-700 rounded w-1/2" }),
1033
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-2 bg-gray-200 dark:bg-gray-700 rounded w-3/4" })
1034
+ ] })
1035
+ ] }, i)) });
1036
+ case "button_group":
1037
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("animate-pulse flex gap-2", className), children: [
1038
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-9 bg-gray-200 dark:bg-gray-700 rounded-lg w-20" }),
1039
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-9 bg-gray-200 dark:bg-gray-700 rounded-lg w-20" }),
1040
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-9 bg-gray-200 dark:bg-gray-700 rounded-lg w-20" })
1041
+ ] });
1042
+ case "form":
1043
+ 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: [
1044
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-1/3" }),
1045
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-3", children: [
1046
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" }),
1047
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
1048
+ ] }),
1049
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-9 bg-gray-200 dark:bg-gray-700 rounded w-24" })
1050
+ ] });
1051
+ case "chart":
1052
+ 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: [
1053
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-1/4 mb-4" }),
1054
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-end gap-2 h-32", children: [
1055
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 bg-gray-200 dark:bg-gray-700 rounded-t h-1/2" }),
1056
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 bg-gray-200 dark:bg-gray-700 rounded-t h-3/4" }),
1057
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 bg-gray-200 dark:bg-gray-700 rounded-t h-1/3" }),
1058
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 bg-gray-200 dark:bg-gray-700 rounded-t h-full" }),
1059
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 bg-gray-200 dark:bg-gray-700 rounded-t h-2/3" })
1060
+ ] })
1061
+ ] });
1062
+ case "image":
1063
+ 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" }) });
1064
+ case "gallery":
1065
+ 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)) });
1066
+ case "map":
1067
+ 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: [
1068
+ /* @__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" }),
1069
+ /* @__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" })
1070
+ ] }) }) });
1071
+ case "table":
1072
+ 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: [
1073
+ /* @__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: [
1074
+ /* @__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" }) }),
1075
+ /* @__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" }) }),
1076
+ /* @__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" }) })
1077
+ ] }),
1078
+ [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: [
1079
+ /* @__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" }) }),
1080
+ /* @__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" }) }),
1081
+ /* @__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" }) })
1082
+ ] }, i))
1083
+ ] });
1084
+ default:
1085
+ 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: [
1086
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-1/2 mb-2" }),
1087
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 bg-gray-200 dark:bg-gray-700 rounded w-full" })
1088
+ ] });
1089
+ }
1090
+ }
1091
+
697
1092
  // src/components/Chat/MarkdownContent.tsx
698
1093
 
1094
+ function isImageUrl(url) {
1095
+ const imageExtensions = /\.(jpg|jpeg|png|gif|webp|svg|bmp|ico)(\?.*)?$/i;
1096
+ return imageExtensions.test(url);
1097
+ }
699
1098
  function parseInlineMarkdown(text, keyPrefix = "") {
700
1099
  const result = [];
701
- const boldRegex = /(\*\*|__)(.+?)\1/g;
1100
+ const inlineRegex = /!\[([^\]]*)\]\(([^)]+)\)|\[([^\]]+)\]\(([^)]+)\)|(\*\*|__)(.+?)\5|`([^`]+)`/g;
702
1101
  let lastIndex = 0;
703
1102
  let match;
704
1103
  let key = 0;
705
- while ((match = boldRegex.exec(text)) !== null) {
1104
+ while ((match = inlineRegex.exec(text)) !== null) {
706
1105
  if (match.index > lastIndex) {
707
1106
  result.push(text.slice(lastIndex, match.index));
708
1107
  }
709
- result.push(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: match[2] }, `${keyPrefix}b${key++}`));
1108
+ if (match[1] !== void 0 || match[2] !== void 0) {
1109
+ const alt = match[1] || "";
1110
+ const src = match[2];
1111
+ result.push(
1112
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1113
+ "img",
1114
+ {
1115
+ src,
1116
+ alt,
1117
+ className: "apteva-md-img"
1118
+ },
1119
+ `${keyPrefix}img${key++}`
1120
+ )
1121
+ );
1122
+ } else if (match[3] !== void 0 || match[4] !== void 0) {
1123
+ const linkText = match[3];
1124
+ const href = match[4];
1125
+ if (isImageUrl(href)) {
1126
+ result.push(
1127
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1128
+ "img",
1129
+ {
1130
+ src: href,
1131
+ alt: linkText,
1132
+ className: "apteva-md-img"
1133
+ },
1134
+ `${keyPrefix}img${key++}`
1135
+ )
1136
+ );
1137
+ } else {
1138
+ result.push(
1139
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1140
+ "a",
1141
+ {
1142
+ href,
1143
+ target: "_blank",
1144
+ rel: "noopener noreferrer",
1145
+ className: "apteva-md-link",
1146
+ children: linkText
1147
+ },
1148
+ `${keyPrefix}a${key++}`
1149
+ )
1150
+ );
1151
+ }
1152
+ } else if (match[5] !== void 0) {
1153
+ result.push(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: match[6] }, `${keyPrefix}b${key++}`));
1154
+ } else if (match[7] !== void 0) {
1155
+ result.push(
1156
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "code", { className: "apteva-md-inline-code", children: match[7] }, `${keyPrefix}code${key++}`)
1157
+ );
1158
+ }
710
1159
  lastIndex = match.index + match[0].length;
711
1160
  }
712
1161
  if (lastIndex < text.length) {
@@ -780,7 +1229,7 @@ function parseMarkdown(content) {
780
1229
  const tableMatch = line.match(/^\|(.+)\|$/);
781
1230
  if (tableMatch && i + 1 < lines.length) {
782
1231
  const separatorLine = lines[i + 1];
783
- const separatorMatch = separatorLine.match(/^\|[\s:-]+\|$/);
1232
+ const separatorMatch = separatorLine.match(/^\|([\s:-]+\|)+$/);
784
1233
  if (separatorMatch) {
785
1234
  const headerCells = line.split("|").filter((cell) => cell.trim() !== "").map((cell) => cell.trim());
786
1235
  i += 2;
@@ -825,30 +1274,108 @@ function MarkdownContent({ content, className = "" }) {
825
1274
  // src/components/Chat/ToolCall.tsx
826
1275
 
827
1276
  function ToolCall({ name, status }) {
828
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-tool-call", children: [
829
- status === "running" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-tool-call-dot apteva-tool-call-dot-running" }),
830
- status === "completed" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-tool-call-dot apteva-tool-call-dot-completed" }),
831
- status === "error" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-tool-call-dot apteva-tool-call-dot-error" }),
832
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-tool-call-name", children: name }),
833
- status === "running" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-tool-call-status", children: "Running..." }),
834
- status === "completed" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-tool-call-status apteva-tool-call-status-completed", children: "Completed" }),
835
- status === "error" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-tool-call-status apteva-tool-call-status-error", children: "Error" })
1277
+ if (status === "running") {
1278
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 px-3 py-2 rounded-xl bg-blue-50 dark:bg-blue-900/30 border border-blue-200 dark:border-blue-700 !text-blue-700 dark:!text-blue-300 text-sm", children: [
1279
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { className: "w-4 h-4 animate-spin", fill: "none", viewBox: "0 0 24 24", children: [
1280
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
1281
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
1282
+ ] }),
1283
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { children: [
1284
+ "Calling ",
1285
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: name }),
1286
+ "..."
1287
+ ] })
1288
+ ] });
1289
+ }
1290
+ if (status === "completed") {
1291
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 px-3 py-2 rounded-xl bg-green-50 dark:bg-green-900/30 border border-green-200 dark:border-green-700 !text-green-700 dark:!text-green-300 text-sm", children: [
1292
+ /* @__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: "M5 13l4 4L19 7" }) }),
1293
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { children: [
1294
+ "Tool completed: ",
1295
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: name })
1296
+ ] })
1297
+ ] });
1298
+ }
1299
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 px-3 py-2 rounded-xl bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-700 !text-red-700 dark:!text-red-300 text-sm", children: [
1300
+ /* @__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: "M6 18L18 6M6 6l12 12" }) }),
1301
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { children: [
1302
+ "Tool failed: ",
1303
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: name })
1304
+ ] })
836
1305
  ] });
837
1306
  }
838
1307
 
839
1308
  // src/components/Chat/Message.tsx
840
1309
 
841
- function Message({ message, onAction }) {
1310
+ function Message({ message, onAction, enableWidgets, onWidgetRender }) {
842
1311
  const isUser = message.role === "user";
843
- const contentSegments = _optionalChain([message, 'access', _16 => _16.metadata, 'optionalAccess', _17 => _17.content_segments]);
1312
+ const contentSegments = _optionalChain([message, 'access', _19 => _19.metadata, 'optionalAccess', _20 => _20.content_segments]);
1313
+ const isStreaming = _optionalChain([message, 'access', _21 => _21.metadata, 'optionalAccess', _22 => _22.isStreaming]) === true;
1314
+ const hasContent = message.content || contentSegments && contentSegments.length > 0;
1315
+ const reportedWidgetsRef = _react.useRef.call(void 0, /* @__PURE__ */ new Set());
1316
+ const parsedWidgets = _react.useMemo.call(void 0, () => {
1317
+ if (!enableWidgets || isUser || !message.content) {
1318
+ return [];
1319
+ }
1320
+ const parsed = parseWidgetsFromText(message.content);
1321
+ return parsed.segments.filter((seg) => seg.type === "widget" && !!seg.widget).map((seg) => seg.widget);
1322
+ }, [enableWidgets, isUser, message.content]);
1323
+ _react.useEffect.call(void 0, () => {
1324
+ if (onWidgetRender && message.widgets) {
1325
+ for (const widget of message.widgets) {
1326
+ if (!reportedWidgetsRef.current.has(widget.id)) {
1327
+ reportedWidgetsRef.current.add(widget.id);
1328
+ onWidgetRender(widget);
1329
+ }
1330
+ }
1331
+ }
1332
+ }, [message.widgets, onWidgetRender]);
1333
+ _react.useEffect.call(void 0, () => {
1334
+ if (onWidgetRender && parsedWidgets.length > 0) {
1335
+ for (const widget of parsedWidgets) {
1336
+ if (!reportedWidgetsRef.current.has(widget.id)) {
1337
+ reportedWidgetsRef.current.add(widget.id);
1338
+ onWidgetRender(widget);
1339
+ }
1340
+ }
1341
+ }
1342
+ }, [parsedWidgets, onWidgetRender]);
1343
+ const renderTextContent = (text) => {
1344
+ if (!enableWidgets || isUser) {
1345
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MarkdownContent, { content: text });
1346
+ }
1347
+ const parsed = parseWidgetsFromText(text);
1348
+ if (parsed.segments.length === 0) {
1349
+ return null;
1350
+ }
1351
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: parsed.segments.map((segment, index) => {
1352
+ if (segment.type === "text" && segment.content) {
1353
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MarkdownContent, { content: segment.content }, `text-${index}`);
1354
+ }
1355
+ if (segment.type === "widget" && segment.widget) {
1356
+ 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}`);
1357
+ }
1358
+ if (segment.type === "widget_pending" && segment.pendingType) {
1359
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "my-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, WidgetSkeleton, { type: segment.pendingType }) }, `pending-${index}`);
1360
+ }
1361
+ return null;
1362
+ }) });
1363
+ };
844
1364
  const renderContent = () => {
845
1365
  if (isUser) {
846
1366
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "whitespace-pre-wrap !text-sm leading-relaxed", children: message.content });
847
1367
  }
1368
+ if (isStreaming && !hasContent) {
1369
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-typing-indicator !text-gray-400", children: [
1370
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", {}),
1371
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", {}),
1372
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", {})
1373
+ ] });
1374
+ }
848
1375
  if (contentSegments && contentSegments.length > 0) {
849
1376
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: contentSegments.map((segment, index) => {
850
1377
  if (segment.type === "text") {
851
- return segment.content ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MarkdownContent, { content: segment.content }, `text-${index}`) : null;
1378
+ return segment.content ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: renderTextContent(segment.content) }, `text-${index}`) : null;
852
1379
  } else if (segment.type === "tool") {
853
1380
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "my-2", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
854
1381
  ToolCall,
@@ -861,19 +1388,19 @@ function Message({ message, onAction }) {
861
1388
  return null;
862
1389
  }) });
863
1390
  }
864
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MarkdownContent, { content: message.content });
1391
+ return renderTextContent(message.content);
865
1392
  };
866
1393
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
867
1394
  "div",
868
1395
  {
869
1396
  className: cn(
870
- "max-w-[80%]",
871
- isUser ? "px-4 py-2.5 rounded-xl bg-gray-100 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 !text-gray-900 dark:!text-gray-100 ml-auto" : "!text-gray-900 dark:!text-gray-100"
1397
+ "max-w-[80%] px-4 py-2.5 rounded-2xl",
1398
+ isUser ? "bg-blue-600 !text-white rounded-br-md" : "bg-gray-100 dark:bg-gray-800 !text-gray-900 dark:!text-gray-100 rounded-bl-md"
872
1399
  ),
873
1400
  children: [
874
1401
  renderContent(),
875
1402
  message.widgets && message.widgets.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn(isUser ? "mt-3" : "mt-2"), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Widgets, { widgets: message.widgets, onAction, layout: "stack" }) }),
876
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("!text-xs opacity-70", isUser ? "mt-1.5 !text-gray-500 dark:!text-gray-400" : "mt-1 !text-gray-500 dark:!text-gray-400"), suppressHydrationWarning: true, children: message.timestamp.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) })
1403
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("!text-xs mt-1.5", isUser ? "!text-blue-200" : "!text-gray-500 dark:!text-gray-400"), suppressHydrationWarning: true, children: message.timestamp.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) })
877
1404
  ]
878
1405
  }
879
1406
  );
@@ -1030,7 +1557,9 @@ function MessageList({
1030
1557
  welcomeIcon,
1031
1558
  suggestedPrompts,
1032
1559
  welcomeVariant,
1033
- onPromptClick
1560
+ onPromptClick,
1561
+ enableWidgets,
1562
+ onWidgetRender
1034
1563
  }) {
1035
1564
  const listRef = _react.useRef.call(void 0, null);
1036
1565
  _react.useEffect.call(void 0, () => {
@@ -1049,13 +1578,13 @@ function MessageList({
1049
1578
  onPromptClick: onPromptClick || (() => {
1050
1579
  })
1051
1580
  }
1052
- ) : messages.map((message) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Message, { message, onAction }, message.id)) });
1581
+ ) : messages.map((message) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `flex ${message.role === "user" ? "justify-end" : "justify-start"}`, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Message, { message, onAction, enableWidgets, onWidgetRender }) }, message.id)) });
1053
1582
  }
1054
1583
 
1055
1584
  // src/components/Chat/Composer.tsx
1056
1585
 
1057
1586
 
1058
- function Composer({ onSendMessage, placeholder = "Type a message...", disabled = false, onFileUpload, onSwitchMode }) {
1587
+ function Composer({ onSendMessage, placeholder = "Type a message...", disabled = false, isLoading = false, onStop, onFileUpload, onSwitchMode }) {
1059
1588
  const [text, setText] = _react.useState.call(void 0, "");
1060
1589
  const [showMenu, setShowMenu] = _react.useState.call(void 0, false);
1061
1590
  const [pendingFiles, setPendingFiles] = _react.useState.call(void 0, []);
@@ -1112,7 +1641,7 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
1112
1641
  setFileError(errors.join(", "));
1113
1642
  setTimeout(() => setFileError(null), 5e3);
1114
1643
  }
1115
- _optionalChain([onFileUpload, 'optionalCall', _18 => _18(e.target.files)]);
1644
+ _optionalChain([onFileUpload, 'optionalCall', _23 => _23(e.target.files)]);
1116
1645
  setShowMenu(false);
1117
1646
  e.target.value = "";
1118
1647
  }
@@ -1182,15 +1711,15 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
1182
1711
  {
1183
1712
  className: "fixed bg-gray-800 dark:bg-gray-700 rounded-xl shadow-lg overflow-hidden z-[9999] min-w-[200px]",
1184
1713
  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
1714
+ left: _nullishCoalesce(_optionalChain([menuButtonRef, 'access', _24 => _24.current, 'optionalAccess', _25 => _25.getBoundingClientRect, 'call', _26 => _26(), 'access', _27 => _27.left]), () => ( 0)),
1715
+ top: (_nullishCoalesce(_optionalChain([menuButtonRef, 'access', _28 => _28.current, 'optionalAccess', _29 => _29.getBoundingClientRect, 'call', _30 => _30(), 'access', _31 => _31.bottom]), () => ( 0))) + 8
1187
1716
  },
1188
1717
  children: [
1189
1718
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1190
1719
  "button",
1191
1720
  {
1192
1721
  onClick: () => {
1193
- _optionalChain([fileInputRef, 'access', _27 => _27.current, 'optionalAccess', _28 => _28.click, 'call', _29 => _29()]);
1722
+ _optionalChain([fileInputRef, 'access', _32 => _32.current, 'optionalAccess', _33 => _33.click, 'call', _34 => _34()]);
1194
1723
  setShowMenu(false);
1195
1724
  },
1196
1725
  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 +1762,15 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
1233
1762
  style: { maxHeight: "120px" }
1234
1763
  }
1235
1764
  ),
1236
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1765
+ isLoading && onStop ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1766
+ "button",
1767
+ {
1768
+ onClick: onStop,
1769
+ 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",
1770
+ title: "Stop generation",
1771
+ 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" }) })
1772
+ }
1773
+ ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1237
1774
  "button",
1238
1775
  {
1239
1776
  onClick: handleSend,
@@ -1272,6 +1809,7 @@ function CommandComposer({
1272
1809
  onApprove,
1273
1810
  onReject,
1274
1811
  onReset,
1812
+ onStop,
1275
1813
  onExpand,
1276
1814
  placeholder = "Enter your command...",
1277
1815
  disabled = false
@@ -1300,8 +1838,8 @@ function CommandComposer({
1300
1838
  }
1301
1839
  };
1302
1840
  const handleNewCommand = () => {
1303
- _optionalChain([onReset, 'optionalCall', _30 => _30()]);
1304
- _optionalChain([inputRef, 'access', _31 => _31.current, 'optionalAccess', _32 => _32.focus, 'call', _33 => _33()]);
1841
+ _optionalChain([onReset, 'optionalCall', _35 => _35()]);
1842
+ _optionalChain([inputRef, 'access', _36 => _36.current, 'optionalAccess', _37 => _37.focus, 'call', _38 => _38()]);
1305
1843
  };
1306
1844
  const handleInputChange = (value) => {
1307
1845
  setInput(value);
@@ -1415,15 +1953,15 @@ function CommandComposer({
1415
1953
  {
1416
1954
  className: "fixed bg-gray-800 dark:bg-gray-700 rounded-xl shadow-lg overflow-hidden z-[9999] min-w-[200px]",
1417
1955
  style: {
1418
- left: _nullishCoalesce(_optionalChain([menuButtonRef, 'access', _34 => _34.current, 'optionalAccess', _35 => _35.getBoundingClientRect, 'call', _36 => _36(), 'access', _37 => _37.left]), () => ( 0)),
1419
- top: (_nullishCoalesce(_optionalChain([menuButtonRef, 'access', _38 => _38.current, 'optionalAccess', _39 => _39.getBoundingClientRect, 'call', _40 => _40(), 'access', _41 => _41.bottom]), () => ( 0))) + 8
1956
+ left: _nullishCoalesce(_optionalChain([menuButtonRef, 'access', _39 => _39.current, 'optionalAccess', _40 => _40.getBoundingClientRect, 'call', _41 => _41(), 'access', _42 => _42.left]), () => ( 0)),
1957
+ top: (_nullishCoalesce(_optionalChain([menuButtonRef, 'access', _43 => _43.current, 'optionalAccess', _44 => _44.getBoundingClientRect, 'call', _45 => _45(), 'access', _46 => _46.bottom]), () => ( 0))) + 8
1420
1958
  },
1421
1959
  children: [
1422
1960
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1423
1961
  "button",
1424
1962
  {
1425
1963
  onClick: () => {
1426
- _optionalChain([fileInputRef, 'access', _42 => _42.current, 'optionalAccess', _43 => _43.click, 'call', _44 => _44()]);
1964
+ _optionalChain([fileInputRef, 'access', _47 => _47.current, 'optionalAccess', _48 => _48.click, 'call', _49 => _49()]);
1427
1965
  setShowMenu(false);
1428
1966
  },
1429
1967
  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",
@@ -1528,6 +2066,15 @@ function CommandComposer({
1528
2066
  }
1529
2067
  )
1530
2068
  ] }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2069
+ state === "loading" && onStop && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2070
+ "button",
2071
+ {
2072
+ onClick: onStop,
2073
+ 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",
2074
+ title: "Stop generation",
2075
+ 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" }) })
2076
+ }
2077
+ ),
1531
2078
  (state === "success" || state === "error") && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1532
2079
  "button",
1533
2080
  {
@@ -1655,7 +2202,7 @@ var AptevaClient = class {
1655
2202
  const error = await response.json().catch(() => ({ error: "Request failed" }));
1656
2203
  throw new Error(error.error || `Request failed with status ${response.status}`);
1657
2204
  }
1658
- const reader = _optionalChain([response, 'access', _45 => _45.body, 'optionalAccess', _46 => _46.getReader, 'call', _47 => _47()]);
2205
+ const reader = _optionalChain([response, 'access', _50 => _50.body, 'optionalAccess', _51 => _51.getReader, 'call', _52 => _52()]);
1659
2206
  if (!reader) {
1660
2207
  throw new Error("Response body is not readable");
1661
2208
  }
@@ -1673,7 +2220,7 @@ var AptevaClient = class {
1673
2220
  if (line.startsWith("data: ")) {
1674
2221
  const data = line.slice(6);
1675
2222
  if (data === "[DONE]") {
1676
- _optionalChain([onComplete, 'optionalCall', _48 => _48(threadId)]);
2223
+ _optionalChain([onComplete, 'optionalCall', _53 => _53(threadId)]);
1677
2224
  return;
1678
2225
  }
1679
2226
  try {
@@ -1688,10 +2235,10 @@ var AptevaClient = class {
1688
2235
  }
1689
2236
  }
1690
2237
  }
1691
- _optionalChain([onComplete, 'optionalCall', _49 => _49(threadId)]);
2238
+ _optionalChain([onComplete, 'optionalCall', _54 => _54(threadId)]);
1692
2239
  } catch (error) {
1693
2240
  const err = error instanceof Error ? error : new Error("Unknown error");
1694
- _optionalChain([onError, 'optionalCall', _50 => _50(err)]);
2241
+ _optionalChain([onError, 'optionalCall', _55 => _55(err)]);
1695
2242
  throw err;
1696
2243
  }
1697
2244
  }
@@ -1731,6 +2278,27 @@ var AptevaClient = class {
1731
2278
  const data = await response.json();
1732
2279
  return data.messages;
1733
2280
  }
2281
+ /**
2282
+ * Cancel an in-progress request
2283
+ */
2284
+ async cancelRequest(agentId, requestId) {
2285
+ try {
2286
+ const response = await fetch(`${this.config.apiUrl}/agents/${agentId}/requests/${requestId}/cancel`, {
2287
+ method: "POST",
2288
+ headers: {
2289
+ "Content-Type": "application/json",
2290
+ "X-API-Key": this.config.apiKey
2291
+ }
2292
+ });
2293
+ if (!response.ok) {
2294
+ const error = await response.json().catch(() => ({ error: "Cancel request failed" }));
2295
+ throw new Error(error.error || `Cancel request failed with status ${response.status}`);
2296
+ }
2297
+ } catch (error) {
2298
+ console.error("[AptevaClient] Cancel request error:", error);
2299
+ throw error;
2300
+ }
2301
+ }
1734
2302
  };
1735
2303
  var aptevaClient = new AptevaClient();
1736
2304
 
@@ -1773,12 +2341,18 @@ function Chat({
1773
2341
  placeholder,
1774
2342
  showHeader = true,
1775
2343
  headerTitle = "Chat",
2344
+ // Widget detection
2345
+ enableWidgets = false,
2346
+ availableWidgets,
2347
+ compactWidgetContext = false,
2348
+ onWidgetRender,
1776
2349
  className
1777
2350
  }) {
1778
2351
  const [messages, setMessages] = _react.useState.call(void 0, initialMessages);
1779
2352
  const [isLoading, setIsLoading] = _react.useState.call(void 0, false);
1780
2353
  const [currentThreadId, setCurrentThreadId] = _react.useState.call(void 0, threadId || null);
1781
2354
  const [mode, setMode] = _react.useState.call(void 0, initialMode);
2355
+ const [chatToolName, setChatToolName] = _react.useState.call(void 0, null);
1782
2356
  const [commandState, setCommandState] = _react.useState.call(void 0, "idle");
1783
2357
  const [commandResult, setCommandResult] = _react.useState.call(void 0, null);
1784
2358
  const [commandError, setCommandError] = _react.useState.call(void 0, null);
@@ -1786,11 +2360,18 @@ function Chat({
1786
2360
  const [commandInput, setCommandInput] = _react.useState.call(void 0, "");
1787
2361
  const [streamedContent, setStreamedContent] = _react.useState.call(void 0, "");
1788
2362
  const [currentToolName, setCurrentToolName] = _react.useState.call(void 0, null);
2363
+ const [currentRequestId, setCurrentRequestId] = _react.useState.call(void 0, null);
1789
2364
  const [plan, setPlan] = _react.useState.call(void 0, "");
1790
2365
  const [pendingCommand, setPendingCommand] = _react.useState.call(void 0, "");
1791
2366
  const [internalPlanMode, setInternalPlanMode] = _react.useState.call(void 0, planMode);
1792
2367
  const [showSettingsMenu, setShowSettingsMenu] = _react.useState.call(void 0, false);
1793
2368
  const fileInputRef = _react.useRef.call(void 0, null);
2369
+ const effectiveContext = _react.useMemo.call(void 0, () => {
2370
+ if (!enableWidgets) return context;
2371
+ const widgetContext = compactWidgetContext ? generateCompactWidgetContext(availableWidgets) : generateWidgetContext(availableWidgets);
2372
+ return context ? `${context}
2373
+ ${widgetContext}` : widgetContext;
2374
+ }, [context, enableWidgets, availableWidgets, compactWidgetContext]);
1794
2375
  _react.useEffect.call(void 0, () => {
1795
2376
  if (apiUrl || apiKey) {
1796
2377
  aptevaClient.configure({
@@ -1801,7 +2382,7 @@ function Chat({
1801
2382
  }, [apiUrl, apiKey]);
1802
2383
  _react.useEffect.call(void 0, () => {
1803
2384
  if (threadId) {
1804
- _optionalChain([onThreadChange, 'optionalCall', _51 => _51(threadId)]);
2385
+ _optionalChain([onThreadChange, 'optionalCall', _56 => _56(threadId)]);
1805
2386
  }
1806
2387
  }, [threadId, onThreadChange]);
1807
2388
  _react.useEffect.call(void 0, () => {
@@ -1819,7 +2400,7 @@ function Chat({
1819
2400
  }, [showSettingsMenu]);
1820
2401
  const handleModeChange = (newMode) => {
1821
2402
  setMode(newMode);
1822
- _optionalChain([onModeChange, 'optionalCall', _52 => _52(newMode)]);
2403
+ _optionalChain([onModeChange, 'optionalCall', _57 => _57(newMode)]);
1823
2404
  if (newMode === "command") {
1824
2405
  setCommandState("idle");
1825
2406
  setCommandResult(null);
@@ -1839,7 +2420,7 @@ function Chat({
1839
2420
  metadata: hasFiles ? { attachments: fileNames } : void 0
1840
2421
  };
1841
2422
  setMessages((prev) => [...prev, userMessage]);
1842
- _optionalChain([onMessageSent, 'optionalCall', _53 => _53(userMessage)]);
2423
+ _optionalChain([onMessageSent, 'optionalCall', _58 => _58(userMessage)]);
1843
2424
  setIsLoading(true);
1844
2425
  try {
1845
2426
  const messagePayload = await buildMessageWithAttachments(text, files);
@@ -1852,6 +2433,7 @@ function Chat({
1852
2433
  let accumulatedWidgets = [];
1853
2434
  let responseThreadId = currentThreadId;
1854
2435
  let toolInputBuffer = "";
2436
+ const streamingMessageId = `msg-${Date.now()}`;
1855
2437
  const updateMessage = () => {
1856
2438
  const segments = [...contentSegments];
1857
2439
  if (currentTextBuffer) {
@@ -1871,19 +2453,19 @@ function Chat({
1871
2453
  ...lastMessage,
1872
2454
  content: currentTextBuffer,
1873
2455
  widgets: accumulatedWidgets.length > 0 ? accumulatedWidgets : void 0,
1874
- metadata: { ...lastMessage.metadata, content_segments: segments }
2456
+ metadata: { ...lastMessage.metadata, content_segments: segments, isStreaming: true }
1875
2457
  }
1876
2458
  ];
1877
2459
  } else {
1878
2460
  return [
1879
2461
  ...prev,
1880
2462
  {
1881
- id: `msg-${Date.now()}-streaming`,
2463
+ id: streamingMessageId,
1882
2464
  role: "assistant",
1883
2465
  content: currentTextBuffer,
1884
2466
  widgets: accumulatedWidgets.length > 0 ? accumulatedWidgets : void 0,
1885
2467
  timestamp: /* @__PURE__ */ new Date(),
1886
- metadata: { content_segments: segments }
2468
+ metadata: { content_segments: segments, isStreaming: true }
1887
2469
  }
1888
2470
  ];
1889
2471
  }
@@ -1895,7 +2477,7 @@ function Chat({
1895
2477
  message: messagePayload,
1896
2478
  stream: true,
1897
2479
  ...currentThreadId && { thread_id: currentThreadId },
1898
- ...context && { system: context }
2480
+ ...effectiveContext && { system: effectiveContext }
1899
2481
  },
1900
2482
  (chunk) => {
1901
2483
  switch (chunk.type) {
@@ -1904,10 +2486,15 @@ function Chat({
1904
2486
  responseThreadId = chunk.thread_id;
1905
2487
  if (!currentThreadId) {
1906
2488
  setCurrentThreadId(chunk.thread_id);
1907
- _optionalChain([onThreadChange, 'optionalCall', _54 => _54(chunk.thread_id)]);
2489
+ _optionalChain([onThreadChange, 'optionalCall', _59 => _59(chunk.thread_id)]);
1908
2490
  }
1909
2491
  }
1910
2492
  break;
2493
+ case "request_id":
2494
+ if (chunk.request_id) {
2495
+ setCurrentRequestId(chunk.request_id);
2496
+ }
2497
+ break;
1911
2498
  case "content":
1912
2499
  case "token":
1913
2500
  if (chunk.content) {
@@ -1923,6 +2510,7 @@ function Chat({
1923
2510
  }
1924
2511
  contentSegments.push({ type: "tool", id: chunk.tool_id, name: chunk.tool_name });
1925
2512
  toolInputBuffer = "";
2513
+ setChatToolName(chunk.tool_name);
1926
2514
  updateMessage();
1927
2515
  }
1928
2516
  break;
@@ -1936,8 +2524,9 @@ function Chat({
1936
2524
  const toolSegment = contentSegments.find((s) => s.type === "tool" && s.id === chunk.tool_id);
1937
2525
  if (toolSegment) {
1938
2526
  toolSegment.result = chunk.content;
1939
- _optionalChain([onToolResult, 'optionalCall', _55 => _55(toolSegment.name, chunk.content)]);
2527
+ _optionalChain([onToolResult, 'optionalCall', _60 => _60(toolSegment.name, chunk.content)]);
1940
2528
  }
2529
+ setChatToolName(null);
1941
2530
  updateMessage();
1942
2531
  }
1943
2532
  break;
@@ -1967,10 +2556,10 @@ function Chat({
1967
2556
  ...prev.slice(0, -1),
1968
2557
  {
1969
2558
  ...lastMessage,
1970
- id: `msg-${Date.now()}`,
2559
+ // Keep the same ID to avoid React remounting the component
1971
2560
  content: currentTextBuffer || "Response received",
1972
2561
  widgets: accumulatedWidgets.length > 0 ? accumulatedWidgets : void 0,
1973
- metadata: { thread_id: threadId2, content_segments: contentSegments }
2562
+ metadata: { thread_id: threadId2, content_segments: contentSegments, isStreaming: false }
1974
2563
  }
1975
2564
  ];
1976
2565
  }
@@ -1978,9 +2567,11 @@ function Chat({
1978
2567
  });
1979
2568
  if (threadId2 && threadId2 !== currentThreadId) {
1980
2569
  setCurrentThreadId(threadId2);
1981
- _optionalChain([onThreadChange, 'optionalCall', _56 => _56(threadId2)]);
2570
+ _optionalChain([onThreadChange, 'optionalCall', _61 => _61(threadId2)]);
1982
2571
  }
1983
2572
  setIsLoading(false);
2573
+ setCurrentRequestId(null);
2574
+ setChatToolName(null);
1984
2575
  },
1985
2576
  (error) => {
1986
2577
  const errorMessage = {
@@ -1998,7 +2589,9 @@ function Chat({
1998
2589
  return [...prev, errorMessage];
1999
2590
  });
2000
2591
  setIsLoading(false);
2001
- _optionalChain([onError, 'optionalCall', _57 => _57(error)]);
2592
+ setCurrentRequestId(null);
2593
+ setChatToolName(null);
2594
+ _optionalChain([onError, 'optionalCall', _62 => _62(error)]);
2002
2595
  }
2003
2596
  );
2004
2597
  }
@@ -2011,7 +2604,7 @@ function Chat({
2011
2604
  metadata: { error: true }
2012
2605
  };
2013
2606
  setMessages((prev) => [...prev, errorMessage]);
2014
- _optionalChain([onError, 'optionalCall', _58 => _58(error instanceof Error ? error : new Error("Unknown error"))]);
2607
+ _optionalChain([onError, 'optionalCall', _63 => _63(error instanceof Error ? error : new Error("Unknown error"))]);
2015
2608
  } finally {
2016
2609
  setIsLoading(false);
2017
2610
  }
@@ -2040,7 +2633,7 @@ function Chat({
2040
2633
  } else {
2041
2634
  try {
2042
2635
  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.`;
2043
- const systemMessage = context ? `${context}
2636
+ const systemMessage = effectiveContext ? `${effectiveContext}
2044
2637
 
2045
2638
  ${planningInstruction}` : planningInstruction;
2046
2639
  const response = await aptevaClient.chat({
@@ -2056,7 +2649,7 @@ ${planningInstruction}` : planningInstruction;
2056
2649
  const error = err instanceof Error ? err : new Error("Failed to generate plan");
2057
2650
  setCommandError(error);
2058
2651
  setCommandState("error");
2059
- _optionalChain([onError, 'optionalCall', _59 => _59(error)]);
2652
+ _optionalChain([onError, 'optionalCall', _64 => _64(error)]);
2060
2653
  }
2061
2654
  }
2062
2655
  return;
@@ -2089,12 +2682,12 @@ ${planningInstruction}` : planningInstruction;
2089
2682
  setCommandResult(result);
2090
2683
  setCommandState("success");
2091
2684
  setProgress(100);
2092
- _optionalChain([onComplete, 'optionalCall', _60 => _60(result)]);
2685
+ _optionalChain([onComplete, 'optionalCall', _65 => _65(result)]);
2093
2686
  },
2094
2687
  (error) => {
2095
2688
  setCommandError(error);
2096
2689
  setCommandState("error");
2097
- _optionalChain([onError, 'optionalCall', _61 => _61(error)]);
2690
+ _optionalChain([onError, 'optionalCall', _66 => _66(error)]);
2098
2691
  }
2099
2692
  );
2100
2693
  } else {
@@ -2107,11 +2700,11 @@ ${planningInstruction}` : planningInstruction;
2107
2700
  setCommandResult(result);
2108
2701
  setCommandState("success");
2109
2702
  setProgress(100);
2110
- _optionalChain([onComplete, 'optionalCall', _62 => _62(result)]);
2703
+ _optionalChain([onComplete, 'optionalCall', _67 => _67(result)]);
2111
2704
  }
2112
2705
  } else {
2113
2706
  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.`;
2114
- const systemMessage = context ? `${context}
2707
+ const systemMessage = effectiveContext ? `${effectiveContext}
2115
2708
 
2116
2709
  ${commandInstruction}` : commandInstruction;
2117
2710
  const messagePayload = files && files.length > 0 ? await buildMessageWithAttachments(currentCommand, files) : currentCommand;
@@ -2139,13 +2732,15 @@ ${commandInstruction}` : commandInstruction;
2139
2732
  accumulatedContent = "";
2140
2733
  setStreamedContent("");
2141
2734
  } else if (chunk.type === "tool_result") {
2142
- _optionalChain([onToolResult, 'optionalCall', _63 => _63(lastToolName, chunk.content)]);
2735
+ _optionalChain([onToolResult, 'optionalCall', _68 => _68(lastToolName, chunk.content)]);
2143
2736
  setCurrentToolName(null);
2144
2737
  } else if (chunk.type === "thread_id" && chunk.thread_id) {
2145
2738
  if (!currentThreadId) {
2146
2739
  setCurrentThreadId(chunk.thread_id);
2147
- _optionalChain([onThreadChange, 'optionalCall', _64 => _64(chunk.thread_id)]);
2740
+ _optionalChain([onThreadChange, 'optionalCall', _69 => _69(chunk.thread_id)]);
2148
2741
  }
2742
+ } else if (chunk.type === "request_id" && chunk.request_id) {
2743
+ setCurrentRequestId(chunk.request_id);
2149
2744
  }
2150
2745
  },
2151
2746
  (threadId2) => {
@@ -2157,12 +2752,14 @@ ${commandInstruction}` : commandInstruction;
2157
2752
  setCommandResult(result);
2158
2753
  setCommandState("success");
2159
2754
  setProgress(100);
2160
- _optionalChain([onComplete, 'optionalCall', _65 => _65(result)]);
2755
+ setCurrentRequestId(null);
2756
+ _optionalChain([onComplete, 'optionalCall', _70 => _70(result)]);
2161
2757
  },
2162
2758
  (error) => {
2163
2759
  setCommandError(error);
2164
2760
  setCommandState("error");
2165
- _optionalChain([onError, 'optionalCall', _66 => _66(error)]);
2761
+ setCurrentRequestId(null);
2762
+ _optionalChain([onError, 'optionalCall', _71 => _71(error)]);
2166
2763
  }
2167
2764
  );
2168
2765
  } else {
@@ -2182,14 +2779,14 @@ ${commandInstruction}` : commandInstruction;
2182
2779
  setCommandResult(result);
2183
2780
  setCommandState("success");
2184
2781
  setProgress(100);
2185
- _optionalChain([onComplete, 'optionalCall', _67 => _67(result)]);
2782
+ _optionalChain([onComplete, 'optionalCall', _72 => _72(result)]);
2186
2783
  }
2187
2784
  }
2188
2785
  } catch (err) {
2189
2786
  const error = err instanceof Error ? err : new Error("Unknown error");
2190
2787
  setCommandError(error);
2191
2788
  setCommandState("error");
2192
- _optionalChain([onError, 'optionalCall', _68 => _68(error)]);
2789
+ _optionalChain([onError, 'optionalCall', _73 => _73(error)]);
2193
2790
  }
2194
2791
  };
2195
2792
  const resetCommand = () => {
@@ -2218,9 +2815,32 @@ ${planToExecute}`;
2218
2815
  setPendingCommand("");
2219
2816
  setCommandState("idle");
2220
2817
  };
2818
+ const handleStop = async () => {
2819
+ if (currentRequestId && agentId) {
2820
+ try {
2821
+ await aptevaClient.cancelRequest(agentId, currentRequestId);
2822
+ } catch (error) {
2823
+ console.error("Failed to cancel request:", error);
2824
+ }
2825
+ }
2826
+ setIsLoading(false);
2827
+ if (commandState === "loading") {
2828
+ setCommandState("idle");
2829
+ setStreamedContent("");
2830
+ setCurrentToolName(null);
2831
+ setProgress(0);
2832
+ }
2833
+ setCurrentRequestId(null);
2834
+ };
2221
2835
  const isCompact = commandVariant === "compact";
2222
2836
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("flex flex-col h-full", className), children: [
2223
- 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 }) }),
2837
+ showHeader && mode === "chat" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "px-4 py-3 flex items-center justify-between", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
2838
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "!text-lg font-semibold !text-gray-900 dark:!text-white", children: headerTitle }),
2839
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: cn(
2840
+ "!text-xs",
2841
+ isLoading ? chatToolName ? "!text-blue-500 dark:!text-blue-400" : "!text-gray-400 dark:!text-gray-500" : "!text-gray-400 dark:!text-gray-500"
2842
+ ), children: isLoading ? chatToolName ? `Using ${chatToolName}...` : "Thinking..." : "Ready" })
2843
+ ] }) }),
2224
2844
  mode === "chat" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2225
2845
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2226
2846
  MessageList,
@@ -2232,16 +2852,19 @@ ${planToExecute}`;
2232
2852
  welcomeIcon,
2233
2853
  suggestedPrompts,
2234
2854
  welcomeVariant,
2235
- onPromptClick: (prompt) => handleSendMessage(prompt)
2855
+ onPromptClick: (prompt) => handleSendMessage(prompt),
2856
+ enableWidgets,
2857
+ onWidgetRender
2236
2858
  }
2237
2859
  ),
2238
- 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..." }),
2239
2860
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2240
2861
  Composer,
2241
2862
  {
2242
2863
  onSendMessage: handleSendMessage,
2243
2864
  placeholder: placeholder || defaultPlaceholder,
2244
2865
  disabled: isLoading,
2866
+ isLoading,
2867
+ onStop: handleStop,
2245
2868
  onFileUpload,
2246
2869
  onSwitchMode: showModeToggle ? () => handleModeChange("command") : void 0
2247
2870
  }
@@ -2255,14 +2878,15 @@ ${planToExecute}`;
2255
2878
  executeCommand(text, files);
2256
2879
  },
2257
2880
  state: commandState,
2258
- response: _optionalChain([commandResult, 'optionalAccess', _69 => _69.data, 'optionalAccess', _70 => _70.summary]) || _optionalChain([commandResult, 'optionalAccess', _71 => _71.message]),
2259
- error: _optionalChain([commandError, 'optionalAccess', _72 => _72.message]),
2881
+ response: _optionalChain([commandResult, 'optionalAccess', _74 => _74.data, 'optionalAccess', _75 => _75.summary]) || _optionalChain([commandResult, 'optionalAccess', _76 => _76.message]),
2882
+ error: _optionalChain([commandError, 'optionalAccess', _77 => _77.message]),
2260
2883
  plan,
2261
2884
  streamedContent,
2262
2885
  toolName: currentToolName,
2263
2886
  onApprove: approvePlan,
2264
2887
  onReject: rejectPlan,
2265
2888
  onReset: resetCommand,
2889
+ onStop: handleStop,
2266
2890
  onExpand: showModeToggle ? () => handleModeChange("chat") : void 0,
2267
2891
  placeholder: placeholder || "Enter your command..."
2268
2892
  }
@@ -2423,13 +3047,13 @@ ${planningInstruction}` : planningInstruction;
2423
3047
  const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
2424
3048
  setError(error2);
2425
3049
  setState("error");
2426
- _optionalChain([onError, 'optionalCall', _73 => _73(error2)]);
3050
+ _optionalChain([onError, 'optionalCall', _78 => _78(error2)]);
2427
3051
  });
2428
3052
  } catch (err) {
2429
3053
  const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
2430
3054
  setError(error2);
2431
3055
  setState("error");
2432
- _optionalChain([onError, 'optionalCall', _74 => _74(error2)]);
3056
+ _optionalChain([onError, 'optionalCall', _79 => _79(error2)]);
2433
3057
  }
2434
3058
  }
2435
3059
  return;
@@ -2440,7 +3064,7 @@ ${planningInstruction}` : planningInstruction;
2440
3064
  setStreamedContent("");
2441
3065
  setCommand("");
2442
3066
  setUploadedFiles([]);
2443
- _optionalChain([onStart, 'optionalCall', _75 => _75()]);
3067
+ _optionalChain([onStart, 'optionalCall', _80 => _80()]);
2444
3068
  try {
2445
3069
  if (useMock) {
2446
3070
  if (enableStreaming) {
@@ -2451,16 +3075,16 @@ ${planningInstruction}` : planningInstruction;
2451
3075
  if (chunk.type === "token" && chunk.content) {
2452
3076
  accumulatedContent += chunk.content;
2453
3077
  setStreamedContent(accumulatedContent);
2454
- _optionalChain([onChunk, 'optionalCall', _76 => _76(chunk.content)]);
3078
+ _optionalChain([onChunk, 'optionalCall', _81 => _81(chunk.content)]);
2455
3079
  const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
2456
3080
  setProgress(estimatedProgress);
2457
- _optionalChain([onProgress, 'optionalCall', _77 => _77(estimatedProgress)]);
3081
+ _optionalChain([onProgress, 'optionalCall', _82 => _82(estimatedProgress)]);
2458
3082
  } else if (chunk.type === "widget" && chunk.widget) {
2459
3083
  const widget = chunk.widget;
2460
3084
  setResult((prev) => ({
2461
3085
  success: true,
2462
- data: _optionalChain([prev, 'optionalAccess', _78 => _78.data]) || {},
2463
- widgets: [..._optionalChain([prev, 'optionalAccess', _79 => _79.widgets]) || [], widget],
3086
+ data: _optionalChain([prev, 'optionalAccess', _83 => _83.data]) || {},
3087
+ widgets: [..._optionalChain([prev, 'optionalAccess', _84 => _84.widgets]) || [], widget],
2464
3088
  message: accumulatedContent || "Command executed successfully"
2465
3089
  }));
2466
3090
  }
@@ -2480,19 +3104,19 @@ ${planningInstruction}` : planningInstruction;
2480
3104
  setResult(result2);
2481
3105
  setState("success");
2482
3106
  setProgress(100);
2483
- _optionalChain([onComplete, 'optionalCall', _80 => _80(result2)]);
3107
+ _optionalChain([onComplete, 'optionalCall', _85 => _85(result2)]);
2484
3108
  },
2485
3109
  (error2) => {
2486
3110
  setError(error2);
2487
3111
  setState("error");
2488
- _optionalChain([onError, 'optionalCall', _81 => _81(error2)]);
3112
+ _optionalChain([onError, 'optionalCall', _86 => _86(error2)]);
2489
3113
  }
2490
3114
  );
2491
3115
  } else {
2492
3116
  const progressInterval = setInterval(() => {
2493
3117
  setProgress((prev) => {
2494
3118
  const next = Math.min(prev + 10, 90);
2495
- _optionalChain([onProgress, 'optionalCall', _82 => _82(next)]);
3119
+ _optionalChain([onProgress, 'optionalCall', _87 => _87(next)]);
2496
3120
  return next;
2497
3121
  });
2498
3122
  }, 200);
@@ -2516,7 +3140,7 @@ ${planningInstruction}` : planningInstruction;
2516
3140
  setResult(result2);
2517
3141
  setState("success");
2518
3142
  setProgress(100);
2519
- _optionalChain([onComplete, 'optionalCall', _83 => _83(result2)]);
3143
+ _optionalChain([onComplete, 'optionalCall', _88 => _88(result2)]);
2520
3144
  }
2521
3145
  } else {
2522
3146
  if (enableStreaming) {
@@ -2562,16 +3186,16 @@ ${commandInstruction}` : commandInstruction;
2562
3186
  if (chunk.type === "token" && chunk.content) {
2563
3187
  accumulatedContent += chunk.content;
2564
3188
  setStreamedContent(accumulatedContent);
2565
- _optionalChain([onChunk, 'optionalCall', _84 => _84(chunk.content)]);
3189
+ _optionalChain([onChunk, 'optionalCall', _89 => _89(chunk.content)]);
2566
3190
  const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
2567
3191
  setProgress(estimatedProgress);
2568
- _optionalChain([onProgress, 'optionalCall', _85 => _85(estimatedProgress)]);
3192
+ _optionalChain([onProgress, 'optionalCall', _90 => _90(estimatedProgress)]);
2569
3193
  } else if (chunk.type === "widget" && chunk.widget) {
2570
3194
  const widget = chunk.widget;
2571
3195
  setResult((prev) => ({
2572
3196
  success: true,
2573
- data: _optionalChain([prev, 'optionalAccess', _86 => _86.data]) || {},
2574
- widgets: [..._optionalChain([prev, 'optionalAccess', _87 => _87.widgets]) || [], widget],
3197
+ data: _optionalChain([prev, 'optionalAccess', _91 => _91.data]) || {},
3198
+ widgets: [..._optionalChain([prev, 'optionalAccess', _92 => _92.widgets]) || [], widget],
2575
3199
  message: accumulatedContent || "Command executed successfully"
2576
3200
  }));
2577
3201
  }
@@ -2591,20 +3215,20 @@ ${commandInstruction}` : commandInstruction;
2591
3215
  setResult(result2);
2592
3216
  setState("success");
2593
3217
  setProgress(100);
2594
- _optionalChain([onComplete, 'optionalCall', _88 => _88(result2)]);
3218
+ _optionalChain([onComplete, 'optionalCall', _93 => _93(result2)]);
2595
3219
  },
2596
3220
  (error2) => {
2597
3221
  const err = error2 instanceof Error ? error2 : new Error("Unknown error");
2598
3222
  setError(err);
2599
3223
  setState("error");
2600
- _optionalChain([onError, 'optionalCall', _89 => _89(err)]);
3224
+ _optionalChain([onError, 'optionalCall', _94 => _94(err)]);
2601
3225
  }
2602
3226
  );
2603
3227
  } else {
2604
3228
  const progressInterval = setInterval(() => {
2605
3229
  setProgress((prev) => {
2606
3230
  const next = Math.min(prev + 10, 90);
2607
- _optionalChain([onProgress, 'optionalCall', _90 => _90(next)]);
3231
+ _optionalChain([onProgress, 'optionalCall', _95 => _95(next)]);
2608
3232
  return next;
2609
3233
  });
2610
3234
  }, 200);
@@ -2660,14 +3284,14 @@ ${commandInstruction}` : commandInstruction;
2660
3284
  setResult(result2);
2661
3285
  setState("success");
2662
3286
  setProgress(100);
2663
- _optionalChain([onComplete, 'optionalCall', _91 => _91(result2)]);
3287
+ _optionalChain([onComplete, 'optionalCall', _96 => _96(result2)]);
2664
3288
  }
2665
3289
  }
2666
3290
  } catch (err) {
2667
3291
  const error2 = err instanceof Error ? err : new Error("Unknown error");
2668
3292
  setError(error2);
2669
3293
  setState("error");
2670
- _optionalChain([onError, 'optionalCall', _92 => _92(error2)]);
3294
+ _optionalChain([onError, 'optionalCall', _97 => _97(error2)]);
2671
3295
  }
2672
3296
  };
2673
3297
  const resetCommand = () => {
@@ -2700,14 +3324,14 @@ ${planToExecute}`;
2700
3324
  };
2701
3325
  const handleFileSelect = async (e) => {
2702
3326
  if (e.target.files && e.target.files.length > 0) {
2703
- _optionalChain([onFileUpload, 'optionalCall', _93 => _93(e.target.files)]);
3327
+ _optionalChain([onFileUpload, 'optionalCall', _98 => _98(e.target.files)]);
2704
3328
  const files = [];
2705
3329
  for (let i = 0; i < e.target.files.length; i++) {
2706
3330
  const file = e.target.files[i];
2707
3331
  const reader = new FileReader();
2708
3332
  await new Promise((resolve) => {
2709
3333
  reader.onload = (event) => {
2710
- if (_optionalChain([event, 'access', _94 => _94.target, 'optionalAccess', _95 => _95.result])) {
3334
+ if (_optionalChain([event, 'access', _99 => _99.target, 'optionalAccess', _100 => _100.result])) {
2711
3335
  const fullDataUrl = event.target.result;
2712
3336
  const base64Data = fullDataUrl.split(",")[1];
2713
3337
  if (file.type.startsWith("image/")) {
@@ -2801,7 +3425,7 @@ ${planToExecute}`;
2801
3425
  enableFileUpload && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2802
3426
  "button",
2803
3427
  {
2804
- onClick: () => _optionalChain([fileInputRef, 'access', _96 => _96.current, 'optionalAccess', _97 => _97.click, 'call', _98 => _98()]),
3428
+ onClick: () => _optionalChain([fileInputRef, 'access', _101 => _101.current, 'optionalAccess', _102 => _102.click, 'call', _103 => _103()]),
2805
3429
  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",
2806
3430
  title: "Attach file",
2807
3431
  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)" }) })
@@ -3020,7 +3644,7 @@ ${planToExecute}`;
3020
3644
  /* @__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" }) }),
3021
3645
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
3022
3646
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-sm font-semibold text-red-800 dark:text-red-400", children: "Error" }),
3023
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-red-700 dark:text-red-300 text-sm mt-1", children: _optionalChain([error, 'optionalAccess', _99 => _99.message]) })
3647
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-red-700 dark:text-red-300 text-sm mt-1", children: _optionalChain([error, 'optionalAccess', _104 => _104.message]) })
3024
3648
  ] })
3025
3649
  ] }) }),
3026
3650
  allowInput && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -3048,7 +3672,7 @@ ${planToExecute}`;
3048
3672
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-green-700 dark:text-green-300 text-sm", children: "Command executed successfully" })
3049
3673
  ] })
3050
3674
  ] }),
3051
- _optionalChain([result, 'access', _100 => _100.data, 'optionalAccess', _101 => _101.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 }),
3675
+ _optionalChain([result, 'access', _105 => _105.data, 'optionalAccess', _106 => _106.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 }),
3052
3676
  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,
3053
3677
  WidgetRenderer,
3054
3678
  {
@@ -3099,7 +3723,7 @@ ${planToExecute}`;
3099
3723
  enableFileUpload && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3100
3724
  "button",
3101
3725
  {
3102
- onClick: () => _optionalChain([fileInputRef, 'access', _102 => _102.current, 'optionalAccess', _103 => _103.click, 'call', _104 => _104()]),
3726
+ onClick: () => _optionalChain([fileInputRef, 'access', _107 => _107.current, 'optionalAccess', _108 => _108.click, 'call', _109 => _109()]),
3103
3727
  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",
3104
3728
  title: "Attach file",
3105
3729
  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)" }) })
@@ -3285,25 +3909,25 @@ function Prompt({
3285
3909
  const newValue = e.target.value;
3286
3910
  if (!maxLength || newValue.length <= maxLength) {
3287
3911
  setValue(newValue);
3288
- _optionalChain([onChange, 'optionalCall', _105 => _105(newValue)]);
3912
+ _optionalChain([onChange, 'optionalCall', _110 => _110(newValue)]);
3289
3913
  }
3290
3914
  };
3291
3915
  const handleSubmit = async () => {
3292
3916
  if (value.length < minLength) return;
3293
- _optionalChain([onSubmit, 'optionalCall', _106 => _106(value)]);
3917
+ _optionalChain([onSubmit, 'optionalCall', _111 => _111(value)]);
3294
3918
  setIsLoading(true);
3295
3919
  try {
3296
3920
  if (useMock) {
3297
3921
  await new Promise((resolve) => setTimeout(resolve, 1500));
3298
3922
  const mockResult = `Enhanced version: ${value} [AI-generated content]`;
3299
- _optionalChain([onResult, 'optionalCall', _107 => _107(mockResult)]);
3923
+ _optionalChain([onResult, 'optionalCall', _112 => _112(mockResult)]);
3300
3924
  setValue("");
3301
3925
  } else {
3302
3926
  const response = await aptevaClient.chat({
3303
3927
  agent_id: agentId,
3304
3928
  message: value
3305
3929
  });
3306
- _optionalChain([onResult, 'optionalCall', _108 => _108(response.message)]);
3930
+ _optionalChain([onResult, 'optionalCall', _113 => _113(response.message)]);
3307
3931
  setValue("");
3308
3932
  }
3309
3933
  } catch (error) {
@@ -3398,7 +4022,7 @@ function Stream({
3398
4022
  }, [autoStart]);
3399
4023
  const startStreaming = async () => {
3400
4024
  setIsStreaming(true);
3401
- _optionalChain([onStart, 'optionalCall', _109 => _109()]);
4025
+ _optionalChain([onStart, 'optionalCall', _114 => _114()]);
3402
4026
  try {
3403
4027
  if (useMock) {
3404
4028
  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.";
@@ -3406,13 +4030,13 @@ function Stream({
3406
4030
  mockText,
3407
4031
  (chunk) => {
3408
4032
  setText((prev) => prev + chunk);
3409
- _optionalChain([onChunk, 'optionalCall', _110 => _110(chunk)]);
4033
+ _optionalChain([onChunk, 'optionalCall', _115 => _115(chunk)]);
3410
4034
  },
3411
4035
  typingSpeed
3412
4036
  );
3413
4037
  setIsComplete(true);
3414
4038
  setIsStreaming(false);
3415
- _optionalChain([onComplete, 'optionalCall', _111 => _111(text + mockText)]);
4039
+ _optionalChain([onComplete, 'optionalCall', _116 => _116(text + mockText)]);
3416
4040
  } else {
3417
4041
  let accumulatedText = "";
3418
4042
  await aptevaClient.chatStream(
@@ -3425,24 +4049,24 @@ function Stream({
3425
4049
  if (chunk.type === "token" && chunk.content) {
3426
4050
  accumulatedText += chunk.content;
3427
4051
  setText(accumulatedText);
3428
- _optionalChain([onChunk, 'optionalCall', _112 => _112(chunk.content)]);
4052
+ _optionalChain([onChunk, 'optionalCall', _117 => _117(chunk.content)]);
3429
4053
  }
3430
4054
  },
3431
4055
  () => {
3432
4056
  setIsComplete(true);
3433
4057
  setIsStreaming(false);
3434
- _optionalChain([onComplete, 'optionalCall', _113 => _113(accumulatedText)]);
4058
+ _optionalChain([onComplete, 'optionalCall', _118 => _118(accumulatedText)]);
3435
4059
  },
3436
4060
  (error) => {
3437
4061
  const err = error instanceof Error ? error : new Error("Streaming error");
3438
- _optionalChain([onError, 'optionalCall', _114 => _114(err)]);
4062
+ _optionalChain([onError, 'optionalCall', _119 => _119(err)]);
3439
4063
  setIsStreaming(false);
3440
4064
  }
3441
4065
  );
3442
4066
  }
3443
4067
  } catch (error) {
3444
4068
  const err = error instanceof Error ? error : new Error("Streaming error");
3445
- _optionalChain([onError, 'optionalCall', _115 => _115(err)]);
4069
+ _optionalChain([onError, 'optionalCall', _120 => _120(err)]);
3446
4070
  setIsStreaming(false);
3447
4071
  }
3448
4072
  };
@@ -3534,7 +4158,7 @@ function ThreadList({
3534
4158
  }) {
3535
4159
  const [searchQuery, setSearchQuery] = _react.useState.call(void 0, "");
3536
4160
  const filteredThreads = threads.filter(
3537
- (thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || _optionalChain([thread, 'access', _116 => _116.preview, 'optionalAccess', _117 => _117.toLowerCase, 'call', _118 => _118(), 'access', _119 => _119.includes, 'call', _120 => _120(searchQuery.toLowerCase())])
4161
+ (thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || _optionalChain([thread, 'access', _121 => _121.preview, 'optionalAccess', _122 => _122.toLowerCase, 'call', _123 => _123(), 'access', _124 => _124.includes, 'call', _125 => _125(searchQuery.toLowerCase())])
3538
4162
  );
3539
4163
  const groupedThreads = groupBy === "date" ? groupThreadsByDate(filteredThreads) : { All: filteredThreads };
3540
4164
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col h-full", children: [
@@ -3556,8 +4180,8 @@ function ThreadList({
3556
4180
  {
3557
4181
  thread,
3558
4182
  isActive: thread.id === currentThreadId,
3559
- onSelect: () => _optionalChain([onThreadSelect, 'optionalCall', _121 => _121(thread.id)]),
3560
- onDelete: () => _optionalChain([onThreadDelete, 'optionalCall', _122 => _122(thread.id)])
4183
+ onSelect: () => _optionalChain([onThreadSelect, 'optionalCall', _126 => _126(thread.id)]),
4184
+ onDelete: () => _optionalChain([onThreadDelete, 'optionalCall', _127 => _127(thread.id)])
3561
4185
  },
3562
4186
  thread.id
3563
4187
  ))
@@ -3619,7 +4243,7 @@ function Threads({
3619
4243
  threads.slice(0, 5).map((thread) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3620
4244
  "button",
3621
4245
  {
3622
- onClick: () => _optionalChain([onThreadSelect, 'optionalCall', _123 => _123(thread.id)]),
4246
+ onClick: () => _optionalChain([onThreadSelect, 'optionalCall', _128 => _128(thread.id)]),
3623
4247
  className: cn(
3624
4248
  "px-4 py-2 whitespace-nowrap font-medium transition-colors",
3625
4249
  thread.id === currentThreadId ? "border-b-2 border-apteva-500 text-apteva-500" : "text-gray-600 hover:text-gray-900"