@apteva/apteva-kit 0.1.12 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +23 -2
- package/dist/index.d.ts +23 -2
- package/dist/index.js +1156 -119
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1348 -311
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
|
|
6
6
|
// src/components/Chat/Chat.tsx
|
|
7
|
-
import { useState as
|
|
7
|
+
import { useState as useState3, useEffect as useEffect3, useRef as useRef4 } from "react";
|
|
8
8
|
|
|
9
9
|
// src/components/Chat/MessageList.tsx
|
|
10
10
|
import { useEffect as useEffect2, useRef } from "react";
|
|
@@ -417,6 +417,87 @@ function generateMockCommandStream(command, onChunk, onComplete, onError, typing
|
|
|
417
417
|
}, typingSpeed);
|
|
418
418
|
}
|
|
419
419
|
|
|
420
|
+
// src/utils/file-utils.ts
|
|
421
|
+
function fileToBase64(file) {
|
|
422
|
+
return new Promise((resolve, reject) => {
|
|
423
|
+
const reader = new FileReader();
|
|
424
|
+
reader.onload = () => {
|
|
425
|
+
const result = reader.result;
|
|
426
|
+
const base64 = result.split(",")[1];
|
|
427
|
+
resolve(base64);
|
|
428
|
+
};
|
|
429
|
+
reader.onerror = () => reject(new Error("Failed to read file"));
|
|
430
|
+
reader.readAsDataURL(file);
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
function getContentBlockType(mimeType) {
|
|
434
|
+
if (mimeType.startsWith("image/")) {
|
|
435
|
+
return "image";
|
|
436
|
+
}
|
|
437
|
+
return "document";
|
|
438
|
+
}
|
|
439
|
+
function isSupportedFileType(file) {
|
|
440
|
+
const supportedTypes = [
|
|
441
|
+
// Images
|
|
442
|
+
"image/jpeg",
|
|
443
|
+
"image/png",
|
|
444
|
+
"image/gif",
|
|
445
|
+
"image/webp",
|
|
446
|
+
// Documents
|
|
447
|
+
"application/pdf",
|
|
448
|
+
"text/plain",
|
|
449
|
+
"application/msword",
|
|
450
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
451
|
+
];
|
|
452
|
+
return supportedTypes.includes(file.type);
|
|
453
|
+
}
|
|
454
|
+
async function fileToContentBlock(file) {
|
|
455
|
+
const base64 = await fileToBase64(file);
|
|
456
|
+
const blockType = getContentBlockType(file.type);
|
|
457
|
+
return {
|
|
458
|
+
type: blockType,
|
|
459
|
+
source: {
|
|
460
|
+
type: "base64",
|
|
461
|
+
media_type: file.type,
|
|
462
|
+
data: base64
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
async function filesToContentBlocks(files) {
|
|
467
|
+
const fileArray = Array.from(files);
|
|
468
|
+
const blocks = await Promise.all(
|
|
469
|
+
fileArray.map((file) => fileToContentBlock(file))
|
|
470
|
+
);
|
|
471
|
+
return blocks;
|
|
472
|
+
}
|
|
473
|
+
async function buildMessageWithAttachments(text, files) {
|
|
474
|
+
if (!files || files.length === 0) {
|
|
475
|
+
return text;
|
|
476
|
+
}
|
|
477
|
+
const blocks = [];
|
|
478
|
+
if (text.trim()) {
|
|
479
|
+
blocks.push({ type: "text", text: text.trim() });
|
|
480
|
+
}
|
|
481
|
+
const fileBlocks = await filesToContentBlocks(files);
|
|
482
|
+
blocks.push(...fileBlocks);
|
|
483
|
+
return blocks;
|
|
484
|
+
}
|
|
485
|
+
function formatFileSize(bytes) {
|
|
486
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
487
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
488
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
489
|
+
}
|
|
490
|
+
var MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
491
|
+
function validateFile(file) {
|
|
492
|
+
if (!isSupportedFileType(file)) {
|
|
493
|
+
return { valid: false, error: `Unsupported file type: ${file.type}` };
|
|
494
|
+
}
|
|
495
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
496
|
+
return { valid: false, error: `File too large: ${formatFileSize(file.size)} (max ${formatFileSize(MAX_FILE_SIZE)})` };
|
|
497
|
+
}
|
|
498
|
+
return { valid: true };
|
|
499
|
+
}
|
|
500
|
+
|
|
420
501
|
// src/components/Widgets/Widgets.tsx
|
|
421
502
|
import { useEffect } from "react";
|
|
422
503
|
|
|
@@ -514,29 +595,78 @@ function Button({ widget, onAction }) {
|
|
|
514
595
|
);
|
|
515
596
|
}
|
|
516
597
|
|
|
598
|
+
// src/components/Widgets/widget-library/ButtonGroup.tsx
|
|
599
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
600
|
+
function ButtonGroup({ widget, onAction }) {
|
|
601
|
+
const { layout = "horizontal", buttons } = widget.props;
|
|
602
|
+
const variantClasses = {
|
|
603
|
+
primary: "bg-blue-500 !text-white hover:bg-blue-600",
|
|
604
|
+
secondary: "bg-gray-200 dark:bg-gray-700 !text-gray-800 dark:!text-gray-200 hover:bg-gray-300 dark:hover:bg-gray-600",
|
|
605
|
+
outline: "border border-gray-300 dark:border-gray-600 !text-gray-700 dark:!text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800"
|
|
606
|
+
};
|
|
607
|
+
const getActionForButton = (buttonId) => {
|
|
608
|
+
return widget.actions?.find((action) => action.payload?.buttonId === buttonId) || widget.actions?.[0];
|
|
609
|
+
};
|
|
610
|
+
return /* @__PURE__ */ jsx4(
|
|
611
|
+
"div",
|
|
612
|
+
{
|
|
613
|
+
className: cn(
|
|
614
|
+
"flex gap-2",
|
|
615
|
+
layout === "vertical" ? "flex-col" : "flex-row flex-wrap"
|
|
616
|
+
),
|
|
617
|
+
children: buttons.map((button) => {
|
|
618
|
+
const action = getActionForButton(button.id);
|
|
619
|
+
return /* @__PURE__ */ jsx4(
|
|
620
|
+
"button",
|
|
621
|
+
{
|
|
622
|
+
onClick: () => {
|
|
623
|
+
if (action) {
|
|
624
|
+
onAction?.({
|
|
625
|
+
type: action.type,
|
|
626
|
+
payload: { ...action.payload, buttonId: button.id },
|
|
627
|
+
widgetId: widget.id,
|
|
628
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
},
|
|
632
|
+
className: cn(
|
|
633
|
+
"px-4 py-2 rounded-lg font-medium transition-colors text-sm",
|
|
634
|
+
variantClasses[button.variant || "secondary"]
|
|
635
|
+
),
|
|
636
|
+
children: button.label
|
|
637
|
+
},
|
|
638
|
+
button.id
|
|
639
|
+
);
|
|
640
|
+
})
|
|
641
|
+
}
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
|
|
517
645
|
// src/components/Widgets/WidgetRenderer.tsx
|
|
518
|
-
import { jsx as
|
|
646
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
519
647
|
function WidgetRenderer({ widget, onAction }) {
|
|
520
648
|
switch (widget.type) {
|
|
521
649
|
case "card":
|
|
522
|
-
return /* @__PURE__ */
|
|
650
|
+
return /* @__PURE__ */ jsx5(Card, { widget, onAction });
|
|
523
651
|
case "list":
|
|
524
|
-
return /* @__PURE__ */
|
|
652
|
+
return /* @__PURE__ */ jsx5(List, { widget, onAction });
|
|
525
653
|
case "button":
|
|
526
|
-
return /* @__PURE__ */
|
|
654
|
+
return /* @__PURE__ */ jsx5(Button, { widget, onAction });
|
|
655
|
+
case "button_group":
|
|
656
|
+
return /* @__PURE__ */ jsx5(ButtonGroup, { widget, onAction });
|
|
527
657
|
default:
|
|
528
658
|
return /* @__PURE__ */ jsxs3("div", { className: "p-4 border border-yellow-300 bg-yellow-50 rounded-lg", children: [
|
|
529
659
|
/* @__PURE__ */ jsxs3("p", { className: "text-sm text-yellow-800", children: [
|
|
530
660
|
"Unknown widget type: ",
|
|
531
661
|
widget.type
|
|
532
662
|
] }),
|
|
533
|
-
/* @__PURE__ */
|
|
663
|
+
/* @__PURE__ */ jsx5("pre", { className: "text-xs mt-2 overflow-auto", children: JSON.stringify(widget, null, 2) })
|
|
534
664
|
] });
|
|
535
665
|
}
|
|
536
666
|
}
|
|
537
667
|
|
|
538
668
|
// src/components/Widgets/Widgets.tsx
|
|
539
|
-
import { jsx as
|
|
669
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
540
670
|
function Widgets({
|
|
541
671
|
widgets,
|
|
542
672
|
onAction,
|
|
@@ -561,11 +691,11 @@ function Widgets({
|
|
|
561
691
|
normal: "gap-4",
|
|
562
692
|
loose: "gap-6"
|
|
563
693
|
};
|
|
564
|
-
return /* @__PURE__ */
|
|
694
|
+
return /* @__PURE__ */ jsx6("div", { className: cn(layoutClasses[layout], spacingClasses[spacing], className), children: widgets.map((widget) => /* @__PURE__ */ jsx6(WidgetRenderer, { widget, onAction }, widget.id)) });
|
|
565
695
|
}
|
|
566
696
|
|
|
567
697
|
// src/components/Chat/MarkdownContent.tsx
|
|
568
|
-
import { jsx as
|
|
698
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
569
699
|
function parseInlineMarkdown(text, keyPrefix = "") {
|
|
570
700
|
const result = [];
|
|
571
701
|
const boldRegex = /(\*\*|__)(.+?)\1/g;
|
|
@@ -576,7 +706,7 @@ function parseInlineMarkdown(text, keyPrefix = "") {
|
|
|
576
706
|
if (match.index > lastIndex) {
|
|
577
707
|
result.push(text.slice(lastIndex, match.index));
|
|
578
708
|
}
|
|
579
|
-
result.push(/* @__PURE__ */
|
|
709
|
+
result.push(/* @__PURE__ */ jsx7("strong", { children: match[2] }, `${keyPrefix}b${key++}`));
|
|
580
710
|
lastIndex = match.index + match[0].length;
|
|
581
711
|
}
|
|
582
712
|
if (lastIndex < text.length) {
|
|
@@ -594,7 +724,7 @@ function parseMarkdown(content) {
|
|
|
594
724
|
const h2Match = line.match(/^##\s+(.*)$/);
|
|
595
725
|
if (h2Match) {
|
|
596
726
|
result.push(
|
|
597
|
-
/* @__PURE__ */
|
|
727
|
+
/* @__PURE__ */ jsx7("h2", { className: "apteva-md-h2", children: parseInlineMarkdown(h2Match[1], `${key}`) }, `h2${key++}`)
|
|
598
728
|
);
|
|
599
729
|
i++;
|
|
600
730
|
continue;
|
|
@@ -602,7 +732,7 @@ function parseMarkdown(content) {
|
|
|
602
732
|
const h3Match = line.match(/^###\s+(.*)$/);
|
|
603
733
|
if (h3Match) {
|
|
604
734
|
result.push(
|
|
605
|
-
/* @__PURE__ */
|
|
735
|
+
/* @__PURE__ */ jsx7("h3", { className: "apteva-md-h3", children: parseInlineMarkdown(h3Match[1], `${key}`) }, `h3${key++}`)
|
|
606
736
|
);
|
|
607
737
|
i++;
|
|
608
738
|
continue;
|
|
@@ -615,7 +745,7 @@ function parseMarkdown(content) {
|
|
|
615
745
|
const itemMatch = lines[i].match(/^(\s*)([-*+])\s+(.*)$/);
|
|
616
746
|
if (itemMatch && itemMatch[1].length === indent) {
|
|
617
747
|
listItems.push(
|
|
618
|
-
/* @__PURE__ */
|
|
748
|
+
/* @__PURE__ */ jsx7("li", { className: "apteva-md-li", children: parseInlineMarkdown(itemMatch[3], `${key}`) }, `li${key++}`)
|
|
619
749
|
);
|
|
620
750
|
i++;
|
|
621
751
|
} else {
|
|
@@ -623,7 +753,7 @@ function parseMarkdown(content) {
|
|
|
623
753
|
}
|
|
624
754
|
}
|
|
625
755
|
result.push(
|
|
626
|
-
/* @__PURE__ */
|
|
756
|
+
/* @__PURE__ */ jsx7("ul", { className: "apteva-md-ul", children: listItems }, `ul${key++}`)
|
|
627
757
|
);
|
|
628
758
|
continue;
|
|
629
759
|
}
|
|
@@ -635,7 +765,7 @@ function parseMarkdown(content) {
|
|
|
635
765
|
const itemMatch = lines[i].match(/^(\s*)(\d+)\.\s+(.*)$/);
|
|
636
766
|
if (itemMatch && itemMatch[1].length === indent) {
|
|
637
767
|
listItems.push(
|
|
638
|
-
/* @__PURE__ */
|
|
768
|
+
/* @__PURE__ */ jsx7("li", { className: "apteva-md-li", children: parseInlineMarkdown(itemMatch[3], `${key}`) }, `li${key++}`)
|
|
639
769
|
);
|
|
640
770
|
i++;
|
|
641
771
|
} else {
|
|
@@ -643,12 +773,39 @@ function parseMarkdown(content) {
|
|
|
643
773
|
}
|
|
644
774
|
}
|
|
645
775
|
result.push(
|
|
646
|
-
/* @__PURE__ */
|
|
776
|
+
/* @__PURE__ */ jsx7("ol", { className: "apteva-md-ol", children: listItems }, `ol${key++}`)
|
|
647
777
|
);
|
|
648
778
|
continue;
|
|
649
779
|
}
|
|
780
|
+
const tableMatch = line.match(/^\|(.+)\|$/);
|
|
781
|
+
if (tableMatch && i + 1 < lines.length) {
|
|
782
|
+
const separatorLine = lines[i + 1];
|
|
783
|
+
const separatorMatch = separatorLine.match(/^\|[\s:-]+\|$/);
|
|
784
|
+
if (separatorMatch) {
|
|
785
|
+
const headerCells = line.split("|").filter((cell) => cell.trim() !== "").map((cell) => cell.trim());
|
|
786
|
+
i += 2;
|
|
787
|
+
const bodyRows = [];
|
|
788
|
+
while (i < lines.length) {
|
|
789
|
+
const rowMatch = lines[i].match(/^\|(.+)\|$/);
|
|
790
|
+
if (rowMatch) {
|
|
791
|
+
const cells = lines[i].split("|").filter((cell) => cell.trim() !== "").map((cell) => cell.trim());
|
|
792
|
+
bodyRows.push(cells);
|
|
793
|
+
i++;
|
|
794
|
+
} else {
|
|
795
|
+
break;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
result.push(
|
|
799
|
+
/* @__PURE__ */ jsx7("div", { className: "apteva-md-table-wrapper", children: /* @__PURE__ */ jsxs4("table", { className: "apteva-md-table", children: [
|
|
800
|
+
/* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsx7("tr", { children: headerCells.map((cell, idx) => /* @__PURE__ */ jsx7("th", { className: "apteva-md-th", children: parseInlineMarkdown(cell, `th${key}${idx}`) }, `th${idx}`)) }) }),
|
|
801
|
+
/* @__PURE__ */ jsx7("tbody", { children: bodyRows.map((row, rowIdx) => /* @__PURE__ */ jsx7("tr", { children: row.map((cell, cellIdx) => /* @__PURE__ */ jsx7("td", { className: "apteva-md-td", children: parseInlineMarkdown(cell, `td${key}${rowIdx}${cellIdx}`) }, `td${cellIdx}`)) }, `tr${rowIdx}`)) })
|
|
802
|
+
] }) }, `table-wrapper${key++}`)
|
|
803
|
+
);
|
|
804
|
+
continue;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
650
807
|
if (line === "") {
|
|
651
|
-
result.push(/* @__PURE__ */
|
|
808
|
+
result.push(/* @__PURE__ */ jsx7("br", {}, `br${key++}`));
|
|
652
809
|
} else {
|
|
653
810
|
result.push(
|
|
654
811
|
/* @__PURE__ */ jsxs4("span", { children: [
|
|
@@ -662,38 +819,38 @@ function parseMarkdown(content) {
|
|
|
662
819
|
return result;
|
|
663
820
|
}
|
|
664
821
|
function MarkdownContent({ content, className = "" }) {
|
|
665
|
-
return /* @__PURE__ */
|
|
822
|
+
return /* @__PURE__ */ jsx7("div", { className: `apteva-md ${className}`, children: parseMarkdown(content) });
|
|
666
823
|
}
|
|
667
824
|
|
|
668
825
|
// src/components/Chat/ToolCall.tsx
|
|
669
|
-
import { jsx as
|
|
826
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
670
827
|
function ToolCall({ name, status }) {
|
|
671
828
|
return /* @__PURE__ */ jsxs5("div", { className: "apteva-tool-call", children: [
|
|
672
|
-
status === "running" && /* @__PURE__ */
|
|
673
|
-
status === "completed" && /* @__PURE__ */
|
|
674
|
-
status === "error" && /* @__PURE__ */
|
|
675
|
-
/* @__PURE__ */
|
|
676
|
-
status === "running" && /* @__PURE__ */
|
|
677
|
-
status === "completed" && /* @__PURE__ */
|
|
678
|
-
status === "error" && /* @__PURE__ */
|
|
829
|
+
status === "running" && /* @__PURE__ */ jsx8("div", { className: "apteva-tool-call-dot apteva-tool-call-dot-running" }),
|
|
830
|
+
status === "completed" && /* @__PURE__ */ jsx8("div", { className: "apteva-tool-call-dot apteva-tool-call-dot-completed" }),
|
|
831
|
+
status === "error" && /* @__PURE__ */ jsx8("div", { className: "apteva-tool-call-dot apteva-tool-call-dot-error" }),
|
|
832
|
+
/* @__PURE__ */ jsx8("span", { className: "apteva-tool-call-name", children: name }),
|
|
833
|
+
status === "running" && /* @__PURE__ */ jsx8("span", { className: "apteva-tool-call-status", children: "Running..." }),
|
|
834
|
+
status === "completed" && /* @__PURE__ */ jsx8("span", { className: "apteva-tool-call-status apteva-tool-call-status-completed", children: "Completed" }),
|
|
835
|
+
status === "error" && /* @__PURE__ */ jsx8("span", { className: "apteva-tool-call-status apteva-tool-call-status-error", children: "Error" })
|
|
679
836
|
] });
|
|
680
837
|
}
|
|
681
838
|
|
|
682
839
|
// src/components/Chat/Message.tsx
|
|
683
|
-
import { jsx as
|
|
840
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
684
841
|
function Message({ message, onAction }) {
|
|
685
842
|
const isUser = message.role === "user";
|
|
686
843
|
const contentSegments = message.metadata?.content_segments;
|
|
687
844
|
const renderContent = () => {
|
|
688
845
|
if (isUser) {
|
|
689
|
-
return /* @__PURE__ */
|
|
846
|
+
return /* @__PURE__ */ jsx9("div", { className: "whitespace-pre-wrap !text-sm leading-relaxed", children: message.content });
|
|
690
847
|
}
|
|
691
848
|
if (contentSegments && contentSegments.length > 0) {
|
|
692
|
-
return /* @__PURE__ */
|
|
849
|
+
return /* @__PURE__ */ jsx9("div", { children: contentSegments.map((segment, index) => {
|
|
693
850
|
if (segment.type === "text") {
|
|
694
|
-
return segment.content ? /* @__PURE__ */
|
|
851
|
+
return segment.content ? /* @__PURE__ */ jsx9(MarkdownContent, { content: segment.content }, `text-${index}`) : null;
|
|
695
852
|
} else if (segment.type === "tool") {
|
|
696
|
-
return /* @__PURE__ */
|
|
853
|
+
return /* @__PURE__ */ jsx9("div", { className: "my-2", children: /* @__PURE__ */ jsx9(
|
|
697
854
|
ToolCall,
|
|
698
855
|
{
|
|
699
856
|
name: segment.name,
|
|
@@ -704,45 +861,205 @@ function Message({ message, onAction }) {
|
|
|
704
861
|
return null;
|
|
705
862
|
}) });
|
|
706
863
|
}
|
|
707
|
-
return /* @__PURE__ */
|
|
864
|
+
return /* @__PURE__ */ jsx9(MarkdownContent, { content: message.content });
|
|
708
865
|
};
|
|
709
866
|
return /* @__PURE__ */ jsxs6(
|
|
710
867
|
"div",
|
|
711
868
|
{
|
|
712
869
|
className: cn(
|
|
713
870
|
"max-w-[80%]",
|
|
714
|
-
isUser ? "px-4 py-2.5 rounded-xl bg-gray-100 dark:bg-gray-800 !text-gray-900 dark:!text-gray-100 ml-auto" : "!text-gray-900 dark:!text-gray-100"
|
|
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"
|
|
715
872
|
),
|
|
716
873
|
children: [
|
|
717
874
|
renderContent(),
|
|
718
|
-
message.widgets && message.widgets.length > 0 && /* @__PURE__ */
|
|
719
|
-
/* @__PURE__ */
|
|
875
|
+
message.widgets && message.widgets.length > 0 && /* @__PURE__ */ jsx9("div", { className: cn(isUser ? "mt-3" : "mt-2"), children: /* @__PURE__ */ jsx9(Widgets, { widgets: message.widgets, onAction, layout: "stack" }) }),
|
|
876
|
+
/* @__PURE__ */ jsx9("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" }) })
|
|
720
877
|
]
|
|
721
878
|
}
|
|
722
879
|
);
|
|
723
880
|
}
|
|
724
881
|
|
|
882
|
+
// src/components/Chat/WelcomeScreen.tsx
|
|
883
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
884
|
+
var DefaultIcon = () => /* @__PURE__ */ jsx10("svg", { className: "w-12 h-12 sm:w-16 sm:h-16", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx10(
|
|
885
|
+
"path",
|
|
886
|
+
{
|
|
887
|
+
strokeLinecap: "round",
|
|
888
|
+
strokeLinejoin: "round",
|
|
889
|
+
strokeWidth: 1.5,
|
|
890
|
+
d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
|
|
891
|
+
}
|
|
892
|
+
) });
|
|
893
|
+
var ArrowIcon = () => /* @__PURE__ */ jsx10("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx10("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 7l5 5m0 0l-5 5m5-5H6" }) });
|
|
894
|
+
function WelcomeScreen({
|
|
895
|
+
title,
|
|
896
|
+
subtitle,
|
|
897
|
+
icon,
|
|
898
|
+
prompts,
|
|
899
|
+
variant = "centered",
|
|
900
|
+
onPromptClick
|
|
901
|
+
}) {
|
|
902
|
+
const normalizedPrompts = (prompts || []).map(
|
|
903
|
+
(p) => typeof p === "string" ? { text: p } : p
|
|
904
|
+
);
|
|
905
|
+
const hasPrompts = normalizedPrompts.length > 0;
|
|
906
|
+
const hasHeader = title || subtitle || icon;
|
|
907
|
+
if (!hasHeader && !hasPrompts) {
|
|
908
|
+
return /* @__PURE__ */ jsx10("div", { className: "flex items-center justify-center h-full !text-gray-500 dark:!text-gray-400", children: /* @__PURE__ */ jsxs7("div", { className: "text-center space-y-2", children: [
|
|
909
|
+
/* @__PURE__ */ jsx10("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx10(DefaultIcon, {}) }),
|
|
910
|
+
/* @__PURE__ */ jsx10("p", { className: "text-sm", children: "No messages yet. Start a conversation!" })
|
|
911
|
+
] }) });
|
|
912
|
+
}
|
|
913
|
+
if (variant === "minimal") {
|
|
914
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col h-full px-4 py-4", children: [
|
|
915
|
+
hasHeader && /* @__PURE__ */ jsxs7("div", { className: "mb-4", children: [
|
|
916
|
+
title && /* @__PURE__ */ jsx10("h2", { className: "text-lg font-semibold !text-gray-900 dark:!text-white", children: title }),
|
|
917
|
+
subtitle && /* @__PURE__ */ jsx10("p", { className: "text-sm !text-gray-500 dark:!text-gray-400 mt-1", children: subtitle })
|
|
918
|
+
] }),
|
|
919
|
+
hasPrompts && /* @__PURE__ */ jsx10("div", { className: "flex-1 space-y-2", children: normalizedPrompts.map((prompt, index) => /* @__PURE__ */ jsx10(
|
|
920
|
+
"button",
|
|
921
|
+
{
|
|
922
|
+
onClick: () => onPromptClick(prompt.text),
|
|
923
|
+
className: cn(
|
|
924
|
+
"w-full text-left px-4 py-3 rounded-xl",
|
|
925
|
+
"bg-gray-50 dark:bg-gray-800/50",
|
|
926
|
+
"border border-gray-200 dark:border-gray-700",
|
|
927
|
+
"hover:bg-gray-100 dark:hover:bg-gray-800",
|
|
928
|
+
"hover:border-gray-300 dark:hover:border-gray-600",
|
|
929
|
+
"transition-all duration-200",
|
|
930
|
+
"group"
|
|
931
|
+
),
|
|
932
|
+
children: /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3", children: [
|
|
933
|
+
/* @__PURE__ */ jsx10("div", { className: "flex-shrink-0 !text-gray-400 dark:!text-gray-500 group-hover:!text-blue-500 dark:group-hover:!text-blue-400 transition-colors", children: prompt.icon || /* @__PURE__ */ jsx10(ArrowIcon, {}) }),
|
|
934
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex-1 min-w-0", children: [
|
|
935
|
+
/* @__PURE__ */ jsx10("p", { className: "text-sm font-medium !text-gray-900 dark:!text-white truncate", children: prompt.text }),
|
|
936
|
+
prompt.description && /* @__PURE__ */ jsx10("p", { className: "text-xs !text-gray-500 dark:!text-gray-400 mt-0.5 truncate", children: prompt.description })
|
|
937
|
+
] })
|
|
938
|
+
] })
|
|
939
|
+
},
|
|
940
|
+
index
|
|
941
|
+
)) })
|
|
942
|
+
] });
|
|
943
|
+
}
|
|
944
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col items-center justify-center h-full px-4 py-6 sm:py-8", children: [
|
|
945
|
+
/* @__PURE__ */ jsxs7("div", { className: "text-center mb-6 sm:mb-8 max-w-md", children: [
|
|
946
|
+
/* @__PURE__ */ jsx10("div", { className: "mb-4 !text-gray-400 dark:!text-gray-500 flex justify-center", children: icon || /* @__PURE__ */ jsx10(DefaultIcon, {}) }),
|
|
947
|
+
title && /* @__PURE__ */ jsx10("h1", { className: "text-xl sm:text-2xl font-semibold !text-gray-900 dark:!text-white mb-2", children: title }),
|
|
948
|
+
subtitle && /* @__PURE__ */ jsx10("p", { className: "text-sm sm:text-base !text-gray-500 dark:!text-gray-400", children: subtitle })
|
|
949
|
+
] }),
|
|
950
|
+
hasPrompts && /* @__PURE__ */ jsxs7("div", { className: "w-full max-w-2xl", children: [
|
|
951
|
+
/* @__PURE__ */ jsx10("div", { className: "sm:hidden space-y-2", children: normalizedPrompts.map((prompt, index) => /* @__PURE__ */ jsx10(
|
|
952
|
+
"button",
|
|
953
|
+
{
|
|
954
|
+
onClick: () => onPromptClick(prompt.text),
|
|
955
|
+
className: cn(
|
|
956
|
+
"w-full text-left px-4 py-3 rounded-xl",
|
|
957
|
+
"bg-white dark:bg-gray-800",
|
|
958
|
+
"border border-gray-200 dark:border-gray-700",
|
|
959
|
+
"hover:bg-gray-50 dark:hover:bg-gray-700",
|
|
960
|
+
"hover:border-blue-300 dark:hover:border-blue-600",
|
|
961
|
+
"active:scale-[0.98]",
|
|
962
|
+
"transition-all duration-200",
|
|
963
|
+
"shadow-sm hover:shadow",
|
|
964
|
+
"group"
|
|
965
|
+
),
|
|
966
|
+
children: /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3", children: [
|
|
967
|
+
/* @__PURE__ */ jsx10("div", { className: "flex-shrink-0 w-8 h-8 rounded-lg bg-gray-100 dark:bg-gray-700 flex items-center justify-center !text-gray-500 dark:!text-gray-400 group-hover:bg-blue-100 dark:group-hover:bg-blue-900/30 group-hover:!text-blue-600 dark:group-hover:!text-blue-400 transition-colors", children: prompt.icon || /* @__PURE__ */ jsx10(ArrowIcon, {}) }),
|
|
968
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex-1 min-w-0", children: [
|
|
969
|
+
/* @__PURE__ */ jsx10("p", { className: "text-sm font-medium !text-gray-900 dark:!text-white", children: prompt.text }),
|
|
970
|
+
prompt.description && /* @__PURE__ */ jsx10("p", { className: "text-xs !text-gray-500 dark:!text-gray-400 mt-0.5 line-clamp-1", children: prompt.description })
|
|
971
|
+
] }),
|
|
972
|
+
/* @__PURE__ */ jsx10(
|
|
973
|
+
"svg",
|
|
974
|
+
{
|
|
975
|
+
className: "w-4 h-4 !text-gray-400 group-hover:!text-blue-500 transition-colors flex-shrink-0",
|
|
976
|
+
fill: "none",
|
|
977
|
+
stroke: "currentColor",
|
|
978
|
+
viewBox: "0 0 24 24",
|
|
979
|
+
children: /* @__PURE__ */ jsx10(
|
|
980
|
+
"path",
|
|
981
|
+
{
|
|
982
|
+
strokeLinecap: "round",
|
|
983
|
+
strokeLinejoin: "round",
|
|
984
|
+
strokeWidth: 2,
|
|
985
|
+
d: "M9 5l7 7-7 7"
|
|
986
|
+
}
|
|
987
|
+
)
|
|
988
|
+
}
|
|
989
|
+
)
|
|
990
|
+
] })
|
|
991
|
+
},
|
|
992
|
+
index
|
|
993
|
+
)) }),
|
|
994
|
+
/* @__PURE__ */ jsx10("div", { className: "hidden sm:grid sm:grid-cols-2 gap-3", children: normalizedPrompts.map((prompt, index) => /* @__PURE__ */ jsx10(
|
|
995
|
+
"button",
|
|
996
|
+
{
|
|
997
|
+
onClick: () => onPromptClick(prompt.text),
|
|
998
|
+
className: cn(
|
|
999
|
+
"text-left p-4 rounded-xl",
|
|
1000
|
+
"bg-white dark:bg-gray-800",
|
|
1001
|
+
"border border-gray-200 dark:border-gray-700",
|
|
1002
|
+
"hover:bg-gray-50 dark:hover:bg-gray-700",
|
|
1003
|
+
"hover:border-blue-300 dark:hover:border-blue-600",
|
|
1004
|
+
"hover:shadow-md",
|
|
1005
|
+
"active:scale-[0.98]",
|
|
1006
|
+
"transition-all duration-200",
|
|
1007
|
+
"group"
|
|
1008
|
+
),
|
|
1009
|
+
children: /* @__PURE__ */ jsxs7("div", { className: "flex items-start gap-3", children: [
|
|
1010
|
+
/* @__PURE__ */ jsx10("div", { className: "flex-shrink-0 w-9 h-9 rounded-lg bg-gray-100 dark:bg-gray-700 flex items-center justify-center !text-gray-500 dark:!text-gray-400 group-hover:bg-blue-100 dark:group-hover:bg-blue-900/30 group-hover:!text-blue-600 dark:group-hover:!text-blue-400 transition-colors", children: prompt.icon || /* @__PURE__ */ jsx10(ArrowIcon, {}) }),
|
|
1011
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex-1 min-w-0", children: [
|
|
1012
|
+
/* @__PURE__ */ jsx10("p", { className: "text-sm font-medium !text-gray-900 dark:!text-white leading-snug", children: prompt.text }),
|
|
1013
|
+
prompt.description && /* @__PURE__ */ jsx10("p", { className: "text-xs !text-gray-500 dark:!text-gray-400 mt-1 line-clamp-2", children: prompt.description })
|
|
1014
|
+
] })
|
|
1015
|
+
] })
|
|
1016
|
+
},
|
|
1017
|
+
index
|
|
1018
|
+
)) })
|
|
1019
|
+
] })
|
|
1020
|
+
] });
|
|
1021
|
+
}
|
|
1022
|
+
|
|
725
1023
|
// src/components/Chat/MessageList.tsx
|
|
726
|
-
import { jsx as
|
|
727
|
-
function MessageList({
|
|
1024
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1025
|
+
function MessageList({
|
|
1026
|
+
messages,
|
|
1027
|
+
onAction,
|
|
1028
|
+
welcomeTitle,
|
|
1029
|
+
welcomeSubtitle,
|
|
1030
|
+
welcomeIcon,
|
|
1031
|
+
suggestedPrompts,
|
|
1032
|
+
welcomeVariant,
|
|
1033
|
+
onPromptClick
|
|
1034
|
+
}) {
|
|
728
1035
|
const listRef = useRef(null);
|
|
729
1036
|
useEffect2(() => {
|
|
730
1037
|
if (listRef.current) {
|
|
731
1038
|
listRef.current.scrollTop = listRef.current.scrollHeight;
|
|
732
1039
|
}
|
|
733
1040
|
}, [messages]);
|
|
734
|
-
return /* @__PURE__ */
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
1041
|
+
return /* @__PURE__ */ jsx11("div", { ref: listRef, className: "flex-1 overflow-y-auto px-4 py-4 space-y-3 apteva-scrollbar-hidden", children: messages.length === 0 ? /* @__PURE__ */ jsx11(
|
|
1042
|
+
WelcomeScreen,
|
|
1043
|
+
{
|
|
1044
|
+
title: welcomeTitle,
|
|
1045
|
+
subtitle: welcomeSubtitle,
|
|
1046
|
+
icon: welcomeIcon,
|
|
1047
|
+
prompts: suggestedPrompts,
|
|
1048
|
+
variant: welcomeVariant,
|
|
1049
|
+
onPromptClick: onPromptClick || (() => {
|
|
1050
|
+
})
|
|
1051
|
+
}
|
|
1052
|
+
) : messages.map((message) => /* @__PURE__ */ jsx11(Message, { message, onAction }, message.id)) });
|
|
738
1053
|
}
|
|
739
1054
|
|
|
740
1055
|
// src/components/Chat/Composer.tsx
|
|
741
1056
|
import { useState, useRef as useRef2 } from "react";
|
|
742
|
-
import { Fragment, jsx as
|
|
743
|
-
function Composer({ onSendMessage, placeholder = "Type a message...", disabled = false, onFileUpload }) {
|
|
1057
|
+
import { Fragment, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1058
|
+
function Composer({ onSendMessage, placeholder = "Type a message...", disabled = false, onFileUpload, onSwitchMode }) {
|
|
744
1059
|
const [text, setText] = useState("");
|
|
745
1060
|
const [showMenu, setShowMenu] = useState(false);
|
|
1061
|
+
const [pendingFiles, setPendingFiles] = useState([]);
|
|
1062
|
+
const [fileError, setFileError] = useState(null);
|
|
746
1063
|
const textareaRef = useRef2(null);
|
|
747
1064
|
const fileInputRef = useRef2(null);
|
|
748
1065
|
const handleKeyDown = (e) => {
|
|
@@ -752,9 +1069,14 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
|
|
|
752
1069
|
}
|
|
753
1070
|
};
|
|
754
1071
|
const handleSend = () => {
|
|
755
|
-
|
|
756
|
-
|
|
1072
|
+
const hasText = text.trim();
|
|
1073
|
+
const hasFiles = pendingFiles.length > 0;
|
|
1074
|
+
if ((hasText || hasFiles) && !disabled) {
|
|
1075
|
+
const filesToSend = pendingFiles.map((pf) => pf.file);
|
|
1076
|
+
onSendMessage(text.trim(), filesToSend.length > 0 ? filesToSend : void 0);
|
|
757
1077
|
setText("");
|
|
1078
|
+
setPendingFiles([]);
|
|
1079
|
+
setFileError(null);
|
|
758
1080
|
if (textareaRef.current) {
|
|
759
1081
|
textareaRef.current.style.height = "auto";
|
|
760
1082
|
}
|
|
@@ -767,36 +1089,123 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
|
|
|
767
1089
|
};
|
|
768
1090
|
const handleFileSelect = (e) => {
|
|
769
1091
|
if (e.target.files && e.target.files.length > 0) {
|
|
1092
|
+
const files = Array.from(e.target.files);
|
|
1093
|
+
const validFiles = [];
|
|
1094
|
+
const errors = [];
|
|
1095
|
+
files.forEach((file) => {
|
|
1096
|
+
const validation = validateFile(file);
|
|
1097
|
+
if (validation.valid) {
|
|
1098
|
+
const pending = { file };
|
|
1099
|
+
if (file.type.startsWith("image/")) {
|
|
1100
|
+
pending.preview = URL.createObjectURL(file);
|
|
1101
|
+
}
|
|
1102
|
+
validFiles.push(pending);
|
|
1103
|
+
} else {
|
|
1104
|
+
errors.push(validation.error || "Invalid file");
|
|
1105
|
+
}
|
|
1106
|
+
});
|
|
1107
|
+
if (validFiles.length > 0) {
|
|
1108
|
+
setPendingFiles((prev) => [...prev, ...validFiles]);
|
|
1109
|
+
}
|
|
1110
|
+
if (errors.length > 0) {
|
|
1111
|
+
setFileError(errors.join(", "));
|
|
1112
|
+
setTimeout(() => setFileError(null), 5e3);
|
|
1113
|
+
}
|
|
770
1114
|
onFileUpload?.(e.target.files);
|
|
771
1115
|
setShowMenu(false);
|
|
1116
|
+
e.target.value = "";
|
|
772
1117
|
}
|
|
773
1118
|
};
|
|
774
|
-
|
|
1119
|
+
const removeFile = (index) => {
|
|
1120
|
+
setPendingFiles((prev) => {
|
|
1121
|
+
const file = prev[index];
|
|
1122
|
+
if (file.preview) {
|
|
1123
|
+
URL.revokeObjectURL(file.preview);
|
|
1124
|
+
}
|
|
1125
|
+
return prev.filter((_, i) => i !== index);
|
|
1126
|
+
});
|
|
1127
|
+
};
|
|
1128
|
+
const getFileIcon = (mimeType) => {
|
|
1129
|
+
if (mimeType.startsWith("image/")) {
|
|
1130
|
+
return /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) });
|
|
1131
|
+
}
|
|
1132
|
+
if (mimeType === "application/pdf") {
|
|
1133
|
+
return /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" }) });
|
|
1134
|
+
}
|
|
1135
|
+
return /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) });
|
|
1136
|
+
};
|
|
1137
|
+
return /* @__PURE__ */ jsxs8("div", { className: "px-4 py-3 relative", children: [
|
|
1138
|
+
fileError && /* @__PURE__ */ jsx12("div", { className: "absolute bottom-full left-4 right-4 mb-2 p-3 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg z-20", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 !text-red-700 dark:!text-red-300 text-sm", children: [
|
|
1139
|
+
/* @__PURE__ */ jsx12("svg", { className: "w-4 h-4 flex-shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
1140
|
+
/* @__PURE__ */ jsx12("span", { children: fileError })
|
|
1141
|
+
] }) }),
|
|
775
1142
|
showMenu && /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
776
|
-
/* @__PURE__ */
|
|
777
|
-
/* @__PURE__ */
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
1143
|
+
/* @__PURE__ */ jsx12("div", { className: "fixed inset-0 z-10", onClick: () => setShowMenu(false) }),
|
|
1144
|
+
/* @__PURE__ */ jsxs8("div", { className: "absolute bottom-full left-4 mb-2 bg-gray-800 dark:bg-gray-700 rounded-xl shadow-lg overflow-hidden z-20 min-w-[240px]", children: [
|
|
1145
|
+
/* @__PURE__ */ jsxs8(
|
|
1146
|
+
"button",
|
|
1147
|
+
{
|
|
1148
|
+
onClick: () => {
|
|
1149
|
+
fileInputRef.current?.click();
|
|
1150
|
+
setShowMenu(false);
|
|
1151
|
+
},
|
|
1152
|
+
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",
|
|
1153
|
+
children: [
|
|
1154
|
+
/* @__PURE__ */ jsx12("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx12("path", { d: "M10.5 3.5L5.5 8.5C4.67157 9.32843 4.67157 10.6716 5.5 11.5C6.32843 12.3284 7.67157 12.3284 8.5 11.5L14.5 5.5C15.8807 4.11929 15.8807 1.88071 14.5 0.5C13.1193 -0.880711 10.8807 -0.880711 9.5 0.5L3.5 6.5C1.56846 8.43154 1.56846 11.5685 3.5 13.5C5.43154 15.4315 8.56846 15.4315 10.5 13.5L15.5 8.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", transform: "translate(2, 3)" }) }),
|
|
1155
|
+
/* @__PURE__ */ jsx12("span", { className: "!text-sm font-medium", children: "Add photos & files" })
|
|
1156
|
+
]
|
|
1157
|
+
}
|
|
1158
|
+
),
|
|
1159
|
+
onSwitchMode && /* @__PURE__ */ jsxs8(
|
|
1160
|
+
"button",
|
|
1161
|
+
{
|
|
1162
|
+
onClick: () => {
|
|
1163
|
+
onSwitchMode();
|
|
1164
|
+
setShowMenu(false);
|
|
1165
|
+
},
|
|
1166
|
+
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 border-t border-gray-700 dark:border-gray-600",
|
|
1167
|
+
children: [
|
|
1168
|
+
/* @__PURE__ */ jsx12("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 10V3L4 14h7v7l9-11h-7z" }) }),
|
|
1169
|
+
/* @__PURE__ */ jsx12("span", { className: "!text-sm font-medium", children: "Switch to command mode" })
|
|
1170
|
+
]
|
|
1171
|
+
}
|
|
1172
|
+
)
|
|
1173
|
+
] })
|
|
788
1174
|
] }),
|
|
1175
|
+
pendingFiles.length > 0 && /* @__PURE__ */ jsx12("div", { className: "mb-2 flex flex-wrap gap-2", children: pendingFiles.map((pf, index) => /* @__PURE__ */ jsxs8(
|
|
1176
|
+
"div",
|
|
1177
|
+
{
|
|
1178
|
+
className: "relative group flex items-center gap-2 px-3 py-2 bg-gray-100 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg",
|
|
1179
|
+
children: [
|
|
1180
|
+
pf.preview ? /* @__PURE__ */ jsx12("img", { src: pf.preview, alt: pf.file.name, className: "w-8 h-8 object-cover rounded" }) : /* @__PURE__ */ jsx12("div", { className: "w-8 h-8 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) }),
|
|
1181
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex flex-col min-w-0", children: [
|
|
1182
|
+
/* @__PURE__ */ jsx12("span", { className: "text-xs font-medium !text-gray-700 dark:!text-gray-300 truncate max-w-[120px]", children: pf.file.name }),
|
|
1183
|
+
/* @__PURE__ */ jsx12("span", { className: "text-xs !text-gray-500 dark:!text-gray-400", children: formatFileSize(pf.file.size) })
|
|
1184
|
+
] }),
|
|
1185
|
+
/* @__PURE__ */ jsx12(
|
|
1186
|
+
"button",
|
|
1187
|
+
{
|
|
1188
|
+
onClick: () => removeFile(index),
|
|
1189
|
+
className: "absolute -top-1.5 -right-1.5 w-5 h-5 bg-gray-500 hover:bg-red-500 text-white rounded-full flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity",
|
|
1190
|
+
title: "Remove file",
|
|
1191
|
+
children: /* @__PURE__ */ jsx12("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
1192
|
+
}
|
|
1193
|
+
)
|
|
1194
|
+
]
|
|
1195
|
+
},
|
|
1196
|
+
index
|
|
1197
|
+
)) }),
|
|
789
1198
|
/* @__PURE__ */ jsxs8("div", { className: "relative border-2 border-gray-300 dark:border-gray-700 rounded-xl bg-white dark:bg-gray-900 transition-all duration-300 flex items-center px-3 py-2 gap-3", children: [
|
|
790
|
-
/* @__PURE__ */
|
|
1199
|
+
/* @__PURE__ */ jsx12(
|
|
791
1200
|
"button",
|
|
792
1201
|
{
|
|
793
1202
|
onClick: () => setShowMenu(!showMenu),
|
|
794
1203
|
className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0 !text-gray-700 dark:!text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800",
|
|
795
1204
|
title: "More options",
|
|
796
|
-
children: /* @__PURE__ */
|
|
1205
|
+
children: /* @__PURE__ */ jsx12("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx12("path", { d: "M10 5v10M5 10h10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
797
1206
|
}
|
|
798
1207
|
),
|
|
799
|
-
/* @__PURE__ */
|
|
1208
|
+
/* @__PURE__ */ jsx12(
|
|
800
1209
|
"textarea",
|
|
801
1210
|
{
|
|
802
1211
|
ref: textareaRef,
|
|
@@ -810,18 +1219,351 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
|
|
|
810
1219
|
style: { maxHeight: "120px" }
|
|
811
1220
|
}
|
|
812
1221
|
),
|
|
813
|
-
/* @__PURE__ */
|
|
1222
|
+
/* @__PURE__ */ jsx12(
|
|
814
1223
|
"button",
|
|
815
1224
|
{
|
|
816
1225
|
onClick: handleSend,
|
|
817
|
-
disabled: !text.trim() || disabled,
|
|
1226
|
+
disabled: !text.trim() && pendingFiles.length === 0 || disabled,
|
|
818
1227
|
className: "w-8 h-8 rounded-lg flex items-center justify-center font-bold transition-all flex-shrink-0 border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 !text-gray-700 dark:!text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-30 disabled:cursor-not-allowed !text-lg",
|
|
819
1228
|
title: "Send message",
|
|
820
|
-
children: /* @__PURE__ */
|
|
1229
|
+
children: /* @__PURE__ */ jsx12("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx12("path", { d: "M8 3L8 13M8 3L4 7M8 3L12 7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
821
1230
|
}
|
|
822
1231
|
)
|
|
823
1232
|
] }),
|
|
824
|
-
/* @__PURE__ */
|
|
1233
|
+
/* @__PURE__ */ jsx12(
|
|
1234
|
+
"input",
|
|
1235
|
+
{
|
|
1236
|
+
ref: fileInputRef,
|
|
1237
|
+
type: "file",
|
|
1238
|
+
multiple: true,
|
|
1239
|
+
onChange: handleFileSelect,
|
|
1240
|
+
className: "hidden",
|
|
1241
|
+
accept: "image/*,application/pdf,.doc,.docx,.txt"
|
|
1242
|
+
}
|
|
1243
|
+
)
|
|
1244
|
+
] });
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
// src/components/Chat/CommandComposer.tsx
|
|
1248
|
+
import { useState as useState2, useRef as useRef3 } from "react";
|
|
1249
|
+
import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1250
|
+
function CommandComposer({
|
|
1251
|
+
onExecute,
|
|
1252
|
+
state,
|
|
1253
|
+
response,
|
|
1254
|
+
error,
|
|
1255
|
+
plan,
|
|
1256
|
+
streamedContent,
|
|
1257
|
+
toolName,
|
|
1258
|
+
onApprove,
|
|
1259
|
+
onReject,
|
|
1260
|
+
onReset,
|
|
1261
|
+
onExpand,
|
|
1262
|
+
placeholder = "Enter your command...",
|
|
1263
|
+
disabled = false
|
|
1264
|
+
}) {
|
|
1265
|
+
const [input, setInput] = useState2("");
|
|
1266
|
+
const [pendingFiles, setPendingFiles] = useState2([]);
|
|
1267
|
+
const [fileError, setFileError] = useState2(null);
|
|
1268
|
+
const [showMenu, setShowMenu] = useState2(false);
|
|
1269
|
+
const inputRef = useRef3(null);
|
|
1270
|
+
const fileInputRef = useRef3(null);
|
|
1271
|
+
const menuButtonRef = useRef3(null);
|
|
1272
|
+
const handleSubmit = () => {
|
|
1273
|
+
const hasText = input.trim();
|
|
1274
|
+
const hasFiles = pendingFiles.length > 0;
|
|
1275
|
+
if ((hasText || hasFiles) && !disabled && state === "idle") {
|
|
1276
|
+
const filesToSend = pendingFiles.map((pf) => pf.file);
|
|
1277
|
+
onExecute(input.trim(), filesToSend.length > 0 ? filesToSend : void 0);
|
|
1278
|
+
setInput("");
|
|
1279
|
+
setPendingFiles([]);
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
1282
|
+
const handleKeyDown = (e) => {
|
|
1283
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
1284
|
+
e.preventDefault();
|
|
1285
|
+
handleSubmit();
|
|
1286
|
+
}
|
|
1287
|
+
};
|
|
1288
|
+
const handleNewCommand = () => {
|
|
1289
|
+
onReset?.();
|
|
1290
|
+
inputRef.current?.focus();
|
|
1291
|
+
};
|
|
1292
|
+
const handleInputChange = (value) => {
|
|
1293
|
+
setInput(value);
|
|
1294
|
+
if (inputRef.current) {
|
|
1295
|
+
inputRef.current.style.height = "auto";
|
|
1296
|
+
inputRef.current.style.height = `${Math.min(inputRef.current.scrollHeight, 120)}px`;
|
|
1297
|
+
}
|
|
1298
|
+
};
|
|
1299
|
+
const handleFileSelect = (e) => {
|
|
1300
|
+
if (e.target.files && e.target.files.length > 0) {
|
|
1301
|
+
const files = Array.from(e.target.files);
|
|
1302
|
+
const validFiles = [];
|
|
1303
|
+
const errors = [];
|
|
1304
|
+
files.forEach((file) => {
|
|
1305
|
+
const validation = validateFile(file);
|
|
1306
|
+
if (validation.valid) {
|
|
1307
|
+
const pending = { file };
|
|
1308
|
+
if (file.type.startsWith("image/")) {
|
|
1309
|
+
pending.preview = URL.createObjectURL(file);
|
|
1310
|
+
}
|
|
1311
|
+
validFiles.push(pending);
|
|
1312
|
+
} else {
|
|
1313
|
+
errors.push(validation.error || "Invalid file");
|
|
1314
|
+
}
|
|
1315
|
+
});
|
|
1316
|
+
if (validFiles.length > 0) {
|
|
1317
|
+
setPendingFiles((prev) => [...prev, ...validFiles]);
|
|
1318
|
+
}
|
|
1319
|
+
if (errors.length > 0) {
|
|
1320
|
+
setFileError(errors.join(", "));
|
|
1321
|
+
setTimeout(() => setFileError(null), 5e3);
|
|
1322
|
+
}
|
|
1323
|
+
setShowMenu(false);
|
|
1324
|
+
e.target.value = "";
|
|
1325
|
+
}
|
|
1326
|
+
};
|
|
1327
|
+
const removeFile = (index) => {
|
|
1328
|
+
setPendingFiles((prev) => {
|
|
1329
|
+
const file = prev[index];
|
|
1330
|
+
if (file.preview) {
|
|
1331
|
+
URL.revokeObjectURL(file.preview);
|
|
1332
|
+
}
|
|
1333
|
+
return prev.filter((_, i) => i !== index);
|
|
1334
|
+
});
|
|
1335
|
+
};
|
|
1336
|
+
const getFileIcon = (mimeType) => {
|
|
1337
|
+
if (mimeType.startsWith("image/")) {
|
|
1338
|
+
return /* @__PURE__ */ jsx13("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) });
|
|
1339
|
+
}
|
|
1340
|
+
if (mimeType === "application/pdf") {
|
|
1341
|
+
return /* @__PURE__ */ jsx13("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" }) });
|
|
1342
|
+
}
|
|
1343
|
+
return /* @__PURE__ */ jsx13("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) });
|
|
1344
|
+
};
|
|
1345
|
+
const getDisplayContent = () => {
|
|
1346
|
+
if (state === "loading") {
|
|
1347
|
+
if (toolName) {
|
|
1348
|
+
return { text: toolName, isToolCall: true };
|
|
1349
|
+
}
|
|
1350
|
+
if (streamedContent) {
|
|
1351
|
+
return { text: streamedContent, isToolCall: false };
|
|
1352
|
+
}
|
|
1353
|
+
return { text: "Processing...", isToolCall: false };
|
|
1354
|
+
}
|
|
1355
|
+
if (state === "success" && response) {
|
|
1356
|
+
return { text: response, isToolCall: false };
|
|
1357
|
+
}
|
|
1358
|
+
if (state === "error" && error) {
|
|
1359
|
+
return { text: error, isToolCall: false };
|
|
1360
|
+
}
|
|
1361
|
+
if (state === "plan-pending" && plan) {
|
|
1362
|
+
return { text: plan, isToolCall: false };
|
|
1363
|
+
}
|
|
1364
|
+
return { text: "", isToolCall: false };
|
|
1365
|
+
};
|
|
1366
|
+
const isShowingResult = state !== "idle";
|
|
1367
|
+
const { text: displayContent, isToolCall } = getDisplayContent();
|
|
1368
|
+
return /* @__PURE__ */ jsxs9("div", { className: "w-full relative", children: [
|
|
1369
|
+
fileError && /* @__PURE__ */ jsx13("div", { className: "absolute -top-12 left-0 right-0 mx-3 p-2 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg z-30", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 !text-red-700 dark:!text-red-300 text-xs", children: [
|
|
1370
|
+
/* @__PURE__ */ jsx13("svg", { className: "w-3 h-3 flex-shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
1371
|
+
/* @__PURE__ */ jsx13("span", { children: fileError })
|
|
1372
|
+
] }) }),
|
|
1373
|
+
showMenu && /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
1374
|
+
/* @__PURE__ */ jsx13("div", { className: "fixed inset-0 z-[9998]", onClick: () => setShowMenu(false) }),
|
|
1375
|
+
/* @__PURE__ */ jsxs9(
|
|
1376
|
+
"div",
|
|
1377
|
+
{
|
|
1378
|
+
className: "fixed bg-gray-800 dark:bg-gray-700 rounded-xl shadow-lg overflow-hidden z-[9999] min-w-[200px]",
|
|
1379
|
+
style: {
|
|
1380
|
+
bottom: "auto",
|
|
1381
|
+
left: menuButtonRef.current?.getBoundingClientRect().left ?? 0,
|
|
1382
|
+
top: (menuButtonRef.current?.getBoundingClientRect().top ?? 0) - 8,
|
|
1383
|
+
transform: "translateY(-100%)"
|
|
1384
|
+
},
|
|
1385
|
+
children: [
|
|
1386
|
+
/* @__PURE__ */ jsxs9(
|
|
1387
|
+
"button",
|
|
1388
|
+
{
|
|
1389
|
+
onClick: () => {
|
|
1390
|
+
fileInputRef.current?.click();
|
|
1391
|
+
setShowMenu(false);
|
|
1392
|
+
},
|
|
1393
|
+
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",
|
|
1394
|
+
children: [
|
|
1395
|
+
/* @__PURE__ */ jsx13("svg", { width: "18", height: "18", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx13("path", { d: "M10.5 3.5L5.5 8.5C4.67157 9.32843 4.67157 10.6716 5.5 11.5C6.32843 12.3284 7.67157 12.3284 8.5 11.5L14.5 5.5C15.8807 4.11929 15.8807 1.88071 14.5 0.5C13.1193 -0.880711 10.8807 -0.880711 9.5 0.5L3.5 6.5C1.56846 8.43154 1.56846 11.5685 3.5 13.5C5.43154 15.4315 8.56846 15.4315 10.5 13.5L15.5 8.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", transform: "translate(2, 3)" }) }),
|
|
1396
|
+
/* @__PURE__ */ jsx13("span", { className: "!text-sm font-medium", children: "Add photos & files" })
|
|
1397
|
+
]
|
|
1398
|
+
}
|
|
1399
|
+
),
|
|
1400
|
+
onExpand && /* @__PURE__ */ jsxs9(
|
|
1401
|
+
"button",
|
|
1402
|
+
{
|
|
1403
|
+
onClick: () => {
|
|
1404
|
+
onExpand();
|
|
1405
|
+
setShowMenu(false);
|
|
1406
|
+
},
|
|
1407
|
+
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 border-t border-gray-700 dark:border-gray-600",
|
|
1408
|
+
children: [
|
|
1409
|
+
/* @__PURE__ */ jsx13("svg", { className: "w-4.5 h-4.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" }) }),
|
|
1410
|
+
/* @__PURE__ */ jsx13("span", { className: "!text-sm font-medium", children: "Expand to chat" })
|
|
1411
|
+
]
|
|
1412
|
+
}
|
|
1413
|
+
)
|
|
1414
|
+
]
|
|
1415
|
+
}
|
|
1416
|
+
)
|
|
1417
|
+
] }),
|
|
1418
|
+
pendingFiles.length > 0 && state === "idle" && /* @__PURE__ */ jsx13("div", { className: "mb-2 flex flex-wrap gap-2", children: pendingFiles.map((pf, index) => /* @__PURE__ */ jsxs9(
|
|
1419
|
+
"div",
|
|
1420
|
+
{
|
|
1421
|
+
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",
|
|
1422
|
+
children: [
|
|
1423
|
+
pf.preview ? /* @__PURE__ */ jsx13("img", { src: pf.preview, alt: pf.file.name, className: "w-6 h-6 object-cover rounded" }) : /* @__PURE__ */ jsx13("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) }),
|
|
1424
|
+
/* @__PURE__ */ jsx13("span", { className: "text-xs font-medium !text-gray-700 dark:!text-gray-300 truncate max-w-[100px]", children: pf.file.name }),
|
|
1425
|
+
/* @__PURE__ */ jsx13(
|
|
1426
|
+
"button",
|
|
1427
|
+
{
|
|
1428
|
+
onClick: () => removeFile(index),
|
|
1429
|
+
className: "w-4 h-4 bg-gray-500 hover:bg-red-500 text-white rounded-full flex items-center justify-center",
|
|
1430
|
+
title: "Remove file",
|
|
1431
|
+
children: /* @__PURE__ */ jsx13("svg", { className: "w-2.5 h-2.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
1432
|
+
}
|
|
1433
|
+
)
|
|
1434
|
+
]
|
|
1435
|
+
},
|
|
1436
|
+
index
|
|
1437
|
+
)) }),
|
|
1438
|
+
/* @__PURE__ */ jsxs9(
|
|
1439
|
+
"div",
|
|
1440
|
+
{
|
|
1441
|
+
className: cn(
|
|
1442
|
+
"flex items-center gap-2 px-3 py-2 border-2 rounded-2xl bg-white dark:bg-gray-900 transition-all duration-200",
|
|
1443
|
+
state === "idle" && "border-gray-200 dark:border-gray-700",
|
|
1444
|
+
state === "loading" && "border-blue-400 dark:border-blue-500",
|
|
1445
|
+
state === "plan-pending" && "border-amber-400 dark:border-amber-500",
|
|
1446
|
+
state === "success" && "border-green-400 dark:border-green-500",
|
|
1447
|
+
state === "error" && "border-red-400 dark:border-red-500"
|
|
1448
|
+
),
|
|
1449
|
+
children: [
|
|
1450
|
+
state === "idle" && /* @__PURE__ */ jsx13(
|
|
1451
|
+
"button",
|
|
1452
|
+
{
|
|
1453
|
+
ref: menuButtonRef,
|
|
1454
|
+
onClick: () => setShowMenu(!showMenu),
|
|
1455
|
+
className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0 !text-gray-500 dark:!text-gray-400 hover:!text-gray-700 dark:hover:!text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-800",
|
|
1456
|
+
title: "More options",
|
|
1457
|
+
children: /* @__PURE__ */ jsx13("svg", { width: "18", height: "18", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx13("path", { d: "M10 5v10M5 10h10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
1458
|
+
}
|
|
1459
|
+
),
|
|
1460
|
+
state === "loading" && !toolName && /* @__PURE__ */ jsx13("div", { className: "w-4 h-4 border-2 border-blue-200 border-t-blue-500 rounded-full animate-spin flex-shrink-0" }),
|
|
1461
|
+
state === "loading" && toolName && /* @__PURE__ */ jsx13("div", { className: "w-2 h-2 rounded-full bg-blue-500 animate-pulse flex-shrink-0" }),
|
|
1462
|
+
state === "idle" ? /* @__PURE__ */ jsx13(
|
|
1463
|
+
"textarea",
|
|
1464
|
+
{
|
|
1465
|
+
ref: inputRef,
|
|
1466
|
+
value: input,
|
|
1467
|
+
onChange: (e) => handleInputChange(e.target.value),
|
|
1468
|
+
onKeyDown: handleKeyDown,
|
|
1469
|
+
placeholder,
|
|
1470
|
+
disabled,
|
|
1471
|
+
rows: 1,
|
|
1472
|
+
className: cn(
|
|
1473
|
+
"flex-1 resize-none bg-transparent border-none focus:outline-none",
|
|
1474
|
+
"!text-gray-900 dark:!text-gray-100 placeholder-gray-400 dark:placeholder-gray-500",
|
|
1475
|
+
"text-sm leading-relaxed py-1",
|
|
1476
|
+
"disabled:opacity-50"
|
|
1477
|
+
),
|
|
1478
|
+
style: { minHeight: "24px", maxHeight: "120px" }
|
|
1479
|
+
}
|
|
1480
|
+
) : /* @__PURE__ */ jsx13(
|
|
1481
|
+
"div",
|
|
1482
|
+
{
|
|
1483
|
+
className: cn(
|
|
1484
|
+
"flex-1 text-sm py-1 truncate flex items-center gap-2",
|
|
1485
|
+
state === "loading" && !isToolCall && "!text-gray-600 dark:!text-gray-400",
|
|
1486
|
+
state === "loading" && isToolCall && "!text-blue-600 dark:!text-blue-400",
|
|
1487
|
+
state === "success" && "!text-gray-900 dark:!text-gray-100",
|
|
1488
|
+
state === "error" && "!text-red-600 dark:!text-red-400",
|
|
1489
|
+
state === "plan-pending" && "!text-amber-700 dark:!text-amber-300"
|
|
1490
|
+
),
|
|
1491
|
+
children: isToolCall ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
1492
|
+
/* @__PURE__ */ jsx13("span", { className: "font-mono", children: displayContent }),
|
|
1493
|
+
/* @__PURE__ */ jsx13("span", { className: "text-gray-400 dark:text-gray-500", children: "Running..." })
|
|
1494
|
+
] }) : displayContent
|
|
1495
|
+
}
|
|
1496
|
+
),
|
|
1497
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1 flex-shrink-0", children: [
|
|
1498
|
+
state === "plan-pending" && /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
1499
|
+
/* @__PURE__ */ jsx13(
|
|
1500
|
+
"button",
|
|
1501
|
+
{
|
|
1502
|
+
onClick: onApprove,
|
|
1503
|
+
className: "px-2 py-1 bg-amber-500 text-white rounded-lg hover:bg-amber-600 transition-colors text-xs font-medium",
|
|
1504
|
+
children: "Approve"
|
|
1505
|
+
}
|
|
1506
|
+
),
|
|
1507
|
+
/* @__PURE__ */ jsx13(
|
|
1508
|
+
"button",
|
|
1509
|
+
{
|
|
1510
|
+
onClick: onReject,
|
|
1511
|
+
className: "px-2 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors text-xs font-medium",
|
|
1512
|
+
children: "Modify"
|
|
1513
|
+
}
|
|
1514
|
+
)
|
|
1515
|
+
] }),
|
|
1516
|
+
(state === "success" || state === "error") && /* @__PURE__ */ jsx13(
|
|
1517
|
+
"button",
|
|
1518
|
+
{
|
|
1519
|
+
onClick: handleNewCommand,
|
|
1520
|
+
className: "w-8 h-8 rounded-lg flex items-center justify-center !text-gray-400 hover:!text-gray-600 dark:hover:!text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors",
|
|
1521
|
+
title: "New command",
|
|
1522
|
+
children: /* @__PURE__ */ jsx13("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
1523
|
+
}
|
|
1524
|
+
),
|
|
1525
|
+
state === "idle" && /* @__PURE__ */ jsx13(
|
|
1526
|
+
"button",
|
|
1527
|
+
{
|
|
1528
|
+
onClick: handleSubmit,
|
|
1529
|
+
disabled: !input.trim() && pendingFiles.length === 0 || disabled,
|
|
1530
|
+
className: cn(
|
|
1531
|
+
"w-8 h-8 rounded-lg flex items-center justify-center transition-all",
|
|
1532
|
+
"border border-gray-200 dark:border-gray-700",
|
|
1533
|
+
"disabled:opacity-30 disabled:cursor-not-allowed",
|
|
1534
|
+
input.trim() || pendingFiles.length > 0 ? "bg-gray-900 dark:bg-white !text-white dark:!text-gray-900 border-gray-900 dark:border-white" : "bg-white dark:bg-gray-800 !text-gray-400"
|
|
1535
|
+
),
|
|
1536
|
+
title: "Execute command",
|
|
1537
|
+
children: /* @__PURE__ */ jsx13("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 12h14M12 5l7 7-7 7" }) })
|
|
1538
|
+
}
|
|
1539
|
+
)
|
|
1540
|
+
] })
|
|
1541
|
+
]
|
|
1542
|
+
}
|
|
1543
|
+
),
|
|
1544
|
+
state === "success" && response?.includes("weather") && /* @__PURE__ */ jsx13("div", { className: "mt-3 p-3 bg-gradient-to-r from-blue-50 to-cyan-50 dark:from-blue-900/20 dark:to-cyan-900/20 border border-blue-200 dark:border-blue-800 rounded-xl", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3", children: [
|
|
1545
|
+
/* @__PURE__ */ jsx13("div", { className: "text-3xl", children: "\u2600\uFE0F" }),
|
|
1546
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex-1", children: [
|
|
1547
|
+
/* @__PURE__ */ jsx13("div", { className: "text-sm font-medium text-gray-900 dark:text-white", children: "Paris, France" }),
|
|
1548
|
+
/* @__PURE__ */ jsx13("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Sunny, 22\xB0C" })
|
|
1549
|
+
] }),
|
|
1550
|
+
/* @__PURE__ */ jsx13("button", { className: "px-3 py-1 text-xs bg-blue-500 text-white rounded-lg hover:bg-blue-600", children: "Details" })
|
|
1551
|
+
] }) }),
|
|
1552
|
+
state === "success" && response?.includes("trip") && /* @__PURE__ */ jsxs9("div", { className: "mt-3 p-3 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl shadow-sm", children: [
|
|
1553
|
+
/* @__PURE__ */ jsx13("img", { src: "https://images.unsplash.com/photo-1502602898657-3e91760cbb34?w=400&h=150&fit=crop", alt: "Paris", className: "w-full h-24 object-cover rounded-lg mb-2" }),
|
|
1554
|
+
/* @__PURE__ */ jsx13("div", { className: "text-sm font-medium text-gray-900 dark:text-white", children: "Paris Weekend Getaway" }),
|
|
1555
|
+
/* @__PURE__ */ jsx13("div", { className: "text-xs text-gray-500 dark:text-gray-400 mb-2", children: "3 days \xB7 $850" }),
|
|
1556
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex gap-2", children: [
|
|
1557
|
+
/* @__PURE__ */ jsx13("button", { className: "flex-1 px-2 py-1 text-xs bg-blue-500 text-white rounded-lg hover:bg-blue-600", children: "Book" }),
|
|
1558
|
+
/* @__PURE__ */ jsx13("button", { className: "flex-1 px-2 py-1 text-xs bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600", children: "Details" })
|
|
1559
|
+
] })
|
|
1560
|
+
] }),
|
|
1561
|
+
state === "success" && response?.includes("task") && /* @__PURE__ */ jsx13("div", { className: "mt-3 border border-gray-200 dark:border-gray-700 rounded-xl overflow-hidden", children: ["Review PR #123", "Update documentation", "Fix login bug"].map((task, i) => /* @__PURE__ */ jsxs9("div", { className: `flex items-center gap-2 px-3 py-2 ${i > 0 ? "border-t border-gray-100 dark:border-gray-800" : ""}`, children: [
|
|
1562
|
+
/* @__PURE__ */ jsx13("div", { className: `w-2 h-2 rounded-full ${i === 0 ? "bg-green-500" : i === 1 ? "bg-yellow-500" : "bg-red-500"}` }),
|
|
1563
|
+
/* @__PURE__ */ jsx13("span", { className: "flex-1 text-sm text-gray-700 dark:text-gray-300", children: task }),
|
|
1564
|
+
/* @__PURE__ */ jsx13("button", { className: "text-xs text-blue-500 hover:text-blue-600", children: "View" })
|
|
1565
|
+
] }, i)) }),
|
|
1566
|
+
/* @__PURE__ */ jsx13(
|
|
825
1567
|
"input",
|
|
826
1568
|
{
|
|
827
1569
|
ref: fileInputRef,
|
|
@@ -836,7 +1578,7 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
|
|
|
836
1578
|
}
|
|
837
1579
|
|
|
838
1580
|
// src/lib/apteva-client.ts
|
|
839
|
-
var DEFAULT_API_URL = "http://
|
|
1581
|
+
var DEFAULT_API_URL = "http://91.99.200.48:3000/agents";
|
|
840
1582
|
var DEFAULT_API_KEY = "agt_894abd5966bc9f1e9f8f17f2a6f6b5e0";
|
|
841
1583
|
var AptevaClient = class {
|
|
842
1584
|
constructor() {
|
|
@@ -1000,7 +1742,7 @@ var AptevaClient = class {
|
|
|
1000
1742
|
var aptevaClient = new AptevaClient();
|
|
1001
1743
|
|
|
1002
1744
|
// src/components/Chat/Chat.tsx
|
|
1003
|
-
import { jsx as
|
|
1745
|
+
import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1004
1746
|
function Chat({
|
|
1005
1747
|
agentId,
|
|
1006
1748
|
threadId,
|
|
@@ -1009,18 +1751,52 @@ function Chat({
|
|
|
1009
1751
|
apiUrl,
|
|
1010
1752
|
apiKey,
|
|
1011
1753
|
useMock = false,
|
|
1754
|
+
// Mode switching
|
|
1755
|
+
initialMode = "chat",
|
|
1756
|
+
showModeToggle = false,
|
|
1757
|
+
onModeChange,
|
|
1758
|
+
// Command mode options
|
|
1759
|
+
commandVariant = "default",
|
|
1760
|
+
planMode = false,
|
|
1761
|
+
onPlanModeChange,
|
|
1762
|
+
enableStreaming = true,
|
|
1763
|
+
showProgress = true,
|
|
1764
|
+
loadingText = "Processing...",
|
|
1765
|
+
// Welcome screen
|
|
1766
|
+
welcomeTitle,
|
|
1767
|
+
welcomeSubtitle,
|
|
1768
|
+
welcomeIcon,
|
|
1769
|
+
suggestedPrompts,
|
|
1770
|
+
welcomeVariant,
|
|
1771
|
+
// Events
|
|
1012
1772
|
onThreadChange,
|
|
1013
1773
|
onMessageSent,
|
|
1014
1774
|
onAction,
|
|
1015
1775
|
onFileUpload,
|
|
1016
|
-
|
|
1776
|
+
onComplete,
|
|
1777
|
+
onError,
|
|
1778
|
+
// UI
|
|
1779
|
+
placeholder,
|
|
1017
1780
|
showHeader = true,
|
|
1018
1781
|
headerTitle = "Chat",
|
|
1019
1782
|
className
|
|
1020
1783
|
}) {
|
|
1021
|
-
const [messages, setMessages] =
|
|
1022
|
-
const [isLoading, setIsLoading] =
|
|
1023
|
-
const [currentThreadId, setCurrentThreadId] =
|
|
1784
|
+
const [messages, setMessages] = useState3(initialMessages);
|
|
1785
|
+
const [isLoading, setIsLoading] = useState3(false);
|
|
1786
|
+
const [currentThreadId, setCurrentThreadId] = useState3(threadId || null);
|
|
1787
|
+
const [mode, setMode] = useState3(initialMode);
|
|
1788
|
+
const [commandState, setCommandState] = useState3("idle");
|
|
1789
|
+
const [commandResult, setCommandResult] = useState3(null);
|
|
1790
|
+
const [commandError, setCommandError] = useState3(null);
|
|
1791
|
+
const [progress, setProgress] = useState3(0);
|
|
1792
|
+
const [commandInput, setCommandInput] = useState3("");
|
|
1793
|
+
const [streamedContent, setStreamedContent] = useState3("");
|
|
1794
|
+
const [currentToolName, setCurrentToolName] = useState3(null);
|
|
1795
|
+
const [plan, setPlan] = useState3("");
|
|
1796
|
+
const [pendingCommand, setPendingCommand] = useState3("");
|
|
1797
|
+
const [internalPlanMode, setInternalPlanMode] = useState3(planMode);
|
|
1798
|
+
const [showSettingsMenu, setShowSettingsMenu] = useState3(false);
|
|
1799
|
+
const fileInputRef = useRef4(null);
|
|
1024
1800
|
useEffect3(() => {
|
|
1025
1801
|
if (apiUrl || apiKey) {
|
|
1026
1802
|
aptevaClient.configure({
|
|
@@ -1031,21 +1807,48 @@ function Chat({
|
|
|
1031
1807
|
}, [apiUrl, apiKey]);
|
|
1032
1808
|
useEffect3(() => {
|
|
1033
1809
|
if (threadId) {
|
|
1034
|
-
console.log("Loading thread:", threadId);
|
|
1035
1810
|
onThreadChange?.(threadId);
|
|
1036
1811
|
}
|
|
1037
1812
|
}, [threadId, onThreadChange]);
|
|
1038
|
-
|
|
1813
|
+
useEffect3(() => {
|
|
1814
|
+
setInternalPlanMode(planMode);
|
|
1815
|
+
}, [planMode]);
|
|
1816
|
+
useEffect3(() => {
|
|
1817
|
+
const handleClickOutside = (event) => {
|
|
1818
|
+
const target = event.target;
|
|
1819
|
+
if (showSettingsMenu && !target.closest(".settings-menu-container")) {
|
|
1820
|
+
setShowSettingsMenu(false);
|
|
1821
|
+
}
|
|
1822
|
+
};
|
|
1823
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1824
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1825
|
+
}, [showSettingsMenu]);
|
|
1826
|
+
const handleModeChange = (newMode) => {
|
|
1827
|
+
setMode(newMode);
|
|
1828
|
+
onModeChange?.(newMode);
|
|
1829
|
+
if (newMode === "command") {
|
|
1830
|
+
setCommandState("idle");
|
|
1831
|
+
setCommandResult(null);
|
|
1832
|
+
setCommandError(null);
|
|
1833
|
+
}
|
|
1834
|
+
};
|
|
1835
|
+
const defaultPlaceholder = mode === "chat" ? "Type a message..." : "Enter your command...";
|
|
1836
|
+
const handleSendMessage = async (text, files) => {
|
|
1837
|
+
const hasFiles = files && files.length > 0;
|
|
1838
|
+
const fileNames = hasFiles ? files.map((f) => f.name) : [];
|
|
1839
|
+
const displayContent = hasFiles ? `${text}${text ? "\n" : ""}[Attached: ${fileNames.join(", ")}]` : text;
|
|
1039
1840
|
const userMessage = {
|
|
1040
1841
|
id: `msg-${Date.now()}`,
|
|
1041
1842
|
role: "user",
|
|
1042
|
-
content:
|
|
1043
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
1843
|
+
content: displayContent,
|
|
1844
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1845
|
+
metadata: hasFiles ? { attachments: fileNames } : void 0
|
|
1044
1846
|
};
|
|
1045
1847
|
setMessages((prev) => [...prev, userMessage]);
|
|
1046
1848
|
onMessageSent?.(userMessage);
|
|
1047
1849
|
setIsLoading(true);
|
|
1048
1850
|
try {
|
|
1851
|
+
const messagePayload = await buildMessageWithAttachments(text, files);
|
|
1049
1852
|
if (useMock) {
|
|
1050
1853
|
const response = await generateMockResponse(1e3);
|
|
1051
1854
|
setMessages((prev) => [...prev, response]);
|
|
@@ -1074,10 +1877,7 @@ function Chat({
|
|
|
1074
1877
|
...lastMessage,
|
|
1075
1878
|
content: currentTextBuffer,
|
|
1076
1879
|
widgets: accumulatedWidgets.length > 0 ? accumulatedWidgets : void 0,
|
|
1077
|
-
metadata: {
|
|
1078
|
-
...lastMessage.metadata,
|
|
1079
|
-
content_segments: segments
|
|
1080
|
-
}
|
|
1880
|
+
metadata: { ...lastMessage.metadata, content_segments: segments }
|
|
1081
1881
|
}
|
|
1082
1882
|
];
|
|
1083
1883
|
} else {
|
|
@@ -1089,9 +1889,7 @@ function Chat({
|
|
|
1089
1889
|
content: currentTextBuffer,
|
|
1090
1890
|
widgets: accumulatedWidgets.length > 0 ? accumulatedWidgets : void 0,
|
|
1091
1891
|
timestamp: /* @__PURE__ */ new Date(),
|
|
1092
|
-
metadata: {
|
|
1093
|
-
content_segments: segments
|
|
1094
|
-
}
|
|
1892
|
+
metadata: { content_segments: segments }
|
|
1095
1893
|
}
|
|
1096
1894
|
];
|
|
1097
1895
|
}
|
|
@@ -1100,15 +1898,13 @@ function Chat({
|
|
|
1100
1898
|
await aptevaClient.chatStream(
|
|
1101
1899
|
{
|
|
1102
1900
|
agent_id: agentId,
|
|
1103
|
-
message:
|
|
1901
|
+
message: messagePayload,
|
|
1104
1902
|
stream: true,
|
|
1105
1903
|
...currentThreadId && { thread_id: currentThreadId },
|
|
1106
1904
|
...context && { system: context }
|
|
1107
1905
|
},
|
|
1108
1906
|
(chunk) => {
|
|
1109
1907
|
switch (chunk.type) {
|
|
1110
|
-
case "start":
|
|
1111
|
-
break;
|
|
1112
1908
|
case "thread_id":
|
|
1113
1909
|
if (chunk.thread_id) {
|
|
1114
1910
|
responseThreadId = chunk.thread_id;
|
|
@@ -1131,11 +1927,7 @@ function Chat({
|
|
|
1131
1927
|
contentSegments.push({ type: "text", content: currentTextBuffer });
|
|
1132
1928
|
currentTextBuffer = "";
|
|
1133
1929
|
}
|
|
1134
|
-
contentSegments.push({
|
|
1135
|
-
type: "tool",
|
|
1136
|
-
id: chunk.tool_id,
|
|
1137
|
-
name: chunk.tool_name
|
|
1138
|
-
});
|
|
1930
|
+
contentSegments.push({ type: "tool", id: chunk.tool_id, name: chunk.tool_name });
|
|
1139
1931
|
toolInputBuffer = "";
|
|
1140
1932
|
updateMessage();
|
|
1141
1933
|
}
|
|
@@ -1145,14 +1937,9 @@ function Chat({
|
|
|
1145
1937
|
toolInputBuffer += chunk.content;
|
|
1146
1938
|
}
|
|
1147
1939
|
break;
|
|
1148
|
-
case "tool_use":
|
|
1149
|
-
toolInputBuffer = "";
|
|
1150
|
-
break;
|
|
1151
1940
|
case "tool_result":
|
|
1152
1941
|
if (chunk.tool_id) {
|
|
1153
|
-
const toolSegment = contentSegments.find(
|
|
1154
|
-
(s) => s.type === "tool" && s.id === chunk.tool_id
|
|
1155
|
-
);
|
|
1942
|
+
const toolSegment = contentSegments.find((s) => s.type === "tool" && s.id === chunk.tool_id);
|
|
1156
1943
|
if (toolSegment) {
|
|
1157
1944
|
toolSegment.result = chunk.content;
|
|
1158
1945
|
}
|
|
@@ -1165,14 +1952,8 @@ function Chat({
|
|
|
1165
1952
|
updateMessage();
|
|
1166
1953
|
}
|
|
1167
1954
|
break;
|
|
1168
|
-
case "stop":
|
|
1169
|
-
break;
|
|
1170
|
-
case "complete":
|
|
1171
|
-
break;
|
|
1172
1955
|
case "error":
|
|
1173
1956
|
throw new Error(chunk.message || "Stream error");
|
|
1174
|
-
default:
|
|
1175
|
-
break;
|
|
1176
1957
|
}
|
|
1177
1958
|
},
|
|
1178
1959
|
(threadId2) => {
|
|
@@ -1194,10 +1975,7 @@ function Chat({
|
|
|
1194
1975
|
id: `msg-${Date.now()}`,
|
|
1195
1976
|
content: currentTextBuffer || "Response received",
|
|
1196
1977
|
widgets: accumulatedWidgets.length > 0 ? accumulatedWidgets : void 0,
|
|
1197
|
-
metadata: {
|
|
1198
|
-
thread_id: threadId2,
|
|
1199
|
-
content_segments: contentSegments
|
|
1200
|
-
}
|
|
1978
|
+
metadata: { thread_id: threadId2, content_segments: contentSegments }
|
|
1201
1979
|
}
|
|
1202
1980
|
];
|
|
1203
1981
|
}
|
|
@@ -1225,11 +2003,11 @@ function Chat({
|
|
|
1225
2003
|
return [...prev, errorMessage];
|
|
1226
2004
|
});
|
|
1227
2005
|
setIsLoading(false);
|
|
2006
|
+
onError?.(error);
|
|
1228
2007
|
}
|
|
1229
2008
|
);
|
|
1230
2009
|
}
|
|
1231
2010
|
} catch (error) {
|
|
1232
|
-
console.error("Chat error:", error);
|
|
1233
2011
|
const errorMessage = {
|
|
1234
2012
|
id: `msg-${Date.now()}-error`,
|
|
1235
2013
|
role: "assistant",
|
|
@@ -1238,21 +2016,280 @@ function Chat({
|
|
|
1238
2016
|
metadata: { error: true }
|
|
1239
2017
|
};
|
|
1240
2018
|
setMessages((prev) => [...prev, errorMessage]);
|
|
2019
|
+
onError?.(error instanceof Error ? error : new Error("Unknown error"));
|
|
1241
2020
|
} finally {
|
|
1242
2021
|
setIsLoading(false);
|
|
1243
2022
|
}
|
|
1244
2023
|
};
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
2024
|
+
const executeCommand = async (commandOverride, files) => {
|
|
2025
|
+
const currentCommand = commandOverride || commandInput;
|
|
2026
|
+
if (!currentCommand.trim() && (!files || files.length === 0)) {
|
|
2027
|
+
setCommandError(new Error("Please enter a command"));
|
|
2028
|
+
setCommandState("error");
|
|
2029
|
+
return;
|
|
2030
|
+
}
|
|
2031
|
+
if (internalPlanMode && commandState !== "plan-pending") {
|
|
2032
|
+
setCommandState("loading");
|
|
2033
|
+
setCommandError(null);
|
|
2034
|
+
setCommandInput("");
|
|
2035
|
+
if (useMock) {
|
|
2036
|
+
setTimeout(() => {
|
|
2037
|
+
const mockPlan = `1. Analyze the request: "${currentCommand}"
|
|
2038
|
+
2. Process the data
|
|
2039
|
+
3. Generate response
|
|
2040
|
+
4. Return results`;
|
|
2041
|
+
setPlan(mockPlan);
|
|
2042
|
+
setPendingCommand(currentCommand);
|
|
2043
|
+
setCommandState("plan-pending");
|
|
2044
|
+
}, 800);
|
|
2045
|
+
} else {
|
|
2046
|
+
try {
|
|
2047
|
+
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.`;
|
|
2048
|
+
const systemMessage = context ? `${context}
|
|
2049
|
+
|
|
2050
|
+
${planningInstruction}` : planningInstruction;
|
|
2051
|
+
const response = await aptevaClient.chat({
|
|
2052
|
+
agent_id: agentId,
|
|
2053
|
+
message: currentCommand,
|
|
2054
|
+
stream: false,
|
|
2055
|
+
system: systemMessage
|
|
2056
|
+
});
|
|
2057
|
+
setPlan(response.message);
|
|
2058
|
+
setPendingCommand(currentCommand);
|
|
2059
|
+
setCommandState("plan-pending");
|
|
2060
|
+
} catch (err) {
|
|
2061
|
+
const error = err instanceof Error ? err : new Error("Failed to generate plan");
|
|
2062
|
+
setCommandError(error);
|
|
2063
|
+
setCommandState("error");
|
|
2064
|
+
onError?.(error);
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
return;
|
|
2068
|
+
}
|
|
2069
|
+
setCommandState("loading");
|
|
2070
|
+
setCommandError(null);
|
|
2071
|
+
setProgress(0);
|
|
2072
|
+
setStreamedContent("");
|
|
2073
|
+
setCommandInput("");
|
|
2074
|
+
try {
|
|
2075
|
+
if (useMock) {
|
|
2076
|
+
if (enableStreaming) {
|
|
2077
|
+
let accumulatedContent = "";
|
|
2078
|
+
generateMockCommandStream(
|
|
2079
|
+
currentCommand,
|
|
2080
|
+
(chunk) => {
|
|
2081
|
+
if (chunk.type === "token" && chunk.content) {
|
|
2082
|
+
accumulatedContent += chunk.content;
|
|
2083
|
+
setStreamedContent(accumulatedContent);
|
|
2084
|
+
const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
|
|
2085
|
+
setProgress(estimatedProgress);
|
|
2086
|
+
}
|
|
2087
|
+
},
|
|
2088
|
+
(threadId2) => {
|
|
2089
|
+
const result = {
|
|
2090
|
+
success: true,
|
|
2091
|
+
data: { summary: accumulatedContent, thread_id: threadId2 },
|
|
2092
|
+
message: accumulatedContent || "Command executed successfully"
|
|
2093
|
+
};
|
|
2094
|
+
setCommandResult(result);
|
|
2095
|
+
setCommandState("success");
|
|
2096
|
+
setProgress(100);
|
|
2097
|
+
onComplete?.(result);
|
|
2098
|
+
},
|
|
2099
|
+
(error) => {
|
|
2100
|
+
setCommandError(error);
|
|
2101
|
+
setCommandState("error");
|
|
2102
|
+
onError?.(error);
|
|
2103
|
+
}
|
|
2104
|
+
);
|
|
2105
|
+
} else {
|
|
2106
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
2107
|
+
const result = {
|
|
2108
|
+
success: true,
|
|
2109
|
+
data: { summary: `Executed: ${currentCommand}` },
|
|
2110
|
+
message: `Command executed successfully`
|
|
2111
|
+
};
|
|
2112
|
+
setCommandResult(result);
|
|
2113
|
+
setCommandState("success");
|
|
2114
|
+
setProgress(100);
|
|
2115
|
+
onComplete?.(result);
|
|
2116
|
+
}
|
|
2117
|
+
} else {
|
|
2118
|
+
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.`;
|
|
2119
|
+
const systemMessage = context ? `${context}
|
|
2120
|
+
|
|
2121
|
+
${commandInstruction}` : commandInstruction;
|
|
2122
|
+
const messagePayload = files && files.length > 0 ? await buildMessageWithAttachments(currentCommand, files) : currentCommand;
|
|
2123
|
+
if (enableStreaming) {
|
|
2124
|
+
let accumulatedContent = "";
|
|
2125
|
+
await aptevaClient.chatStream(
|
|
2126
|
+
{
|
|
2127
|
+
agent_id: agentId,
|
|
2128
|
+
message: messagePayload,
|
|
2129
|
+
stream: true,
|
|
2130
|
+
...currentThreadId && { thread_id: currentThreadId },
|
|
2131
|
+
system: systemMessage
|
|
2132
|
+
},
|
|
2133
|
+
(chunk) => {
|
|
2134
|
+
if ((chunk.type === "token" || chunk.type === "content") && chunk.content) {
|
|
2135
|
+
accumulatedContent += chunk.content;
|
|
2136
|
+
setStreamedContent(accumulatedContent);
|
|
2137
|
+
setCurrentToolName(null);
|
|
2138
|
+
const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
|
|
2139
|
+
setProgress(estimatedProgress);
|
|
2140
|
+
} else if (chunk.type === "tool_call" && chunk.tool_name) {
|
|
2141
|
+
setCurrentToolName(chunk.tool_name);
|
|
2142
|
+
accumulatedContent = "";
|
|
2143
|
+
setStreamedContent("");
|
|
2144
|
+
} else if (chunk.type === "tool_result") {
|
|
2145
|
+
setCurrentToolName(null);
|
|
2146
|
+
} else if (chunk.type === "thread_id" && chunk.thread_id) {
|
|
2147
|
+
if (!currentThreadId) {
|
|
2148
|
+
setCurrentThreadId(chunk.thread_id);
|
|
2149
|
+
onThreadChange?.(chunk.thread_id);
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
},
|
|
2153
|
+
(threadId2) => {
|
|
2154
|
+
const result = {
|
|
2155
|
+
success: true,
|
|
2156
|
+
data: { summary: accumulatedContent, thread_id: threadId2 },
|
|
2157
|
+
message: accumulatedContent || "Command executed successfully"
|
|
2158
|
+
};
|
|
2159
|
+
setCommandResult(result);
|
|
2160
|
+
setCommandState("success");
|
|
2161
|
+
setProgress(100);
|
|
2162
|
+
onComplete?.(result);
|
|
2163
|
+
},
|
|
2164
|
+
(error) => {
|
|
2165
|
+
setCommandError(error);
|
|
2166
|
+
setCommandState("error");
|
|
2167
|
+
onError?.(error);
|
|
2168
|
+
}
|
|
2169
|
+
);
|
|
2170
|
+
} else {
|
|
2171
|
+
const response = await aptevaClient.chat({
|
|
2172
|
+
agent_id: agentId,
|
|
2173
|
+
message: messagePayload,
|
|
2174
|
+
stream: false,
|
|
2175
|
+
...currentThreadId && { thread_id: currentThreadId },
|
|
2176
|
+
system: systemMessage
|
|
2177
|
+
});
|
|
2178
|
+
const result = {
|
|
2179
|
+
success: true,
|
|
2180
|
+
data: { summary: response.message, thread_id: response.thread_id },
|
|
2181
|
+
widgets: response.widgets,
|
|
2182
|
+
message: response.message
|
|
2183
|
+
};
|
|
2184
|
+
setCommandResult(result);
|
|
2185
|
+
setCommandState("success");
|
|
2186
|
+
setProgress(100);
|
|
2187
|
+
onComplete?.(result);
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
} catch (err) {
|
|
2191
|
+
const error = err instanceof Error ? err : new Error("Unknown error");
|
|
2192
|
+
setCommandError(error);
|
|
2193
|
+
setCommandState("error");
|
|
2194
|
+
onError?.(error);
|
|
2195
|
+
}
|
|
2196
|
+
};
|
|
2197
|
+
const resetCommand = () => {
|
|
2198
|
+
setCommandState("idle");
|
|
2199
|
+
setCommandResult(null);
|
|
2200
|
+
setCommandError(null);
|
|
2201
|
+
setProgress(0);
|
|
2202
|
+
setCommandInput("");
|
|
2203
|
+
setPlan("");
|
|
2204
|
+
setPendingCommand("");
|
|
2205
|
+
setStreamedContent("");
|
|
2206
|
+
setCurrentToolName(null);
|
|
2207
|
+
};
|
|
2208
|
+
const approvePlan = () => {
|
|
2209
|
+
const planToExecute = plan;
|
|
2210
|
+
setPlan("");
|
|
2211
|
+
setPendingCommand("");
|
|
2212
|
+
const executionMessage = `Execute this plan now:
|
|
2213
|
+
|
|
2214
|
+
${planToExecute}`;
|
|
2215
|
+
executeCommand(executionMessage);
|
|
2216
|
+
};
|
|
2217
|
+
const rejectPlan = () => {
|
|
2218
|
+
setCommandInput(pendingCommand);
|
|
2219
|
+
setPlan("");
|
|
2220
|
+
setPendingCommand("");
|
|
2221
|
+
setCommandState("idle");
|
|
2222
|
+
};
|
|
2223
|
+
const isCompact = commandVariant === "compact";
|
|
2224
|
+
return /* @__PURE__ */ jsxs10("div", { className: cn("flex flex-col h-full", className), children: [
|
|
2225
|
+
showHeader && mode === "chat" && /* @__PURE__ */ jsx14("div", { className: "px-4 py-3 flex items-center justify-between", children: /* @__PURE__ */ jsx14("h2", { className: "!text-lg font-semibold !text-gray-900 dark:!text-white", children: headerTitle }) }),
|
|
2226
|
+
mode === "chat" && /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
2227
|
+
/* @__PURE__ */ jsx14(
|
|
2228
|
+
MessageList,
|
|
2229
|
+
{
|
|
2230
|
+
messages,
|
|
2231
|
+
onAction,
|
|
2232
|
+
welcomeTitle,
|
|
2233
|
+
welcomeSubtitle,
|
|
2234
|
+
welcomeIcon,
|
|
2235
|
+
suggestedPrompts,
|
|
2236
|
+
welcomeVariant,
|
|
2237
|
+
onPromptClick: (prompt) => handleSendMessage(prompt)
|
|
2238
|
+
}
|
|
2239
|
+
),
|
|
2240
|
+
isLoading && /* @__PURE__ */ jsx14("div", { className: "px-4 py-2 !text-sm !text-gray-500 dark:!text-gray-400 italic", children: "AI is thinking..." }),
|
|
2241
|
+
/* @__PURE__ */ jsx14(
|
|
2242
|
+
Composer,
|
|
2243
|
+
{
|
|
2244
|
+
onSendMessage: handleSendMessage,
|
|
2245
|
+
placeholder: placeholder || defaultPlaceholder,
|
|
2246
|
+
disabled: isLoading,
|
|
2247
|
+
onFileUpload,
|
|
2248
|
+
onSwitchMode: showModeToggle ? () => handleModeChange("command") : void 0
|
|
2249
|
+
}
|
|
2250
|
+
)
|
|
2251
|
+
] }),
|
|
2252
|
+
mode === "command" && /* @__PURE__ */ jsx14("div", { className: "w-full", children: /* @__PURE__ */ jsx14(
|
|
2253
|
+
CommandComposer,
|
|
2254
|
+
{
|
|
2255
|
+
onExecute: (text, files) => {
|
|
2256
|
+
setCommandInput(text);
|
|
2257
|
+
executeCommand(text, files);
|
|
2258
|
+
},
|
|
2259
|
+
state: commandState,
|
|
2260
|
+
response: commandResult?.data?.summary || commandResult?.message,
|
|
2261
|
+
error: commandError?.message,
|
|
2262
|
+
plan,
|
|
2263
|
+
streamedContent,
|
|
2264
|
+
toolName: currentToolName,
|
|
2265
|
+
onApprove: approvePlan,
|
|
2266
|
+
onReject: rejectPlan,
|
|
2267
|
+
onReset: resetCommand,
|
|
2268
|
+
onExpand: showModeToggle ? () => handleModeChange("chat") : void 0,
|
|
2269
|
+
placeholder: placeholder || "Enter your command..."
|
|
2270
|
+
}
|
|
2271
|
+
) }),
|
|
2272
|
+
/* @__PURE__ */ jsx14("style", { dangerouslySetInnerHTML: {
|
|
2273
|
+
__html: `
|
|
2274
|
+
@keyframes pulse-border {
|
|
2275
|
+
0%, 100% { border-color: rgb(59, 130, 246); }
|
|
2276
|
+
50% { border-color: rgb(147, 197, 253); }
|
|
2277
|
+
}
|
|
2278
|
+
.animate-pulse-border {
|
|
2279
|
+
animation: pulse-border 2s ease-in-out infinite;
|
|
2280
|
+
}
|
|
2281
|
+
`
|
|
2282
|
+
} })
|
|
1250
2283
|
] });
|
|
1251
2284
|
}
|
|
1252
2285
|
|
|
2286
|
+
// src/components/Chat/CommandOutput.tsx
|
|
2287
|
+
import { useState as useState4 } from "react";
|
|
2288
|
+
import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2289
|
+
|
|
1253
2290
|
// src/components/Command/Command.tsx
|
|
1254
|
-
import React, { useState as
|
|
1255
|
-
import { Fragment as
|
|
2291
|
+
import React, { useState as useState5, useEffect as useEffect4 } from "react";
|
|
2292
|
+
import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1256
2293
|
function Command({
|
|
1257
2294
|
agentId,
|
|
1258
2295
|
command: initialCommand,
|
|
@@ -1279,18 +2316,18 @@ function Command({
|
|
|
1279
2316
|
resultRenderer,
|
|
1280
2317
|
className
|
|
1281
2318
|
}) {
|
|
1282
|
-
const [state, setState] =
|
|
1283
|
-
const [result, setResult] =
|
|
1284
|
-
const [error, setError] =
|
|
1285
|
-
const [progress, setProgress] =
|
|
1286
|
-
const [command, setCommand] =
|
|
1287
|
-
const [streamedContent, setStreamedContent] =
|
|
1288
|
-
const [plan, setPlan] =
|
|
1289
|
-
const [pendingCommand, setPendingCommand] =
|
|
1290
|
-
const [showPlanDetails, setShowPlanDetails] =
|
|
1291
|
-
const [uploadedFiles, setUploadedFiles] =
|
|
1292
|
-
const [showSettingsMenu, setShowSettingsMenu] =
|
|
1293
|
-
const [internalPlanMode, setInternalPlanMode] =
|
|
2319
|
+
const [state, setState] = useState5("idle");
|
|
2320
|
+
const [result, setResult] = useState5(null);
|
|
2321
|
+
const [error, setError] = useState5(null);
|
|
2322
|
+
const [progress, setProgress] = useState5(0);
|
|
2323
|
+
const [command, setCommand] = useState5(initialCommand || "");
|
|
2324
|
+
const [streamedContent, setStreamedContent] = useState5("");
|
|
2325
|
+
const [plan, setPlan] = useState5("");
|
|
2326
|
+
const [pendingCommand, setPendingCommand] = useState5("");
|
|
2327
|
+
const [showPlanDetails, setShowPlanDetails] = useState5(false);
|
|
2328
|
+
const [uploadedFiles, setUploadedFiles] = useState5([]);
|
|
2329
|
+
const [showSettingsMenu, setShowSettingsMenu] = useState5(false);
|
|
2330
|
+
const [internalPlanMode, setInternalPlanMode] = useState5(planMode);
|
|
1294
2331
|
const fileInputRef = React.useRef(null);
|
|
1295
2332
|
useEffect4(() => {
|
|
1296
2333
|
if (autoExecute && state === "idle" && command) {
|
|
@@ -1702,7 +2739,7 @@ ${planToExecute}`;
|
|
|
1702
2739
|
setUploadedFiles((prev) => prev.filter((_, i) => i !== index));
|
|
1703
2740
|
};
|
|
1704
2741
|
const isCompact = variant === "compact";
|
|
1705
|
-
return /* @__PURE__ */
|
|
2742
|
+
return /* @__PURE__ */ jsxs12(
|
|
1706
2743
|
"div",
|
|
1707
2744
|
{
|
|
1708
2745
|
className: cn(
|
|
@@ -1717,9 +2754,9 @@ ${planToExecute}`;
|
|
|
1717
2754
|
),
|
|
1718
2755
|
style: { minHeight: isCompact ? "auto" : "180px" },
|
|
1719
2756
|
children: [
|
|
1720
|
-
/* @__PURE__ */
|
|
1721
|
-
state === "idle" && allowInput && !isCompact && /* @__PURE__ */
|
|
1722
|
-
/* @__PURE__ */
|
|
2757
|
+
/* @__PURE__ */ jsxs12("div", { className: cn("flex-1 flex", isCompact ? "flex-row items-center p-3 gap-3" : "flex-col p-4"), children: [
|
|
2758
|
+
state === "idle" && allowInput && !isCompact && /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
2759
|
+
/* @__PURE__ */ jsx16(
|
|
1723
2760
|
"textarea",
|
|
1724
2761
|
{
|
|
1725
2762
|
value: command,
|
|
@@ -1735,42 +2772,42 @@ ${planToExecute}`;
|
|
|
1735
2772
|
rows: 6
|
|
1736
2773
|
}
|
|
1737
2774
|
),
|
|
1738
|
-
uploadedFiles.length > 0 && /* @__PURE__ */
|
|
1739
|
-
file.type === "image" ? /* @__PURE__ */
|
|
2775
|
+
uploadedFiles.length > 0 && /* @__PURE__ */ jsx16("div", { className: "flex flex-wrap gap-2 mt-2", children: uploadedFiles.map((file, index) => /* @__PURE__ */ jsxs12("div", { className: "relative group", children: [
|
|
2776
|
+
file.type === "image" ? /* @__PURE__ */ jsx16(
|
|
1740
2777
|
"img",
|
|
1741
2778
|
{
|
|
1742
2779
|
src: file.preview,
|
|
1743
2780
|
alt: file.name,
|
|
1744
2781
|
className: "w-20 h-20 object-cover rounded-lg border-2 border-gray-300 dark:border-gray-600"
|
|
1745
2782
|
}
|
|
1746
|
-
) : /* @__PURE__ */
|
|
1747
|
-
/* @__PURE__ */
|
|
1748
|
-
/* @__PURE__ */
|
|
2783
|
+
) : /* @__PURE__ */ jsxs12("div", { className: "w-20 h-20 flex flex-col items-center justify-center rounded-lg border-2 border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800", children: [
|
|
2784
|
+
/* @__PURE__ */ jsx16("svg", { className: "w-8 h-8 text-gray-500 dark:text-gray-400", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx16("path", { fillRule: "evenodd", d: "M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z", clipRule: "evenodd" }) }),
|
|
2785
|
+
/* @__PURE__ */ jsx16("span", { className: "text-[8px] text-gray-500 dark:text-gray-400 mt-1 px-1 truncate max-w-full", children: file.name.length > 12 ? file.name.slice(0, 12) + "..." : file.name })
|
|
1749
2786
|
] }),
|
|
1750
|
-
/* @__PURE__ */
|
|
2787
|
+
/* @__PURE__ */ jsx16(
|
|
1751
2788
|
"button",
|
|
1752
2789
|
{
|
|
1753
2790
|
onClick: () => removeFile(index),
|
|
1754
2791
|
className: "absolute -top-2 -right-2 w-6 h-6 bg-red-500 hover:bg-red-600 text-white rounded-full flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity",
|
|
1755
2792
|
title: `Remove ${file.type}`,
|
|
1756
|
-
children: /* @__PURE__ */
|
|
2793
|
+
children: /* @__PURE__ */ jsx16("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx16("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
1757
2794
|
}
|
|
1758
2795
|
)
|
|
1759
2796
|
] }, index)) })
|
|
1760
2797
|
] }),
|
|
1761
|
-
state === "idle" && allowInput && isCompact && /* @__PURE__ */
|
|
1762
|
-
/* @__PURE__ */
|
|
1763
|
-
enableFileUpload && /* @__PURE__ */
|
|
2798
|
+
state === "idle" && allowInput && isCompact && /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
2799
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-0.5 flex-shrink-0", children: [
|
|
2800
|
+
enableFileUpload && /* @__PURE__ */ jsx16(
|
|
1764
2801
|
"button",
|
|
1765
2802
|
{
|
|
1766
2803
|
onClick: () => fileInputRef.current?.click(),
|
|
1767
2804
|
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",
|
|
1768
2805
|
title: "Attach file",
|
|
1769
|
-
children: /* @__PURE__ */
|
|
2806
|
+
children: /* @__PURE__ */ jsx16("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx16("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)" }) })
|
|
1770
2807
|
}
|
|
1771
2808
|
),
|
|
1772
|
-
planMode && /* @__PURE__ */
|
|
1773
|
-
/* @__PURE__ */
|
|
2809
|
+
planMode && /* @__PURE__ */ jsxs12("div", { className: "relative settings-menu-container", children: [
|
|
2810
|
+
/* @__PURE__ */ jsx16(
|
|
1774
2811
|
"button",
|
|
1775
2812
|
{
|
|
1776
2813
|
onClick: () => setShowSettingsMenu(!showSettingsMenu),
|
|
@@ -1779,28 +2816,28 @@ ${planToExecute}`;
|
|
|
1779
2816
|
internalPlanMode ? "!text-blue-600 dark:!text-blue-400" : "!text-gray-500 dark:!text-gray-500"
|
|
1780
2817
|
),
|
|
1781
2818
|
title: "Settings",
|
|
1782
|
-
children: /* @__PURE__ */
|
|
1783
|
-
/* @__PURE__ */
|
|
1784
|
-
/* @__PURE__ */
|
|
1785
|
-
/* @__PURE__ */
|
|
1786
|
-
/* @__PURE__ */
|
|
1787
|
-
/* @__PURE__ */
|
|
1788
|
-
/* @__PURE__ */
|
|
1789
|
-
/* @__PURE__ */
|
|
1790
|
-
/* @__PURE__ */
|
|
1791
|
-
/* @__PURE__ */
|
|
2819
|
+
children: /* @__PURE__ */ jsxs12("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2820
|
+
/* @__PURE__ */ jsx16("line", { x1: "4", y1: "21", x2: "4", y2: "14" }),
|
|
2821
|
+
/* @__PURE__ */ jsx16("line", { x1: "4", y1: "10", x2: "4", y2: "3" }),
|
|
2822
|
+
/* @__PURE__ */ jsx16("line", { x1: "12", y1: "21", x2: "12", y2: "12" }),
|
|
2823
|
+
/* @__PURE__ */ jsx16("line", { x1: "12", y1: "8", x2: "12", y2: "3" }),
|
|
2824
|
+
/* @__PURE__ */ jsx16("line", { x1: "20", y1: "21", x2: "20", y2: "16" }),
|
|
2825
|
+
/* @__PURE__ */ jsx16("line", { x1: "20", y1: "12", x2: "20", y2: "3" }),
|
|
2826
|
+
/* @__PURE__ */ jsx16("line", { x1: "1", y1: "14", x2: "7", y2: "14" }),
|
|
2827
|
+
/* @__PURE__ */ jsx16("line", { x1: "9", y1: "8", x2: "15", y2: "8" }),
|
|
2828
|
+
/* @__PURE__ */ jsx16("line", { x1: "17", y1: "16", x2: "23", y2: "16" })
|
|
1792
2829
|
] })
|
|
1793
2830
|
}
|
|
1794
2831
|
),
|
|
1795
|
-
showSettingsMenu && /* @__PURE__ */
|
|
1796
|
-
/* @__PURE__ */
|
|
1797
|
-
/* @__PURE__ */
|
|
1798
|
-
/* @__PURE__ */
|
|
1799
|
-
/* @__PURE__ */
|
|
1800
|
-
/* @__PURE__ */
|
|
2832
|
+
showSettingsMenu && /* @__PURE__ */ jsx16("div", { className: "absolute top-10 left-0 z-50 w-56 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg p-2.5 settings-menu-container", children: /* @__PURE__ */ jsxs12("label", { className: "flex items-center justify-between cursor-pointer group", children: [
|
|
2833
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
|
|
2834
|
+
/* @__PURE__ */ jsx16("svg", { className: "w-3.5 h-3.5 text-gray-500 dark:text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx16("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" }) }),
|
|
2835
|
+
/* @__PURE__ */ jsxs12("div", { children: [
|
|
2836
|
+
/* @__PURE__ */ jsx16("div", { className: "text-xs font-medium text-gray-700 dark:text-gray-300", children: "Plan Mode" }),
|
|
2837
|
+
/* @__PURE__ */ jsx16("div", { className: "text-[10px] text-gray-500 dark:text-gray-400", children: "Review first" })
|
|
1801
2838
|
] })
|
|
1802
2839
|
] }),
|
|
1803
|
-
/* @__PURE__ */
|
|
2840
|
+
/* @__PURE__ */ jsx16(
|
|
1804
2841
|
"button",
|
|
1805
2842
|
{
|
|
1806
2843
|
onClick: (e) => {
|
|
@@ -1812,7 +2849,7 @@ ${planToExecute}`;
|
|
|
1812
2849
|
internalPlanMode ? "bg-blue-600" : "bg-gray-300 dark:bg-gray-600"
|
|
1813
2850
|
),
|
|
1814
2851
|
type: "button",
|
|
1815
|
-
children: /* @__PURE__ */
|
|
2852
|
+
children: /* @__PURE__ */ jsx16(
|
|
1816
2853
|
"span",
|
|
1817
2854
|
{
|
|
1818
2855
|
className: cn(
|
|
@@ -1826,26 +2863,26 @@ ${planToExecute}`;
|
|
|
1826
2863
|
] }) })
|
|
1827
2864
|
] })
|
|
1828
2865
|
] }),
|
|
1829
|
-
uploadedFiles.length > 0 && /* @__PURE__ */
|
|
1830
|
-
file.type === "image" ? /* @__PURE__ */
|
|
2866
|
+
uploadedFiles.length > 0 && /* @__PURE__ */ jsx16("div", { className: "flex gap-1 flex-shrink-0", children: uploadedFiles.map((file, index) => /* @__PURE__ */ jsxs12("div", { className: "relative group", children: [
|
|
2867
|
+
file.type === "image" ? /* @__PURE__ */ jsx16(
|
|
1831
2868
|
"img",
|
|
1832
2869
|
{
|
|
1833
2870
|
src: file.preview,
|
|
1834
2871
|
alt: file.name,
|
|
1835
2872
|
className: "w-8 h-8 object-cover rounded border border-gray-300 dark:border-gray-600"
|
|
1836
2873
|
}
|
|
1837
|
-
) : /* @__PURE__ */
|
|
1838
|
-
/* @__PURE__ */
|
|
2874
|
+
) : /* @__PURE__ */ jsx16("div", { className: "w-8 h-8 flex items-center justify-center rounded border border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800", title: file.name, children: /* @__PURE__ */ jsx16("svg", { className: "w-4 h-4 text-gray-500 dark:text-gray-400", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx16("path", { fillRule: "evenodd", d: "M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z", clipRule: "evenodd" }) }) }),
|
|
2875
|
+
/* @__PURE__ */ jsx16(
|
|
1839
2876
|
"button",
|
|
1840
2877
|
{
|
|
1841
2878
|
onClick: () => removeFile(index),
|
|
1842
2879
|
className: "absolute -top-1 -right-1 w-4 h-4 bg-red-500 hover:bg-red-600 text-white rounded-full flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity",
|
|
1843
2880
|
title: "Remove",
|
|
1844
|
-
children: /* @__PURE__ */
|
|
2881
|
+
children: /* @__PURE__ */ jsx16("svg", { className: "w-2.5 h-2.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 3, children: /* @__PURE__ */ jsx16("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) })
|
|
1845
2882
|
}
|
|
1846
2883
|
)
|
|
1847
2884
|
] }, index)) }),
|
|
1848
|
-
/* @__PURE__ */
|
|
2885
|
+
/* @__PURE__ */ jsx16(
|
|
1849
2886
|
"input",
|
|
1850
2887
|
{
|
|
1851
2888
|
type: "text",
|
|
@@ -1861,7 +2898,7 @@ ${planToExecute}`;
|
|
|
1861
2898
|
className: "flex-1 bg-transparent border-none focus:outline-none !text-gray-900 dark:!text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 py-1"
|
|
1862
2899
|
}
|
|
1863
2900
|
),
|
|
1864
|
-
/* @__PURE__ */
|
|
2901
|
+
/* @__PURE__ */ jsx16(
|
|
1865
2902
|
"button",
|
|
1866
2903
|
{
|
|
1867
2904
|
onClick: () => executeCommand(),
|
|
@@ -1877,33 +2914,33 @@ ${planToExecute}`;
|
|
|
1877
2914
|
!command.trim() && "border-gray-200 dark:border-gray-700 !text-gray-400 dark:!text-gray-600"
|
|
1878
2915
|
),
|
|
1879
2916
|
title: "Execute",
|
|
1880
|
-
children: /* @__PURE__ */
|
|
2917
|
+
children: /* @__PURE__ */ jsx16("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx16("path", { d: "M8 3L8 13M8 3L4 7M8 3L12 7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
1881
2918
|
}
|
|
1882
2919
|
)
|
|
1883
2920
|
] }),
|
|
1884
|
-
state === "loading" && !isCompact && /* @__PURE__ */
|
|
1885
|
-
/* @__PURE__ */
|
|
1886
|
-
/* @__PURE__ */
|
|
1887
|
-
showProgress && /* @__PURE__ */
|
|
1888
|
-
/* @__PURE__ */
|
|
2921
|
+
state === "loading" && !isCompact && /* @__PURE__ */ jsxs12("div", { className: "flex-1 flex flex-col items-center justify-center space-y-4 py-8", children: [
|
|
2922
|
+
/* @__PURE__ */ jsx16("div", { className: "w-6 h-6 border-2 border-gray-300 border-t-blue-500 rounded-full animate-spin" }),
|
|
2923
|
+
/* @__PURE__ */ jsx16("div", { className: "text-gray-600 dark:text-gray-400 text-sm text-center max-w-md", children: enableStreaming && streamedContent ? streamedContent : loadingText }),
|
|
2924
|
+
showProgress && /* @__PURE__ */ jsxs12("div", { className: "w-full max-w-sm", children: [
|
|
2925
|
+
/* @__PURE__ */ jsx16("div", { className: "w-full bg-gray-200 dark:bg-gray-700 rounded-full h-1.5", children: /* @__PURE__ */ jsx16(
|
|
1889
2926
|
"div",
|
|
1890
2927
|
{
|
|
1891
2928
|
className: "bg-blue-500 h-1.5 rounded-full transition-all duration-300",
|
|
1892
2929
|
style: { width: `${progress}%` }
|
|
1893
2930
|
}
|
|
1894
2931
|
) }),
|
|
1895
|
-
/* @__PURE__ */
|
|
2932
|
+
/* @__PURE__ */ jsxs12("p", { className: "text-xs text-gray-500 mt-2 text-center", children: [
|
|
1896
2933
|
progress,
|
|
1897
2934
|
"%"
|
|
1898
2935
|
] })
|
|
1899
2936
|
] })
|
|
1900
2937
|
] }),
|
|
1901
|
-
state === "loading" && isCompact && /* @__PURE__ */
|
|
1902
|
-
/* @__PURE__ */
|
|
1903
|
-
/* @__PURE__ */
|
|
1904
|
-
/* @__PURE__ */
|
|
2938
|
+
state === "loading" && isCompact && /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
2939
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex-1 flex items-center gap-3 py-1", children: [
|
|
2940
|
+
/* @__PURE__ */ jsx16("div", { className: "w-4 h-4 border-2 border-gray-300 border-t-blue-500 rounded-full animate-spin" }),
|
|
2941
|
+
/* @__PURE__ */ jsx16("div", { className: "text-gray-600 dark:text-gray-400 text-sm truncate", children: enableStreaming && streamedContent ? streamedContent : loadingText })
|
|
1905
2942
|
] }),
|
|
1906
|
-
/* @__PURE__ */
|
|
2943
|
+
/* @__PURE__ */ jsx16(
|
|
1907
2944
|
"button",
|
|
1908
2945
|
{
|
|
1909
2946
|
disabled: true,
|
|
@@ -1915,20 +2952,20 @@ ${planToExecute}`;
|
|
|
1915
2952
|
"!text-lg",
|
|
1916
2953
|
"opacity-30 cursor-not-allowed"
|
|
1917
2954
|
),
|
|
1918
|
-
children: /* @__PURE__ */
|
|
2955
|
+
children: /* @__PURE__ */ jsx16("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx16("path", { d: "M8 3L8 13M8 3L4 7M8 3L12 7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
1919
2956
|
}
|
|
1920
2957
|
)
|
|
1921
2958
|
] }),
|
|
1922
|
-
state === "plan-pending" && !isCompact && /* @__PURE__ */
|
|
1923
|
-
/* @__PURE__ */
|
|
1924
|
-
/* @__PURE__ */
|
|
1925
|
-
/* @__PURE__ */
|
|
1926
|
-
/* @__PURE__ */
|
|
1927
|
-
/* @__PURE__ */
|
|
2959
|
+
state === "plan-pending" && !isCompact && /* @__PURE__ */ jsx16("div", { className: "flex-1 flex flex-col", children: /* @__PURE__ */ jsxs12("div", { className: "mb-4 p-4 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg", children: [
|
|
2960
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-2 mb-3", children: [
|
|
2961
|
+
/* @__PURE__ */ jsx16("svg", { className: "w-5 h-5 text-blue-600 dark:text-blue-400 mt-0.5 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx16("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" }) }),
|
|
2962
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex-1", children: [
|
|
2963
|
+
/* @__PURE__ */ jsx16("h3", { className: "text-sm font-semibold text-blue-800 dark:text-blue-300 mb-1", children: "Proposed Plan" }),
|
|
2964
|
+
/* @__PURE__ */ jsx16("div", { className: "text-blue-700 dark:text-blue-300 text-sm whitespace-pre-line leading-relaxed", children: plan })
|
|
1928
2965
|
] })
|
|
1929
2966
|
] }),
|
|
1930
|
-
/* @__PURE__ */
|
|
1931
|
-
/* @__PURE__ */
|
|
2967
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex gap-2 mt-4", children: [
|
|
2968
|
+
/* @__PURE__ */ jsx16(
|
|
1932
2969
|
"button",
|
|
1933
2970
|
{
|
|
1934
2971
|
onClick: approvePlan,
|
|
@@ -1936,7 +2973,7 @@ ${planToExecute}`;
|
|
|
1936
2973
|
children: "Approve & Execute"
|
|
1937
2974
|
}
|
|
1938
2975
|
),
|
|
1939
|
-
/* @__PURE__ */
|
|
2976
|
+
/* @__PURE__ */ jsx16(
|
|
1940
2977
|
"button",
|
|
1941
2978
|
{
|
|
1942
2979
|
onClick: rejectPlan,
|
|
@@ -1946,20 +2983,20 @@ ${planToExecute}`;
|
|
|
1946
2983
|
)
|
|
1947
2984
|
] })
|
|
1948
2985
|
] }) }),
|
|
1949
|
-
state === "plan-pending" && isCompact && /* @__PURE__ */
|
|
1950
|
-
/* @__PURE__ */
|
|
2986
|
+
state === "plan-pending" && isCompact && /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
2987
|
+
/* @__PURE__ */ jsxs12(
|
|
1951
2988
|
"button",
|
|
1952
2989
|
{
|
|
1953
2990
|
onClick: () => setShowPlanDetails(true),
|
|
1954
2991
|
className: "flex-1 flex items-center gap-2 px-3 py-2 bg-blue-50 dark:bg-blue-900/30 hover:bg-blue-100 dark:hover:bg-blue-900/40 border border-blue-200 dark:border-blue-800 rounded-lg transition-colors",
|
|
1955
2992
|
children: [
|
|
1956
|
-
/* @__PURE__ */
|
|
1957
|
-
/* @__PURE__ */
|
|
2993
|
+
/* @__PURE__ */ jsx16("svg", { className: "w-4 h-4 text-blue-600 dark:text-blue-400 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx16("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" }) }),
|
|
2994
|
+
/* @__PURE__ */ jsx16("span", { className: "text-sm font-medium text-blue-700 dark:text-blue-300 truncate flex-1", children: "View Execution Plan" })
|
|
1958
2995
|
]
|
|
1959
2996
|
}
|
|
1960
2997
|
),
|
|
1961
|
-
/* @__PURE__ */
|
|
1962
|
-
/* @__PURE__ */
|
|
2998
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex gap-2 flex-shrink-0", children: [
|
|
2999
|
+
/* @__PURE__ */ jsx16(
|
|
1963
3000
|
"button",
|
|
1964
3001
|
{
|
|
1965
3002
|
onClick: approvePlan,
|
|
@@ -1967,7 +3004,7 @@ ${planToExecute}`;
|
|
|
1967
3004
|
children: "Approve"
|
|
1968
3005
|
}
|
|
1969
3006
|
),
|
|
1970
|
-
/* @__PURE__ */
|
|
3007
|
+
/* @__PURE__ */ jsx16(
|
|
1971
3008
|
"button",
|
|
1972
3009
|
{
|
|
1973
3010
|
onClick: rejectPlan,
|
|
@@ -1977,15 +3014,15 @@ ${planToExecute}`;
|
|
|
1977
3014
|
)
|
|
1978
3015
|
] })
|
|
1979
3016
|
] }),
|
|
1980
|
-
state === "error" && /* @__PURE__ */
|
|
1981
|
-
/* @__PURE__ */
|
|
1982
|
-
/* @__PURE__ */
|
|
1983
|
-
/* @__PURE__ */
|
|
1984
|
-
/* @__PURE__ */
|
|
1985
|
-
/* @__PURE__ */
|
|
3017
|
+
state === "error" && /* @__PURE__ */ jsxs12("div", { className: "flex-1 flex flex-col", children: [
|
|
3018
|
+
/* @__PURE__ */ jsx16("div", { className: "mb-4 p-3 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-2", children: [
|
|
3019
|
+
/* @__PURE__ */ jsx16("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__ */ jsx16("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
3020
|
+
/* @__PURE__ */ jsxs12("div", { children: [
|
|
3021
|
+
/* @__PURE__ */ jsx16("h3", { className: "text-sm font-semibold text-red-800 dark:text-red-400", children: "Error" }),
|
|
3022
|
+
/* @__PURE__ */ jsx16("p", { className: "text-red-700 dark:text-red-300 text-sm mt-1", children: error?.message })
|
|
1986
3023
|
] })
|
|
1987
3024
|
] }) }),
|
|
1988
|
-
allowInput && /* @__PURE__ */
|
|
3025
|
+
allowInput && /* @__PURE__ */ jsx16(
|
|
1989
3026
|
"textarea",
|
|
1990
3027
|
{
|
|
1991
3028
|
value: command,
|
|
@@ -2002,16 +3039,16 @@ ${planToExecute}`;
|
|
|
2002
3039
|
}
|
|
2003
3040
|
)
|
|
2004
3041
|
] }),
|
|
2005
|
-
state === "success" && result && !isCompact && /* @__PURE__ */
|
|
2006
|
-
/* @__PURE__ */
|
|
2007
|
-
/* @__PURE__ */
|
|
2008
|
-
/* @__PURE__ */
|
|
2009
|
-
/* @__PURE__ */
|
|
2010
|
-
/* @__PURE__ */
|
|
3042
|
+
state === "success" && result && !isCompact && /* @__PURE__ */ jsx16("div", { className: "flex-1 overflow-auto", children: resultRenderer ? resultRenderer(result.data) : /* @__PURE__ */ jsxs12("div", { className: "space-y-4", children: [
|
|
3043
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-3 p-3 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg", children: [
|
|
3044
|
+
/* @__PURE__ */ jsx16("svg", { className: "w-5 h-5 text-green-600 mt-0.5 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx16("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
3045
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex-1", children: [
|
|
3046
|
+
/* @__PURE__ */ jsx16("h3", { className: "text-sm font-semibold text-green-800 dark:text-green-400 mb-1", children: "Success" }),
|
|
3047
|
+
/* @__PURE__ */ jsx16("p", { className: "text-green-700 dark:text-green-300 text-sm", children: "Command executed successfully" })
|
|
2011
3048
|
] })
|
|
2012
3049
|
] }),
|
|
2013
|
-
result.data?.summary && /* @__PURE__ */
|
|
2014
|
-
result.widgets && result.widgets.length > 0 && /* @__PURE__ */
|
|
3050
|
+
result.data?.summary && /* @__PURE__ */ jsx16("div", { className: "text-gray-700 dark:text-gray-300 text-sm leading-relaxed whitespace-pre-line", children: result.data.summary }),
|
|
3051
|
+
result.widgets && result.widgets.length > 0 && /* @__PURE__ */ jsx16("div", { className: "space-y-3", children: result.widgets.map((widget) => /* @__PURE__ */ jsx16(
|
|
2015
3052
|
WidgetRenderer,
|
|
2016
3053
|
{
|
|
2017
3054
|
widget,
|
|
@@ -2020,8 +3057,8 @@ ${planToExecute}`;
|
|
|
2020
3057
|
widget.id
|
|
2021
3058
|
)) })
|
|
2022
3059
|
] }) }),
|
|
2023
|
-
state === "success" && result && isCompact && /* @__PURE__ */
|
|
2024
|
-
/* @__PURE__ */
|
|
3060
|
+
state === "success" && result && isCompact && /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
3061
|
+
/* @__PURE__ */ jsxs12(
|
|
2025
3062
|
"div",
|
|
2026
3063
|
{
|
|
2027
3064
|
className: "flex-1 flex items-center gap-2 py-1 cursor-text min-w-0",
|
|
@@ -2030,12 +3067,12 @@ ${planToExecute}`;
|
|
|
2030
3067
|
setResult(null);
|
|
2031
3068
|
},
|
|
2032
3069
|
children: [
|
|
2033
|
-
/* @__PURE__ */
|
|
2034
|
-
/* @__PURE__ */
|
|
3070
|
+
/* @__PURE__ */ jsx16("svg", { className: "w-4 h-4 text-green-600 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx16("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
3071
|
+
/* @__PURE__ */ jsx16("div", { className: "text-green-700 dark:text-green-300 text-sm truncate flex-1 min-w-0", children: resultRenderer ? resultRenderer(result.data) : result.message || "Command executed successfully" })
|
|
2035
3072
|
]
|
|
2036
3073
|
}
|
|
2037
3074
|
),
|
|
2038
|
-
/* @__PURE__ */
|
|
3075
|
+
/* @__PURE__ */ jsx16(
|
|
2039
3076
|
"button",
|
|
2040
3077
|
{
|
|
2041
3078
|
onClick: () => {
|
|
@@ -2051,24 +3088,24 @@ ${planToExecute}`;
|
|
|
2051
3088
|
"!text-lg"
|
|
2052
3089
|
),
|
|
2053
3090
|
title: "New command",
|
|
2054
|
-
children: /* @__PURE__ */
|
|
3091
|
+
children: /* @__PURE__ */ jsx16("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx16("path", { d: "M8 3L8 13M8 3L4 7M8 3L12 7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
2055
3092
|
}
|
|
2056
3093
|
)
|
|
2057
3094
|
] })
|
|
2058
3095
|
] }),
|
|
2059
|
-
!isCompact && /* @__PURE__ */
|
|
2060
|
-
/* @__PURE__ */
|
|
2061
|
-
enableFileUpload && /* @__PURE__ */
|
|
3096
|
+
!isCompact && /* @__PURE__ */ jsxs12("div", { className: "p-3 flex items-center justify-between gap-2", children: [
|
|
3097
|
+
/* @__PURE__ */ jsx16("div", { className: "flex items-center gap-1", children: state === "idle" && allowInput && /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
3098
|
+
enableFileUpload && /* @__PURE__ */ jsx16(
|
|
2062
3099
|
"button",
|
|
2063
3100
|
{
|
|
2064
3101
|
onClick: () => fileInputRef.current?.click(),
|
|
2065
3102
|
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",
|
|
2066
3103
|
title: "Attach file",
|
|
2067
|
-
children: /* @__PURE__ */
|
|
3104
|
+
children: /* @__PURE__ */ jsx16("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx16("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)" }) })
|
|
2068
3105
|
}
|
|
2069
3106
|
),
|
|
2070
|
-
planMode && /* @__PURE__ */
|
|
2071
|
-
/* @__PURE__ */
|
|
3107
|
+
planMode && /* @__PURE__ */ jsxs12("div", { className: "relative settings-menu-container", children: [
|
|
3108
|
+
/* @__PURE__ */ jsx16(
|
|
2072
3109
|
"button",
|
|
2073
3110
|
{
|
|
2074
3111
|
onClick: () => setShowSettingsMenu(!showSettingsMenu),
|
|
@@ -2077,28 +3114,28 @@ ${planToExecute}`;
|
|
|
2077
3114
|
internalPlanMode ? "!text-blue-600 dark:!text-blue-400" : "!text-gray-500 dark:!text-gray-500"
|
|
2078
3115
|
),
|
|
2079
3116
|
title: "Settings",
|
|
2080
|
-
children: /* @__PURE__ */
|
|
2081
|
-
/* @__PURE__ */
|
|
2082
|
-
/* @__PURE__ */
|
|
2083
|
-
/* @__PURE__ */
|
|
2084
|
-
/* @__PURE__ */
|
|
2085
|
-
/* @__PURE__ */
|
|
2086
|
-
/* @__PURE__ */
|
|
2087
|
-
/* @__PURE__ */
|
|
2088
|
-
/* @__PURE__ */
|
|
2089
|
-
/* @__PURE__ */
|
|
3117
|
+
children: /* @__PURE__ */ jsxs12("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
3118
|
+
/* @__PURE__ */ jsx16("line", { x1: "4", y1: "21", x2: "4", y2: "14" }),
|
|
3119
|
+
/* @__PURE__ */ jsx16("line", { x1: "4", y1: "10", x2: "4", y2: "3" }),
|
|
3120
|
+
/* @__PURE__ */ jsx16("line", { x1: "12", y1: "21", x2: "12", y2: "12" }),
|
|
3121
|
+
/* @__PURE__ */ jsx16("line", { x1: "12", y1: "8", x2: "12", y2: "3" }),
|
|
3122
|
+
/* @__PURE__ */ jsx16("line", { x1: "20", y1: "21", x2: "20", y2: "16" }),
|
|
3123
|
+
/* @__PURE__ */ jsx16("line", { x1: "20", y1: "12", x2: "20", y2: "3" }),
|
|
3124
|
+
/* @__PURE__ */ jsx16("line", { x1: "1", y1: "14", x2: "7", y2: "14" }),
|
|
3125
|
+
/* @__PURE__ */ jsx16("line", { x1: "9", y1: "8", x2: "15", y2: "8" }),
|
|
3126
|
+
/* @__PURE__ */ jsx16("line", { x1: "17", y1: "16", x2: "23", y2: "16" })
|
|
2090
3127
|
] })
|
|
2091
3128
|
}
|
|
2092
3129
|
),
|
|
2093
|
-
showSettingsMenu && /* @__PURE__ */
|
|
2094
|
-
/* @__PURE__ */
|
|
2095
|
-
/* @__PURE__ */
|
|
2096
|
-
/* @__PURE__ */
|
|
2097
|
-
/* @__PURE__ */
|
|
2098
|
-
/* @__PURE__ */
|
|
3130
|
+
showSettingsMenu && /* @__PURE__ */ jsx16("div", { className: "absolute top-10 left-0 z-50 w-64 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg p-3 settings-menu-container", children: /* @__PURE__ */ jsxs12("label", { className: "flex items-center justify-between cursor-pointer group", children: [
|
|
3131
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
|
|
3132
|
+
/* @__PURE__ */ jsx16("svg", { className: "w-4 h-4 text-gray-500 dark:text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx16("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" }) }),
|
|
3133
|
+
/* @__PURE__ */ jsxs12("div", { children: [
|
|
3134
|
+
/* @__PURE__ */ jsx16("div", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: "Plan Mode" }),
|
|
3135
|
+
/* @__PURE__ */ jsx16("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Review before executing" })
|
|
2099
3136
|
] })
|
|
2100
3137
|
] }),
|
|
2101
|
-
/* @__PURE__ */
|
|
3138
|
+
/* @__PURE__ */ jsx16(
|
|
2102
3139
|
"button",
|
|
2103
3140
|
{
|
|
2104
3141
|
onClick: (e) => {
|
|
@@ -2110,7 +3147,7 @@ ${planToExecute}`;
|
|
|
2110
3147
|
internalPlanMode ? "bg-blue-600" : "bg-gray-300 dark:bg-gray-600"
|
|
2111
3148
|
),
|
|
2112
3149
|
type: "button",
|
|
2113
|
-
children: /* @__PURE__ */
|
|
3150
|
+
children: /* @__PURE__ */ jsx16(
|
|
2114
3151
|
"span",
|
|
2115
3152
|
{
|
|
2116
3153
|
className: cn(
|
|
@@ -2124,9 +3161,9 @@ ${planToExecute}`;
|
|
|
2124
3161
|
] }) })
|
|
2125
3162
|
] })
|
|
2126
3163
|
] }) }),
|
|
2127
|
-
!(state === "idle" && allowInput) && /* @__PURE__ */
|
|
2128
|
-
/* @__PURE__ */
|
|
2129
|
-
(state === "success" || state === "error") && allowInput && /* @__PURE__ */
|
|
3164
|
+
!(state === "idle" && allowInput) && /* @__PURE__ */ jsx16("div", {}),
|
|
3165
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
|
|
3166
|
+
(state === "success" || state === "error") && allowInput && /* @__PURE__ */ jsx16(
|
|
2130
3167
|
"button",
|
|
2131
3168
|
{
|
|
2132
3169
|
onClick: resetCommand,
|
|
@@ -2134,7 +3171,7 @@ ${planToExecute}`;
|
|
|
2134
3171
|
children: "Reset"
|
|
2135
3172
|
}
|
|
2136
3173
|
),
|
|
2137
|
-
(state === "idle" || state === "error") && /* @__PURE__ */
|
|
3174
|
+
(state === "idle" || state === "error") && /* @__PURE__ */ jsx16(
|
|
2138
3175
|
"button",
|
|
2139
3176
|
{
|
|
2140
3177
|
onClick: () => executeCommand(),
|
|
@@ -2150,29 +3187,29 @@ ${planToExecute}`;
|
|
|
2150
3187
|
!command.trim() && "border-gray-200 dark:border-gray-700 !text-gray-400 dark:!text-gray-600"
|
|
2151
3188
|
),
|
|
2152
3189
|
title: state === "error" ? "Retry" : "Execute",
|
|
2153
|
-
children: state === "error" ? /* @__PURE__ */
|
|
3190
|
+
children: state === "error" ? /* @__PURE__ */ jsx16("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx16("path", { d: "M13 8C13 10.7614 10.7614 13 8 13C5.23858 13 3 10.7614 3 8C3 5.23858 5.23858 3 8 3C9.65685 3 11.1257 3.82818 12 5.09091M12 3V5.09091M12 5.09091H9.81818", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) : /* @__PURE__ */ jsx16("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx16("path", { d: "M8 3L8 13M8 3L4 7M8 3L12 7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
2154
3191
|
}
|
|
2155
3192
|
)
|
|
2156
3193
|
] })
|
|
2157
3194
|
] }),
|
|
2158
|
-
showPlanDetails && isCompact && state === "plan-pending" && /* @__PURE__ */
|
|
2159
|
-
/* @__PURE__ */
|
|
2160
|
-
/* @__PURE__ */
|
|
2161
|
-
/* @__PURE__ */
|
|
2162
|
-
/* @__PURE__ */
|
|
3195
|
+
showPlanDetails && isCompact && state === "plan-pending" && /* @__PURE__ */ jsx16("div", { className: "fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4", onClick: () => setShowPlanDetails(false), children: /* @__PURE__ */ jsxs12("div", { className: "bg-white dark:bg-gray-900 rounded-2xl shadow-2xl max-w-2xl w-full max-h-[80vh] overflow-hidden", onClick: (e) => e.stopPropagation(), children: [
|
|
3196
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700", children: [
|
|
3197
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
|
|
3198
|
+
/* @__PURE__ */ jsx16("svg", { className: "w-6 h-6 text-blue-600 dark:text-blue-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx16("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" }) }),
|
|
3199
|
+
/* @__PURE__ */ jsx16("h2", { className: "text-xl font-semibold text-gray-900 dark:text-white", children: "Proposed Execution Plan" })
|
|
2163
3200
|
] }),
|
|
2164
|
-
/* @__PURE__ */
|
|
3201
|
+
/* @__PURE__ */ jsx16(
|
|
2165
3202
|
"button",
|
|
2166
3203
|
{
|
|
2167
3204
|
onClick: () => setShowPlanDetails(false),
|
|
2168
3205
|
className: "text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors",
|
|
2169
|
-
children: /* @__PURE__ */
|
|
3206
|
+
children: /* @__PURE__ */ jsx16("svg", { className: "w-6 h-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx16("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
2170
3207
|
}
|
|
2171
3208
|
)
|
|
2172
3209
|
] }),
|
|
2173
|
-
/* @__PURE__ */
|
|
2174
|
-
/* @__PURE__ */
|
|
2175
|
-
/* @__PURE__ */
|
|
3210
|
+
/* @__PURE__ */ jsx16("div", { className: "p-6 overflow-y-auto max-h-[calc(80vh-180px)]", children: /* @__PURE__ */ jsx16("div", { className: "prose prose-sm dark:prose-invert max-w-none", children: /* @__PURE__ */ jsx16("div", { className: "text-gray-700 dark:text-gray-300 whitespace-pre-line leading-relaxed", children: plan }) }) }),
|
|
3211
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-end gap-3 p-6 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50", children: [
|
|
3212
|
+
/* @__PURE__ */ jsx16(
|
|
2176
3213
|
"button",
|
|
2177
3214
|
{
|
|
2178
3215
|
onClick: rejectPlan,
|
|
@@ -2180,7 +3217,7 @@ ${planToExecute}`;
|
|
|
2180
3217
|
children: "Modify Command"
|
|
2181
3218
|
}
|
|
2182
3219
|
),
|
|
2183
|
-
/* @__PURE__ */
|
|
3220
|
+
/* @__PURE__ */ jsx16(
|
|
2184
3221
|
"button",
|
|
2185
3222
|
{
|
|
2186
3223
|
onClick: approvePlan,
|
|
@@ -2190,7 +3227,7 @@ ${planToExecute}`;
|
|
|
2190
3227
|
)
|
|
2191
3228
|
] })
|
|
2192
3229
|
] }) }),
|
|
2193
|
-
/* @__PURE__ */
|
|
3230
|
+
/* @__PURE__ */ jsx16(
|
|
2194
3231
|
"input",
|
|
2195
3232
|
{
|
|
2196
3233
|
ref: fileInputRef,
|
|
@@ -2201,7 +3238,7 @@ ${planToExecute}`;
|
|
|
2201
3238
|
accept: "image/*,application/pdf,.doc,.docx,.txt"
|
|
2202
3239
|
}
|
|
2203
3240
|
),
|
|
2204
|
-
/* @__PURE__ */
|
|
3241
|
+
/* @__PURE__ */ jsx16("style", { dangerouslySetInnerHTML: {
|
|
2205
3242
|
__html: `
|
|
2206
3243
|
@keyframes pulse-border {
|
|
2207
3244
|
0%, 100% {
|
|
@@ -2222,8 +3259,8 @@ ${planToExecute}`;
|
|
|
2222
3259
|
}
|
|
2223
3260
|
|
|
2224
3261
|
// src/components/Prompt/Prompt.tsx
|
|
2225
|
-
import { useState as
|
|
2226
|
-
import { jsx as
|
|
3262
|
+
import { useState as useState6 } from "react";
|
|
3263
|
+
import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2227
3264
|
function Prompt({
|
|
2228
3265
|
agentId,
|
|
2229
3266
|
placeholder = "Enter your prompt...",
|
|
@@ -2240,9 +3277,9 @@ function Prompt({
|
|
|
2240
3277
|
showSuggestions = false,
|
|
2241
3278
|
className
|
|
2242
3279
|
}) {
|
|
2243
|
-
const [value, setValue] =
|
|
2244
|
-
const [isLoading, setIsLoading] =
|
|
2245
|
-
const [suggestions] =
|
|
3280
|
+
const [value, setValue] = useState6(initialValue);
|
|
3281
|
+
const [isLoading, setIsLoading] = useState6(false);
|
|
3282
|
+
const [suggestions] = useState6(["Plan a trip", "Write a description", "Analyze data"]);
|
|
2246
3283
|
const handleChange = (e) => {
|
|
2247
3284
|
const newValue = e.target.value;
|
|
2248
3285
|
if (!maxLength || newValue.length <= maxLength) {
|
|
@@ -2285,9 +3322,9 @@ function Prompt({
|
|
|
2285
3322
|
handleSubmit();
|
|
2286
3323
|
}
|
|
2287
3324
|
};
|
|
2288
|
-
return /* @__PURE__ */
|
|
2289
|
-
/* @__PURE__ */
|
|
2290
|
-
/* @__PURE__ */
|
|
3325
|
+
return /* @__PURE__ */ jsxs13("div", { className: cn("space-y-2", className), children: [
|
|
3326
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex gap-2", children: [
|
|
3327
|
+
/* @__PURE__ */ jsx17(
|
|
2291
3328
|
"input",
|
|
2292
3329
|
{
|
|
2293
3330
|
type: "text",
|
|
@@ -2300,7 +3337,7 @@ function Prompt({
|
|
|
2300
3337
|
className: "flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-apteva-500 dark:bg-gray-800 dark:border-gray-600 dark:text-white"
|
|
2301
3338
|
}
|
|
2302
3339
|
),
|
|
2303
|
-
submitOn === "button" && /* @__PURE__ */
|
|
3340
|
+
submitOn === "button" && /* @__PURE__ */ jsx17(
|
|
2304
3341
|
"button",
|
|
2305
3342
|
{
|
|
2306
3343
|
onClick: handleSubmit,
|
|
@@ -2310,13 +3347,13 @@ function Prompt({
|
|
|
2310
3347
|
}
|
|
2311
3348
|
)
|
|
2312
3349
|
] }),
|
|
2313
|
-
maxLength && /* @__PURE__ */
|
|
3350
|
+
maxLength && /* @__PURE__ */ jsxs13("p", { className: "text-xs text-gray-500", children: [
|
|
2314
3351
|
value.length,
|
|
2315
3352
|
" / ",
|
|
2316
3353
|
maxLength,
|
|
2317
3354
|
" characters"
|
|
2318
3355
|
] }),
|
|
2319
|
-
showSuggestions && !value && /* @__PURE__ */
|
|
3356
|
+
showSuggestions && !value && /* @__PURE__ */ jsx17("div", { className: "flex flex-wrap gap-2", children: suggestions.map((suggestion, idx) => /* @__PURE__ */ jsx17(
|
|
2320
3357
|
"button",
|
|
2321
3358
|
{
|
|
2322
3359
|
onClick: () => setValue(suggestion),
|
|
@@ -2325,16 +3362,16 @@ function Prompt({
|
|
|
2325
3362
|
},
|
|
2326
3363
|
idx
|
|
2327
3364
|
)) }),
|
|
2328
|
-
isLoading && /* @__PURE__ */
|
|
2329
|
-
/* @__PURE__ */
|
|
2330
|
-
/* @__PURE__ */
|
|
3365
|
+
isLoading && /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 text-sm text-gray-500", children: [
|
|
3366
|
+
/* @__PURE__ */ jsx17("div", { className: "w-4 h-4 border-2 border-apteva-500 border-t-transparent rounded-full animate-spin" }),
|
|
3367
|
+
/* @__PURE__ */ jsx17("span", { children: "AI is processing your request..." })
|
|
2331
3368
|
] })
|
|
2332
3369
|
] });
|
|
2333
3370
|
}
|
|
2334
3371
|
|
|
2335
3372
|
// src/components/Stream/Stream.tsx
|
|
2336
|
-
import { useState as
|
|
2337
|
-
import { jsx as
|
|
3373
|
+
import { useState as useState7, useEffect as useEffect5 } from "react";
|
|
3374
|
+
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2338
3375
|
function Stream({
|
|
2339
3376
|
agentId,
|
|
2340
3377
|
prompt,
|
|
@@ -2350,9 +3387,9 @@ function Stream({
|
|
|
2350
3387
|
typingSpeed = 30,
|
|
2351
3388
|
className
|
|
2352
3389
|
}) {
|
|
2353
|
-
const [text, setText] =
|
|
2354
|
-
const [isStreaming, setIsStreaming] =
|
|
2355
|
-
const [isComplete, setIsComplete] =
|
|
3390
|
+
const [text, setText] = useState7("");
|
|
3391
|
+
const [isStreaming, setIsStreaming] = useState7(false);
|
|
3392
|
+
const [isComplete, setIsComplete] = useState7(false);
|
|
2356
3393
|
useEffect5(() => {
|
|
2357
3394
|
if (autoStart && !isStreaming && !isComplete) {
|
|
2358
3395
|
startStreaming();
|
|
@@ -2414,7 +3451,7 @@ function Stream({
|
|
|
2414
3451
|
plain: "text-gray-900 dark:text-gray-100"
|
|
2415
3452
|
};
|
|
2416
3453
|
if (!isStreaming && !isComplete) {
|
|
2417
|
-
return /* @__PURE__ */
|
|
3454
|
+
return /* @__PURE__ */ jsx18("div", { className: cn("p-4", className), children: /* @__PURE__ */ jsx18(
|
|
2418
3455
|
"button",
|
|
2419
3456
|
{
|
|
2420
3457
|
onClick: startStreaming,
|
|
@@ -2423,19 +3460,19 @@ function Stream({
|
|
|
2423
3460
|
}
|
|
2424
3461
|
) });
|
|
2425
3462
|
}
|
|
2426
|
-
return /* @__PURE__ */
|
|
3463
|
+
return /* @__PURE__ */ jsxs14("div", { className: cn(variantClasses[variant], className), children: [
|
|
2427
3464
|
text,
|
|
2428
|
-
isStreaming && showCursor && /* @__PURE__ */
|
|
3465
|
+
isStreaming && showCursor && /* @__PURE__ */ jsx18("span", { className: "apteva-stream-cursor" })
|
|
2429
3466
|
] });
|
|
2430
3467
|
}
|
|
2431
3468
|
|
|
2432
3469
|
// src/components/Threads/ThreadList.tsx
|
|
2433
|
-
import { useState as
|
|
3470
|
+
import { useState as useState8 } from "react";
|
|
2434
3471
|
|
|
2435
3472
|
// src/components/Threads/ThreadItem.tsx
|
|
2436
|
-
import { jsx as
|
|
3473
|
+
import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2437
3474
|
function ThreadItem({ thread, isActive = false, onSelect, onDelete }) {
|
|
2438
|
-
return /* @__PURE__ */
|
|
3475
|
+
return /* @__PURE__ */ jsxs15(
|
|
2439
3476
|
"div",
|
|
2440
3477
|
{
|
|
2441
3478
|
className: cn("apteva-thread-item", {
|
|
@@ -2443,19 +3480,19 @@ function ThreadItem({ thread, isActive = false, onSelect, onDelete }) {
|
|
|
2443
3480
|
}),
|
|
2444
3481
|
onClick: onSelect,
|
|
2445
3482
|
children: [
|
|
2446
|
-
/* @__PURE__ */
|
|
2447
|
-
/* @__PURE__ */
|
|
2448
|
-
thread.preview && /* @__PURE__ */
|
|
2449
|
-
/* @__PURE__ */
|
|
2450
|
-
/* @__PURE__ */
|
|
3483
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex-1 min-w-0", children: [
|
|
3484
|
+
/* @__PURE__ */ jsx19("h4", { className: "font-semibold text-gray-900 dark:text-white truncate", children: thread.title }),
|
|
3485
|
+
thread.preview && /* @__PURE__ */ jsx19("p", { className: "text-sm text-gray-600 dark:text-gray-400 truncate", children: thread.preview }),
|
|
3486
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2 mt-1 text-xs text-gray-500", children: [
|
|
3487
|
+
/* @__PURE__ */ jsxs15("span", { children: [
|
|
2451
3488
|
thread.messageCount,
|
|
2452
3489
|
" messages"
|
|
2453
3490
|
] }),
|
|
2454
|
-
/* @__PURE__ */
|
|
2455
|
-
/* @__PURE__ */
|
|
3491
|
+
/* @__PURE__ */ jsx19("span", { children: "\u2022" }),
|
|
3492
|
+
/* @__PURE__ */ jsx19("span", { children: formatRelativeTime(thread.updatedAt) })
|
|
2456
3493
|
] })
|
|
2457
3494
|
] }),
|
|
2458
|
-
onDelete && /* @__PURE__ */
|
|
3495
|
+
onDelete && /* @__PURE__ */ jsx19(
|
|
2459
3496
|
"button",
|
|
2460
3497
|
{
|
|
2461
3498
|
onClick: (e) => {
|
|
@@ -2485,7 +3522,7 @@ function formatRelativeTime(date) {
|
|
|
2485
3522
|
}
|
|
2486
3523
|
|
|
2487
3524
|
// src/components/Threads/ThreadList.tsx
|
|
2488
|
-
import { jsx as
|
|
3525
|
+
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2489
3526
|
function ThreadList({
|
|
2490
3527
|
threads,
|
|
2491
3528
|
currentThreadId,
|
|
@@ -2494,13 +3531,13 @@ function ThreadList({
|
|
|
2494
3531
|
showSearch = false,
|
|
2495
3532
|
groupBy = "none"
|
|
2496
3533
|
}) {
|
|
2497
|
-
const [searchQuery, setSearchQuery] =
|
|
3534
|
+
const [searchQuery, setSearchQuery] = useState8("");
|
|
2498
3535
|
const filteredThreads = threads.filter(
|
|
2499
3536
|
(thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || thread.preview?.toLowerCase().includes(searchQuery.toLowerCase())
|
|
2500
3537
|
);
|
|
2501
3538
|
const groupedThreads = groupBy === "date" ? groupThreadsByDate(filteredThreads) : { All: filteredThreads };
|
|
2502
|
-
return /* @__PURE__ */
|
|
2503
|
-
showSearch && /* @__PURE__ */
|
|
3539
|
+
return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col h-full", children: [
|
|
3540
|
+
showSearch && /* @__PURE__ */ jsx20("div", { className: "p-3 border-b border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ jsx20(
|
|
2504
3541
|
"input",
|
|
2505
3542
|
{
|
|
2506
3543
|
type: "text",
|
|
@@ -2510,10 +3547,10 @@ function ThreadList({
|
|
|
2510
3547
|
className: "w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-apteva-500 dark:bg-gray-800 dark:border-gray-600 dark:text-white"
|
|
2511
3548
|
}
|
|
2512
3549
|
) }),
|
|
2513
|
-
/* @__PURE__ */
|
|
2514
|
-
Object.entries(groupedThreads).map(([group, groupThreads]) => /* @__PURE__ */
|
|
2515
|
-
groupBy !== "none" && /* @__PURE__ */
|
|
2516
|
-
groupThreads.map((thread) => /* @__PURE__ */
|
|
3550
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex-1 overflow-y-auto", children: [
|
|
3551
|
+
Object.entries(groupedThreads).map(([group, groupThreads]) => /* @__PURE__ */ jsxs16("div", { children: [
|
|
3552
|
+
groupBy !== "none" && /* @__PURE__ */ jsx20("div", { className: "px-3 py-2 text-xs font-semibold text-gray-500 uppercase", children: group }),
|
|
3553
|
+
groupThreads.map((thread) => /* @__PURE__ */ jsx20(
|
|
2517
3554
|
ThreadItem,
|
|
2518
3555
|
{
|
|
2519
3556
|
thread,
|
|
@@ -2524,9 +3561,9 @@ function ThreadList({
|
|
|
2524
3561
|
thread.id
|
|
2525
3562
|
))
|
|
2526
3563
|
] }, group)),
|
|
2527
|
-
filteredThreads.length === 0 && /* @__PURE__ */
|
|
2528
|
-
/* @__PURE__ */
|
|
2529
|
-
/* @__PURE__ */
|
|
3564
|
+
filteredThreads.length === 0 && /* @__PURE__ */ jsxs16("div", { className: "p-8 text-center text-gray-500", children: [
|
|
3565
|
+
/* @__PURE__ */ jsx20("svg", { className: "w-10 h-10 mx-auto mb-2 opacity-50", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx20("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" }) }),
|
|
3566
|
+
/* @__PURE__ */ jsx20("p", { children: "No conversations found" })
|
|
2530
3567
|
] })
|
|
2531
3568
|
] })
|
|
2532
3569
|
] });
|
|
@@ -2558,7 +3595,7 @@ function groupThreadsByDate(threads) {
|
|
|
2558
3595
|
}
|
|
2559
3596
|
|
|
2560
3597
|
// src/components/Threads/Threads.tsx
|
|
2561
|
-
import { jsx as
|
|
3598
|
+
import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2562
3599
|
function Threads({
|
|
2563
3600
|
threads,
|
|
2564
3601
|
currentThreadId,
|
|
@@ -2577,8 +3614,8 @@ function Threads({
|
|
|
2577
3614
|
tabs: "flex gap-2 border-b border-gray-200 dark:border-gray-700 overflow-x-auto"
|
|
2578
3615
|
};
|
|
2579
3616
|
if (variant === "tabs") {
|
|
2580
|
-
return /* @__PURE__ */
|
|
2581
|
-
threads.slice(0, 5).map((thread) => /* @__PURE__ */
|
|
3617
|
+
return /* @__PURE__ */ jsxs17("div", { className: cn(variantClasses[variant], className), children: [
|
|
3618
|
+
threads.slice(0, 5).map((thread) => /* @__PURE__ */ jsx21(
|
|
2582
3619
|
"button",
|
|
2583
3620
|
{
|
|
2584
3621
|
onClick: () => onThreadSelect?.(thread.id),
|
|
@@ -2590,7 +3627,7 @@ function Threads({
|
|
|
2590
3627
|
},
|
|
2591
3628
|
thread.id
|
|
2592
3629
|
)),
|
|
2593
|
-
showNewButton && onNewThread && /* @__PURE__ */
|
|
3630
|
+
showNewButton && onNewThread && /* @__PURE__ */ jsx21(
|
|
2594
3631
|
"button",
|
|
2595
3632
|
{
|
|
2596
3633
|
onClick: onNewThread,
|
|
@@ -2600,8 +3637,8 @@ function Threads({
|
|
|
2600
3637
|
)
|
|
2601
3638
|
] });
|
|
2602
3639
|
}
|
|
2603
|
-
return /* @__PURE__ */
|
|
2604
|
-
showNewButton && onNewThread && /* @__PURE__ */
|
|
3640
|
+
return /* @__PURE__ */ jsxs17("div", { className: cn(variantClasses[variant], "flex flex-col", className), children: [
|
|
3641
|
+
showNewButton && onNewThread && /* @__PURE__ */ jsx21("div", { className: "p-3 border-b border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ jsx21(
|
|
2605
3642
|
"button",
|
|
2606
3643
|
{
|
|
2607
3644
|
onClick: onNewThread,
|
|
@@ -2609,7 +3646,7 @@ function Threads({
|
|
|
2609
3646
|
children: "+ New Conversation"
|
|
2610
3647
|
}
|
|
2611
3648
|
) }),
|
|
2612
|
-
/* @__PURE__ */
|
|
3649
|
+
/* @__PURE__ */ jsx21(
|
|
2613
3650
|
ThreadList,
|
|
2614
3651
|
{
|
|
2615
3652
|
threads,
|