@apteva/apteva-kit 0.1.11 → 0.1.14
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 +1164 -127
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1349 -312
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -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
|
|
|
422
503
|
|
|
@@ -514,6 +595,53 @@ function Button({ widget, onAction }) {
|
|
|
514
595
|
);
|
|
515
596
|
}
|
|
516
597
|
|
|
598
|
+
// src/components/Widgets/widget-library/ButtonGroup.tsx
|
|
599
|
+
|
|
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 _optionalChain([widget, 'access', _7 => _7.actions, 'optionalAccess', _8 => _8.find, 'call', _9 => _9((action) => _optionalChain([action, 'access', _10 => _10.payload, 'optionalAccess', _11 => _11.buttonId]) === buttonId)]) || _optionalChain([widget, 'access', _12 => _12.actions, 'optionalAccess', _13 => _13[0]]);
|
|
609
|
+
};
|
|
610
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0,
|
|
620
|
+
"button",
|
|
621
|
+
{
|
|
622
|
+
onClick: () => {
|
|
623
|
+
if (action) {
|
|
624
|
+
_optionalChain([onAction, 'optionalCall', _14 => _14({
|
|
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
646
|
|
|
519
647
|
function WidgetRenderer({ widget, onAction }) {
|
|
@@ -524,6 +652,8 @@ function WidgetRenderer({ widget, onAction }) {
|
|
|
524
652
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, List, { widget, onAction });
|
|
525
653
|
case "button":
|
|
526
654
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { widget, onAction });
|
|
655
|
+
case "button_group":
|
|
656
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ButtonGroup, { widget, onAction });
|
|
527
657
|
default:
|
|
528
658
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "p-4 border border-yellow-300 bg-yellow-50 rounded-lg", children: [
|
|
529
659
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "text-sm text-yellow-800", children: [
|
|
@@ -548,7 +678,7 @@ function Widgets({
|
|
|
548
678
|
}) {
|
|
549
679
|
_react.useEffect.call(void 0, () => {
|
|
550
680
|
widgets.forEach((widget) => {
|
|
551
|
-
_optionalChain([onWidgetMount, 'optionalCall',
|
|
681
|
+
_optionalChain([onWidgetMount, 'optionalCall', _15 => _15(widget.id)]);
|
|
552
682
|
});
|
|
553
683
|
}, [widgets, onWidgetMount]);
|
|
554
684
|
const layoutClasses = {
|
|
@@ -647,6 +777,33 @@ function parseMarkdown(content) {
|
|
|
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__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-md-table-wrapper", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "table", { className: "apteva-md-table", children: [
|
|
800
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "thead", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tr", { children: headerCells.map((cell, idx) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { className: "apteva-md-th", children: parseInlineMarkdown(cell, `th${key}${idx}`) }, `th${idx}`)) }) }),
|
|
801
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tbody", { children: bodyRows.map((row, rowIdx) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tr", { children: row.map((cell, cellIdx) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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
808
|
result.push(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {}, `br${key++}`));
|
|
652
809
|
} else {
|
|
@@ -668,14 +825,14 @@ function MarkdownContent({ content, className = "" }) {
|
|
|
668
825
|
// src/components/Chat/ToolCall.tsx
|
|
669
826
|
|
|
670
827
|
function ToolCall({ name, status }) {
|
|
671
|
-
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "
|
|
672
|
-
status === "running" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "
|
|
673
|
-
status === "completed" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "
|
|
674
|
-
status === "error" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "
|
|
675
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "
|
|
676
|
-
status === "running" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "
|
|
677
|
-
status === "completed" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "
|
|
678
|
-
status === "error" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "
|
|
828
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "apteva-tool-call", children: [
|
|
829
|
+
status === "running" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-tool-call-dot apteva-tool-call-dot-running" }),
|
|
830
|
+
status === "completed" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-tool-call-dot apteva-tool-call-dot-completed" }),
|
|
831
|
+
status === "error" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "apteva-tool-call-dot apteva-tool-call-dot-error" }),
|
|
832
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-tool-call-name", children: name }),
|
|
833
|
+
status === "running" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-tool-call-status", children: "Running..." }),
|
|
834
|
+
status === "completed" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-tool-call-status apteva-tool-call-status-completed", children: "Completed" }),
|
|
835
|
+
status === "error" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "apteva-tool-call-status apteva-tool-call-status-error", children: "Error" })
|
|
679
836
|
] });
|
|
680
837
|
}
|
|
681
838
|
|
|
@@ -683,7 +840,7 @@ function ToolCall({ name, status }) {
|
|
|
683
840
|
|
|
684
841
|
function Message({ message, onAction }) {
|
|
685
842
|
const isUser = message.role === "user";
|
|
686
|
-
const contentSegments = _optionalChain([message, 'access',
|
|
843
|
+
const contentSegments = _optionalChain([message, 'access', _16 => _16.metadata, 'optionalAccess', _17 => _17.content_segments]);
|
|
687
844
|
const renderContent = () => {
|
|
688
845
|
if (isUser) {
|
|
689
846
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "whitespace-pre-wrap !text-sm leading-relaxed", children: message.content });
|
|
@@ -711,7 +868,7 @@ function Message({ message, onAction }) {
|
|
|
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(),
|
|
@@ -722,27 +879,187 @@ function Message({ message, onAction }) {
|
|
|
722
879
|
);
|
|
723
880
|
}
|
|
724
881
|
|
|
882
|
+
// src/components/Chat/WelcomeScreen.tsx
|
|
883
|
+
|
|
884
|
+
var DefaultIcon = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-12 h-12 sm:w-16 sm:h-16", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "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__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-center h-full !text-gray-500 dark:!text-gray-400", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "text-center space-y-2", children: [
|
|
909
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DefaultIcon, {}) }),
|
|
910
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm", children: "No messages yet. Start a conversation!" })
|
|
911
|
+
] }) });
|
|
912
|
+
}
|
|
913
|
+
if (variant === "minimal") {
|
|
914
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col h-full px-4 py-4", children: [
|
|
915
|
+
hasHeader && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mb-4", children: [
|
|
916
|
+
title && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "text-lg font-semibold !text-gray-900 dark:!text-white", children: title }),
|
|
917
|
+
subtitle && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm !text-gray-500 dark:!text-gray-400 mt-1", children: subtitle })
|
|
918
|
+
] }),
|
|
919
|
+
hasPrompts && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 space-y-2", children: normalizedPrompts.map((prompt, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3", children: [
|
|
933
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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__ */ _jsxruntime.jsx.call(void 0, ArrowIcon, {}) }),
|
|
934
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0", children: [
|
|
935
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm font-medium !text-gray-900 dark:!text-white truncate", children: prompt.text }),
|
|
936
|
+
prompt.description && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center justify-center h-full px-4 py-6 sm:py-8", children: [
|
|
945
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "text-center mb-6 sm:mb-8 max-w-md", children: [
|
|
946
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mb-4 !text-gray-400 dark:!text-gray-500 flex justify-center", children: icon || /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DefaultIcon, {}) }),
|
|
947
|
+
title && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h1", { className: "text-xl sm:text-2xl font-semibold !text-gray-900 dark:!text-white mb-2", children: title }),
|
|
948
|
+
subtitle && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm sm:text-base !text-gray-500 dark:!text-gray-400", children: subtitle })
|
|
949
|
+
] }),
|
|
950
|
+
hasPrompts && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "w-full max-w-2xl", children: [
|
|
951
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "sm:hidden space-y-2", children: normalizedPrompts.map((prompt, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3", children: [
|
|
967
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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__ */ _jsxruntime.jsx.call(void 0, ArrowIcon, {}) }),
|
|
968
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0", children: [
|
|
969
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm font-medium !text-gray-900 dark:!text-white", children: prompt.text }),
|
|
970
|
+
prompt.description && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-xs !text-gray-500 dark:!text-gray-400 mt-0.5 line-clamp-1", children: prompt.description })
|
|
971
|
+
] }),
|
|
972
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, "div", { className: "hidden sm:grid sm:grid-cols-2 gap-3", children: normalizedPrompts.map((prompt, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-start gap-3", children: [
|
|
1010
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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__ */ _jsxruntime.jsx.call(void 0, ArrowIcon, {}) }),
|
|
1011
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0", children: [
|
|
1012
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm font-medium !text-gray-900 dark:!text-white leading-snug", children: prompt.text }),
|
|
1013
|
+
prompt.description && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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
1024
|
|
|
727
|
-
function MessageList({
|
|
1025
|
+
function MessageList({
|
|
1026
|
+
messages,
|
|
1027
|
+
onAction,
|
|
1028
|
+
welcomeTitle,
|
|
1029
|
+
welcomeSubtitle,
|
|
1030
|
+
welcomeIcon,
|
|
1031
|
+
suggestedPrompts,
|
|
1032
|
+
welcomeVariant,
|
|
1033
|
+
onPromptClick
|
|
1034
|
+
}) {
|
|
728
1035
|
const listRef = _react.useRef.call(void 0, null);
|
|
729
1036
|
_react.useEffect.call(void 0, () => {
|
|
730
1037
|
if (listRef.current) {
|
|
731
1038
|
listRef.current.scrollTop = listRef.current.scrollHeight;
|
|
732
1039
|
}
|
|
733
1040
|
}, [messages]);
|
|
734
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { ref: listRef, className: "flex-1 overflow-y-auto px-4 py-4 space-y-3 apteva-scrollbar-hidden", children: messages.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
1041
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { ref: listRef, className: "flex-1 overflow-y-auto px-4 py-4 space-y-3 apteva-scrollbar-hidden", children: messages.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, Message, { message, onAction }, message.id)) });
|
|
738
1053
|
}
|
|
739
1054
|
|
|
740
1055
|
// src/components/Chat/Composer.tsx
|
|
741
1056
|
|
|
742
1057
|
|
|
743
|
-
function Composer({ onSendMessage, placeholder = "Type a message...", disabled = false, onFileUpload }) {
|
|
1058
|
+
function Composer({ onSendMessage, placeholder = "Type a message...", disabled = false, onFileUpload, onSwitchMode }) {
|
|
744
1059
|
const [text, setText] = _react.useState.call(void 0, "");
|
|
745
1060
|
const [showMenu, setShowMenu] = _react.useState.call(void 0, false);
|
|
1061
|
+
const [pendingFiles, setPendingFiles] = _react.useState.call(void 0, []);
|
|
1062
|
+
const [fileError, setFileError] = _react.useState.call(void 0, null);
|
|
746
1063
|
const textareaRef = _react.useRef.call(void 0, null);
|
|
747
1064
|
const fileInputRef = _react.useRef.call(void 0, 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,25 +1089,112 @@ 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) {
|
|
770
|
-
|
|
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
|
+
}
|
|
1114
|
+
_optionalChain([onFileUpload, 'optionalCall', _18 => _18(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__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "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__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "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__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) });
|
|
1136
|
+
};
|
|
1137
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "px-4 py-3 relative", children: [
|
|
1138
|
+
fileError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute bottom-full left-4 right-4 mb-2 p-3 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg z-20", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 !text-red-700 dark:!text-red-300 text-sm", children: [
|
|
1139
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-4 h-4 flex-shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
1140
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: fileError })
|
|
1141
|
+
] }) }),
|
|
775
1142
|
showMenu && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
776
1143
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fixed inset-0 z-10", onClick: () => setShowMenu(false) }),
|
|
777
|
-
/* @__PURE__ */ _jsxruntime.
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
1144
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "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__ */ _jsxruntime.jsxs.call(void 0,
|
|
1146
|
+
"button",
|
|
1147
|
+
{
|
|
1148
|
+
onClick: () => {
|
|
1149
|
+
_optionalChain([fileInputRef, 'access', _19 => _19.current, 'optionalAccess', _20 => _20.click, 'call', _21 => _21()]);
|
|
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__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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__ */ _jsxruntime.jsx.call(void 0, "span", { className: "!text-sm font-medium", children: "Add photos & files" })
|
|
1156
|
+
]
|
|
1157
|
+
}
|
|
1158
|
+
),
|
|
1159
|
+
onSwitchMode && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 10V3L4 14h7v7l9-11h-7z" }) }),
|
|
1169
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "!text-sm font-medium", children: "Switch to command mode" })
|
|
1170
|
+
]
|
|
1171
|
+
}
|
|
1172
|
+
)
|
|
1173
|
+
] })
|
|
788
1174
|
] }),
|
|
1175
|
+
pendingFiles.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mb-2 flex flex-wrap gap-2", children: pendingFiles.map((pf, index) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, "img", { src: pf.preview, alt: pf.file.name, className: "w-8 h-8 object-cover rounded" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-8 h-8 flex items-center justify-center bg-gray-200 dark:bg-gray-700 rounded !text-gray-500 dark:!text-gray-400", children: getFileIcon(pf.file.type) }),
|
|
1181
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col min-w-0", children: [
|
|
1182
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-xs font-medium !text-gray-700 dark:!text-gray-300 truncate max-w-[120px]", children: pf.file.name }),
|
|
1183
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-xs !text-gray-500 dark:!text-gray-400", children: formatFileSize(pf.file.size) })
|
|
1184
|
+
] }),
|
|
1185
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
1192
|
+
}
|
|
1193
|
+
)
|
|
1194
|
+
]
|
|
1195
|
+
},
|
|
1196
|
+
index
|
|
1197
|
+
)) }),
|
|
789
1198
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "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
1199
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
791
1200
|
"button",
|
|
@@ -814,7 +1223,7 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
|
|
|
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
1229
|
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M8 3L8 13M8 3L4 7M8 3L12 7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
@@ -835,8 +1244,341 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
|
|
|
835
1244
|
] });
|
|
836
1245
|
}
|
|
837
1246
|
|
|
1247
|
+
// src/components/Chat/CommandComposer.tsx
|
|
1248
|
+
|
|
1249
|
+
|
|
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] = _react.useState.call(void 0, "");
|
|
1266
|
+
const [pendingFiles, setPendingFiles] = _react.useState.call(void 0, []);
|
|
1267
|
+
const [fileError, setFileError] = _react.useState.call(void 0, null);
|
|
1268
|
+
const [showMenu, setShowMenu] = _react.useState.call(void 0, false);
|
|
1269
|
+
const inputRef = _react.useRef.call(void 0, null);
|
|
1270
|
+
const fileInputRef = _react.useRef.call(void 0, null);
|
|
1271
|
+
const menuButtonRef = _react.useRef.call(void 0, 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
|
+
_optionalChain([onReset, 'optionalCall', _22 => _22()]);
|
|
1290
|
+
_optionalChain([inputRef, 'access', _23 => _23.current, 'optionalAccess', _24 => _24.focus, 'call', _25 => _25()]);
|
|
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__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "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__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "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__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) });
|
|
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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "w-full relative", children: [
|
|
1369
|
+
fileError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute -top-12 left-0 right-0 mx-3 p-2 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg z-30", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 !text-red-700 dark:!text-red-300 text-xs", children: [
|
|
1370
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-3 h-3 flex-shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
1371
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: fileError })
|
|
1372
|
+
] }) }),
|
|
1373
|
+
showMenu && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
1374
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fixed inset-0 z-[9998]", onClick: () => setShowMenu(false) }),
|
|
1375
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
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: _nullishCoalesce(_optionalChain([menuButtonRef, 'access', _26 => _26.current, 'optionalAccess', _27 => _27.getBoundingClientRect, 'call', _28 => _28(), 'access', _29 => _29.left]), () => ( 0)),
|
|
1382
|
+
top: (_nullishCoalesce(_optionalChain([menuButtonRef, 'access', _30 => _30.current, 'optionalAccess', _31 => _31.getBoundingClientRect, 'call', _32 => _32(), 'access', _33 => _33.top]), () => ( 0))) - 8,
|
|
1383
|
+
transform: "translateY(-100%)"
|
|
1384
|
+
},
|
|
1385
|
+
children: [
|
|
1386
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
1387
|
+
"button",
|
|
1388
|
+
{
|
|
1389
|
+
onClick: () => {
|
|
1390
|
+
_optionalChain([fileInputRef, 'access', _34 => _34.current, 'optionalAccess', _35 => _35.click, 'call', _36 => _36()]);
|
|
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__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "18", height: "18", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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__ */ _jsxruntime.jsx.call(void 0, "span", { className: "!text-sm font-medium", children: "Add photos & files" })
|
|
1397
|
+
]
|
|
1398
|
+
}
|
|
1399
|
+
),
|
|
1400
|
+
onExpand && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-4.5 h-4.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "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__ */ _jsxruntime.jsx.call(void 0, "span", { className: "!text-sm font-medium", children: "Expand to chat" })
|
|
1411
|
+
]
|
|
1412
|
+
}
|
|
1413
|
+
)
|
|
1414
|
+
]
|
|
1415
|
+
}
|
|
1416
|
+
)
|
|
1417
|
+
] }),
|
|
1418
|
+
pendingFiles.length > 0 && state === "idle" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mb-2 flex flex-wrap gap-2", children: pendingFiles.map((pf, index) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, "img", { src: pf.preview, alt: pf.file.name, className: "w-6 h-6 object-cover rounded" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-6 h-6 flex items-center justify-center bg-gray-200 dark:bg-gray-700 rounded !text-gray-500 dark:!text-gray-400", children: getFileIcon(pf.file.type) }),
|
|
1424
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-xs font-medium !text-gray-700 dark:!text-gray-300 truncate max-w-[100px]", children: pf.file.name }),
|
|
1425
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-2.5 h-2.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
1432
|
+
}
|
|
1433
|
+
)
|
|
1434
|
+
]
|
|
1435
|
+
},
|
|
1436
|
+
index
|
|
1437
|
+
)) }),
|
|
1438
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "18", height: "18", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 5v10M5 10h10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
1458
|
+
}
|
|
1459
|
+
),
|
|
1460
|
+
state === "loading" && !toolName && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-4 h-4 border-2 border-blue-200 border-t-blue-500 rounded-full animate-spin flex-shrink-0" }),
|
|
1461
|
+
state === "loading" && toolName && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-2 h-2 rounded-full bg-blue-500 animate-pulse flex-shrink-0" }),
|
|
1462
|
+
state === "idle" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
1492
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-mono", children: displayContent }),
|
|
1493
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-gray-400 dark:text-gray-500", children: "Running..." })
|
|
1494
|
+
] }) : displayContent
|
|
1495
|
+
}
|
|
1496
|
+
),
|
|
1497
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1 flex-shrink-0", children: [
|
|
1498
|
+
state === "plan-pending" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
1499
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
1523
|
+
}
|
|
1524
|
+
),
|
|
1525
|
+
state === "idle" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 12h14M12 5l7 7-7 7" }) })
|
|
1538
|
+
}
|
|
1539
|
+
)
|
|
1540
|
+
] })
|
|
1541
|
+
]
|
|
1542
|
+
}
|
|
1543
|
+
),
|
|
1544
|
+
state === "success" && _optionalChain([response, 'optionalAccess', _37 => _37.includes, 'call', _38 => _38("weather")]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3", children: [
|
|
1545
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-3xl", children: "\u2600\uFE0F" }),
|
|
1546
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1", children: [
|
|
1547
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-sm font-medium text-gray-900 dark:text-white", children: "Paris, France" }),
|
|
1548
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Sunny, 22\xB0C" })
|
|
1549
|
+
] }),
|
|
1550
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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" && _optionalChain([response, 'optionalAccess', _39 => _39.includes, 'call', _40 => _40("trip")]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "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__ */ _jsxruntime.jsx.call(void 0, "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__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-sm font-medium text-gray-900 dark:text-white", children: "Paris Weekend Getaway" }),
|
|
1555
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-xs text-gray-500 dark:text-gray-400 mb-2", children: "3 days \xB7 $850" }),
|
|
1556
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-2", children: [
|
|
1557
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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__ */ _jsxruntime.jsx.call(void 0, "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" && _optionalChain([response, 'optionalAccess', _41 => _41.includes, 'call', _42 => _42("task")]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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__ */ _jsxruntime.jsxs.call(void 0, "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__ */ _jsxruntime.jsx.call(void 0, "div", { className: `w-2 h-2 rounded-full ${i === 0 ? "bg-green-500" : i === 1 ? "bg-yellow-500" : "bg-red-500"}` }),
|
|
1563
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "flex-1 text-sm text-gray-700 dark:text-gray-300", children: task }),
|
|
1564
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { className: "text-xs text-blue-500 hover:text-blue-600", children: "View" })
|
|
1565
|
+
] }, i)) }),
|
|
1566
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1567
|
+
"input",
|
|
1568
|
+
{
|
|
1569
|
+
ref: fileInputRef,
|
|
1570
|
+
type: "file",
|
|
1571
|
+
multiple: true,
|
|
1572
|
+
onChange: handleFileSelect,
|
|
1573
|
+
className: "hidden",
|
|
1574
|
+
accept: "image/*,application/pdf,.doc,.docx,.txt"
|
|
1575
|
+
}
|
|
1576
|
+
)
|
|
1577
|
+
] });
|
|
1578
|
+
}
|
|
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() {
|
|
@@ -920,7 +1662,7 @@ var AptevaClient = class {
|
|
|
920
1662
|
const error = await response.json().catch(() => ({ error: "Request failed" }));
|
|
921
1663
|
throw new Error(error.error || `Request failed with status ${response.status}`);
|
|
922
1664
|
}
|
|
923
|
-
const reader = _optionalChain([response, 'access',
|
|
1665
|
+
const reader = _optionalChain([response, 'access', _43 => _43.body, 'optionalAccess', _44 => _44.getReader, 'call', _45 => _45()]);
|
|
924
1666
|
if (!reader) {
|
|
925
1667
|
throw new Error("Response body is not readable");
|
|
926
1668
|
}
|
|
@@ -938,7 +1680,7 @@ var AptevaClient = class {
|
|
|
938
1680
|
if (line.startsWith("data: ")) {
|
|
939
1681
|
const data = line.slice(6);
|
|
940
1682
|
if (data === "[DONE]") {
|
|
941
|
-
_optionalChain([onComplete, 'optionalCall',
|
|
1683
|
+
_optionalChain([onComplete, 'optionalCall', _46 => _46(threadId)]);
|
|
942
1684
|
return;
|
|
943
1685
|
}
|
|
944
1686
|
try {
|
|
@@ -953,10 +1695,10 @@ var AptevaClient = class {
|
|
|
953
1695
|
}
|
|
954
1696
|
}
|
|
955
1697
|
}
|
|
956
|
-
_optionalChain([onComplete, 'optionalCall',
|
|
1698
|
+
_optionalChain([onComplete, 'optionalCall', _47 => _47(threadId)]);
|
|
957
1699
|
} catch (error) {
|
|
958
1700
|
const err = error instanceof Error ? error : new Error("Unknown error");
|
|
959
|
-
_optionalChain([onError, 'optionalCall',
|
|
1701
|
+
_optionalChain([onError, 'optionalCall', _48 => _48(err)]);
|
|
960
1702
|
throw err;
|
|
961
1703
|
}
|
|
962
1704
|
}
|
|
@@ -1009,11 +1751,32 @@ 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
|
|
@@ -1021,6 +1784,19 @@ function Chat({
|
|
|
1021
1784
|
const [messages, setMessages] = _react.useState.call(void 0, initialMessages);
|
|
1022
1785
|
const [isLoading, setIsLoading] = _react.useState.call(void 0, false);
|
|
1023
1786
|
const [currentThreadId, setCurrentThreadId] = _react.useState.call(void 0, threadId || null);
|
|
1787
|
+
const [mode, setMode] = _react.useState.call(void 0, initialMode);
|
|
1788
|
+
const [commandState, setCommandState] = _react.useState.call(void 0, "idle");
|
|
1789
|
+
const [commandResult, setCommandResult] = _react.useState.call(void 0, null);
|
|
1790
|
+
const [commandError, setCommandError] = _react.useState.call(void 0, null);
|
|
1791
|
+
const [progress, setProgress] = _react.useState.call(void 0, 0);
|
|
1792
|
+
const [commandInput, setCommandInput] = _react.useState.call(void 0, "");
|
|
1793
|
+
const [streamedContent, setStreamedContent] = _react.useState.call(void 0, "");
|
|
1794
|
+
const [currentToolName, setCurrentToolName] = _react.useState.call(void 0, null);
|
|
1795
|
+
const [plan, setPlan] = _react.useState.call(void 0, "");
|
|
1796
|
+
const [pendingCommand, setPendingCommand] = _react.useState.call(void 0, "");
|
|
1797
|
+
const [internalPlanMode, setInternalPlanMode] = _react.useState.call(void 0, planMode);
|
|
1798
|
+
const [showSettingsMenu, setShowSettingsMenu] = _react.useState.call(void 0, false);
|
|
1799
|
+
const fileInputRef = _react.useRef.call(void 0, null);
|
|
1024
1800
|
_react.useEffect.call(void 0, () => {
|
|
1025
1801
|
if (apiUrl || apiKey) {
|
|
1026
1802
|
aptevaClient.configure({
|
|
@@ -1031,21 +1807,48 @@ function Chat({
|
|
|
1031
1807
|
}, [apiUrl, apiKey]);
|
|
1032
1808
|
_react.useEffect.call(void 0, () => {
|
|
1033
1809
|
if (threadId) {
|
|
1034
|
-
|
|
1035
|
-
_optionalChain([onThreadChange, 'optionalCall', _20 => _20(threadId)]);
|
|
1810
|
+
_optionalChain([onThreadChange, 'optionalCall', _49 => _49(threadId)]);
|
|
1036
1811
|
}
|
|
1037
1812
|
}, [threadId, onThreadChange]);
|
|
1038
|
-
|
|
1813
|
+
_react.useEffect.call(void 0, () => {
|
|
1814
|
+
setInternalPlanMode(planMode);
|
|
1815
|
+
}, [planMode]);
|
|
1816
|
+
_react.useEffect.call(void 0, () => {
|
|
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
|
+
_optionalChain([onModeChange, 'optionalCall', _50 => _50(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
|
-
_optionalChain([onMessageSent, 'optionalCall',
|
|
1848
|
+
_optionalChain([onMessageSent, 'optionalCall', _51 => _51(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,21 +1898,19 @@ 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;
|
|
1115
1911
|
if (!currentThreadId) {
|
|
1116
1912
|
setCurrentThreadId(chunk.thread_id);
|
|
1117
|
-
_optionalChain([onThreadChange, 'optionalCall',
|
|
1913
|
+
_optionalChain([onThreadChange, 'optionalCall', _52 => _52(chunk.thread_id)]);
|
|
1118
1914
|
}
|
|
1119
1915
|
}
|
|
1120
1916
|
break;
|
|
@@ -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
|
}
|
|
@@ -1205,7 +1983,7 @@ function Chat({
|
|
|
1205
1983
|
});
|
|
1206
1984
|
if (threadId2 && threadId2 !== currentThreadId) {
|
|
1207
1985
|
setCurrentThreadId(threadId2);
|
|
1208
|
-
_optionalChain([onThreadChange, 'optionalCall',
|
|
1986
|
+
_optionalChain([onThreadChange, 'optionalCall', _53 => _53(threadId2)]);
|
|
1209
1987
|
}
|
|
1210
1988
|
setIsLoading(false);
|
|
1211
1989
|
},
|
|
@@ -1225,11 +2003,11 @@ function Chat({
|
|
|
1225
2003
|
return [...prev, errorMessage];
|
|
1226
2004
|
});
|
|
1227
2005
|
setIsLoading(false);
|
|
2006
|
+
_optionalChain([onError, 'optionalCall', _54 => _54(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,18 +2016,277 @@ function Chat({
|
|
|
1238
2016
|
metadata: { error: true }
|
|
1239
2017
|
};
|
|
1240
2018
|
setMessages((prev) => [...prev, errorMessage]);
|
|
2019
|
+
_optionalChain([onError, 'optionalCall', _55 => _55(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
|
+
_optionalChain([onError, 'optionalCall', _56 => _56(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
|
+
_optionalChain([onComplete, 'optionalCall', _57 => _57(result)]);
|
|
2098
|
+
},
|
|
2099
|
+
(error) => {
|
|
2100
|
+
setCommandError(error);
|
|
2101
|
+
setCommandState("error");
|
|
2102
|
+
_optionalChain([onError, 'optionalCall', _58 => _58(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
|
+
_optionalChain([onComplete, 'optionalCall', _59 => _59(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
|
+
_optionalChain([onThreadChange, 'optionalCall', _60 => _60(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
|
+
_optionalChain([onComplete, 'optionalCall', _61 => _61(result)]);
|
|
2163
|
+
},
|
|
2164
|
+
(error) => {
|
|
2165
|
+
setCommandError(error);
|
|
2166
|
+
setCommandState("error");
|
|
2167
|
+
_optionalChain([onError, 'optionalCall', _62 => _62(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
|
+
_optionalChain([onComplete, 'optionalCall', _63 => _63(result)]);
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
} catch (err) {
|
|
2191
|
+
const error = err instanceof Error ? err : new Error("Unknown error");
|
|
2192
|
+
setCommandError(error);
|
|
2193
|
+
setCommandState("error");
|
|
2194
|
+
_optionalChain([onError, 'optionalCall', _64 => _64(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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("flex flex-col h-full", className), children: [
|
|
2225
|
+
showHeader && mode === "chat" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "px-4 py-3 flex items-center justify-between", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "!text-lg font-semibold !text-gray-900 dark:!text-white", children: headerTitle }) }),
|
|
2226
|
+
mode === "chat" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
2227
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, "div", { className: "px-4 py-2 !text-sm !text-gray-500 dark:!text-gray-400 italic", children: "AI is thinking..." }),
|
|
2241
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 flex flex-col items-center justify-center p-4", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full max-w-2xl", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
2253
|
+
CommandComposer,
|
|
2254
|
+
{
|
|
2255
|
+
onExecute: (text, files) => {
|
|
2256
|
+
setCommandInput(text);
|
|
2257
|
+
executeCommand(text, files);
|
|
2258
|
+
},
|
|
2259
|
+
state: commandState,
|
|
2260
|
+
response: _optionalChain([commandResult, 'optionalAccess', _65 => _65.data, 'optionalAccess', _66 => _66.summary]) || _optionalChain([commandResult, 'optionalAccess', _67 => _67.message]),
|
|
2261
|
+
error: _optionalChain([commandError, 'optionalAccess', _68 => _68.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__ */ _jsxruntime.jsx.call(void 0, "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
|
+
|
|
2288
|
+
|
|
2289
|
+
|
|
1253
2290
|
// src/components/Command/Command.tsx
|
|
1254
2291
|
|
|
1255
2292
|
|
|
@@ -1385,13 +2422,13 @@ ${planningInstruction}` : planningInstruction;
|
|
|
1385
2422
|
const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
|
|
1386
2423
|
setError(error2);
|
|
1387
2424
|
setState("error");
|
|
1388
|
-
_optionalChain([onError, 'optionalCall',
|
|
2425
|
+
_optionalChain([onError, 'optionalCall', _69 => _69(error2)]);
|
|
1389
2426
|
});
|
|
1390
2427
|
} catch (err) {
|
|
1391
2428
|
const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
|
|
1392
2429
|
setError(error2);
|
|
1393
2430
|
setState("error");
|
|
1394
|
-
_optionalChain([onError, 'optionalCall',
|
|
2431
|
+
_optionalChain([onError, 'optionalCall', _70 => _70(error2)]);
|
|
1395
2432
|
}
|
|
1396
2433
|
}
|
|
1397
2434
|
return;
|
|
@@ -1402,7 +2439,7 @@ ${planningInstruction}` : planningInstruction;
|
|
|
1402
2439
|
setStreamedContent("");
|
|
1403
2440
|
setCommand("");
|
|
1404
2441
|
setUploadedFiles([]);
|
|
1405
|
-
_optionalChain([onStart, 'optionalCall',
|
|
2442
|
+
_optionalChain([onStart, 'optionalCall', _71 => _71()]);
|
|
1406
2443
|
try {
|
|
1407
2444
|
if (useMock) {
|
|
1408
2445
|
if (enableStreaming) {
|
|
@@ -1413,16 +2450,16 @@ ${planningInstruction}` : planningInstruction;
|
|
|
1413
2450
|
if (chunk.type === "token" && chunk.content) {
|
|
1414
2451
|
accumulatedContent += chunk.content;
|
|
1415
2452
|
setStreamedContent(accumulatedContent);
|
|
1416
|
-
_optionalChain([onChunk, 'optionalCall',
|
|
2453
|
+
_optionalChain([onChunk, 'optionalCall', _72 => _72(chunk.content)]);
|
|
1417
2454
|
const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
|
|
1418
2455
|
setProgress(estimatedProgress);
|
|
1419
|
-
_optionalChain([onProgress, 'optionalCall',
|
|
2456
|
+
_optionalChain([onProgress, 'optionalCall', _73 => _73(estimatedProgress)]);
|
|
1420
2457
|
} else if (chunk.type === "widget" && chunk.widget) {
|
|
1421
2458
|
const widget = chunk.widget;
|
|
1422
2459
|
setResult((prev) => ({
|
|
1423
2460
|
success: true,
|
|
1424
|
-
data: _optionalChain([prev, 'optionalAccess',
|
|
1425
|
-
widgets: [..._optionalChain([prev, 'optionalAccess',
|
|
2461
|
+
data: _optionalChain([prev, 'optionalAccess', _74 => _74.data]) || {},
|
|
2462
|
+
widgets: [..._optionalChain([prev, 'optionalAccess', _75 => _75.widgets]) || [], widget],
|
|
1426
2463
|
message: accumulatedContent || "Command executed successfully"
|
|
1427
2464
|
}));
|
|
1428
2465
|
}
|
|
@@ -1442,19 +2479,19 @@ ${planningInstruction}` : planningInstruction;
|
|
|
1442
2479
|
setResult(result2);
|
|
1443
2480
|
setState("success");
|
|
1444
2481
|
setProgress(100);
|
|
1445
|
-
_optionalChain([onComplete, 'optionalCall',
|
|
2482
|
+
_optionalChain([onComplete, 'optionalCall', _76 => _76(result2)]);
|
|
1446
2483
|
},
|
|
1447
2484
|
(error2) => {
|
|
1448
2485
|
setError(error2);
|
|
1449
2486
|
setState("error");
|
|
1450
|
-
_optionalChain([onError, 'optionalCall',
|
|
2487
|
+
_optionalChain([onError, 'optionalCall', _77 => _77(error2)]);
|
|
1451
2488
|
}
|
|
1452
2489
|
);
|
|
1453
2490
|
} else {
|
|
1454
2491
|
const progressInterval = setInterval(() => {
|
|
1455
2492
|
setProgress((prev) => {
|
|
1456
2493
|
const next = Math.min(prev + 10, 90);
|
|
1457
|
-
_optionalChain([onProgress, 'optionalCall',
|
|
2494
|
+
_optionalChain([onProgress, 'optionalCall', _78 => _78(next)]);
|
|
1458
2495
|
return next;
|
|
1459
2496
|
});
|
|
1460
2497
|
}, 200);
|
|
@@ -1478,7 +2515,7 @@ ${planningInstruction}` : planningInstruction;
|
|
|
1478
2515
|
setResult(result2);
|
|
1479
2516
|
setState("success");
|
|
1480
2517
|
setProgress(100);
|
|
1481
|
-
_optionalChain([onComplete, 'optionalCall',
|
|
2518
|
+
_optionalChain([onComplete, 'optionalCall', _79 => _79(result2)]);
|
|
1482
2519
|
}
|
|
1483
2520
|
} else {
|
|
1484
2521
|
if (enableStreaming) {
|
|
@@ -1524,16 +2561,16 @@ ${commandInstruction}` : commandInstruction;
|
|
|
1524
2561
|
if (chunk.type === "token" && chunk.content) {
|
|
1525
2562
|
accumulatedContent += chunk.content;
|
|
1526
2563
|
setStreamedContent(accumulatedContent);
|
|
1527
|
-
_optionalChain([onChunk, 'optionalCall',
|
|
2564
|
+
_optionalChain([onChunk, 'optionalCall', _80 => _80(chunk.content)]);
|
|
1528
2565
|
const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
|
|
1529
2566
|
setProgress(estimatedProgress);
|
|
1530
|
-
_optionalChain([onProgress, 'optionalCall',
|
|
2567
|
+
_optionalChain([onProgress, 'optionalCall', _81 => _81(estimatedProgress)]);
|
|
1531
2568
|
} else if (chunk.type === "widget" && chunk.widget) {
|
|
1532
2569
|
const widget = chunk.widget;
|
|
1533
2570
|
setResult((prev) => ({
|
|
1534
2571
|
success: true,
|
|
1535
|
-
data: _optionalChain([prev, 'optionalAccess',
|
|
1536
|
-
widgets: [..._optionalChain([prev, 'optionalAccess',
|
|
2572
|
+
data: _optionalChain([prev, 'optionalAccess', _82 => _82.data]) || {},
|
|
2573
|
+
widgets: [..._optionalChain([prev, 'optionalAccess', _83 => _83.widgets]) || [], widget],
|
|
1537
2574
|
message: accumulatedContent || "Command executed successfully"
|
|
1538
2575
|
}));
|
|
1539
2576
|
}
|
|
@@ -1553,20 +2590,20 @@ ${commandInstruction}` : commandInstruction;
|
|
|
1553
2590
|
setResult(result2);
|
|
1554
2591
|
setState("success");
|
|
1555
2592
|
setProgress(100);
|
|
1556
|
-
_optionalChain([onComplete, 'optionalCall',
|
|
2593
|
+
_optionalChain([onComplete, 'optionalCall', _84 => _84(result2)]);
|
|
1557
2594
|
},
|
|
1558
2595
|
(error2) => {
|
|
1559
2596
|
const err = error2 instanceof Error ? error2 : new Error("Unknown error");
|
|
1560
2597
|
setError(err);
|
|
1561
2598
|
setState("error");
|
|
1562
|
-
_optionalChain([onError, 'optionalCall',
|
|
2599
|
+
_optionalChain([onError, 'optionalCall', _85 => _85(err)]);
|
|
1563
2600
|
}
|
|
1564
2601
|
);
|
|
1565
2602
|
} else {
|
|
1566
2603
|
const progressInterval = setInterval(() => {
|
|
1567
2604
|
setProgress((prev) => {
|
|
1568
2605
|
const next = Math.min(prev + 10, 90);
|
|
1569
|
-
_optionalChain([onProgress, 'optionalCall',
|
|
2606
|
+
_optionalChain([onProgress, 'optionalCall', _86 => _86(next)]);
|
|
1570
2607
|
return next;
|
|
1571
2608
|
});
|
|
1572
2609
|
}, 200);
|
|
@@ -1622,14 +2659,14 @@ ${commandInstruction}` : commandInstruction;
|
|
|
1622
2659
|
setResult(result2);
|
|
1623
2660
|
setState("success");
|
|
1624
2661
|
setProgress(100);
|
|
1625
|
-
_optionalChain([onComplete, 'optionalCall',
|
|
2662
|
+
_optionalChain([onComplete, 'optionalCall', _87 => _87(result2)]);
|
|
1626
2663
|
}
|
|
1627
2664
|
}
|
|
1628
2665
|
} catch (err) {
|
|
1629
2666
|
const error2 = err instanceof Error ? err : new Error("Unknown error");
|
|
1630
2667
|
setError(error2);
|
|
1631
2668
|
setState("error");
|
|
1632
|
-
_optionalChain([onError, 'optionalCall',
|
|
2669
|
+
_optionalChain([onError, 'optionalCall', _88 => _88(error2)]);
|
|
1633
2670
|
}
|
|
1634
2671
|
};
|
|
1635
2672
|
const resetCommand = () => {
|
|
@@ -1662,14 +2699,14 @@ ${planToExecute}`;
|
|
|
1662
2699
|
};
|
|
1663
2700
|
const handleFileSelect = async (e) => {
|
|
1664
2701
|
if (e.target.files && e.target.files.length > 0) {
|
|
1665
|
-
_optionalChain([onFileUpload, 'optionalCall',
|
|
2702
|
+
_optionalChain([onFileUpload, 'optionalCall', _89 => _89(e.target.files)]);
|
|
1666
2703
|
const files = [];
|
|
1667
2704
|
for (let i = 0; i < e.target.files.length; i++) {
|
|
1668
2705
|
const file = e.target.files[i];
|
|
1669
2706
|
const reader = new FileReader();
|
|
1670
2707
|
await new Promise((resolve) => {
|
|
1671
2708
|
reader.onload = (event) => {
|
|
1672
|
-
if (_optionalChain([event, 'access',
|
|
2709
|
+
if (_optionalChain([event, 'access', _90 => _90.target, 'optionalAccess', _91 => _91.result])) {
|
|
1673
2710
|
const fullDataUrl = event.target.result;
|
|
1674
2711
|
const base64Data = fullDataUrl.split(",")[1];
|
|
1675
2712
|
if (file.type.startsWith("image/")) {
|
|
@@ -1763,7 +2800,7 @@ ${planToExecute}`;
|
|
|
1763
2800
|
enableFileUpload && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1764
2801
|
"button",
|
|
1765
2802
|
{
|
|
1766
|
-
onClick: () => _optionalChain([fileInputRef, 'access',
|
|
2803
|
+
onClick: () => _optionalChain([fileInputRef, 'access', _92 => _92.current, 'optionalAccess', _93 => _93.click, 'call', _94 => _94()]),
|
|
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
2806
|
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M8.4 2.8L4.4 6.8C3.736 7.464 3.736 8.536 4.4 9.2C5.064 9.864 6.136 9.864 6.8 9.2L11.6 4.4C12.704 3.296 12.704 1.504 11.6 0.4C10.496 -0.704 8.704 -0.704 7.6 0.4L2.8 5.2C1.256 6.744 1.256 9.256 2.8 10.8C4.344 12.344 6.856 12.344 8.4 10.8L12.4 6.8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round", transform: "translate(1.6, 2.4)" }) })
|
|
@@ -1982,7 +3019,7 @@ ${planToExecute}`;
|
|
|
1982
3019
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-5 h-5 text-red-600 mt-0.5 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
1983
3020
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
|
|
1984
3021
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-sm font-semibold text-red-800 dark:text-red-400", children: "Error" }),
|
|
1985
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-red-700 dark:text-red-300 text-sm mt-1", children: _optionalChain([error, 'optionalAccess',
|
|
3022
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-red-700 dark:text-red-300 text-sm mt-1", children: _optionalChain([error, 'optionalAccess', _95 => _95.message]) })
|
|
1986
3023
|
] })
|
|
1987
3024
|
] }) }),
|
|
1988
3025
|
allowInput && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
@@ -2010,7 +3047,7 @@ ${planToExecute}`;
|
|
|
2010
3047
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-green-700 dark:text-green-300 text-sm", children: "Command executed successfully" })
|
|
2011
3048
|
] })
|
|
2012
3049
|
] }),
|
|
2013
|
-
_optionalChain([result, 'access',
|
|
3050
|
+
_optionalChain([result, 'access', _96 => _96.data, 'optionalAccess', _97 => _97.summary]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-gray-700 dark:text-gray-300 text-sm leading-relaxed whitespace-pre-line", children: result.data.summary }),
|
|
2014
3051
|
result.widgets && result.widgets.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "space-y-3", children: result.widgets.map((widget) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
2015
3052
|
WidgetRenderer,
|
|
2016
3053
|
{
|
|
@@ -2061,7 +3098,7 @@ ${planToExecute}`;
|
|
|
2061
3098
|
enableFileUpload && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
2062
3099
|
"button",
|
|
2063
3100
|
{
|
|
2064
|
-
onClick: () => _optionalChain([fileInputRef, 'access',
|
|
3101
|
+
onClick: () => _optionalChain([fileInputRef, 'access', _98 => _98.current, 'optionalAccess', _99 => _99.click, 'call', _100 => _100()]),
|
|
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
3104
|
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M8.4 2.8L4.4 6.8C3.736 7.464 3.736 8.536 4.4 9.2C5.064 9.864 6.136 9.864 6.8 9.2L11.6 4.4C12.704 3.296 12.704 1.504 11.6 0.4C10.496 -0.704 8.704 -0.704 7.6 0.4L2.8 5.2C1.256 6.744 1.256 9.256 2.8 10.8C4.344 12.344 6.856 12.344 8.4 10.8L12.4 6.8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round", transform: "translate(1.6, 2.4)" }) })
|
|
@@ -2247,25 +3284,25 @@ function Prompt({
|
|
|
2247
3284
|
const newValue = e.target.value;
|
|
2248
3285
|
if (!maxLength || newValue.length <= maxLength) {
|
|
2249
3286
|
setValue(newValue);
|
|
2250
|
-
_optionalChain([onChange, 'optionalCall',
|
|
3287
|
+
_optionalChain([onChange, 'optionalCall', _101 => _101(newValue)]);
|
|
2251
3288
|
}
|
|
2252
3289
|
};
|
|
2253
3290
|
const handleSubmit = async () => {
|
|
2254
3291
|
if (value.length < minLength) return;
|
|
2255
|
-
_optionalChain([onSubmit, 'optionalCall',
|
|
3292
|
+
_optionalChain([onSubmit, 'optionalCall', _102 => _102(value)]);
|
|
2256
3293
|
setIsLoading(true);
|
|
2257
3294
|
try {
|
|
2258
3295
|
if (useMock) {
|
|
2259
3296
|
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
2260
3297
|
const mockResult = `Enhanced version: ${value} [AI-generated content]`;
|
|
2261
|
-
_optionalChain([onResult, 'optionalCall',
|
|
3298
|
+
_optionalChain([onResult, 'optionalCall', _103 => _103(mockResult)]);
|
|
2262
3299
|
setValue("");
|
|
2263
3300
|
} else {
|
|
2264
3301
|
const response = await aptevaClient.chat({
|
|
2265
3302
|
agent_id: agentId,
|
|
2266
3303
|
message: value
|
|
2267
3304
|
});
|
|
2268
|
-
_optionalChain([onResult, 'optionalCall',
|
|
3305
|
+
_optionalChain([onResult, 'optionalCall', _104 => _104(response.message)]);
|
|
2269
3306
|
setValue("");
|
|
2270
3307
|
}
|
|
2271
3308
|
} catch (error) {
|
|
@@ -2360,7 +3397,7 @@ function Stream({
|
|
|
2360
3397
|
}, [autoStart]);
|
|
2361
3398
|
const startStreaming = async () => {
|
|
2362
3399
|
setIsStreaming(true);
|
|
2363
|
-
_optionalChain([onStart, 'optionalCall',
|
|
3400
|
+
_optionalChain([onStart, 'optionalCall', _105 => _105()]);
|
|
2364
3401
|
try {
|
|
2365
3402
|
if (useMock) {
|
|
2366
3403
|
const mockText = "This is a simulated streaming response from the AI agent. In a real implementation, this would stream data from your backend API. The text appears word by word to simulate the streaming effect. You can customize the typing speed and styling based on your needs.";
|
|
@@ -2368,13 +3405,13 @@ function Stream({
|
|
|
2368
3405
|
mockText,
|
|
2369
3406
|
(chunk) => {
|
|
2370
3407
|
setText((prev) => prev + chunk);
|
|
2371
|
-
_optionalChain([onChunk, 'optionalCall',
|
|
3408
|
+
_optionalChain([onChunk, 'optionalCall', _106 => _106(chunk)]);
|
|
2372
3409
|
},
|
|
2373
3410
|
typingSpeed
|
|
2374
3411
|
);
|
|
2375
3412
|
setIsComplete(true);
|
|
2376
3413
|
setIsStreaming(false);
|
|
2377
|
-
_optionalChain([onComplete, 'optionalCall',
|
|
3414
|
+
_optionalChain([onComplete, 'optionalCall', _107 => _107(text + mockText)]);
|
|
2378
3415
|
} else {
|
|
2379
3416
|
let accumulatedText = "";
|
|
2380
3417
|
await aptevaClient.chatStream(
|
|
@@ -2387,24 +3424,24 @@ function Stream({
|
|
|
2387
3424
|
if (chunk.type === "token" && chunk.content) {
|
|
2388
3425
|
accumulatedText += chunk.content;
|
|
2389
3426
|
setText(accumulatedText);
|
|
2390
|
-
_optionalChain([onChunk, 'optionalCall',
|
|
3427
|
+
_optionalChain([onChunk, 'optionalCall', _108 => _108(chunk.content)]);
|
|
2391
3428
|
}
|
|
2392
3429
|
},
|
|
2393
3430
|
() => {
|
|
2394
3431
|
setIsComplete(true);
|
|
2395
3432
|
setIsStreaming(false);
|
|
2396
|
-
_optionalChain([onComplete, 'optionalCall',
|
|
3433
|
+
_optionalChain([onComplete, 'optionalCall', _109 => _109(accumulatedText)]);
|
|
2397
3434
|
},
|
|
2398
3435
|
(error) => {
|
|
2399
3436
|
const err = error instanceof Error ? error : new Error("Streaming error");
|
|
2400
|
-
_optionalChain([onError, 'optionalCall',
|
|
3437
|
+
_optionalChain([onError, 'optionalCall', _110 => _110(err)]);
|
|
2401
3438
|
setIsStreaming(false);
|
|
2402
3439
|
}
|
|
2403
3440
|
);
|
|
2404
3441
|
}
|
|
2405
3442
|
} catch (error) {
|
|
2406
3443
|
const err = error instanceof Error ? error : new Error("Streaming error");
|
|
2407
|
-
_optionalChain([onError, 'optionalCall',
|
|
3444
|
+
_optionalChain([onError, 'optionalCall', _111 => _111(err)]);
|
|
2408
3445
|
setIsStreaming(false);
|
|
2409
3446
|
}
|
|
2410
3447
|
};
|
|
@@ -2496,7 +3533,7 @@ function ThreadList({
|
|
|
2496
3533
|
}) {
|
|
2497
3534
|
const [searchQuery, setSearchQuery] = _react.useState.call(void 0, "");
|
|
2498
3535
|
const filteredThreads = threads.filter(
|
|
2499
|
-
(thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || _optionalChain([thread, 'access',
|
|
3536
|
+
(thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || _optionalChain([thread, 'access', _112 => _112.preview, 'optionalAccess', _113 => _113.toLowerCase, 'call', _114 => _114(), 'access', _115 => _115.includes, 'call', _116 => _116(searchQuery.toLowerCase())])
|
|
2500
3537
|
);
|
|
2501
3538
|
const groupedThreads = groupBy === "date" ? groupThreadsByDate(filteredThreads) : { All: filteredThreads };
|
|
2502
3539
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col h-full", children: [
|
|
@@ -2518,14 +3555,14 @@ function ThreadList({
|
|
|
2518
3555
|
{
|
|
2519
3556
|
thread,
|
|
2520
3557
|
isActive: thread.id === currentThreadId,
|
|
2521
|
-
onSelect: () => _optionalChain([onThreadSelect, 'optionalCall',
|
|
2522
|
-
onDelete: () => _optionalChain([onThreadDelete, 'optionalCall',
|
|
3558
|
+
onSelect: () => _optionalChain([onThreadSelect, 'optionalCall', _117 => _117(thread.id)]),
|
|
3559
|
+
onDelete: () => _optionalChain([onThreadDelete, 'optionalCall', _118 => _118(thread.id)])
|
|
2523
3560
|
},
|
|
2524
3561
|
thread.id
|
|
2525
3562
|
))
|
|
2526
3563
|
] }, group)),
|
|
2527
3564
|
filteredThreads.length === 0 && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "p-8 text-center text-gray-500", children: [
|
|
2528
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "
|
|
3565
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { className: "w-10 h-10 mx-auto mb-2 opacity-50", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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" }) }),
|
|
2529
3566
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { children: "No conversations found" })
|
|
2530
3567
|
] })
|
|
2531
3568
|
] })
|
|
@@ -2581,7 +3618,7 @@ function Threads({
|
|
|
2581
3618
|
threads.slice(0, 5).map((thread) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
2582
3619
|
"button",
|
|
2583
3620
|
{
|
|
2584
|
-
onClick: () => _optionalChain([onThreadSelect, 'optionalCall',
|
|
3621
|
+
onClick: () => _optionalChain([onThreadSelect, 'optionalCall', _119 => _119(thread.id)]),
|
|
2585
3622
|
className: cn(
|
|
2586
3623
|
"px-4 py-2 whitespace-nowrap font-medium transition-colors",
|
|
2587
3624
|
thread.id === currentThreadId ? "border-b-2 border-apteva-500 text-apteva-500" : "text-gray-600 hover:text-gray-900"
|