@cadraos/sdk 0.1.6 → 0.1.7
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/chat/index.cjs +1046 -34
- package/dist/chat/index.cjs.map +1 -1
- package/dist/chat/index.d.cts +173 -7
- package/dist/chat/index.d.ts +173 -7
- package/dist/chat/index.js +1046 -37
- package/dist/chat/index.js.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/package.json +3 -3
package/dist/chat/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createContext,
|
|
2
|
-
import {
|
|
1
|
+
import { createContext, forwardRef, useState, useRef, useImperativeHandle, useCallback, useEffect, useMemo, useContext } from 'react';
|
|
2
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import ReactMarkdown from 'react-markdown';
|
|
4
4
|
import remarkGfm from 'remark-gfm';
|
|
5
5
|
|
|
@@ -3214,8 +3214,9 @@ function useAgentChat(options) {
|
|
|
3214
3214
|
[adapter, handleExecutionLog, updateStreamingMessage, updateToolCall, handleClarification, handleComplete, handleError]
|
|
3215
3215
|
);
|
|
3216
3216
|
const sendMessage = useCallback(
|
|
3217
|
-
async (content) => {
|
|
3217
|
+
async (content, options2) => {
|
|
3218
3218
|
if (!content.trim()) return;
|
|
3219
|
+
const attachmentUuids = options2?.attachmentUuids;
|
|
3219
3220
|
lastMessageContentRef.current = content;
|
|
3220
3221
|
setIsLoading(true);
|
|
3221
3222
|
setError(null);
|
|
@@ -3246,7 +3247,8 @@ function useAgentChat(options) {
|
|
|
3246
3247
|
agentId,
|
|
3247
3248
|
teamId,
|
|
3248
3249
|
sessionId: currentSessionId ?? void 0,
|
|
3249
|
-
content: content.trim()
|
|
3250
|
+
content: content.trim(),
|
|
3251
|
+
attachmentUuids
|
|
3250
3252
|
});
|
|
3251
3253
|
console.log("[useAgentChat] Execution started:", result);
|
|
3252
3254
|
if (!currentSessionId && result.sessionId) {
|
|
@@ -3455,6 +3457,222 @@ function useAgentChat(options) {
|
|
|
3455
3457
|
loadSession
|
|
3456
3458
|
};
|
|
3457
3459
|
}
|
|
3460
|
+
|
|
3461
|
+
// src/chat/utils/compress-image.ts
|
|
3462
|
+
var DEFAULT_TARGET_SIZE_KB = 150;
|
|
3463
|
+
var MAX_DIMENSION = 1920;
|
|
3464
|
+
var QUALITY_START = 0.85;
|
|
3465
|
+
var QUALITY_STEP = 0.05;
|
|
3466
|
+
var QUALITY_MIN = 0.1;
|
|
3467
|
+
function loadImage(file) {
|
|
3468
|
+
return new Promise((resolve, reject) => {
|
|
3469
|
+
const img = new Image();
|
|
3470
|
+
const url = URL.createObjectURL(file);
|
|
3471
|
+
img.onload = () => {
|
|
3472
|
+
URL.revokeObjectURL(url);
|
|
3473
|
+
resolve(img);
|
|
3474
|
+
};
|
|
3475
|
+
img.onerror = () => {
|
|
3476
|
+
URL.revokeObjectURL(url);
|
|
3477
|
+
reject(new Error(`Failed to load image: ${file.name}`));
|
|
3478
|
+
};
|
|
3479
|
+
img.src = url;
|
|
3480
|
+
});
|
|
3481
|
+
}
|
|
3482
|
+
function getScaledDimensions(width, height, maxDim) {
|
|
3483
|
+
if (width <= maxDim && height <= maxDim) {
|
|
3484
|
+
return { width, height };
|
|
3485
|
+
}
|
|
3486
|
+
const ratio = Math.min(maxDim / width, maxDim / height);
|
|
3487
|
+
return {
|
|
3488
|
+
width: Math.round(width * ratio),
|
|
3489
|
+
height: Math.round(height * ratio)
|
|
3490
|
+
};
|
|
3491
|
+
}
|
|
3492
|
+
function canvasToBlob(img, width, height, format, quality) {
|
|
3493
|
+
return new Promise((resolve, reject) => {
|
|
3494
|
+
const canvas = document.createElement("canvas");
|
|
3495
|
+
canvas.width = width;
|
|
3496
|
+
canvas.height = height;
|
|
3497
|
+
const ctx = canvas.getContext("2d");
|
|
3498
|
+
if (!ctx) {
|
|
3499
|
+
reject(new Error("Failed to get canvas 2d context"));
|
|
3500
|
+
return;
|
|
3501
|
+
}
|
|
3502
|
+
ctx.drawImage(img, 0, 0, width, height);
|
|
3503
|
+
canvas.toBlob(
|
|
3504
|
+
(blob) => {
|
|
3505
|
+
if (!blob) {
|
|
3506
|
+
reject(new Error("Canvas toBlob returned null"));
|
|
3507
|
+
return;
|
|
3508
|
+
}
|
|
3509
|
+
resolve(blob);
|
|
3510
|
+
},
|
|
3511
|
+
format,
|
|
3512
|
+
quality
|
|
3513
|
+
);
|
|
3514
|
+
});
|
|
3515
|
+
}
|
|
3516
|
+
var webpSupported = null;
|
|
3517
|
+
function supportsWebP() {
|
|
3518
|
+
if (webpSupported !== null) return webpSupported;
|
|
3519
|
+
try {
|
|
3520
|
+
const canvas = document.createElement("canvas");
|
|
3521
|
+
canvas.width = 1;
|
|
3522
|
+
canvas.height = 1;
|
|
3523
|
+
webpSupported = canvas.toDataURL("image/webp").startsWith("data:image/webp");
|
|
3524
|
+
} catch {
|
|
3525
|
+
webpSupported = false;
|
|
3526
|
+
}
|
|
3527
|
+
return webpSupported;
|
|
3528
|
+
}
|
|
3529
|
+
function getOutputFormat(_originalType) {
|
|
3530
|
+
if (supportsWebP()) {
|
|
3531
|
+
return { mime: "image/webp", ext: ".webp" };
|
|
3532
|
+
}
|
|
3533
|
+
return { mime: "image/jpeg", ext: ".jpg" };
|
|
3534
|
+
}
|
|
3535
|
+
function replaceExtension(filename, newExt) {
|
|
3536
|
+
const dotIndex = filename.lastIndexOf(".");
|
|
3537
|
+
if (dotIndex === -1) return filename + newExt;
|
|
3538
|
+
return filename.substring(0, dotIndex) + newExt;
|
|
3539
|
+
}
|
|
3540
|
+
async function compressImage(file, targetSizeKB = DEFAULT_TARGET_SIZE_KB) {
|
|
3541
|
+
if (!file.type.startsWith("image/")) {
|
|
3542
|
+
return file;
|
|
3543
|
+
}
|
|
3544
|
+
if (file.type === "image/svg+xml") {
|
|
3545
|
+
return file;
|
|
3546
|
+
}
|
|
3547
|
+
if (file.type === "image/gif") {
|
|
3548
|
+
return file;
|
|
3549
|
+
}
|
|
3550
|
+
const targetBytes = targetSizeKB * 1024;
|
|
3551
|
+
if (file.size <= targetBytes) {
|
|
3552
|
+
return file;
|
|
3553
|
+
}
|
|
3554
|
+
const img = await loadImage(file);
|
|
3555
|
+
const { width, height } = getScaledDimensions(
|
|
3556
|
+
img.naturalWidth,
|
|
3557
|
+
img.naturalHeight,
|
|
3558
|
+
MAX_DIMENSION
|
|
3559
|
+
);
|
|
3560
|
+
const { mime, ext } = getOutputFormat(file.type);
|
|
3561
|
+
let quality = QUALITY_START;
|
|
3562
|
+
let blob = null;
|
|
3563
|
+
while (quality >= QUALITY_MIN) {
|
|
3564
|
+
blob = await canvasToBlob(img, width, height, mime, quality);
|
|
3565
|
+
if (blob.size <= targetBytes) {
|
|
3566
|
+
break;
|
|
3567
|
+
}
|
|
3568
|
+
quality -= QUALITY_STEP;
|
|
3569
|
+
}
|
|
3570
|
+
if (!blob) {
|
|
3571
|
+
blob = await canvasToBlob(img, width, height, mime, QUALITY_MIN);
|
|
3572
|
+
}
|
|
3573
|
+
if (blob.size >= file.size) {
|
|
3574
|
+
return file;
|
|
3575
|
+
}
|
|
3576
|
+
const newFilename = replaceExtension(file.name, ext);
|
|
3577
|
+
return new File([blob], newFilename, {
|
|
3578
|
+
type: mime,
|
|
3579
|
+
lastModified: Date.now()
|
|
3580
|
+
});
|
|
3581
|
+
}
|
|
3582
|
+
|
|
3583
|
+
// src/chat/hooks/useFileAttachments.ts
|
|
3584
|
+
function useFileAttachments(options) {
|
|
3585
|
+
const { onUpload, onConfirmUpload, onSubmitUpload, onError, maxFiles = 10, maxTotalSizeMB = 100 } = options;
|
|
3586
|
+
const [files, setFiles] = useState([]);
|
|
3587
|
+
const filesRef = useRef(files);
|
|
3588
|
+
filesRef.current = files;
|
|
3589
|
+
const onFilesChange = useCallback((newFiles) => {
|
|
3590
|
+
filesRef.current = newFiles;
|
|
3591
|
+
setFiles(newFiles);
|
|
3592
|
+
}, []);
|
|
3593
|
+
const removeFile = useCallback((uuid) => {
|
|
3594
|
+
setFiles((prev) => {
|
|
3595
|
+
const file = prev.find((f) => f.uuid === uuid);
|
|
3596
|
+
if (file?.previewUrl) {
|
|
3597
|
+
URL.revokeObjectURL(file.previewUrl);
|
|
3598
|
+
}
|
|
3599
|
+
return prev.filter((f) => f.uuid !== uuid);
|
|
3600
|
+
});
|
|
3601
|
+
}, []);
|
|
3602
|
+
const getReadyUuids = useCallback(() => {
|
|
3603
|
+
return filesRef.current.filter((f) => f.status === "ready").map((f) => f.uuid);
|
|
3604
|
+
}, []);
|
|
3605
|
+
const getReadyUrls = useCallback(() => {
|
|
3606
|
+
return filesRef.current.filter((f) => f.status === "ready").map((f) => f.uuid);
|
|
3607
|
+
}, []);
|
|
3608
|
+
const prepareForSubmit = useCallback(async () => {
|
|
3609
|
+
const readyFiles = filesRef.current.filter((f) => f.status === "ready");
|
|
3610
|
+
console.log("[useFileAttachments] prepareForSubmit - readyFiles:", readyFiles.length, "hasSubmitUpload:", !!onSubmitUpload);
|
|
3611
|
+
if (readyFiles.length === 0) return [];
|
|
3612
|
+
if (!onSubmitUpload) {
|
|
3613
|
+
return readyFiles.map((f) => f.uuid);
|
|
3614
|
+
}
|
|
3615
|
+
const aiUuids = [];
|
|
3616
|
+
for (const attachment of readyFiles) {
|
|
3617
|
+
try {
|
|
3618
|
+
let fileToSend = attachment.file;
|
|
3619
|
+
if (attachment.category === "image") {
|
|
3620
|
+
try {
|
|
3621
|
+
fileToSend = await compressImage(attachment.file);
|
|
3622
|
+
} catch {
|
|
3623
|
+
}
|
|
3624
|
+
}
|
|
3625
|
+
console.log("[useFileAttachments] Uploading to AI service:", attachment.file.name, "localUuid:", attachment.uuid.substring(0, 40));
|
|
3626
|
+
const aiUuid = await onSubmitUpload(
|
|
3627
|
+
fileToSend,
|
|
3628
|
+
attachment.uuid,
|
|
3629
|
+
{ filename: fileToSend.name, mimeType: fileToSend.type, size: fileToSend.size }
|
|
3630
|
+
);
|
|
3631
|
+
console.log("[useFileAttachments] AI service returned UUID:", aiUuid);
|
|
3632
|
+
aiUuids.push(aiUuid);
|
|
3633
|
+
} catch (err) {
|
|
3634
|
+
const msg = err instanceof Error ? err.message : "Submit upload failed";
|
|
3635
|
+
console.error("[useFileAttachments] Submit upload failed for:", attachment.file.name, msg);
|
|
3636
|
+
onError?.(msg);
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
console.log("[useFileAttachments] prepareForSubmit result:", aiUuids);
|
|
3640
|
+
return aiUuids;
|
|
3641
|
+
}, [onSubmitUpload, onError]);
|
|
3642
|
+
const clear = useCallback(() => {
|
|
3643
|
+
for (const file of filesRef.current) {
|
|
3644
|
+
if (file.previewUrl) {
|
|
3645
|
+
URL.revokeObjectURL(file.previewUrl);
|
|
3646
|
+
}
|
|
3647
|
+
}
|
|
3648
|
+
setFiles([]);
|
|
3649
|
+
}, []);
|
|
3650
|
+
const isUploading = files.some(
|
|
3651
|
+
(f) => f.status === "uploading" || f.status === "pending" || f.status === "processing"
|
|
3652
|
+
);
|
|
3653
|
+
const hasReadyFiles = files.some((f) => f.status === "ready");
|
|
3654
|
+
const dropZoneProps = {
|
|
3655
|
+
files,
|
|
3656
|
+
onFilesChange,
|
|
3657
|
+
onUpload,
|
|
3658
|
+
onConfirmUpload,
|
|
3659
|
+
onError,
|
|
3660
|
+
maxFiles,
|
|
3661
|
+
maxTotalSizeMB
|
|
3662
|
+
};
|
|
3663
|
+
return {
|
|
3664
|
+
files,
|
|
3665
|
+
dropZoneProps,
|
|
3666
|
+
removeFile,
|
|
3667
|
+
getReadyUuids,
|
|
3668
|
+
getReadyUrls,
|
|
3669
|
+
prepareForSubmit,
|
|
3670
|
+
clear,
|
|
3671
|
+
isUploading,
|
|
3672
|
+
hasReadyFiles,
|
|
3673
|
+
fileCount: files.length
|
|
3674
|
+
};
|
|
3675
|
+
}
|
|
3458
3676
|
function cn(...classes) {
|
|
3459
3677
|
return classes.filter(Boolean).join(" ");
|
|
3460
3678
|
}
|
|
@@ -4104,6 +4322,51 @@ function ChatContainer({
|
|
|
4104
4322
|
function cn3(...classes) {
|
|
4105
4323
|
return classes.filter(Boolean).join(" ");
|
|
4106
4324
|
}
|
|
4325
|
+
function formatFileSize(bytes) {
|
|
4326
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
4327
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
4328
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
4329
|
+
}
|
|
4330
|
+
function AttachmentChip({ attachment, onRemove }) {
|
|
4331
|
+
const isLoading = attachment.status === "uploading" || attachment.status === "pending" || attachment.status === "processing";
|
|
4332
|
+
const isError = attachment.status === "error" || attachment.status === "failed";
|
|
4333
|
+
return /* @__PURE__ */ jsxs(
|
|
4334
|
+
"div",
|
|
4335
|
+
{
|
|
4336
|
+
className: cn3(
|
|
4337
|
+
"inline-flex items-center gap-1.5 px-2 py-1 rounded-md text-xs max-w-[180px]",
|
|
4338
|
+
isError ? "bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-300 border border-red-200 dark:border-red-800" : "bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 border border-gray-200 dark:border-gray-600"
|
|
4339
|
+
),
|
|
4340
|
+
children: [
|
|
4341
|
+
attachment.previewUrl && /* @__PURE__ */ jsx(
|
|
4342
|
+
"img",
|
|
4343
|
+
{
|
|
4344
|
+
src: attachment.previewUrl,
|
|
4345
|
+
alt: "",
|
|
4346
|
+
className: "w-5 h-5 rounded object-cover flex-shrink-0"
|
|
4347
|
+
}
|
|
4348
|
+
),
|
|
4349
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: attachment.file.name }),
|
|
4350
|
+
isLoading ? /* @__PURE__ */ jsx(LoadingSpinner, { className: "h-3 w-3 flex-shrink-0" }) : isError ? /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-red-500", title: attachment.error, children: "!" }) : /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-gray-400 dark:text-gray-500", children: formatFileSize(attachment.actualSize ?? attachment.file.size) }),
|
|
4351
|
+
/* @__PURE__ */ jsx(
|
|
4352
|
+
"button",
|
|
4353
|
+
{
|
|
4354
|
+
type: "button",
|
|
4355
|
+
onClick: (e) => {
|
|
4356
|
+
e.preventDefault();
|
|
4357
|
+
e.stopPropagation();
|
|
4358
|
+
onRemove(attachment.uuid);
|
|
4359
|
+
},
|
|
4360
|
+
className: "flex-shrink-0 p-0.5 rounded hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors",
|
|
4361
|
+
"aria-label": `Remove ${attachment.file.name}`,
|
|
4362
|
+
disabled: isLoading,
|
|
4363
|
+
children: /* @__PURE__ */ jsx(XIcon, { className: "h-3 w-3" })
|
|
4364
|
+
}
|
|
4365
|
+
)
|
|
4366
|
+
]
|
|
4367
|
+
}
|
|
4368
|
+
);
|
|
4369
|
+
}
|
|
4107
4370
|
function ChatInput({
|
|
4108
4371
|
onSend,
|
|
4109
4372
|
onStop,
|
|
@@ -4111,10 +4374,15 @@ function ChatInput({
|
|
|
4111
4374
|
disabled = false,
|
|
4112
4375
|
isLoading = false,
|
|
4113
4376
|
enableAttachments = false,
|
|
4377
|
+
attachments = [],
|
|
4378
|
+
onRemoveAttachment,
|
|
4379
|
+
dropZoneRef,
|
|
4380
|
+
isUploadingAttachments = false,
|
|
4114
4381
|
className
|
|
4115
4382
|
}) {
|
|
4116
4383
|
const [content, setContent] = useState("");
|
|
4117
4384
|
const textareaRef = useRef(null);
|
|
4385
|
+
const hasAttachments = enableAttachments && attachments.length > 0;
|
|
4118
4386
|
useEffect(() => {
|
|
4119
4387
|
const textarea = textareaRef.current;
|
|
4120
4388
|
if (textarea) {
|
|
@@ -4124,10 +4392,10 @@ function ChatInput({
|
|
|
4124
4392
|
}, [content]);
|
|
4125
4393
|
const handleSubmit = useCallback(async () => {
|
|
4126
4394
|
const trimmedContent = content.trim();
|
|
4127
|
-
if (!trimmedContent || disabled || isLoading) return;
|
|
4395
|
+
if (!trimmedContent && !hasAttachments || disabled || isLoading || isUploadingAttachments) return;
|
|
4128
4396
|
setContent("");
|
|
4129
4397
|
await onSend(trimmedContent);
|
|
4130
|
-
}, [content, disabled, isLoading, onSend]);
|
|
4398
|
+
}, [content, hasAttachments, disabled, isLoading, isUploadingAttachments, onSend]);
|
|
4131
4399
|
const handleKeyDown = useCallback(
|
|
4132
4400
|
(e) => {
|
|
4133
4401
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
@@ -4140,7 +4408,10 @@ function ChatInput({
|
|
|
4140
4408
|
const handleStopClick = useCallback(() => {
|
|
4141
4409
|
onStop?.();
|
|
4142
4410
|
}, [onStop]);
|
|
4143
|
-
const
|
|
4411
|
+
const handleAttachClick = useCallback(() => {
|
|
4412
|
+
dropZoneRef?.current?.openFileDialog();
|
|
4413
|
+
}, [dropZoneRef]);
|
|
4414
|
+
const canSend = (content.trim().length > 0 || hasAttachments) && !disabled && !isLoading && !isUploadingAttachments;
|
|
4144
4415
|
const showStopButton = isLoading && onStop;
|
|
4145
4416
|
return /* @__PURE__ */ jsxs(
|
|
4146
4417
|
"div",
|
|
@@ -4150,7 +4421,34 @@ function ChatInput({
|
|
|
4150
4421
|
className
|
|
4151
4422
|
),
|
|
4152
4423
|
children: [
|
|
4424
|
+
hasAttachments && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5 mb-2", children: attachments.map((attachment) => /* @__PURE__ */ jsx(
|
|
4425
|
+
AttachmentChip,
|
|
4426
|
+
{
|
|
4427
|
+
attachment,
|
|
4428
|
+
onRemove: onRemoveAttachment ?? (() => {
|
|
4429
|
+
})
|
|
4430
|
+
},
|
|
4431
|
+
attachment.uuid
|
|
4432
|
+
)) }),
|
|
4153
4433
|
/* @__PURE__ */ jsxs("div", { className: "flex items-end gap-2", children: [
|
|
4434
|
+
enableAttachments && /* @__PURE__ */ jsx(
|
|
4435
|
+
"button",
|
|
4436
|
+
{
|
|
4437
|
+
type: "button",
|
|
4438
|
+
onClick: handleAttachClick,
|
|
4439
|
+
disabled: disabled || isLoading,
|
|
4440
|
+
className: cn3(
|
|
4441
|
+
"flex-shrink-0 p-3 rounded-lg transition-colors",
|
|
4442
|
+
"text-gray-500 dark:text-gray-400",
|
|
4443
|
+
"hover:bg-gray-100 dark:hover:bg-gray-700",
|
|
4444
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
4445
|
+
"focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
|
|
4446
|
+
),
|
|
4447
|
+
"aria-label": "Attach files",
|
|
4448
|
+
title: "Attach files",
|
|
4449
|
+
children: /* @__PURE__ */ jsx(PaperclipIcon, { className: "h-5 w-5" })
|
|
4450
|
+
}
|
|
4451
|
+
),
|
|
4154
4452
|
/* @__PURE__ */ jsx("div", { className: "flex-1 relative", children: /* @__PURE__ */ jsx(
|
|
4155
4453
|
"textarea",
|
|
4156
4454
|
{
|
|
@@ -4158,7 +4456,7 @@ function ChatInput({
|
|
|
4158
4456
|
value: content,
|
|
4159
4457
|
onChange: (e) => setContent(e.target.value),
|
|
4160
4458
|
onKeyDown: handleKeyDown,
|
|
4161
|
-
placeholder,
|
|
4459
|
+
placeholder: hasAttachments && !content ? `${attachments.length} file${attachments.length > 1 ? "s" : ""} attached. Add a message or press Enter to send.` : placeholder,
|
|
4162
4460
|
disabled,
|
|
4163
4461
|
rows: 1,
|
|
4164
4462
|
className: cn3(
|
|
@@ -4208,9 +4506,664 @@ function ChatInput({
|
|
|
4208
4506
|
}
|
|
4209
4507
|
);
|
|
4210
4508
|
}
|
|
4509
|
+
function Upload({ className }) {
|
|
4510
|
+
return /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
4511
|
+
/* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
|
|
4512
|
+
/* @__PURE__ */ jsx("polyline", { points: "17 8 12 3 7 8" }),
|
|
4513
|
+
/* @__PURE__ */ jsx("line", { x1: "12", x2: "12", y1: "3", y2: "15" })
|
|
4514
|
+
] });
|
|
4515
|
+
}
|
|
4516
|
+
function X({ className }) {
|
|
4517
|
+
return /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
4518
|
+
/* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
|
|
4519
|
+
/* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
|
|
4520
|
+
] });
|
|
4521
|
+
}
|
|
4522
|
+
function FileText({ className }) {
|
|
4523
|
+
return /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
4524
|
+
/* @__PURE__ */ jsx("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
|
|
4525
|
+
/* @__PURE__ */ jsx("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" }),
|
|
4526
|
+
/* @__PURE__ */ jsx("line", { x1: "16", x2: "8", y1: "13", y2: "13" }),
|
|
4527
|
+
/* @__PURE__ */ jsx("line", { x1: "16", x2: "8", y1: "17", y2: "17" }),
|
|
4528
|
+
/* @__PURE__ */ jsx("line", { x1: "10", x2: "8", y1: "9", y2: "9" })
|
|
4529
|
+
] });
|
|
4530
|
+
}
|
|
4531
|
+
function ImageIcon2({ className }) {
|
|
4532
|
+
return /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
4533
|
+
/* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
|
|
4534
|
+
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "2" }),
|
|
4535
|
+
/* @__PURE__ */ jsx("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
|
|
4536
|
+
] });
|
|
4537
|
+
}
|
|
4538
|
+
function Music({ className }) {
|
|
4539
|
+
return /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
4540
|
+
/* @__PURE__ */ jsx("path", { d: "M9 18V5l12-2v13" }),
|
|
4541
|
+
/* @__PURE__ */ jsx("circle", { cx: "6", cy: "18", r: "3" }),
|
|
4542
|
+
/* @__PURE__ */ jsx("circle", { cx: "18", cy: "16", r: "3" })
|
|
4543
|
+
] });
|
|
4544
|
+
}
|
|
4545
|
+
function Loader2({ className }) {
|
|
4546
|
+
return /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
|
|
4547
|
+
}
|
|
4548
|
+
function FileIcon2({ className }) {
|
|
4549
|
+
return /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
4550
|
+
/* @__PURE__ */ jsx("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
|
|
4551
|
+
/* @__PURE__ */ jsx("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
|
|
4552
|
+
] });
|
|
4553
|
+
}
|
|
4554
|
+
function RotateCw({ className }) {
|
|
4555
|
+
return /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
4556
|
+
/* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8" }),
|
|
4557
|
+
/* @__PURE__ */ jsx("path", { d: "M21 3v5h-5" })
|
|
4558
|
+
] });
|
|
4559
|
+
}
|
|
4211
4560
|
function cn4(...classes) {
|
|
4212
4561
|
return classes.filter(Boolean).join(" ");
|
|
4213
4562
|
}
|
|
4563
|
+
var SUPPORTED_TYPES = {
|
|
4564
|
+
document: {
|
|
4565
|
+
mimeTypes: [
|
|
4566
|
+
"application/pdf",
|
|
4567
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
4568
|
+
"application/msword",
|
|
4569
|
+
"text/plain",
|
|
4570
|
+
"text/markdown",
|
|
4571
|
+
"text/csv",
|
|
4572
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
4573
|
+
"application/vnd.ms-excel"
|
|
4574
|
+
],
|
|
4575
|
+
extensions: [
|
|
4576
|
+
".pdf",
|
|
4577
|
+
".docx",
|
|
4578
|
+
".doc",
|
|
4579
|
+
".txt",
|
|
4580
|
+
".md",
|
|
4581
|
+
".csv",
|
|
4582
|
+
".xlsx",
|
|
4583
|
+
".xls"
|
|
4584
|
+
],
|
|
4585
|
+
maxSizeMB: 25,
|
|
4586
|
+
label: "Documents"
|
|
4587
|
+
},
|
|
4588
|
+
image: {
|
|
4589
|
+
mimeTypes: [
|
|
4590
|
+
"image/png",
|
|
4591
|
+
"image/jpeg",
|
|
4592
|
+
"image/gif",
|
|
4593
|
+
"image/webp",
|
|
4594
|
+
"image/svg+xml"
|
|
4595
|
+
],
|
|
4596
|
+
extensions: [".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg"],
|
|
4597
|
+
maxSizeMB: 10,
|
|
4598
|
+
label: "Images"
|
|
4599
|
+
},
|
|
4600
|
+
audio: {
|
|
4601
|
+
mimeTypes: [
|
|
4602
|
+
"audio/mpeg",
|
|
4603
|
+
"audio/wav",
|
|
4604
|
+
"audio/mp4",
|
|
4605
|
+
"audio/ogg",
|
|
4606
|
+
"audio/webm"
|
|
4607
|
+
],
|
|
4608
|
+
extensions: [".mp3", ".wav", ".m4a", ".ogg", ".webm"],
|
|
4609
|
+
maxSizeMB: 50,
|
|
4610
|
+
label: "Audio"
|
|
4611
|
+
}
|
|
4612
|
+
};
|
|
4613
|
+
var MAX_FILES_PER_DROP = 10;
|
|
4614
|
+
var MAX_TOTAL_SIZE_MB = 100;
|
|
4615
|
+
function categorizeFile(mimeType) {
|
|
4616
|
+
for (const [category, config] of Object.entries(SUPPORTED_TYPES)) {
|
|
4617
|
+
if (config.mimeTypes.includes(mimeType)) {
|
|
4618
|
+
return category;
|
|
4619
|
+
}
|
|
4620
|
+
}
|
|
4621
|
+
return null;
|
|
4622
|
+
}
|
|
4623
|
+
function validateFile(file) {
|
|
4624
|
+
const category = categorizeFile(file.type);
|
|
4625
|
+
if (!category) {
|
|
4626
|
+
return {
|
|
4627
|
+
valid: false,
|
|
4628
|
+
error: `Unsupported file type: ${file.type || file.name.split(".").pop()}`
|
|
4629
|
+
};
|
|
4630
|
+
}
|
|
4631
|
+
const config = SUPPORTED_TYPES[category];
|
|
4632
|
+
const maxSizeBytes = config.maxSizeMB * 1024 * 1024;
|
|
4633
|
+
if (file.size > maxSizeBytes) {
|
|
4634
|
+
return {
|
|
4635
|
+
valid: false,
|
|
4636
|
+
error: `${file.name} exceeds ${config.maxSizeMB}MB limit for ${config.label.toLowerCase()}`
|
|
4637
|
+
};
|
|
4638
|
+
}
|
|
4639
|
+
return { valid: true, category };
|
|
4640
|
+
}
|
|
4641
|
+
function formatFileSize2(bytes) {
|
|
4642
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
4643
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
4644
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
4645
|
+
}
|
|
4646
|
+
function getCategoryIcon(category) {
|
|
4647
|
+
switch (category) {
|
|
4648
|
+
case "document":
|
|
4649
|
+
return FileText;
|
|
4650
|
+
case "image":
|
|
4651
|
+
return ImageIcon2;
|
|
4652
|
+
case "audio":
|
|
4653
|
+
return Music;
|
|
4654
|
+
default:
|
|
4655
|
+
return FileIcon2;
|
|
4656
|
+
}
|
|
4657
|
+
}
|
|
4658
|
+
var FileDropZone = forwardRef(
|
|
4659
|
+
function FileDropZone2({
|
|
4660
|
+
onFilesChange,
|
|
4661
|
+
files,
|
|
4662
|
+
onUpload,
|
|
4663
|
+
onConfirmUpload,
|
|
4664
|
+
onError,
|
|
4665
|
+
maxFiles = MAX_FILES_PER_DROP,
|
|
4666
|
+
maxTotalSizeMB = MAX_TOTAL_SIZE_MB,
|
|
4667
|
+
disabled = false,
|
|
4668
|
+
className,
|
|
4669
|
+
accept,
|
|
4670
|
+
compact = false,
|
|
4671
|
+
children
|
|
4672
|
+
}, ref) {
|
|
4673
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
4674
|
+
const fileInputRef = useRef(null);
|
|
4675
|
+
const dropZoneRef = useRef(null);
|
|
4676
|
+
const dragCounter = useRef(0);
|
|
4677
|
+
useImperativeHandle(
|
|
4678
|
+
ref,
|
|
4679
|
+
() => ({
|
|
4680
|
+
openFileDialog: () => {
|
|
4681
|
+
if (!disabled) {
|
|
4682
|
+
fileInputRef.current?.click();
|
|
4683
|
+
}
|
|
4684
|
+
}
|
|
4685
|
+
}),
|
|
4686
|
+
[disabled]
|
|
4687
|
+
);
|
|
4688
|
+
const currentTotalSize = files.reduce((sum, f) => sum + f.file.size, 0);
|
|
4689
|
+
const uploadFile = useCallback(
|
|
4690
|
+
async (file, _tempId) => {
|
|
4691
|
+
const result = await onUpload(file, {
|
|
4692
|
+
filename: file.name,
|
|
4693
|
+
mimeType: file.type,
|
|
4694
|
+
size: file.size
|
|
4695
|
+
});
|
|
4696
|
+
if (result.uploadUrl) {
|
|
4697
|
+
const uploadResponse = await fetch(result.uploadUrl, {
|
|
4698
|
+
method: "PUT",
|
|
4699
|
+
body: file,
|
|
4700
|
+
headers: { "Content-Type": file.type }
|
|
4701
|
+
});
|
|
4702
|
+
if (!uploadResponse.ok) {
|
|
4703
|
+
throw new Error(`Upload failed: ${uploadResponse.statusText}`);
|
|
4704
|
+
}
|
|
4705
|
+
}
|
|
4706
|
+
if (onConfirmUpload) {
|
|
4707
|
+
await onConfirmUpload(result.uuid);
|
|
4708
|
+
}
|
|
4709
|
+
return result.uuid;
|
|
4710
|
+
},
|
|
4711
|
+
[onUpload, onConfirmUpload]
|
|
4712
|
+
);
|
|
4713
|
+
const handleFiles = useCallback(
|
|
4714
|
+
async (selectedFiles) => {
|
|
4715
|
+
if (disabled) return;
|
|
4716
|
+
if (files.length + selectedFiles.length > maxFiles) {
|
|
4717
|
+
onError?.(`Maximum ${maxFiles} files allowed`);
|
|
4718
|
+
return;
|
|
4719
|
+
}
|
|
4720
|
+
const validFiles = [];
|
|
4721
|
+
let newTotalSize = currentTotalSize;
|
|
4722
|
+
for (const file of selectedFiles) {
|
|
4723
|
+
const validation = validateFile(file);
|
|
4724
|
+
if (!validation.valid) {
|
|
4725
|
+
onError?.(validation.error);
|
|
4726
|
+
continue;
|
|
4727
|
+
}
|
|
4728
|
+
newTotalSize += file.size;
|
|
4729
|
+
if (newTotalSize > maxTotalSizeMB * 1024 * 1024) {
|
|
4730
|
+
onError?.(`Total upload size exceeds ${maxTotalSizeMB}MB`);
|
|
4731
|
+
break;
|
|
4732
|
+
}
|
|
4733
|
+
validFiles.push({ file, category: validation.category });
|
|
4734
|
+
}
|
|
4735
|
+
if (validFiles.length === 0) return;
|
|
4736
|
+
const processedFiles = [];
|
|
4737
|
+
for (const entry of validFiles) {
|
|
4738
|
+
if (entry.category === "image") {
|
|
4739
|
+
try {
|
|
4740
|
+
const compressed = await compressImage(entry.file);
|
|
4741
|
+
processedFiles.push({ file: compressed, category: entry.category });
|
|
4742
|
+
} catch (err) {
|
|
4743
|
+
console.warn("Image compression failed, using original:", err);
|
|
4744
|
+
processedFiles.push(entry);
|
|
4745
|
+
}
|
|
4746
|
+
} else {
|
|
4747
|
+
processedFiles.push(entry);
|
|
4748
|
+
}
|
|
4749
|
+
}
|
|
4750
|
+
const newAttachments = processedFiles.map(
|
|
4751
|
+
({ file, category }) => {
|
|
4752
|
+
const tempId = `temp-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
4753
|
+
return {
|
|
4754
|
+
uuid: tempId,
|
|
4755
|
+
file,
|
|
4756
|
+
status: "pending",
|
|
4757
|
+
progress: 0,
|
|
4758
|
+
category,
|
|
4759
|
+
previewUrl: category === "image" ? URL.createObjectURL(file) : void 0
|
|
4760
|
+
};
|
|
4761
|
+
}
|
|
4762
|
+
);
|
|
4763
|
+
let currentFiles = [...files, ...newAttachments];
|
|
4764
|
+
onFilesChange(currentFiles);
|
|
4765
|
+
for (const attachment of newAttachments) {
|
|
4766
|
+
try {
|
|
4767
|
+
currentFiles = currentFiles.map(
|
|
4768
|
+
(f) => f.uuid === attachment.uuid ? { ...f, status: "uploading", progress: 10 } : f
|
|
4769
|
+
);
|
|
4770
|
+
onFilesChange(currentFiles);
|
|
4771
|
+
const realUuid = await uploadFile(attachment.file, attachment.uuid);
|
|
4772
|
+
currentFiles = currentFiles.map(
|
|
4773
|
+
(f) => f.uuid === attachment.uuid ? {
|
|
4774
|
+
...f,
|
|
4775
|
+
uuid: realUuid,
|
|
4776
|
+
status: "ready",
|
|
4777
|
+
progress: 100,
|
|
4778
|
+
hasThumbnail: f.category === "image"
|
|
4779
|
+
} : f
|
|
4780
|
+
);
|
|
4781
|
+
onFilesChange(currentFiles);
|
|
4782
|
+
} catch (error) {
|
|
4783
|
+
console.error("Upload error:", error);
|
|
4784
|
+
currentFiles = currentFiles.map(
|
|
4785
|
+
(f) => f.uuid === attachment.uuid ? {
|
|
4786
|
+
...f,
|
|
4787
|
+
status: "error",
|
|
4788
|
+
error: error instanceof Error ? error.message : "Upload failed"
|
|
4789
|
+
} : f
|
|
4790
|
+
);
|
|
4791
|
+
onFilesChange(currentFiles);
|
|
4792
|
+
onError?.(`Failed to upload ${attachment.file.name}`);
|
|
4793
|
+
}
|
|
4794
|
+
}
|
|
4795
|
+
},
|
|
4796
|
+
[
|
|
4797
|
+
disabled,
|
|
4798
|
+
files,
|
|
4799
|
+
maxFiles,
|
|
4800
|
+
currentTotalSize,
|
|
4801
|
+
maxTotalSizeMB,
|
|
4802
|
+
onFilesChange,
|
|
4803
|
+
uploadFile,
|
|
4804
|
+
onError
|
|
4805
|
+
]
|
|
4806
|
+
);
|
|
4807
|
+
const handleRemove = useCallback(
|
|
4808
|
+
(uuid) => {
|
|
4809
|
+
const file = files.find((f) => f.uuid === uuid);
|
|
4810
|
+
if (file?.previewUrl) {
|
|
4811
|
+
URL.revokeObjectURL(file.previewUrl);
|
|
4812
|
+
}
|
|
4813
|
+
onFilesChange(files.filter((f) => f.uuid !== uuid));
|
|
4814
|
+
},
|
|
4815
|
+
[files, onFilesChange]
|
|
4816
|
+
);
|
|
4817
|
+
const handleRetry = useCallback(
|
|
4818
|
+
async (uuid) => {
|
|
4819
|
+
const attachment = files.find((f) => f.uuid === uuid);
|
|
4820
|
+
if (!attachment || attachment.status !== "error") return;
|
|
4821
|
+
let currentFiles = files.map(
|
|
4822
|
+
(f) => f.uuid === uuid ? { ...f, status: "pending", progress: 0, error: void 0 } : f
|
|
4823
|
+
);
|
|
4824
|
+
onFilesChange(currentFiles);
|
|
4825
|
+
try {
|
|
4826
|
+
currentFiles = currentFiles.map(
|
|
4827
|
+
(f) => f.uuid === uuid ? { ...f, status: "uploading", progress: 10 } : f
|
|
4828
|
+
);
|
|
4829
|
+
onFilesChange(currentFiles);
|
|
4830
|
+
const realUuid = await uploadFile(attachment.file, uuid);
|
|
4831
|
+
currentFiles = currentFiles.map(
|
|
4832
|
+
(f) => f.uuid === uuid ? {
|
|
4833
|
+
...f,
|
|
4834
|
+
uuid: realUuid,
|
|
4835
|
+
status: "ready",
|
|
4836
|
+
progress: 100,
|
|
4837
|
+
hasThumbnail: f.category === "image"
|
|
4838
|
+
} : f
|
|
4839
|
+
);
|
|
4840
|
+
onFilesChange(currentFiles);
|
|
4841
|
+
} catch (error) {
|
|
4842
|
+
console.error("Retry upload error:", error);
|
|
4843
|
+
currentFiles = currentFiles.map(
|
|
4844
|
+
(f) => f.uuid === uuid ? {
|
|
4845
|
+
...f,
|
|
4846
|
+
status: "error",
|
|
4847
|
+
error: error instanceof Error ? error.message : "Upload failed"
|
|
4848
|
+
} : f
|
|
4849
|
+
);
|
|
4850
|
+
onFilesChange(currentFiles);
|
|
4851
|
+
onError?.(`Failed to upload ${attachment.file.name}`);
|
|
4852
|
+
}
|
|
4853
|
+
},
|
|
4854
|
+
[files, onFilesChange, uploadFile, onError]
|
|
4855
|
+
);
|
|
4856
|
+
const hasDraggedFiles = useCallback((e) => {
|
|
4857
|
+
if (e.dataTransfer.types) {
|
|
4858
|
+
for (const type of e.dataTransfer.types) {
|
|
4859
|
+
if (type === "Files") return true;
|
|
4860
|
+
}
|
|
4861
|
+
}
|
|
4862
|
+
return false;
|
|
4863
|
+
}, []);
|
|
4864
|
+
const handleDragEnter = useCallback(
|
|
4865
|
+
(e) => {
|
|
4866
|
+
e.preventDefault();
|
|
4867
|
+
e.stopPropagation();
|
|
4868
|
+
if (!hasDraggedFiles(e)) return;
|
|
4869
|
+
dragCounter.current++;
|
|
4870
|
+
if (!disabled && dragCounter.current === 1) {
|
|
4871
|
+
setIsDragging(true);
|
|
4872
|
+
}
|
|
4873
|
+
},
|
|
4874
|
+
[disabled, hasDraggedFiles]
|
|
4875
|
+
);
|
|
4876
|
+
const handleDragOver = useCallback(
|
|
4877
|
+
(e) => {
|
|
4878
|
+
e.preventDefault();
|
|
4879
|
+
e.stopPropagation();
|
|
4880
|
+
if (hasDraggedFiles(e)) {
|
|
4881
|
+
e.dataTransfer.dropEffect = disabled ? "none" : "copy";
|
|
4882
|
+
}
|
|
4883
|
+
},
|
|
4884
|
+
[disabled, hasDraggedFiles]
|
|
4885
|
+
);
|
|
4886
|
+
const handleDragLeave = useCallback((e) => {
|
|
4887
|
+
e.preventDefault();
|
|
4888
|
+
e.stopPropagation();
|
|
4889
|
+
if (dragCounter.current > 0) {
|
|
4890
|
+
dragCounter.current--;
|
|
4891
|
+
if (dragCounter.current === 0) {
|
|
4892
|
+
setIsDragging(false);
|
|
4893
|
+
}
|
|
4894
|
+
}
|
|
4895
|
+
}, []);
|
|
4896
|
+
const handleDrop = useCallback(
|
|
4897
|
+
(e) => {
|
|
4898
|
+
e.preventDefault();
|
|
4899
|
+
e.stopPropagation();
|
|
4900
|
+
dragCounter.current = 0;
|
|
4901
|
+
setIsDragging(false);
|
|
4902
|
+
if (disabled) return;
|
|
4903
|
+
const droppedFiles = Array.from(e.dataTransfer.files);
|
|
4904
|
+
if (droppedFiles.length > 0) {
|
|
4905
|
+
handleFiles(droppedFiles);
|
|
4906
|
+
}
|
|
4907
|
+
},
|
|
4908
|
+
[handleFiles, disabled]
|
|
4909
|
+
);
|
|
4910
|
+
const handleFileSelect = useCallback(
|
|
4911
|
+
(e) => {
|
|
4912
|
+
const selectedFiles = e.target.files;
|
|
4913
|
+
if (selectedFiles) {
|
|
4914
|
+
handleFiles(Array.from(selectedFiles));
|
|
4915
|
+
}
|
|
4916
|
+
if (fileInputRef.current) {
|
|
4917
|
+
fileInputRef.current.value = "";
|
|
4918
|
+
}
|
|
4919
|
+
},
|
|
4920
|
+
[handleFiles]
|
|
4921
|
+
);
|
|
4922
|
+
const handleClick = useCallback(() => {
|
|
4923
|
+
if (!disabled) {
|
|
4924
|
+
fileInputRef.current?.click();
|
|
4925
|
+
}
|
|
4926
|
+
}, [disabled]);
|
|
4927
|
+
const checkDataTransferHasFiles = useCallback(
|
|
4928
|
+
(dataTransfer) => {
|
|
4929
|
+
if (!dataTransfer?.types) return false;
|
|
4930
|
+
for (let i = 0; i < dataTransfer.types.length; i++) {
|
|
4931
|
+
if (dataTransfer.types[i] === "Files") return true;
|
|
4932
|
+
}
|
|
4933
|
+
return false;
|
|
4934
|
+
},
|
|
4935
|
+
[]
|
|
4936
|
+
);
|
|
4937
|
+
useEffect(() => {
|
|
4938
|
+
if (!children || !dropZoneRef.current) return;
|
|
4939
|
+
const element = dropZoneRef.current;
|
|
4940
|
+
let enterCounter = 0;
|
|
4941
|
+
const handleDragEnterNative = (e) => {
|
|
4942
|
+
e.preventDefault();
|
|
4943
|
+
e.stopPropagation();
|
|
4944
|
+
if (!checkDataTransferHasFiles(e.dataTransfer)) return;
|
|
4945
|
+
enterCounter++;
|
|
4946
|
+
if (enterCounter === 1 && !disabled) {
|
|
4947
|
+
setIsDragging(true);
|
|
4948
|
+
}
|
|
4949
|
+
};
|
|
4950
|
+
const handleDragLeaveNative = (e) => {
|
|
4951
|
+
e.preventDefault();
|
|
4952
|
+
e.stopPropagation();
|
|
4953
|
+
if (!checkDataTransferHasFiles(e.dataTransfer)) return;
|
|
4954
|
+
enterCounter--;
|
|
4955
|
+
if (enterCounter <= 0) {
|
|
4956
|
+
enterCounter = 0;
|
|
4957
|
+
setIsDragging(false);
|
|
4958
|
+
}
|
|
4959
|
+
};
|
|
4960
|
+
const handleDragOverNative = (e) => {
|
|
4961
|
+
e.preventDefault();
|
|
4962
|
+
e.stopPropagation();
|
|
4963
|
+
if (checkDataTransferHasFiles(e.dataTransfer) && !disabled && e.dataTransfer) {
|
|
4964
|
+
e.dataTransfer.dropEffect = "copy";
|
|
4965
|
+
}
|
|
4966
|
+
};
|
|
4967
|
+
const handleDropNative = (e) => {
|
|
4968
|
+
e.preventDefault();
|
|
4969
|
+
e.stopPropagation();
|
|
4970
|
+
enterCounter = 0;
|
|
4971
|
+
setIsDragging(false);
|
|
4972
|
+
if (disabled) return;
|
|
4973
|
+
const droppedFiles = e.dataTransfer?.files;
|
|
4974
|
+
if (droppedFiles && droppedFiles.length > 0) {
|
|
4975
|
+
handleFiles(Array.from(droppedFiles));
|
|
4976
|
+
}
|
|
4977
|
+
};
|
|
4978
|
+
element.addEventListener("dragenter", handleDragEnterNative, true);
|
|
4979
|
+
element.addEventListener("dragleave", handleDragLeaveNative, true);
|
|
4980
|
+
element.addEventListener("dragover", handleDragOverNative, true);
|
|
4981
|
+
element.addEventListener("drop", handleDropNative, true);
|
|
4982
|
+
return () => {
|
|
4983
|
+
element.removeEventListener("dragenter", handleDragEnterNative, true);
|
|
4984
|
+
element.removeEventListener("dragleave", handleDragLeaveNative, true);
|
|
4985
|
+
element.removeEventListener("dragover", handleDragOverNative, true);
|
|
4986
|
+
element.removeEventListener("drop", handleDropNative, true);
|
|
4987
|
+
};
|
|
4988
|
+
}, [children, disabled, handleFiles, checkDataTransferHasFiles]);
|
|
4989
|
+
useEffect(() => {
|
|
4990
|
+
if (disabled) {
|
|
4991
|
+
dragCounter.current = 0;
|
|
4992
|
+
setIsDragging(false);
|
|
4993
|
+
}
|
|
4994
|
+
}, [disabled]);
|
|
4995
|
+
const acceptTypes = accept || Object.values(SUPPORTED_TYPES).flatMap((t) => [...t.mimeTypes, ...t.extensions]).join(",");
|
|
4996
|
+
const hasFiles = files.length > 0;
|
|
4997
|
+
const isUploading = files.some((f) => f.status === "uploading");
|
|
4998
|
+
if (children) {
|
|
4999
|
+
return /* @__PURE__ */ jsxs(
|
|
5000
|
+
"div",
|
|
5001
|
+
{
|
|
5002
|
+
ref: dropZoneRef,
|
|
5003
|
+
"data-dropzone": "wrapper",
|
|
5004
|
+
className: cn4("relative w-full h-full", className),
|
|
5005
|
+
style: { minHeight: "inherit" },
|
|
5006
|
+
children: [
|
|
5007
|
+
/* @__PURE__ */ jsx(
|
|
5008
|
+
"input",
|
|
5009
|
+
{
|
|
5010
|
+
ref: fileInputRef,
|
|
5011
|
+
type: "file",
|
|
5012
|
+
multiple: true,
|
|
5013
|
+
accept: acceptTypes,
|
|
5014
|
+
onChange: handleFileSelect,
|
|
5015
|
+
className: "hidden",
|
|
5016
|
+
disabled
|
|
5017
|
+
}
|
|
5018
|
+
),
|
|
5019
|
+
children,
|
|
5020
|
+
isDragging && !disabled && /* @__PURE__ */ jsx(
|
|
5021
|
+
"div",
|
|
5022
|
+
{
|
|
5023
|
+
className: "absolute inset-0 z-50 bg-primary/10 border-2 border-dashed border-primary rounded-xl flex flex-col items-center justify-center backdrop-blur-sm transition-opacity duration-200",
|
|
5024
|
+
style: { pointerEvents: "none" },
|
|
5025
|
+
children: /* @__PURE__ */ jsxs("div", { className: "bg-background/80 rounded-xl p-8 flex flex-col items-center shadow-lg", children: [
|
|
5026
|
+
/* @__PURE__ */ jsx(Upload, { className: "h-12 w-12 text-primary mb-4 animate-bounce" }),
|
|
5027
|
+
/* @__PURE__ */ jsx("p", { className: "text-lg font-medium text-primary", children: "Drop files here" }),
|
|
5028
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-2", children: "Documents, images, or audio files" })
|
|
5029
|
+
] })
|
|
5030
|
+
}
|
|
5031
|
+
)
|
|
5032
|
+
]
|
|
5033
|
+
}
|
|
5034
|
+
);
|
|
5035
|
+
}
|
|
5036
|
+
return /* @__PURE__ */ jsxs("div", { className: cn4("w-full", className), children: [
|
|
5037
|
+
/* @__PURE__ */ jsx(
|
|
5038
|
+
"input",
|
|
5039
|
+
{
|
|
5040
|
+
ref: fileInputRef,
|
|
5041
|
+
type: "file",
|
|
5042
|
+
multiple: true,
|
|
5043
|
+
accept: acceptTypes,
|
|
5044
|
+
onChange: handleFileSelect,
|
|
5045
|
+
className: "hidden",
|
|
5046
|
+
disabled
|
|
5047
|
+
}
|
|
5048
|
+
),
|
|
5049
|
+
/* @__PURE__ */ jsxs(
|
|
5050
|
+
"div",
|
|
5051
|
+
{
|
|
5052
|
+
onDragEnter: handleDragEnter,
|
|
5053
|
+
onDragOver: handleDragOver,
|
|
5054
|
+
onDragLeave: handleDragLeave,
|
|
5055
|
+
onDrop: handleDrop,
|
|
5056
|
+
onClick: handleClick,
|
|
5057
|
+
className: cn4(
|
|
5058
|
+
"relative rounded-lg border-2 border-dashed transition-all cursor-pointer",
|
|
5059
|
+
"flex flex-col items-center justify-center",
|
|
5060
|
+
compact ? "p-2 min-h-[60px]" : "p-4 min-h-[100px]",
|
|
5061
|
+
isDragging && !disabled ? "border-primary bg-primary/5" : "border-muted-foreground/25",
|
|
5062
|
+
disabled ? "opacity-50 cursor-not-allowed" : "hover:border-primary/50 hover:bg-muted/25"
|
|
5063
|
+
),
|
|
5064
|
+
children: [
|
|
5065
|
+
isUploading ? /* @__PURE__ */ jsx(
|
|
5066
|
+
Loader2,
|
|
5067
|
+
{
|
|
5068
|
+
className: cn4(
|
|
5069
|
+
"animate-spin text-muted-foreground",
|
|
5070
|
+
compact ? "h-5 w-5 mb-1" : "h-8 w-8 mb-2"
|
|
5071
|
+
)
|
|
5072
|
+
}
|
|
5073
|
+
) : /* @__PURE__ */ jsx(
|
|
5074
|
+
Upload,
|
|
5075
|
+
{
|
|
5076
|
+
className: cn4(
|
|
5077
|
+
"text-muted-foreground",
|
|
5078
|
+
compact ? "h-5 w-5 mb-1" : "h-8 w-8 mb-2"
|
|
5079
|
+
)
|
|
5080
|
+
}
|
|
5081
|
+
),
|
|
5082
|
+
/* @__PURE__ */ jsx(
|
|
5083
|
+
"p",
|
|
5084
|
+
{
|
|
5085
|
+
className: cn4(
|
|
5086
|
+
"font-medium text-center text-muted-foreground",
|
|
5087
|
+
compact ? "text-xs" : "text-sm"
|
|
5088
|
+
),
|
|
5089
|
+
children: isDragging ? "Drop files here" : isUploading ? "Uploading..." : "Click to upload or drag and drop"
|
|
5090
|
+
}
|
|
5091
|
+
),
|
|
5092
|
+
!compact && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground/70 text-center mt-1", children: "Documents, images, or audio files" })
|
|
5093
|
+
]
|
|
5094
|
+
}
|
|
5095
|
+
),
|
|
5096
|
+
hasFiles && /* @__PURE__ */ jsx("div", { className: cn4("space-y-2", compact ? "mt-2" : "mt-3"), children: files.map((attachment) => {
|
|
5097
|
+
const Icon = getCategoryIcon(attachment.category);
|
|
5098
|
+
const isError = attachment.status === "error";
|
|
5099
|
+
const isLoading = attachment.status === "uploading" || attachment.status === "processing";
|
|
5100
|
+
return /* @__PURE__ */ jsxs(
|
|
5101
|
+
"div",
|
|
5102
|
+
{
|
|
5103
|
+
className: cn4(
|
|
5104
|
+
"flex items-center gap-3 p-2 rounded-lg border",
|
|
5105
|
+
isError ? "border-destructive/50 bg-destructive/5" : "border-border bg-muted/25"
|
|
5106
|
+
),
|
|
5107
|
+
children: [
|
|
5108
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex-shrink-0 w-10 h-10 rounded overflow-hidden bg-muted flex items-center justify-center", children: [
|
|
5109
|
+
attachment.previewUrl ? /* @__PURE__ */ jsx(
|
|
5110
|
+
"img",
|
|
5111
|
+
{
|
|
5112
|
+
src: attachment.previewUrl,
|
|
5113
|
+
alt: attachment.file.name,
|
|
5114
|
+
className: "w-full h-full object-cover"
|
|
5115
|
+
}
|
|
5116
|
+
) : /* @__PURE__ */ jsx(Icon, { className: "h-5 w-5 text-muted-foreground" }),
|
|
5117
|
+
isLoading && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-background/80 flex items-center justify-center", children: /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }) })
|
|
5118
|
+
] }),
|
|
5119
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
5120
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium truncate", children: attachment.file.name }),
|
|
5121
|
+
/* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
5122
|
+
formatFileSize2(attachment.file.size),
|
|
5123
|
+
isError && attachment.error && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-2", children: attachment.error })
|
|
5124
|
+
] })
|
|
5125
|
+
] }),
|
|
5126
|
+
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: isLoading ? /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
5127
|
+
attachment.progress,
|
|
5128
|
+
"%"
|
|
5129
|
+
] }) : attachment.status === "ready" ? /* @__PURE__ */ jsx("span", { className: "text-xs text-green-600", children: "Ready" }) : null }),
|
|
5130
|
+
isError && /* @__PURE__ */ jsx(
|
|
5131
|
+
"button",
|
|
5132
|
+
{
|
|
5133
|
+
type: "button",
|
|
5134
|
+
className: "flex-shrink-0 h-8 w-8 inline-flex items-center justify-center rounded-md text-primary hover:bg-muted transition-colors",
|
|
5135
|
+
onClick: (e) => {
|
|
5136
|
+
e.stopPropagation();
|
|
5137
|
+
handleRetry(attachment.uuid);
|
|
5138
|
+
},
|
|
5139
|
+
title: "Retry upload",
|
|
5140
|
+
children: /* @__PURE__ */ jsx(RotateCw, { className: "h-4 w-4" })
|
|
5141
|
+
}
|
|
5142
|
+
),
|
|
5143
|
+
/* @__PURE__ */ jsx(
|
|
5144
|
+
"button",
|
|
5145
|
+
{
|
|
5146
|
+
type: "button",
|
|
5147
|
+
className: "flex-shrink-0 h-8 w-8 inline-flex items-center justify-center rounded-md hover:bg-muted transition-colors disabled:opacity-50",
|
|
5148
|
+
onClick: (e) => {
|
|
5149
|
+
e.stopPropagation();
|
|
5150
|
+
handleRemove(attachment.uuid);
|
|
5151
|
+
},
|
|
5152
|
+
disabled: isLoading,
|
|
5153
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
5154
|
+
}
|
|
5155
|
+
)
|
|
5156
|
+
]
|
|
5157
|
+
},
|
|
5158
|
+
attachment.uuid
|
|
5159
|
+
);
|
|
5160
|
+
}) })
|
|
5161
|
+
] });
|
|
5162
|
+
}
|
|
5163
|
+
);
|
|
5164
|
+
function cn5(...classes) {
|
|
5165
|
+
return classes.filter(Boolean).join(" ");
|
|
5166
|
+
}
|
|
4214
5167
|
function AskUserPrompt({
|
|
4215
5168
|
question,
|
|
4216
5169
|
options,
|
|
@@ -4244,7 +5197,7 @@ function AskUserPrompt({
|
|
|
4244
5197
|
return /* @__PURE__ */ jsxs(
|
|
4245
5198
|
"div",
|
|
4246
5199
|
{
|
|
4247
|
-
className:
|
|
5200
|
+
className: cn5(
|
|
4248
5201
|
"rounded-lg border p-4 space-y-3",
|
|
4249
5202
|
status === "waiting" ? "border-blue-200 bg-blue-50/50 dark:border-blue-800 dark:bg-blue-950/20" : "border-green-200 bg-green-50/50 dark:border-green-800 dark:bg-green-950/20",
|
|
4250
5203
|
className
|
|
@@ -4256,7 +5209,7 @@ function AskUserPrompt({
|
|
|
4256
5209
|
/* @__PURE__ */ jsx(
|
|
4257
5210
|
"span",
|
|
4258
5211
|
{
|
|
4259
|
-
className:
|
|
5212
|
+
className: cn5(
|
|
4260
5213
|
"ml-auto text-xs px-2 py-1 rounded-full font-medium",
|
|
4261
5214
|
status === "waiting" ? "bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300" : "bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300"
|
|
4262
5215
|
),
|
|
@@ -4271,7 +5224,7 @@ function AskUserPrompt({
|
|
|
4271
5224
|
type: "button",
|
|
4272
5225
|
onClick: () => handleOptionSelect(option),
|
|
4273
5226
|
disabled,
|
|
4274
|
-
className:
|
|
5227
|
+
className: cn5(
|
|
4275
5228
|
"px-3 py-1.5 text-sm rounded-md border transition-all",
|
|
4276
5229
|
selectedOption === option ? "bg-blue-600 text-white border-blue-600 hover:bg-blue-700" : "bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300",
|
|
4277
5230
|
disabled && "opacity-50 cursor-not-allowed"
|
|
@@ -4291,7 +5244,7 @@ function AskUserPrompt({
|
|
|
4291
5244
|
},
|
|
4292
5245
|
onKeyDown: handleKeyDown,
|
|
4293
5246
|
placeholder: options?.length ? "Or type a custom response..." : "Type your response...",
|
|
4294
|
-
className:
|
|
5247
|
+
className: cn5(
|
|
4295
5248
|
"flex-1 min-h-[60px] px-3 py-2 text-sm resize-none rounded-md border",
|
|
4296
5249
|
"border-gray-300 dark:border-gray-600",
|
|
4297
5250
|
"bg-white dark:bg-gray-800",
|
|
@@ -4309,7 +5262,7 @@ function AskUserPrompt({
|
|
|
4309
5262
|
type: "button",
|
|
4310
5263
|
onClick: handleSubmit,
|
|
4311
5264
|
disabled: isSubmitDisabled,
|
|
4312
|
-
className:
|
|
5265
|
+
className: cn5(
|
|
4313
5266
|
"self-end px-4 py-2 rounded-md text-white transition-colors",
|
|
4314
5267
|
"bg-blue-600 hover:bg-blue-700",
|
|
4315
5268
|
"disabled:opacity-50 disabled:cursor-not-allowed"
|
|
@@ -4330,7 +5283,7 @@ function AskUserPrompt({
|
|
|
4330
5283
|
}
|
|
4331
5284
|
);
|
|
4332
5285
|
}
|
|
4333
|
-
function
|
|
5286
|
+
function cn6(...classes) {
|
|
4334
5287
|
return classes.filter(Boolean).join(" ");
|
|
4335
5288
|
}
|
|
4336
5289
|
function MarkdownContent({
|
|
@@ -4391,7 +5344,7 @@ function MarkdownContent({
|
|
|
4391
5344
|
if (isCodeBlock) {
|
|
4392
5345
|
return /* @__PURE__ */ jsxs("div", { className: "relative my-2", children: [
|
|
4393
5346
|
language && /* @__PURE__ */ jsx("div", { className: "absolute top-0 right-0 px-2 py-1 text-xs font-mono text-gray-500 dark:text-gray-400 bg-gray-100 dark:bg-gray-800 rounded-bl rounded-tr border-b border-l border-gray-200 dark:border-gray-700", children: language }),
|
|
4394
|
-
/* @__PURE__ */ jsx("pre", { className: "bg-gray-100 dark:bg-gray-800 rounded-lg p-4 overflow-x-auto text-sm", children: /* @__PURE__ */ jsx("code", { className:
|
|
5347
|
+
/* @__PURE__ */ jsx("pre", { className: "bg-gray-100 dark:bg-gray-800 rounded-lg p-4 overflow-x-auto text-sm", children: /* @__PURE__ */ jsx("code", { className: cn6("font-mono", codeClassName), ...props, children }) })
|
|
4395
5348
|
] });
|
|
4396
5349
|
}
|
|
4397
5350
|
return /* @__PURE__ */ jsx(
|
|
@@ -4438,7 +5391,7 @@ function MarkdownContent({
|
|
|
4438
5391
|
() => customComponents ? { ...defaultComponents, ...customComponents } : defaultComponents,
|
|
4439
5392
|
[defaultComponents, customComponents]
|
|
4440
5393
|
);
|
|
4441
|
-
return /* @__PURE__ */ jsx("div", { className:
|
|
5394
|
+
return /* @__PURE__ */ jsx("div", { className: cn6("prose prose-sm dark:prose-invert max-w-none", className), children: /* @__PURE__ */ jsx(
|
|
4442
5395
|
ReactMarkdown,
|
|
4443
5396
|
{
|
|
4444
5397
|
remarkPlugins: [remarkGfm],
|
|
@@ -4448,7 +5401,7 @@ function MarkdownContent({
|
|
|
4448
5401
|
}
|
|
4449
5402
|
) });
|
|
4450
5403
|
}
|
|
4451
|
-
function
|
|
5404
|
+
function cn7(...classes) {
|
|
4452
5405
|
return classes.filter(Boolean).join(" ");
|
|
4453
5406
|
}
|
|
4454
5407
|
function formatToolName(toolName) {
|
|
@@ -4596,7 +5549,7 @@ function ToolCallEntry({
|
|
|
4596
5549
|
return /* @__PURE__ */ jsxs(
|
|
4597
5550
|
"div",
|
|
4598
5551
|
{
|
|
4599
|
-
className:
|
|
5552
|
+
className: cn7(
|
|
4600
5553
|
"rounded-lg border text-sm",
|
|
4601
5554
|
statusColor,
|
|
4602
5555
|
className
|
|
@@ -4617,7 +5570,7 @@ function ToolCallEntry({
|
|
|
4617
5570
|
]
|
|
4618
5571
|
}
|
|
4619
5572
|
),
|
|
4620
|
-
hasImages && /* @__PURE__ */ jsx("div", { className: "px-3 pb-2", children: /* @__PURE__ */ jsx("div", { className:
|
|
5573
|
+
hasImages && /* @__PURE__ */ jsx("div", { className: "px-3 pb-2", children: /* @__PURE__ */ jsx("div", { className: cn7(
|
|
4621
5574
|
"grid gap-2",
|
|
4622
5575
|
resultImages.length === 1 ? "grid-cols-1" : "grid-cols-2"
|
|
4623
5576
|
), children: resultImages.map((img, idx) => {
|
|
@@ -4676,7 +5629,7 @@ function ToolCallEntry({
|
|
|
4676
5629
|
}
|
|
4677
5630
|
);
|
|
4678
5631
|
}
|
|
4679
|
-
function
|
|
5632
|
+
function cn8(...classes) {
|
|
4680
5633
|
return classes.filter(Boolean).join(" ");
|
|
4681
5634
|
}
|
|
4682
5635
|
function ChatMessage({
|
|
@@ -4698,7 +5651,7 @@ function ChatMessage({
|
|
|
4698
5651
|
return /* @__PURE__ */ jsxs(
|
|
4699
5652
|
"div",
|
|
4700
5653
|
{
|
|
4701
|
-
className:
|
|
5654
|
+
className: cn8(
|
|
4702
5655
|
"flex gap-3 p-4",
|
|
4703
5656
|
isUser ? "flex-row-reverse" : "flex-row",
|
|
4704
5657
|
className
|
|
@@ -4707,7 +5660,7 @@ function ChatMessage({
|
|
|
4707
5660
|
/* @__PURE__ */ jsx(
|
|
4708
5661
|
"div",
|
|
4709
5662
|
{
|
|
4710
|
-
className:
|
|
5663
|
+
className: cn8(
|
|
4711
5664
|
"flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center",
|
|
4712
5665
|
isUser ? "bg-blue-500 text-white" : "bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-300"
|
|
4713
5666
|
),
|
|
@@ -4717,7 +5670,7 @@ function ChatMessage({
|
|
|
4717
5670
|
/* @__PURE__ */ jsxs(
|
|
4718
5671
|
"div",
|
|
4719
5672
|
{
|
|
4720
|
-
className:
|
|
5673
|
+
className: cn8(
|
|
4721
5674
|
"flex-1 min-w-0 space-y-2",
|
|
4722
5675
|
isUser ? "text-right" : "text-left"
|
|
4723
5676
|
),
|
|
@@ -4725,7 +5678,7 @@ function ChatMessage({
|
|
|
4725
5678
|
/* @__PURE__ */ jsxs(
|
|
4726
5679
|
"div",
|
|
4727
5680
|
{
|
|
4728
|
-
className:
|
|
5681
|
+
className: cn8(
|
|
4729
5682
|
"flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400",
|
|
4730
5683
|
isUser ? "justify-end" : "justify-start"
|
|
4731
5684
|
),
|
|
@@ -4758,7 +5711,7 @@ function ChatMessage({
|
|
|
4758
5711
|
message.content && /* @__PURE__ */ jsx(
|
|
4759
5712
|
"div",
|
|
4760
5713
|
{
|
|
4761
|
-
className:
|
|
5714
|
+
className: cn8(
|
|
4762
5715
|
"rounded-lg p-3",
|
|
4763
5716
|
isUser ? "bg-blue-500 text-white" : "bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-gray-100"
|
|
4764
5717
|
),
|
|
@@ -4788,7 +5741,7 @@ function ChatMessage({
|
|
|
4788
5741
|
}
|
|
4789
5742
|
);
|
|
4790
5743
|
}
|
|
4791
|
-
function
|
|
5744
|
+
function cn9(...classes) {
|
|
4792
5745
|
return classes.filter(Boolean).join(" ");
|
|
4793
5746
|
}
|
|
4794
5747
|
function MessageList({
|
|
@@ -4818,7 +5771,7 @@ function MessageList({
|
|
|
4818
5771
|
"div",
|
|
4819
5772
|
{
|
|
4820
5773
|
ref: scrollRef,
|
|
4821
|
-
className:
|
|
5774
|
+
className: cn9(
|
|
4822
5775
|
"flex-1 overflow-y-auto",
|
|
4823
5776
|
className
|
|
4824
5777
|
),
|
|
@@ -4911,6 +5864,7 @@ function AgentChat({
|
|
|
4911
5864
|
isStreaming,
|
|
4912
5865
|
isLoadingHistory,
|
|
4913
5866
|
error,
|
|
5867
|
+
sessionId: currentSessionId,
|
|
4914
5868
|
clarification,
|
|
4915
5869
|
sendMessage,
|
|
4916
5870
|
respondToClarification,
|
|
@@ -4931,8 +5885,59 @@ function AgentChat({
|
|
|
4931
5885
|
onToolResult,
|
|
4932
5886
|
onClarification
|
|
4933
5887
|
});
|
|
5888
|
+
const dropZoneRef = useRef(null);
|
|
5889
|
+
const attachments = useFileAttachments({
|
|
5890
|
+
onUpload: enableAttachments && adapter ? async (_file, meta) => {
|
|
5891
|
+
const result = await adapter.getUploadUrl({
|
|
5892
|
+
sessionId: currentSessionId ?? "",
|
|
5893
|
+
...meta
|
|
5894
|
+
});
|
|
5895
|
+
return { uuid: result.attachmentUuid, uploadUrl: result.uploadUrl };
|
|
5896
|
+
} : async () => ({ uuid: "", uploadUrl: "" }),
|
|
5897
|
+
onConfirmUpload: enableAttachments && adapter ? (uuid) => adapter.confirmUpload(uuid) : void 0,
|
|
5898
|
+
onError: (msg) => {
|
|
5899
|
+
console.error("[AgentChat] Attachment error:", msg);
|
|
5900
|
+
}
|
|
5901
|
+
});
|
|
5902
|
+
const handleSend = useCallback(
|
|
5903
|
+
async (content) => {
|
|
5904
|
+
if (enableAttachments && attachments.hasReadyFiles) {
|
|
5905
|
+
const uuids = attachments.getReadyUuids();
|
|
5906
|
+
await sendMessage(content, { attachmentUuids: uuids });
|
|
5907
|
+
attachments.clear();
|
|
5908
|
+
} else {
|
|
5909
|
+
await sendMessage(content);
|
|
5910
|
+
}
|
|
5911
|
+
},
|
|
5912
|
+
[enableAttachments, attachments, sendMessage]
|
|
5913
|
+
);
|
|
4934
5914
|
return /* @__PURE__ */ jsxs(ChatContainer, { maxHeight, className, theme, children: [
|
|
4935
|
-
/* @__PURE__ */ jsx(
|
|
5915
|
+
enableAttachments ? /* @__PURE__ */ jsx(
|
|
5916
|
+
FileDropZone,
|
|
5917
|
+
{
|
|
5918
|
+
ref: dropZoneRef,
|
|
5919
|
+
...attachments.dropZoneProps,
|
|
5920
|
+
disabled: isLoading || !!clarification || isLoadingHistory,
|
|
5921
|
+
children: /* @__PURE__ */ jsx(
|
|
5922
|
+
MessageList,
|
|
5923
|
+
{
|
|
5924
|
+
messages,
|
|
5925
|
+
welcomeMessage,
|
|
5926
|
+
renderWelcome,
|
|
5927
|
+
isLoading,
|
|
5928
|
+
isStreaming,
|
|
5929
|
+
isLoadingHistory,
|
|
5930
|
+
enableMarkdown,
|
|
5931
|
+
showToolCalls,
|
|
5932
|
+
markdownComponents,
|
|
5933
|
+
markdownUrlTransform,
|
|
5934
|
+
markdownContentTransform,
|
|
5935
|
+
onImageClick,
|
|
5936
|
+
sendMessage: handleSend
|
|
5937
|
+
}
|
|
5938
|
+
)
|
|
5939
|
+
}
|
|
5940
|
+
) : /* @__PURE__ */ jsx(
|
|
4936
5941
|
MessageList,
|
|
4937
5942
|
{
|
|
4938
5943
|
messages,
|
|
@@ -4947,7 +5952,7 @@ function AgentChat({
|
|
|
4947
5952
|
markdownUrlTransform,
|
|
4948
5953
|
markdownContentTransform,
|
|
4949
5954
|
onImageClick,
|
|
4950
|
-
sendMessage
|
|
5955
|
+
sendMessage: handleSend
|
|
4951
5956
|
}
|
|
4952
5957
|
),
|
|
4953
5958
|
clarification && /* @__PURE__ */ jsx("div", { className: "border-t border-gray-200 dark:border-gray-700 p-4", children: /* @__PURE__ */ jsx(
|
|
@@ -4962,17 +5967,21 @@ function AgentChat({
|
|
|
4962
5967
|
/* @__PURE__ */ jsx(
|
|
4963
5968
|
ChatInput,
|
|
4964
5969
|
{
|
|
4965
|
-
onSend:
|
|
5970
|
+
onSend: handleSend,
|
|
4966
5971
|
onStop: isStreaming ? cancel : void 0,
|
|
4967
5972
|
placeholder,
|
|
4968
5973
|
disabled: !!clarification || isLoadingHistory,
|
|
4969
5974
|
isLoading,
|
|
4970
|
-
enableAttachments
|
|
5975
|
+
enableAttachments,
|
|
5976
|
+
attachments: enableAttachments ? attachments.files : void 0,
|
|
5977
|
+
onRemoveAttachment: enableAttachments ? attachments.removeFile : void 0,
|
|
5978
|
+
dropZoneRef: enableAttachments ? dropZoneRef : void 0,
|
|
5979
|
+
isUploadingAttachments: enableAttachments ? attachments.isUploading : void 0
|
|
4971
5980
|
}
|
|
4972
5981
|
)
|
|
4973
5982
|
] });
|
|
4974
5983
|
}
|
|
4975
|
-
function
|
|
5984
|
+
function cn10(...classes) {
|
|
4976
5985
|
return classes.filter(Boolean).join(" ");
|
|
4977
5986
|
}
|
|
4978
5987
|
function TodoList({
|
|
@@ -5001,7 +6010,7 @@ function TodoList({
|
|
|
5001
6010
|
return /* @__PURE__ */ jsxs(
|
|
5002
6011
|
"div",
|
|
5003
6012
|
{
|
|
5004
|
-
className:
|
|
6013
|
+
className: cn10(
|
|
5005
6014
|
"rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden",
|
|
5006
6015
|
className
|
|
5007
6016
|
),
|
|
@@ -5009,7 +6018,7 @@ function TodoList({
|
|
|
5009
6018
|
/* @__PURE__ */ jsxs(
|
|
5010
6019
|
"div",
|
|
5011
6020
|
{
|
|
5012
|
-
className:
|
|
6021
|
+
className: cn10(
|
|
5013
6022
|
"flex items-center gap-2 px-3 py-2 bg-gray-50 dark:bg-gray-800/50",
|
|
5014
6023
|
collapsible && "cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800"
|
|
5015
6024
|
),
|
|
@@ -5040,7 +6049,7 @@ function TodoList({
|
|
|
5040
6049
|
!isCollapsed && /* @__PURE__ */ jsx("ul", { className: "divide-y divide-gray-100 dark:divide-gray-700", children: todos.map((todo, idx) => /* @__PURE__ */ jsxs(
|
|
5041
6050
|
"li",
|
|
5042
6051
|
{
|
|
5043
|
-
className:
|
|
6052
|
+
className: cn10(
|
|
5044
6053
|
"px-3 py-2 flex items-start gap-2 text-sm",
|
|
5045
6054
|
todo.status === "in_progress" && "bg-blue-50/50 dark:bg-blue-950/20",
|
|
5046
6055
|
todo.status === "completed" && "opacity-60"
|
|
@@ -5050,7 +6059,7 @@ function TodoList({
|
|
|
5050
6059
|
/* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx(
|
|
5051
6060
|
"p",
|
|
5052
6061
|
{
|
|
5053
|
-
className:
|
|
6062
|
+
className: cn10(
|
|
5054
6063
|
"text-gray-700 dark:text-gray-300",
|
|
5055
6064
|
todo.status === "completed" && "line-through"
|
|
5056
6065
|
),
|
|
@@ -5067,6 +6076,6 @@ function TodoList({
|
|
|
5067
6076
|
);
|
|
5068
6077
|
}
|
|
5069
6078
|
|
|
5070
|
-
export { AgentChat, AlertCircleIcon, AskUserPrompt, BotIcon, ChatConfigProvider, ChatContainer, ChatInput, ChatMessage, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, CircleIcon, ClockIcon, CodeIcon, CopyIcon, DatabaseIcon, DownloadIcon, ExternalLinkIcon, FileIcon, FileTextIcon, HelpCircleIcon, ImageIcon, ImagesIcon, ListTodoIcon, LoadingSpinner, MarkdownContent, Maximize2Icon, MessageCircleIcon, MessageList, Minimize2Icon, PaperclipIcon, SendIcon, SparklesIcon, StopCircleIcon, TodoList, ToolCallEntry, UserIcon, XIcon, ZoomInIcon, ZoomOutIcon, createDefaultAdapter, useAgentChat, useChatConfig, useChatConfigOptional, useExecutionStream };
|
|
6079
|
+
export { AgentChat, AlertCircleIcon, AskUserPrompt, BotIcon, ChatConfigProvider, ChatContainer, ChatInput, ChatMessage, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, CircleIcon, ClockIcon, CodeIcon, CopyIcon, DatabaseIcon, DownloadIcon, ExternalLinkIcon, FileDropZone, FileIcon, FileTextIcon, HelpCircleIcon, ImageIcon, ImagesIcon, ListTodoIcon, LoadingSpinner, MarkdownContent, Maximize2Icon, MessageCircleIcon, MessageList, Minimize2Icon, PaperclipIcon, SendIcon, SparklesIcon, StopCircleIcon, TodoList, ToolCallEntry, UserIcon, XIcon, ZoomInIcon, ZoomOutIcon, compressImage, createDefaultAdapter, useAgentChat, useChatConfig, useChatConfigOptional, useExecutionStream, useFileAttachments };
|
|
5071
6080
|
//# sourceMappingURL=index.js.map
|
|
5072
6081
|
//# sourceMappingURL=index.js.map
|