@meetsmore-oss/use-ai-client 1.2.4 → 1.4.0
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/bundled.js +710 -222
- package/dist/bundled.js.map +1 -1
- package/dist/{chunk-EGD4LT6R.js → chunk-AKQM6IWU.js} +1 -1
- package/dist/chunk-AKQM6IWU.js.map +1 -0
- package/dist/{chunk-EGKUR4C7.js → chunk-QTQR7MAU.js} +1 -1
- package/dist/chunk-QTQR7MAU.js.map +1 -0
- package/dist/index.d.ts +292 -74
- package/dist/index.js +710 -222
- package/dist/index.js.map +1 -1
- package/dist/{types-INERONQV.js → types-64CH2HXY.js} +2 -2
- package/dist/{types-TVUXB3NB.js → types-STDS67SG.js} +2 -2
- package/package.json +2 -2
- package/dist/chunk-EGD4LT6R.js.map +0 -1
- package/dist/chunk-EGKUR4C7.js.map +0 -1
- /package/dist/{types-INERONQV.js.map → types-64CH2HXY.js.map} +0 -0
- /package/dist/{types-TVUXB3NB.js.map → types-STDS67SG.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generateChatId,
|
|
3
3
|
generateMessageId
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QTQR7MAU.js";
|
|
5
5
|
|
|
6
6
|
// src/useAI.ts
|
|
7
7
|
import { useState as useState11, useEffect as useEffect10, useRef as useRef11, useCallback as useCallback10, useMemo as useMemo6 } from "react";
|
|
@@ -51,7 +51,9 @@ var defaultStrings = {
|
|
|
51
51
|
/** Input placeholder when connecting */
|
|
52
52
|
connectingPlaceholder: "Connecting...",
|
|
53
53
|
/** Loading indicator text */
|
|
54
|
-
thinking: "Thinking"
|
|
54
|
+
thinking: "Thinking",
|
|
55
|
+
/** File processing indicator text (shown during file transformation like OCR) */
|
|
56
|
+
processingFile: "Processing file..."
|
|
55
57
|
},
|
|
56
58
|
// File upload
|
|
57
59
|
fileUpload: {
|
|
@@ -378,8 +380,131 @@ function MarkdownContent({ content }) {
|
|
|
378
380
|
);
|
|
379
381
|
}
|
|
380
382
|
|
|
381
|
-
// src/components/
|
|
383
|
+
// src/components/Spinner.tsx
|
|
382
384
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
385
|
+
function Spinner({
|
|
386
|
+
size = 16,
|
|
387
|
+
color = "currentColor",
|
|
388
|
+
trackColor,
|
|
389
|
+
strokeWidth = 2
|
|
390
|
+
}) {
|
|
391
|
+
const radius = 10;
|
|
392
|
+
const circumference = 2 * Math.PI * radius;
|
|
393
|
+
return /* @__PURE__ */ jsxs2(
|
|
394
|
+
"svg",
|
|
395
|
+
{
|
|
396
|
+
"data-testid": "spinner",
|
|
397
|
+
width: size,
|
|
398
|
+
height: size,
|
|
399
|
+
viewBox: "0 0 24 24",
|
|
400
|
+
style: {
|
|
401
|
+
animation: "use-ai-spin 1s linear infinite"
|
|
402
|
+
},
|
|
403
|
+
children: [
|
|
404
|
+
/* @__PURE__ */ jsx3("style", { children: `
|
|
405
|
+
@keyframes use-ai-spin {
|
|
406
|
+
from { transform: rotate(0deg); }
|
|
407
|
+
to { transform: rotate(360deg); }
|
|
408
|
+
}
|
|
409
|
+
` }),
|
|
410
|
+
/* @__PURE__ */ jsx3(
|
|
411
|
+
"circle",
|
|
412
|
+
{
|
|
413
|
+
cx: "12",
|
|
414
|
+
cy: "12",
|
|
415
|
+
r: radius,
|
|
416
|
+
fill: "none",
|
|
417
|
+
stroke: trackColor || color,
|
|
418
|
+
strokeWidth,
|
|
419
|
+
opacity: trackColor ? 1 : 0.25
|
|
420
|
+
}
|
|
421
|
+
),
|
|
422
|
+
/* @__PURE__ */ jsx3(
|
|
423
|
+
"circle",
|
|
424
|
+
{
|
|
425
|
+
cx: "12",
|
|
426
|
+
cy: "12",
|
|
427
|
+
r: radius,
|
|
428
|
+
fill: "none",
|
|
429
|
+
stroke: color,
|
|
430
|
+
strokeWidth,
|
|
431
|
+
strokeLinecap: "round",
|
|
432
|
+
strokeDasharray: circumference,
|
|
433
|
+
strokeDashoffset: circumference * 0.75,
|
|
434
|
+
style: {
|
|
435
|
+
transformOrigin: "center"
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
)
|
|
439
|
+
]
|
|
440
|
+
}
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// src/components/ProgressBar.tsx
|
|
445
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
446
|
+
function ProgressBar({
|
|
447
|
+
progress,
|
|
448
|
+
size = 16,
|
|
449
|
+
color = "currentColor",
|
|
450
|
+
trackColor,
|
|
451
|
+
strokeWidth = 2
|
|
452
|
+
}) {
|
|
453
|
+
const clampedProgress = Math.min(100, Math.max(0, progress));
|
|
454
|
+
const radius = 10;
|
|
455
|
+
const circumference = 2 * Math.PI * radius;
|
|
456
|
+
const strokeDashoffset = circumference * (1 - clampedProgress / 100);
|
|
457
|
+
return /* @__PURE__ */ jsxs3(
|
|
458
|
+
"svg",
|
|
459
|
+
{
|
|
460
|
+
"data-testid": "progress-bar",
|
|
461
|
+
role: "progressbar",
|
|
462
|
+
"aria-valuenow": clampedProgress,
|
|
463
|
+
"aria-valuemin": 0,
|
|
464
|
+
"aria-valuemax": 100,
|
|
465
|
+
width: size,
|
|
466
|
+
height: size,
|
|
467
|
+
viewBox: "0 0 24 24",
|
|
468
|
+
style: {
|
|
469
|
+
transform: "rotate(-90deg)"
|
|
470
|
+
},
|
|
471
|
+
children: [
|
|
472
|
+
/* @__PURE__ */ jsx4(
|
|
473
|
+
"circle",
|
|
474
|
+
{
|
|
475
|
+
cx: "12",
|
|
476
|
+
cy: "12",
|
|
477
|
+
r: radius,
|
|
478
|
+
fill: "none",
|
|
479
|
+
stroke: trackColor || color,
|
|
480
|
+
strokeWidth,
|
|
481
|
+
opacity: trackColor ? 1 : 0.25
|
|
482
|
+
}
|
|
483
|
+
),
|
|
484
|
+
/* @__PURE__ */ jsx4(
|
|
485
|
+
"circle",
|
|
486
|
+
{
|
|
487
|
+
cx: "12",
|
|
488
|
+
cy: "12",
|
|
489
|
+
r: radius,
|
|
490
|
+
fill: "none",
|
|
491
|
+
stroke: color,
|
|
492
|
+
strokeWidth,
|
|
493
|
+
strokeLinecap: "round",
|
|
494
|
+
strokeDasharray: circumference,
|
|
495
|
+
strokeDashoffset,
|
|
496
|
+
style: {
|
|
497
|
+
transition: "stroke-dashoffset 0.2s ease"
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
)
|
|
501
|
+
]
|
|
502
|
+
}
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// src/components/FileChip.tsx
|
|
507
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
383
508
|
function formatFileSize(bytes) {
|
|
384
509
|
if (bytes < 1024) return `${bytes} B`;
|
|
385
510
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
@@ -394,11 +519,14 @@ function truncateFilename(name, maxLength = 20) {
|
|
|
394
519
|
if (maxBaseLength < 5) return name.substring(0, maxLength - 3) + "...";
|
|
395
520
|
return baseName.substring(0, maxBaseLength) + "..." + ext;
|
|
396
521
|
}
|
|
397
|
-
function FileChip({ attachment, onRemove, disabled }) {
|
|
522
|
+
function FileChip({ attachment, onRemove, disabled, processingState }) {
|
|
398
523
|
const theme = useTheme();
|
|
399
524
|
const { file, preview } = attachment;
|
|
400
525
|
const isImage = file.type.startsWith("image/");
|
|
401
|
-
|
|
526
|
+
const isProcessing = processingState?.status === "processing";
|
|
527
|
+
const hasError = processingState?.status === "error";
|
|
528
|
+
const progress = processingState?.progress;
|
|
529
|
+
return /* @__PURE__ */ jsxs4(
|
|
402
530
|
"div",
|
|
403
531
|
{
|
|
404
532
|
"data-testid": "file-chip",
|
|
@@ -411,10 +539,12 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
411
539
|
borderRadius: "8px",
|
|
412
540
|
fontSize: "13px",
|
|
413
541
|
color: theme.textColor,
|
|
414
|
-
maxWidth: "200px"
|
|
542
|
+
maxWidth: "200px",
|
|
543
|
+
position: "relative",
|
|
544
|
+
opacity: isProcessing ? 0.7 : 1
|
|
415
545
|
},
|
|
416
546
|
children: [
|
|
417
|
-
isImage && preview ? /* @__PURE__ */
|
|
547
|
+
isImage && preview ? /* @__PURE__ */ jsx5(
|
|
418
548
|
"img",
|
|
419
549
|
{
|
|
420
550
|
src: preview,
|
|
@@ -426,7 +556,7 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
426
556
|
objectFit: "cover"
|
|
427
557
|
}
|
|
428
558
|
}
|
|
429
|
-
) : /* @__PURE__ */
|
|
559
|
+
) : /* @__PURE__ */ jsx5(
|
|
430
560
|
"div",
|
|
431
561
|
{
|
|
432
562
|
style: {
|
|
@@ -442,8 +572,8 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
442
572
|
children: "\u{1F4CE}"
|
|
443
573
|
}
|
|
444
574
|
),
|
|
445
|
-
/* @__PURE__ */
|
|
446
|
-
/* @__PURE__ */
|
|
575
|
+
/* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: [
|
|
576
|
+
/* @__PURE__ */ jsx5(
|
|
447
577
|
"div",
|
|
448
578
|
{
|
|
449
579
|
style: {
|
|
@@ -456,28 +586,28 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
456
586
|
children: truncateFilename(file.name)
|
|
457
587
|
}
|
|
458
588
|
),
|
|
459
|
-
/* @__PURE__ */
|
|
589
|
+
/* @__PURE__ */ jsx5("div", { style: { fontSize: "11px", color: theme.secondaryTextColor }, children: formatFileSize(file.size) })
|
|
460
590
|
] }),
|
|
461
|
-
/* @__PURE__ */
|
|
591
|
+
/* @__PURE__ */ jsx5(
|
|
462
592
|
"button",
|
|
463
593
|
{
|
|
464
594
|
"data-testid": "file-chip-remove",
|
|
465
595
|
onClick: onRemove,
|
|
466
|
-
disabled,
|
|
596
|
+
disabled: disabled || isProcessing,
|
|
467
597
|
style: {
|
|
468
598
|
background: "transparent",
|
|
469
599
|
border: "none",
|
|
470
600
|
padding: "2px 4px",
|
|
471
|
-
cursor: disabled ? "not-allowed" : "pointer",
|
|
601
|
+
cursor: disabled || isProcessing ? "not-allowed" : "pointer",
|
|
472
602
|
color: theme.placeholderTextColor,
|
|
473
603
|
fontSize: "16px",
|
|
474
604
|
lineHeight: 1,
|
|
475
605
|
borderRadius: "4px",
|
|
476
606
|
transition: "all 0.15s",
|
|
477
|
-
opacity: disabled ? 0.5 : 1
|
|
607
|
+
opacity: disabled || isProcessing ? 0.5 : 1
|
|
478
608
|
},
|
|
479
609
|
onMouseEnter: (e) => {
|
|
480
|
-
if (!disabled) {
|
|
610
|
+
if (!disabled && !isProcessing) {
|
|
481
611
|
e.currentTarget.style.background = theme.borderColor;
|
|
482
612
|
e.currentTarget.style.color = theme.textColor;
|
|
483
613
|
}
|
|
@@ -488,6 +618,44 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
488
618
|
},
|
|
489
619
|
children: "\xD7"
|
|
490
620
|
}
|
|
621
|
+
),
|
|
622
|
+
isProcessing && /* @__PURE__ */ jsx5(
|
|
623
|
+
"div",
|
|
624
|
+
{
|
|
625
|
+
"data-testid": "file-chip-processing",
|
|
626
|
+
style: {
|
|
627
|
+
position: "absolute",
|
|
628
|
+
inset: 0,
|
|
629
|
+
display: "flex",
|
|
630
|
+
alignItems: "center",
|
|
631
|
+
justifyContent: "center",
|
|
632
|
+
background: "rgba(255, 255, 255, 0.7)",
|
|
633
|
+
borderRadius: "inherit"
|
|
634
|
+
},
|
|
635
|
+
children: progress !== void 0 ? /* @__PURE__ */ jsx5(ProgressBar, { progress, size: 16, color: theme.secondaryTextColor }) : /* @__PURE__ */ jsx5(Spinner, { size: 16, color: theme.secondaryTextColor })
|
|
636
|
+
}
|
|
637
|
+
),
|
|
638
|
+
hasError && /* @__PURE__ */ jsx5(
|
|
639
|
+
"div",
|
|
640
|
+
{
|
|
641
|
+
"data-testid": "file-chip-error",
|
|
642
|
+
style: {
|
|
643
|
+
position: "absolute",
|
|
644
|
+
bottom: "-2px",
|
|
645
|
+
right: "-2px",
|
|
646
|
+
width: "12px",
|
|
647
|
+
height: "12px",
|
|
648
|
+
borderRadius: "50%",
|
|
649
|
+
background: "#ef4444",
|
|
650
|
+
display: "flex",
|
|
651
|
+
alignItems: "center",
|
|
652
|
+
justifyContent: "center",
|
|
653
|
+
fontSize: "8px",
|
|
654
|
+
color: "white",
|
|
655
|
+
fontWeight: "bold"
|
|
656
|
+
},
|
|
657
|
+
children: "!"
|
|
658
|
+
}
|
|
491
659
|
)
|
|
492
660
|
]
|
|
493
661
|
}
|
|
@@ -495,7 +663,7 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
495
663
|
}
|
|
496
664
|
function FilePlaceholder({ name, size }) {
|
|
497
665
|
const theme = useTheme();
|
|
498
|
-
return /* @__PURE__ */
|
|
666
|
+
return /* @__PURE__ */ jsxs4(
|
|
499
667
|
"div",
|
|
500
668
|
{
|
|
501
669
|
"data-testid": "file-placeholder",
|
|
@@ -512,9 +680,9 @@ function FilePlaceholder({ name, size }) {
|
|
|
512
680
|
maxWidth: "200px"
|
|
513
681
|
},
|
|
514
682
|
children: [
|
|
515
|
-
/* @__PURE__ */
|
|
516
|
-
/* @__PURE__ */
|
|
517
|
-
/* @__PURE__ */
|
|
683
|
+
/* @__PURE__ */ jsx5("span", { children: "\u{1F4CE}" }),
|
|
684
|
+
/* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: [
|
|
685
|
+
/* @__PURE__ */ jsx5(
|
|
518
686
|
"div",
|
|
519
687
|
{
|
|
520
688
|
style: {
|
|
@@ -526,7 +694,7 @@ function FilePlaceholder({ name, size }) {
|
|
|
526
694
|
children: truncateFilename(name)
|
|
527
695
|
}
|
|
528
696
|
),
|
|
529
|
-
/* @__PURE__ */
|
|
697
|
+
/* @__PURE__ */ jsx5("div", { style: { fontSize: "11px" }, children: formatFileSize(size) })
|
|
530
698
|
] })
|
|
531
699
|
]
|
|
532
700
|
}
|
|
@@ -555,7 +723,7 @@ function validateCommandName(name) {
|
|
|
555
723
|
|
|
556
724
|
// src/components/CommandAutocomplete.tsx
|
|
557
725
|
import { useEffect, useRef } from "react";
|
|
558
|
-
import { jsx as
|
|
726
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
559
727
|
var MAX_VISIBLE_ITEMS = 8;
|
|
560
728
|
function CommandAutocomplete({
|
|
561
729
|
commands,
|
|
@@ -586,7 +754,7 @@ function CommandAutocomplete({
|
|
|
586
754
|
}
|
|
587
755
|
}, [highlightedIndex]);
|
|
588
756
|
if (filteredCommands.length === 0) {
|
|
589
|
-
return /* @__PURE__ */
|
|
757
|
+
return /* @__PURE__ */ jsx6(
|
|
590
758
|
"div",
|
|
591
759
|
{
|
|
592
760
|
"data-testid": "command-autocomplete",
|
|
@@ -602,7 +770,7 @@ function CommandAutocomplete({
|
|
|
602
770
|
overflow: "hidden",
|
|
603
771
|
zIndex: 1005
|
|
604
772
|
},
|
|
605
|
-
children: /* @__PURE__ */
|
|
773
|
+
children: /* @__PURE__ */ jsx6(
|
|
606
774
|
"div",
|
|
607
775
|
{
|
|
608
776
|
style: {
|
|
@@ -617,7 +785,7 @@ function CommandAutocomplete({
|
|
|
617
785
|
}
|
|
618
786
|
);
|
|
619
787
|
}
|
|
620
|
-
return /* @__PURE__ */
|
|
788
|
+
return /* @__PURE__ */ jsx6(
|
|
621
789
|
"div",
|
|
622
790
|
{
|
|
623
791
|
"data-testid": "command-autocomplete",
|
|
@@ -636,7 +804,7 @@ function CommandAutocomplete({
|
|
|
636
804
|
overflowY: "auto",
|
|
637
805
|
zIndex: 1005
|
|
638
806
|
},
|
|
639
|
-
children: filteredCommands.map((cmd, index) => /* @__PURE__ */
|
|
807
|
+
children: filteredCommands.map((cmd, index) => /* @__PURE__ */ jsxs5(
|
|
640
808
|
"div",
|
|
641
809
|
{
|
|
642
810
|
ref: (el) => {
|
|
@@ -656,8 +824,8 @@ function CommandAutocomplete({
|
|
|
656
824
|
gap: "8px"
|
|
657
825
|
},
|
|
658
826
|
children: [
|
|
659
|
-
/* @__PURE__ */
|
|
660
|
-
/* @__PURE__ */
|
|
827
|
+
/* @__PURE__ */ jsxs5("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
828
|
+
/* @__PURE__ */ jsxs5(
|
|
661
829
|
"div",
|
|
662
830
|
{
|
|
663
831
|
style: {
|
|
@@ -671,7 +839,7 @@ function CommandAutocomplete({
|
|
|
671
839
|
]
|
|
672
840
|
}
|
|
673
841
|
),
|
|
674
|
-
/* @__PURE__ */
|
|
842
|
+
/* @__PURE__ */ jsx6(
|
|
675
843
|
"div",
|
|
676
844
|
{
|
|
677
845
|
style: {
|
|
@@ -686,7 +854,7 @@ function CommandAutocomplete({
|
|
|
686
854
|
}
|
|
687
855
|
)
|
|
688
856
|
] }),
|
|
689
|
-
onDelete && /* @__PURE__ */
|
|
857
|
+
onDelete && /* @__PURE__ */ jsx6(
|
|
690
858
|
"button",
|
|
691
859
|
{
|
|
692
860
|
"data-testid": "command-delete-button",
|
|
@@ -717,7 +885,7 @@ function CommandAutocomplete({
|
|
|
717
885
|
e.currentTarget.style.background = "transparent";
|
|
718
886
|
},
|
|
719
887
|
title: strings.commands.deleteCommand,
|
|
720
|
-
children: /* @__PURE__ */
|
|
888
|
+
children: /* @__PURE__ */ jsx6("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("path", { d: "M2 4H14M6.5 7V11M9.5 7V11M3 4L4 13C4 13.5304 4.21071 14.0391 4.58579 14.4142C4.96086 14.7893 5.46957 15 6 15H10C10.5304 15 11.0391 14.7893 11.4142 14.4142C11.7893 14.0391 12 13.5304 12 13L13 4M5.5 4V2.5C5.5 2.23478 5.60536 1.98043 5.79289 1.79289C5.98043 1.60536 6.23478 1.5 6.5 1.5H9.5C9.76522 1.5 10.0196 1.60536 10.2071 1.79289C10.3946 1.98043 10.5 2.23478 10.5 2.5V4" }) })
|
|
721
889
|
}
|
|
722
890
|
)
|
|
723
891
|
]
|
|
@@ -735,7 +903,7 @@ function getFilteredCommandsCount(commands, searchPrefix) {
|
|
|
735
903
|
}
|
|
736
904
|
|
|
737
905
|
// src/hooks/useSlashCommands.tsx
|
|
738
|
-
import { jsx as
|
|
906
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
739
907
|
var MAX_VISIBLE_ITEMS2 = 8;
|
|
740
908
|
function useSlashCommands({
|
|
741
909
|
commands,
|
|
@@ -870,7 +1038,7 @@ function useSlashCommands({
|
|
|
870
1038
|
}
|
|
871
1039
|
}
|
|
872
1040
|
}, [savingMessageId, savingMessageText, commandNameInput, commands, onRenameCommand, onSaveCommand, cancelInlineSave, strings]);
|
|
873
|
-
const AutocompleteComponent = showAutocomplete && commands.length > 0 ? /* @__PURE__ */
|
|
1041
|
+
const AutocompleteComponent = showAutocomplete && commands.length > 0 ? /* @__PURE__ */ jsx7(
|
|
874
1042
|
CommandAutocomplete,
|
|
875
1043
|
{
|
|
876
1044
|
commands,
|
|
@@ -886,7 +1054,7 @@ function useSlashCommands({
|
|
|
886
1054
|
if (savingMessageId !== messageId) {
|
|
887
1055
|
return null;
|
|
888
1056
|
}
|
|
889
|
-
return /* @__PURE__ */
|
|
1057
|
+
return /* @__PURE__ */ jsxs6(
|
|
890
1058
|
"div",
|
|
891
1059
|
{
|
|
892
1060
|
"data-testid": "inline-save-command",
|
|
@@ -900,9 +1068,9 @@ function useSlashCommands({
|
|
|
900
1068
|
gap: "4px"
|
|
901
1069
|
},
|
|
902
1070
|
children: [
|
|
903
|
-
/* @__PURE__ */
|
|
904
|
-
/* @__PURE__ */
|
|
905
|
-
/* @__PURE__ */
|
|
1071
|
+
/* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
|
|
1072
|
+
/* @__PURE__ */ jsx7("span", { style: { color: theme.primaryColor, fontSize: "13px", fontWeight: 500 }, children: "/" }),
|
|
1073
|
+
/* @__PURE__ */ jsx7(
|
|
906
1074
|
"input",
|
|
907
1075
|
{
|
|
908
1076
|
ref: commandNameInputRef,
|
|
@@ -934,7 +1102,7 @@ function useSlashCommands({
|
|
|
934
1102
|
}
|
|
935
1103
|
}
|
|
936
1104
|
),
|
|
937
|
-
/* @__PURE__ */
|
|
1105
|
+
/* @__PURE__ */ jsx7(
|
|
938
1106
|
"button",
|
|
939
1107
|
{
|
|
940
1108
|
"data-testid": "save-command-confirm",
|
|
@@ -952,15 +1120,15 @@ function useSlashCommands({
|
|
|
952
1120
|
justifyContent: "center"
|
|
953
1121
|
},
|
|
954
1122
|
title: strings.commands.saveCommand,
|
|
955
|
-
children: /* @__PURE__ */
|
|
956
|
-
/* @__PURE__ */
|
|
957
|
-
/* @__PURE__ */
|
|
958
|
-
/* @__PURE__ */
|
|
1123
|
+
children: /* @__PURE__ */ jsxs6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1124
|
+
/* @__PURE__ */ jsx7("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }),
|
|
1125
|
+
/* @__PURE__ */ jsx7("polyline", { points: "17 21 17 13 7 13 7 21" }),
|
|
1126
|
+
/* @__PURE__ */ jsx7("polyline", { points: "7 3 7 8 15 8" })
|
|
959
1127
|
] })
|
|
960
1128
|
}
|
|
961
1129
|
)
|
|
962
1130
|
] }),
|
|
963
|
-
commandSaveError && /* @__PURE__ */
|
|
1131
|
+
commandSaveError && /* @__PURE__ */ jsx7(
|
|
964
1132
|
"div",
|
|
965
1133
|
{
|
|
966
1134
|
"data-testid": "command-save-error",
|
|
@@ -995,9 +1163,150 @@ import { useState as useState2, useRef as useRef3, useCallback as useCallback2,
|
|
|
995
1163
|
// src/fileUpload/types.ts
|
|
996
1164
|
var DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
997
1165
|
|
|
1166
|
+
// src/fileUpload/mimeTypeMatcher.ts
|
|
1167
|
+
function matchesMimeType(mimeType, pattern) {
|
|
1168
|
+
if (!pattern.includes("*")) {
|
|
1169
|
+
return mimeType === pattern;
|
|
1170
|
+
}
|
|
1171
|
+
const regexPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
1172
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
1173
|
+
return regex.test(mimeType);
|
|
1174
|
+
}
|
|
1175
|
+
function findTransformer(mimeType, transformers) {
|
|
1176
|
+
if (!transformers) {
|
|
1177
|
+
return void 0;
|
|
1178
|
+
}
|
|
1179
|
+
let bestMatch;
|
|
1180
|
+
let bestIsExact = false;
|
|
1181
|
+
let bestLength = -1;
|
|
1182
|
+
for (const [pattern, transformer] of Object.entries(transformers)) {
|
|
1183
|
+
if (!matchesMimeType(mimeType, pattern)) {
|
|
1184
|
+
continue;
|
|
1185
|
+
}
|
|
1186
|
+
const isExact = !pattern.includes("*");
|
|
1187
|
+
if (isExact && !bestIsExact) {
|
|
1188
|
+
bestMatch = transformer;
|
|
1189
|
+
bestIsExact = true;
|
|
1190
|
+
bestLength = pattern.length;
|
|
1191
|
+
continue;
|
|
1192
|
+
}
|
|
1193
|
+
if (isExact === bestIsExact && pattern.length > bestLength) {
|
|
1194
|
+
bestMatch = transformer;
|
|
1195
|
+
bestLength = pattern.length;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
return bestMatch;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
// src/fileUpload/EmbedFileUploadBackend.ts
|
|
1202
|
+
var EmbedFileUploadBackend = class {
|
|
1203
|
+
/**
|
|
1204
|
+
* Converts a File to a base64 data URL.
|
|
1205
|
+
*
|
|
1206
|
+
* @param file - The File object to convert
|
|
1207
|
+
* @returns Promise resolving to a base64 data URL (e.g., "data:image/png;base64,...")
|
|
1208
|
+
* @throws Error if file reading fails
|
|
1209
|
+
*/
|
|
1210
|
+
async prepareForSend(file) {
|
|
1211
|
+
return new Promise((resolve, reject) => {
|
|
1212
|
+
const reader = new FileReader();
|
|
1213
|
+
reader.onload = () => {
|
|
1214
|
+
if (typeof reader.result === "string") {
|
|
1215
|
+
resolve(reader.result);
|
|
1216
|
+
} else {
|
|
1217
|
+
reject(new Error("Failed to read file as data URL"));
|
|
1218
|
+
}
|
|
1219
|
+
};
|
|
1220
|
+
reader.onerror = () => {
|
|
1221
|
+
reject(new Error(`Failed to read file: ${file.name}`));
|
|
1222
|
+
};
|
|
1223
|
+
reader.readAsDataURL(file);
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1226
|
+
};
|
|
1227
|
+
|
|
1228
|
+
// src/fileUpload/processAttachments.ts
|
|
1229
|
+
var transformationCache = /* @__PURE__ */ new Map();
|
|
1230
|
+
function getFileCacheKey(file) {
|
|
1231
|
+
return `${file.name}:${file.size}:${file.lastModified}`;
|
|
1232
|
+
}
|
|
1233
|
+
async function getTransformedContent(file, transformer, context, onProgress) {
|
|
1234
|
+
const cacheKey = getFileCacheKey(file);
|
|
1235
|
+
const cached = transformationCache.get(cacheKey);
|
|
1236
|
+
if (cached !== void 0) {
|
|
1237
|
+
return cached;
|
|
1238
|
+
}
|
|
1239
|
+
const result = await transformer.transform(file, context, onProgress);
|
|
1240
|
+
transformationCache.set(cacheKey, result);
|
|
1241
|
+
return result;
|
|
1242
|
+
}
|
|
1243
|
+
async function processAttachments(attachments, config) {
|
|
1244
|
+
const { getCurrentChat, backend = new EmbedFileUploadBackend(), transformers = {}, onFileProgress } = config;
|
|
1245
|
+
const contentParts = [];
|
|
1246
|
+
const chat = await getCurrentChat();
|
|
1247
|
+
const context = { chat };
|
|
1248
|
+
for (const attachment of attachments) {
|
|
1249
|
+
try {
|
|
1250
|
+
if (attachment.transformedContent !== void 0) {
|
|
1251
|
+
contentParts.push({
|
|
1252
|
+
type: "transformed_file",
|
|
1253
|
+
text: attachment.transformedContent,
|
|
1254
|
+
originalFile: {
|
|
1255
|
+
name: attachment.file.name,
|
|
1256
|
+
mimeType: attachment.file.type,
|
|
1257
|
+
size: attachment.file.size
|
|
1258
|
+
}
|
|
1259
|
+
});
|
|
1260
|
+
continue;
|
|
1261
|
+
}
|
|
1262
|
+
const transformer = findTransformer(attachment.file.type, transformers);
|
|
1263
|
+
if (transformer) {
|
|
1264
|
+
onFileProgress?.(attachment.id, { status: "processing" });
|
|
1265
|
+
const transformedText = await getTransformedContent(
|
|
1266
|
+
attachment.file,
|
|
1267
|
+
transformer,
|
|
1268
|
+
context,
|
|
1269
|
+
(progress) => {
|
|
1270
|
+
onFileProgress?.(attachment.id, { status: "processing", progress });
|
|
1271
|
+
}
|
|
1272
|
+
);
|
|
1273
|
+
contentParts.push({
|
|
1274
|
+
type: "transformed_file",
|
|
1275
|
+
text: transformedText,
|
|
1276
|
+
originalFile: {
|
|
1277
|
+
name: attachment.file.name,
|
|
1278
|
+
mimeType: attachment.file.type,
|
|
1279
|
+
size: attachment.file.size
|
|
1280
|
+
}
|
|
1281
|
+
});
|
|
1282
|
+
onFileProgress?.(attachment.id, { status: "done" });
|
|
1283
|
+
} else {
|
|
1284
|
+
const url = await backend.prepareForSend(attachment.file);
|
|
1285
|
+
if (attachment.file.type.startsWith("image/")) {
|
|
1286
|
+
contentParts.push({ type: "image", url });
|
|
1287
|
+
} else {
|
|
1288
|
+
contentParts.push({
|
|
1289
|
+
type: "file",
|
|
1290
|
+
url,
|
|
1291
|
+
mimeType: attachment.file.type,
|
|
1292
|
+
name: attachment.file.name
|
|
1293
|
+
});
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
} catch (error) {
|
|
1297
|
+
onFileProgress?.(attachment.id, { status: "error" });
|
|
1298
|
+
throw error;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
return contentParts;
|
|
1302
|
+
}
|
|
1303
|
+
function clearTransformationCache() {
|
|
1304
|
+
transformationCache.clear();
|
|
1305
|
+
}
|
|
1306
|
+
|
|
998
1307
|
// src/hooks/useFileUpload.tsx
|
|
999
1308
|
import { v4 as uuidv4 } from "uuid";
|
|
1000
|
-
import { jsx as
|
|
1309
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1001
1310
|
async function generateImagePreview(file) {
|
|
1002
1311
|
if (!file.type.startsWith("image/")) {
|
|
1003
1312
|
return void 0;
|
|
@@ -1030,18 +1339,21 @@ function isTypeAccepted(mimeType, acceptedTypes) {
|
|
|
1030
1339
|
function useFileUpload({
|
|
1031
1340
|
config,
|
|
1032
1341
|
disabled = false,
|
|
1033
|
-
resetDependency
|
|
1342
|
+
resetDependency,
|
|
1343
|
+
getCurrentChat
|
|
1034
1344
|
}) {
|
|
1035
1345
|
const strings = useStrings();
|
|
1036
1346
|
const theme = useTheme();
|
|
1037
1347
|
const [attachments, setAttachments] = useState2([]);
|
|
1038
1348
|
const [isDragging, setIsDragging] = useState2(false);
|
|
1039
1349
|
const [fileError, setFileError] = useState2(null);
|
|
1350
|
+
const [processingState, setProcessingState] = useState2(/* @__PURE__ */ new Map());
|
|
1040
1351
|
const fileInputRef = useRef3(null);
|
|
1041
1352
|
const dragCounterRef = useRef3(0);
|
|
1042
1353
|
const enabled = config !== void 0;
|
|
1043
1354
|
const maxFileSize = config?.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
|
|
1044
1355
|
const acceptedTypes = config?.acceptedTypes;
|
|
1356
|
+
const transformers = config?.transformers;
|
|
1045
1357
|
useEffect3(() => {
|
|
1046
1358
|
if (fileError) {
|
|
1047
1359
|
const timer = setTimeout(() => setFileError(null), 3e3);
|
|
@@ -1051,7 +1363,28 @@ function useFileUpload({
|
|
|
1051
1363
|
useEffect3(() => {
|
|
1052
1364
|
setAttachments([]);
|
|
1053
1365
|
setFileError(null);
|
|
1366
|
+
setProcessingState(/* @__PURE__ */ new Map());
|
|
1054
1367
|
}, [resetDependency]);
|
|
1368
|
+
const runTransformer = useCallback2(async (attachmentId, file, transformer) => {
|
|
1369
|
+
setProcessingState((prev) => new Map(prev).set(attachmentId, { status: "processing" }));
|
|
1370
|
+
try {
|
|
1371
|
+
const chat = await getCurrentChat();
|
|
1372
|
+
const context = { chat };
|
|
1373
|
+
const transformedContent = await getTransformedContent(file, transformer, context, (progress) => {
|
|
1374
|
+
setProcessingState((prev) => new Map(prev).set(attachmentId, {
|
|
1375
|
+
status: "processing",
|
|
1376
|
+
progress
|
|
1377
|
+
}));
|
|
1378
|
+
});
|
|
1379
|
+
setAttachments((prev) => prev.map(
|
|
1380
|
+
(a) => a.id === attachmentId ? { ...a, transformedContent } : a
|
|
1381
|
+
));
|
|
1382
|
+
setProcessingState((prev) => new Map(prev).set(attachmentId, { status: "done" }));
|
|
1383
|
+
} catch (error) {
|
|
1384
|
+
console.error(`[useFileUpload] Transformation failed for ${file.name}:`, error);
|
|
1385
|
+
setProcessingState((prev) => new Map(prev).set(attachmentId, { status: "error" }));
|
|
1386
|
+
}
|
|
1387
|
+
}, [getCurrentChat]);
|
|
1055
1388
|
const handleFiles = useCallback2(async (files) => {
|
|
1056
1389
|
const fileArray = Array.from(files);
|
|
1057
1390
|
for (const file of fileArray) {
|
|
@@ -1066,21 +1399,30 @@ function useFileUpload({
|
|
|
1066
1399
|
continue;
|
|
1067
1400
|
}
|
|
1068
1401
|
const preview = await generateImagePreview(file);
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1402
|
+
const attachmentId = uuidv4();
|
|
1403
|
+
const attachment = {
|
|
1404
|
+
id: attachmentId,
|
|
1405
|
+
file,
|
|
1406
|
+
preview
|
|
1407
|
+
};
|
|
1408
|
+
setAttachments((prev) => [...prev, attachment]);
|
|
1409
|
+
const transformer = findTransformer(file.type, transformers);
|
|
1410
|
+
if (transformer) {
|
|
1411
|
+
runTransformer(attachmentId, file, transformer);
|
|
1412
|
+
}
|
|
1077
1413
|
}
|
|
1078
|
-
}, [maxFileSize, acceptedTypes, strings]);
|
|
1414
|
+
}, [maxFileSize, acceptedTypes, strings, transformers, runTransformer]);
|
|
1079
1415
|
const removeAttachment = useCallback2((id) => {
|
|
1080
1416
|
setAttachments((prev) => prev.filter((a) => a.id !== id));
|
|
1417
|
+
setProcessingState((prev) => {
|
|
1418
|
+
const next = new Map(prev);
|
|
1419
|
+
next.delete(id);
|
|
1420
|
+
return next;
|
|
1421
|
+
});
|
|
1081
1422
|
}, []);
|
|
1082
1423
|
const clearAttachments = useCallback2(() => {
|
|
1083
1424
|
setAttachments([]);
|
|
1425
|
+
setProcessingState(/* @__PURE__ */ new Map());
|
|
1084
1426
|
}, []);
|
|
1085
1427
|
const openFilePicker = useCallback2(() => {
|
|
1086
1428
|
fileInputRef.current?.click();
|
|
@@ -1133,7 +1475,7 @@ function useFileUpload({
|
|
|
1133
1475
|
}), [handleDragEnter, handleDragOver, handleDragLeave, handleDrop]);
|
|
1134
1476
|
const DropZoneOverlay = useMemo(() => {
|
|
1135
1477
|
if (!isDragging || !enabled) return null;
|
|
1136
|
-
return /* @__PURE__ */
|
|
1478
|
+
return /* @__PURE__ */ jsx8(
|
|
1137
1479
|
"div",
|
|
1138
1480
|
{
|
|
1139
1481
|
style: {
|
|
@@ -1148,7 +1490,7 @@ function useFileUpload({
|
|
|
1148
1490
|
zIndex: 1010,
|
|
1149
1491
|
pointerEvents: "none"
|
|
1150
1492
|
},
|
|
1151
|
-
children: /* @__PURE__ */
|
|
1493
|
+
children: /* @__PURE__ */ jsx8(
|
|
1152
1494
|
"div",
|
|
1153
1495
|
{
|
|
1154
1496
|
style: {
|
|
@@ -1157,7 +1499,7 @@ function useFileUpload({
|
|
|
1157
1499
|
borderRadius: "12px",
|
|
1158
1500
|
boxShadow: theme.buttonShadow
|
|
1159
1501
|
},
|
|
1160
|
-
children: /* @__PURE__ */
|
|
1502
|
+
children: /* @__PURE__ */ jsx8("span", { style: { color: theme.primaryColor, fontWeight: 600, fontSize: "16px" }, children: strings.fileUpload.dropFilesHere })
|
|
1161
1503
|
}
|
|
1162
1504
|
)
|
|
1163
1505
|
}
|
|
@@ -1170,6 +1512,7 @@ function useFileUpload({
|
|
|
1170
1512
|
enabled,
|
|
1171
1513
|
maxFileSize,
|
|
1172
1514
|
acceptedTypes,
|
|
1515
|
+
processingState,
|
|
1173
1516
|
fileInputRef,
|
|
1174
1517
|
handleFiles,
|
|
1175
1518
|
removeAttachment,
|
|
@@ -1187,7 +1530,7 @@ function useFileUpload({
|
|
|
1187
1530
|
|
|
1188
1531
|
// src/hooks/useDropdownState.tsx
|
|
1189
1532
|
import { useState as useState3, useCallback as useCallback3, useMemo as useMemo2 } from "react";
|
|
1190
|
-
import { jsx as
|
|
1533
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1191
1534
|
function useDropdownState(options = {}) {
|
|
1192
1535
|
const { backdropZIndex = 1002, initialOpen = false } = options;
|
|
1193
1536
|
const [isOpen, setIsOpen] = useState3(initialOpen);
|
|
@@ -1202,7 +1545,7 @@ function useDropdownState(options = {}) {
|
|
|
1202
1545
|
}, []);
|
|
1203
1546
|
const Backdrop = useMemo2(() => {
|
|
1204
1547
|
if (!isOpen) return null;
|
|
1205
|
-
return /* @__PURE__ */
|
|
1548
|
+
return /* @__PURE__ */ jsx9(
|
|
1206
1549
|
"div",
|
|
1207
1550
|
{
|
|
1208
1551
|
onClick: close,
|
|
@@ -1227,7 +1570,7 @@ function useDropdownState(options = {}) {
|
|
|
1227
1570
|
}
|
|
1228
1571
|
|
|
1229
1572
|
// src/components/UseAIChatPanel.tsx
|
|
1230
|
-
import { Fragment, jsx as
|
|
1573
|
+
import { Fragment, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1231
1574
|
function getTextContent(content) {
|
|
1232
1575
|
if (typeof content === "string") {
|
|
1233
1576
|
return content;
|
|
@@ -1248,12 +1591,14 @@ function UseAIChatPanel({
|
|
|
1248
1591
|
onLoadChat,
|
|
1249
1592
|
onDeleteChat,
|
|
1250
1593
|
onListChats,
|
|
1594
|
+
onGetChat,
|
|
1251
1595
|
suggestions,
|
|
1252
1596
|
availableAgents,
|
|
1253
1597
|
defaultAgent,
|
|
1254
1598
|
selectedAgent,
|
|
1255
1599
|
onAgentChange,
|
|
1256
1600
|
fileUploadConfig,
|
|
1601
|
+
fileProcessing,
|
|
1257
1602
|
commands = [],
|
|
1258
1603
|
onSaveCommand,
|
|
1259
1604
|
onRenameCommand,
|
|
@@ -1275,6 +1620,7 @@ function UseAIChatPanel({
|
|
|
1275
1620
|
fileError,
|
|
1276
1621
|
enabled: fileUploadEnabled,
|
|
1277
1622
|
acceptedTypes,
|
|
1623
|
+
processingState: fileProcessingState,
|
|
1278
1624
|
fileInputRef,
|
|
1279
1625
|
removeAttachment,
|
|
1280
1626
|
clearAttachments,
|
|
@@ -1283,6 +1629,7 @@ function UseAIChatPanel({
|
|
|
1283
1629
|
getDropZoneProps,
|
|
1284
1630
|
DropZoneOverlay
|
|
1285
1631
|
} = useFileUpload({
|
|
1632
|
+
getCurrentChat: onGetChat ?? (async () => null),
|
|
1286
1633
|
config: fileUploadConfig,
|
|
1287
1634
|
disabled: loading,
|
|
1288
1635
|
resetDependency: currentChatId
|
|
@@ -1354,7 +1701,7 @@ function UseAIChatPanel({
|
|
|
1354
1701
|
chatHistoryDropdown.close();
|
|
1355
1702
|
}
|
|
1356
1703
|
};
|
|
1357
|
-
return /* @__PURE__ */
|
|
1704
|
+
return /* @__PURE__ */ jsxs7(
|
|
1358
1705
|
"div",
|
|
1359
1706
|
{
|
|
1360
1707
|
onClick: () => {
|
|
@@ -1372,7 +1719,7 @@ function UseAIChatPanel({
|
|
|
1372
1719
|
},
|
|
1373
1720
|
children: [
|
|
1374
1721
|
DropZoneOverlay,
|
|
1375
|
-
/* @__PURE__ */
|
|
1722
|
+
/* @__PURE__ */ jsxs7(
|
|
1376
1723
|
"div",
|
|
1377
1724
|
{
|
|
1378
1725
|
style: {
|
|
@@ -1385,7 +1732,7 @@ function UseAIChatPanel({
|
|
|
1385
1732
|
gap: "12px"
|
|
1386
1733
|
},
|
|
1387
1734
|
children: [
|
|
1388
|
-
/* @__PURE__ */
|
|
1735
|
+
/* @__PURE__ */ jsx10("div", { style: { flex: 1, minWidth: 0, position: "relative" }, children: onListChats ? /* @__PURE__ */ jsxs7(
|
|
1389
1736
|
"button",
|
|
1390
1737
|
{
|
|
1391
1738
|
"data-testid": "chat-history-dropdown-button",
|
|
@@ -1418,7 +1765,7 @@ function UseAIChatPanel({
|
|
|
1418
1765
|
e.currentTarget.style.background = "transparent";
|
|
1419
1766
|
},
|
|
1420
1767
|
children: [
|
|
1421
|
-
/* @__PURE__ */
|
|
1768
|
+
/* @__PURE__ */ jsx10("span", { style: {
|
|
1422
1769
|
overflow: "hidden",
|
|
1423
1770
|
textOverflow: "ellipsis",
|
|
1424
1771
|
whiteSpace: "nowrap",
|
|
@@ -1435,13 +1782,13 @@ function UseAIChatPanel({
|
|
|
1435
1782
|
}
|
|
1436
1783
|
return strings.header.newChat;
|
|
1437
1784
|
})() }),
|
|
1438
|
-
/* @__PURE__ */
|
|
1785
|
+
/* @__PURE__ */ jsx10("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx10("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
1439
1786
|
]
|
|
1440
1787
|
}
|
|
1441
|
-
) : /* @__PURE__ */
|
|
1442
|
-
/* @__PURE__ */
|
|
1443
|
-
availableAgents && availableAgents.length > 1 && onAgentChange && /* @__PURE__ */
|
|
1444
|
-
/* @__PURE__ */
|
|
1788
|
+
) : /* @__PURE__ */ jsx10("div", { style: { fontSize: "14px", fontWeight: "600", color: theme.textColor, padding: "6px 8px" }, children: strings.header.aiAssistant }) }),
|
|
1789
|
+
/* @__PURE__ */ jsxs7("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
|
|
1790
|
+
availableAgents && availableAgents.length > 1 && onAgentChange && /* @__PURE__ */ jsxs7("div", { style: { position: "relative" }, children: [
|
|
1791
|
+
/* @__PURE__ */ jsxs7(
|
|
1445
1792
|
"button",
|
|
1446
1793
|
{
|
|
1447
1794
|
"data-testid": "agent-selector",
|
|
@@ -1470,7 +1817,7 @@ function UseAIChatPanel({
|
|
|
1470
1817
|
},
|
|
1471
1818
|
title: "Select AI model",
|
|
1472
1819
|
children: [
|
|
1473
|
-
/* @__PURE__ */
|
|
1820
|
+
/* @__PURE__ */ jsx10("span", { style: {
|
|
1474
1821
|
overflow: "hidden",
|
|
1475
1822
|
textOverflow: "ellipsis",
|
|
1476
1823
|
whiteSpace: "nowrap",
|
|
@@ -1479,11 +1826,11 @@ function UseAIChatPanel({
|
|
|
1479
1826
|
const agent = availableAgents.find((a) => a.id === (selectedAgent ?? defaultAgent));
|
|
1480
1827
|
return agent?.name || "AI";
|
|
1481
1828
|
})() }),
|
|
1482
|
-
/* @__PURE__ */
|
|
1829
|
+
/* @__PURE__ */ jsx10("svg", { width: "10", height: "10", viewBox: "0 0 12 12", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx10("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
1483
1830
|
]
|
|
1484
1831
|
}
|
|
1485
1832
|
),
|
|
1486
|
-
agentDropdown.isOpen && /* @__PURE__ */
|
|
1833
|
+
agentDropdown.isOpen && /* @__PURE__ */ jsx10(
|
|
1487
1834
|
"div",
|
|
1488
1835
|
{
|
|
1489
1836
|
style: {
|
|
@@ -1503,7 +1850,7 @@ function UseAIChatPanel({
|
|
|
1503
1850
|
},
|
|
1504
1851
|
children: availableAgents.map((agent) => {
|
|
1505
1852
|
const isSelected = agent.id === (selectedAgent ?? defaultAgent);
|
|
1506
|
-
return /* @__PURE__ */
|
|
1853
|
+
return /* @__PURE__ */ jsxs7(
|
|
1507
1854
|
"div",
|
|
1508
1855
|
{
|
|
1509
1856
|
"data-testid": "agent-option",
|
|
@@ -1533,13 +1880,13 @@ function UseAIChatPanel({
|
|
|
1533
1880
|
}
|
|
1534
1881
|
},
|
|
1535
1882
|
children: [
|
|
1536
|
-
/* @__PURE__ */
|
|
1537
|
-
/* @__PURE__ */
|
|
1883
|
+
/* @__PURE__ */ jsxs7("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
1884
|
+
/* @__PURE__ */ jsx10("div", { style: {
|
|
1538
1885
|
fontSize: "13px",
|
|
1539
1886
|
fontWeight: isSelected ? "600" : "500",
|
|
1540
1887
|
color: isSelected ? theme.primaryColor : theme.textColor
|
|
1541
1888
|
}, children: agent.name }),
|
|
1542
|
-
agent.annotation && /* @__PURE__ */
|
|
1889
|
+
agent.annotation && /* @__PURE__ */ jsx10("div", { style: {
|
|
1543
1890
|
fontSize: "11px",
|
|
1544
1891
|
color: theme.secondaryTextColor,
|
|
1545
1892
|
marginTop: "2px",
|
|
@@ -1548,7 +1895,7 @@ function UseAIChatPanel({
|
|
|
1548
1895
|
whiteSpace: "nowrap"
|
|
1549
1896
|
}, children: agent.annotation })
|
|
1550
1897
|
] }),
|
|
1551
|
-
isSelected && /* @__PURE__ */
|
|
1898
|
+
isSelected && /* @__PURE__ */ jsx10("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx10("path", { d: "M2 7L5.5 10.5L12 4", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
1552
1899
|
]
|
|
1553
1900
|
},
|
|
1554
1901
|
agent.id
|
|
@@ -1557,7 +1904,7 @@ function UseAIChatPanel({
|
|
|
1557
1904
|
}
|
|
1558
1905
|
)
|
|
1559
1906
|
] }),
|
|
1560
|
-
onNewChat && /* @__PURE__ */
|
|
1907
|
+
onNewChat && /* @__PURE__ */ jsx10(
|
|
1561
1908
|
"button",
|
|
1562
1909
|
{
|
|
1563
1910
|
"data-testid": "new-chat-button",
|
|
@@ -1584,10 +1931,10 @@ function UseAIChatPanel({
|
|
|
1584
1931
|
e.currentTarget.style.color = theme.secondaryTextColor;
|
|
1585
1932
|
},
|
|
1586
1933
|
title: strings.header.newChat,
|
|
1587
|
-
children: /* @__PURE__ */
|
|
1934
|
+
children: /* @__PURE__ */ jsx10("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx10("path", { d: "M8 3.5V12.5M3.5 8H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) })
|
|
1588
1935
|
}
|
|
1589
1936
|
),
|
|
1590
|
-
onDeleteChat && messages.length > 0 && /* @__PURE__ */
|
|
1937
|
+
onDeleteChat && messages.length > 0 && /* @__PURE__ */ jsx10(
|
|
1591
1938
|
"button",
|
|
1592
1939
|
{
|
|
1593
1940
|
"data-testid": "delete-chat-button",
|
|
@@ -1611,7 +1958,7 @@ function UseAIChatPanel({
|
|
|
1611
1958
|
e.currentTarget.style.color = theme.secondaryTextColor;
|
|
1612
1959
|
},
|
|
1613
1960
|
title: strings.header.deleteChat,
|
|
1614
|
-
children: /* @__PURE__ */
|
|
1961
|
+
children: /* @__PURE__ */ jsx10("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx10("path", { d: "M2 4H14M6.5 7V11M9.5 7V11M3 4L4 13C4 13.5304 4.21071 14.0391 4.58579 14.4142C4.96086 14.7893 5.46957 15 6 15H10C10.5304 15 11.0391 14.7893 11.4142 14.4142C11.7893 14.0391 12 13.5304 12 13L13 4M5.5 4V2.5C5.5 2.23478 5.60536 1.98043 5.79289 1.79289C5.98043 1.60536 6.23478 1.5 6.5 1.5H9.5C9.76522 1.5 10.0196 1.60536 10.2071 1.79289C10.3946 1.98043 10.5 2.23478 10.5 2.5V4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
1615
1962
|
}
|
|
1616
1963
|
),
|
|
1617
1964
|
closeButton
|
|
@@ -1619,7 +1966,7 @@ function UseAIChatPanel({
|
|
|
1619
1966
|
]
|
|
1620
1967
|
}
|
|
1621
1968
|
),
|
|
1622
|
-
chatHistoryDropdown.isOpen && onListChats && /* @__PURE__ */
|
|
1969
|
+
chatHistoryDropdown.isOpen && onListChats && /* @__PURE__ */ jsx10(
|
|
1623
1970
|
"div",
|
|
1624
1971
|
{
|
|
1625
1972
|
style: {
|
|
@@ -1636,7 +1983,7 @@ function UseAIChatPanel({
|
|
|
1636
1983
|
flexDirection: "column",
|
|
1637
1984
|
overflow: "hidden"
|
|
1638
1985
|
},
|
|
1639
|
-
children: /* @__PURE__ */
|
|
1986
|
+
children: /* @__PURE__ */ jsx10(
|
|
1640
1987
|
"div",
|
|
1641
1988
|
{
|
|
1642
1989
|
style: {
|
|
@@ -1644,7 +1991,7 @@ function UseAIChatPanel({
|
|
|
1644
1991
|
overflowY: "auto",
|
|
1645
1992
|
padding: "8px"
|
|
1646
1993
|
},
|
|
1647
|
-
children: chatHistory.length === 0 ? /* @__PURE__ */
|
|
1994
|
+
children: chatHistory.length === 0 ? /* @__PURE__ */ jsx10(
|
|
1648
1995
|
"div",
|
|
1649
1996
|
{
|
|
1650
1997
|
style: {
|
|
@@ -1653,9 +2000,9 @@ function UseAIChatPanel({
|
|
|
1653
2000
|
padding: "32px 16px",
|
|
1654
2001
|
fontSize: "13px"
|
|
1655
2002
|
},
|
|
1656
|
-
children: /* @__PURE__ */
|
|
2003
|
+
children: /* @__PURE__ */ jsx10("p", { style: { margin: 0 }, children: strings.chatHistory.noChatHistory })
|
|
1657
2004
|
}
|
|
1658
|
-
) : chatHistory.map((chat) => /* @__PURE__ */
|
|
2005
|
+
) : chatHistory.map((chat) => /* @__PURE__ */ jsxs7(
|
|
1659
2006
|
"div",
|
|
1660
2007
|
{
|
|
1661
2008
|
"data-testid": "chat-history-item",
|
|
@@ -1679,10 +2026,10 @@ function UseAIChatPanel({
|
|
|
1679
2026
|
}
|
|
1680
2027
|
},
|
|
1681
2028
|
children: [
|
|
1682
|
-
/* @__PURE__ */
|
|
1683
|
-
/* @__PURE__ */
|
|
2029
|
+
/* @__PURE__ */ jsx10("div", { style: { fontSize: "13px", fontWeight: "500", color: theme.textColor, marginBottom: "4px", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: chat.title || strings.header.newChat }),
|
|
2030
|
+
/* @__PURE__ */ jsxs7("div", { style: { fontSize: "11px", color: theme.secondaryTextColor }, children: [
|
|
1684
2031
|
new Date(chat.updatedAt).toLocaleDateString([], { month: "short", day: "numeric" }),
|
|
1685
|
-
currentChatId === chat.id && /* @__PURE__ */
|
|
2032
|
+
currentChatId === chat.id && /* @__PURE__ */ jsxs7("span", { style: {
|
|
1686
2033
|
marginLeft: "8px",
|
|
1687
2034
|
color: theme.primaryColor,
|
|
1688
2035
|
fontWeight: "600"
|
|
@@ -1701,7 +2048,7 @@ function UseAIChatPanel({
|
|
|
1701
2048
|
),
|
|
1702
2049
|
chatHistoryDropdown.Backdrop,
|
|
1703
2050
|
agentDropdown.Backdrop,
|
|
1704
|
-
/* @__PURE__ */
|
|
2051
|
+
/* @__PURE__ */ jsxs7(
|
|
1705
2052
|
"div",
|
|
1706
2053
|
{
|
|
1707
2054
|
style: {
|
|
@@ -1713,7 +2060,7 @@ function UseAIChatPanel({
|
|
|
1713
2060
|
gap: "12px"
|
|
1714
2061
|
},
|
|
1715
2062
|
children: [
|
|
1716
|
-
messages.length === 0 && /* @__PURE__ */
|
|
2063
|
+
messages.length === 0 && /* @__PURE__ */ jsxs7(
|
|
1717
2064
|
"div",
|
|
1718
2065
|
{
|
|
1719
2066
|
style: {
|
|
@@ -1724,12 +2071,12 @@ function UseAIChatPanel({
|
|
|
1724
2071
|
gap: "20px"
|
|
1725
2072
|
},
|
|
1726
2073
|
children: [
|
|
1727
|
-
/* @__PURE__ */
|
|
1728
|
-
/* @__PURE__ */
|
|
1729
|
-
/* @__PURE__ */
|
|
1730
|
-
/* @__PURE__ */
|
|
2074
|
+
/* @__PURE__ */ jsxs7("div", { style: { textAlign: "center", color: theme.secondaryTextColor, fontSize: "14px" }, children: [
|
|
2075
|
+
/* @__PURE__ */ jsx10("p", { style: { margin: 0, fontSize: "32px", marginBottom: "12px" }, children: "\u{1F4AC}" }),
|
|
2076
|
+
/* @__PURE__ */ jsx10("p", { style: { margin: 0 }, children: strings.emptyChat.startConversation }),
|
|
2077
|
+
/* @__PURE__ */ jsx10("p", { style: { margin: "8px 0 0", fontSize: "12px" }, children: strings.emptyChat.askMeToHelp })
|
|
1731
2078
|
] }),
|
|
1732
|
-
displayedSuggestions.length > 0 && /* @__PURE__ */
|
|
2079
|
+
displayedSuggestions.length > 0 && /* @__PURE__ */ jsx10(
|
|
1733
2080
|
"div",
|
|
1734
2081
|
{
|
|
1735
2082
|
style: {
|
|
@@ -1739,7 +2086,7 @@ function UseAIChatPanel({
|
|
|
1739
2086
|
width: "100%",
|
|
1740
2087
|
maxWidth: "320px"
|
|
1741
2088
|
},
|
|
1742
|
-
children: displayedSuggestions.map((suggestion, index) => /* @__PURE__ */
|
|
2089
|
+
children: displayedSuggestions.map((suggestion, index) => /* @__PURE__ */ jsx10(
|
|
1743
2090
|
"button",
|
|
1744
2091
|
{
|
|
1745
2092
|
"data-testid": "chat-suggestion-button",
|
|
@@ -1783,7 +2130,7 @@ function UseAIChatPanel({
|
|
|
1783
2130
|
]
|
|
1784
2131
|
}
|
|
1785
2132
|
),
|
|
1786
|
-
messages.map((message) => /* @__PURE__ */
|
|
2133
|
+
messages.map((message) => /* @__PURE__ */ jsxs7(
|
|
1787
2134
|
"div",
|
|
1788
2135
|
{
|
|
1789
2136
|
"data-testid": `chat-message-${message.role}`,
|
|
@@ -1796,7 +2143,7 @@ function UseAIChatPanel({
|
|
|
1796
2143
|
onMouseEnter: () => message.role === "user" && setHoveredMessageId(message.id),
|
|
1797
2144
|
onMouseLeave: () => setHoveredMessageId(null),
|
|
1798
2145
|
children: [
|
|
1799
|
-
/* @__PURE__ */
|
|
2146
|
+
/* @__PURE__ */ jsxs7(
|
|
1800
2147
|
"div",
|
|
1801
2148
|
{
|
|
1802
2149
|
style: {
|
|
@@ -1804,7 +2151,7 @@ function UseAIChatPanel({
|
|
|
1804
2151
|
maxWidth: "80%"
|
|
1805
2152
|
},
|
|
1806
2153
|
children: [
|
|
1807
|
-
message.role === "user" && hoveredMessageId === message.id && onSaveCommand && !slashCommands.isSavingCommand(message.id) && /* @__PURE__ */
|
|
2154
|
+
message.role === "user" && hoveredMessageId === message.id && onSaveCommand && !slashCommands.isSavingCommand(message.id) && /* @__PURE__ */ jsx10(
|
|
1808
2155
|
"button",
|
|
1809
2156
|
{
|
|
1810
2157
|
"data-testid": "save-command-button",
|
|
@@ -1840,14 +2187,14 @@ function UseAIChatPanel({
|
|
|
1840
2187
|
e.currentTarget.style.transform = "scale(1)";
|
|
1841
2188
|
e.currentTarget.style.boxShadow = "0 2px 6px rgba(0, 0, 0, 0.15)";
|
|
1842
2189
|
},
|
|
1843
|
-
children: /* @__PURE__ */
|
|
1844
|
-
/* @__PURE__ */
|
|
1845
|
-
/* @__PURE__ */
|
|
1846
|
-
/* @__PURE__ */
|
|
2190
|
+
children: /* @__PURE__ */ jsxs7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2191
|
+
/* @__PURE__ */ jsx10("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }),
|
|
2192
|
+
/* @__PURE__ */ jsx10("polyline", { points: "17 21 17 13 7 13 7 21" }),
|
|
2193
|
+
/* @__PURE__ */ jsx10("polyline", { points: "7 3 7 8 15 8" })
|
|
1847
2194
|
] })
|
|
1848
2195
|
}
|
|
1849
2196
|
),
|
|
1850
|
-
/* @__PURE__ */
|
|
2197
|
+
/* @__PURE__ */ jsxs7(
|
|
1851
2198
|
"div",
|
|
1852
2199
|
{
|
|
1853
2200
|
"data-testid": "chat-message-content",
|
|
@@ -1862,7 +2209,7 @@ function UseAIChatPanel({
|
|
|
1862
2209
|
wordWrap: "break-word"
|
|
1863
2210
|
},
|
|
1864
2211
|
children: [
|
|
1865
|
-
message.role === "user" && hasFileContent(message.content) && /* @__PURE__ */
|
|
2212
|
+
message.role === "user" && hasFileContent(message.content) && /* @__PURE__ */ jsx10("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px", marginBottom: "8px" }, children: message.content.filter((part) => part.type === "file").map((part, idx) => /* @__PURE__ */ jsx10(
|
|
1866
2213
|
FilePlaceholder,
|
|
1867
2214
|
{
|
|
1868
2215
|
name: part.file.name,
|
|
@@ -1870,7 +2217,7 @@ function UseAIChatPanel({
|
|
|
1870
2217
|
},
|
|
1871
2218
|
idx
|
|
1872
2219
|
)) }),
|
|
1873
|
-
message.role === "assistant" ? /* @__PURE__ */
|
|
2220
|
+
message.role === "assistant" ? /* @__PURE__ */ jsx10(MarkdownContent, { content: getTextContent(message.content) }) : getTextContent(message.content)
|
|
1874
2221
|
]
|
|
1875
2222
|
}
|
|
1876
2223
|
),
|
|
@@ -1881,7 +2228,7 @@ function UseAIChatPanel({
|
|
|
1881
2228
|
]
|
|
1882
2229
|
}
|
|
1883
2230
|
),
|
|
1884
|
-
/* @__PURE__ */
|
|
2231
|
+
/* @__PURE__ */ jsx10(
|
|
1885
2232
|
"div",
|
|
1886
2233
|
{
|
|
1887
2234
|
style: {
|
|
@@ -1900,14 +2247,14 @@ function UseAIChatPanel({
|
|
|
1900
2247
|
},
|
|
1901
2248
|
message.id
|
|
1902
2249
|
)),
|
|
1903
|
-
loading && /* @__PURE__ */
|
|
2250
|
+
loading && /* @__PURE__ */ jsx10(
|
|
1904
2251
|
"div",
|
|
1905
2252
|
{
|
|
1906
2253
|
style: {
|
|
1907
2254
|
display: "flex",
|
|
1908
2255
|
alignItems: "flex-start"
|
|
1909
2256
|
},
|
|
1910
|
-
children: /* @__PURE__ */
|
|
2257
|
+
children: /* @__PURE__ */ jsx10(
|
|
1911
2258
|
"div",
|
|
1912
2259
|
{
|
|
1913
2260
|
className: "markdown-content",
|
|
@@ -1920,19 +2267,41 @@ function UseAIChatPanel({
|
|
|
1920
2267
|
color: theme.textColor,
|
|
1921
2268
|
maxWidth: "80%"
|
|
1922
2269
|
},
|
|
1923
|
-
children: streamingText ? /* @__PURE__ */
|
|
1924
|
-
/* @__PURE__ */
|
|
1925
|
-
/* @__PURE__ */
|
|
2270
|
+
children: streamingText ? /* @__PURE__ */ jsx10(MarkdownContent, { content: streamingText }) : fileProcessing && fileProcessing.status === "processing" ? /* @__PURE__ */ jsxs7("div", { children: [
|
|
2271
|
+
/* @__PURE__ */ jsx10("span", { style: { opacity: 0.6 }, children: strings.input.processingFile }),
|
|
2272
|
+
fileProcessing.progress != null && /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
2273
|
+
/* @__PURE__ */ jsxs7("span", { style: { opacity: 0.6, marginLeft: "4px" }, children: [
|
|
2274
|
+
Math.round(fileProcessing.progress),
|
|
2275
|
+
"%"
|
|
2276
|
+
] }),
|
|
2277
|
+
/* @__PURE__ */ jsx10("div", { style: {
|
|
2278
|
+
marginTop: "6px",
|
|
2279
|
+
height: "4px",
|
|
2280
|
+
borderRadius: "2px",
|
|
2281
|
+
background: theme.borderColor,
|
|
2282
|
+
overflow: "hidden"
|
|
2283
|
+
}, children: /* @__PURE__ */ jsx10("div", { style: {
|
|
2284
|
+
height: "100%",
|
|
2285
|
+
width: `${fileProcessing.progress}%`,
|
|
2286
|
+
borderRadius: "2px",
|
|
2287
|
+
background: theme.primaryColor,
|
|
2288
|
+
transition: "width 0.3s ease"
|
|
2289
|
+
} }) })
|
|
2290
|
+
] }),
|
|
2291
|
+
fileProcessing.progress == null && /* @__PURE__ */ jsx10("span", { className: "dots", style: { marginLeft: "4px" }, children: "..." })
|
|
2292
|
+
] }) : /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
2293
|
+
/* @__PURE__ */ jsx10("span", { style: { opacity: 0.6 }, children: strings.input.thinking }),
|
|
2294
|
+
/* @__PURE__ */ jsx10("span", { className: "dots", style: { marginLeft: "4px" }, children: "..." })
|
|
1926
2295
|
] })
|
|
1927
2296
|
}
|
|
1928
2297
|
)
|
|
1929
2298
|
}
|
|
1930
2299
|
),
|
|
1931
|
-
/* @__PURE__ */
|
|
2300
|
+
/* @__PURE__ */ jsx10("div", { ref: messagesEndRef })
|
|
1932
2301
|
]
|
|
1933
2302
|
}
|
|
1934
2303
|
),
|
|
1935
|
-
/* @__PURE__ */
|
|
2304
|
+
/* @__PURE__ */ jsxs7(
|
|
1936
2305
|
"div",
|
|
1937
2306
|
{
|
|
1938
2307
|
style: {
|
|
@@ -1940,7 +2309,7 @@ function UseAIChatPanel({
|
|
|
1940
2309
|
borderTop: `1px solid ${theme.borderColor}`
|
|
1941
2310
|
},
|
|
1942
2311
|
children: [
|
|
1943
|
-
fileError && /* @__PURE__ */
|
|
2312
|
+
fileError && /* @__PURE__ */ jsx10(
|
|
1944
2313
|
"div",
|
|
1945
2314
|
{
|
|
1946
2315
|
"data-testid": "file-error",
|
|
@@ -1955,7 +2324,7 @@ function UseAIChatPanel({
|
|
|
1955
2324
|
children: fileError
|
|
1956
2325
|
}
|
|
1957
2326
|
),
|
|
1958
|
-
attachments.length > 0 && /* @__PURE__ */
|
|
2327
|
+
attachments.length > 0 && /* @__PURE__ */ jsx10(
|
|
1959
2328
|
"div",
|
|
1960
2329
|
{
|
|
1961
2330
|
"data-testid": "file-attachments",
|
|
@@ -1965,18 +2334,19 @@ function UseAIChatPanel({
|
|
|
1965
2334
|
gap: "8px",
|
|
1966
2335
|
marginBottom: "8px"
|
|
1967
2336
|
},
|
|
1968
|
-
children: attachments.map((attachment) => /* @__PURE__ */
|
|
2337
|
+
children: attachments.map((attachment) => /* @__PURE__ */ jsx10(
|
|
1969
2338
|
FileChip,
|
|
1970
2339
|
{
|
|
1971
2340
|
attachment,
|
|
1972
2341
|
onRemove: () => removeAttachment(attachment.id),
|
|
1973
|
-
disabled: loading
|
|
2342
|
+
disabled: loading,
|
|
2343
|
+
processingState: fileProcessingState.get(attachment.id)
|
|
1974
2344
|
},
|
|
1975
2345
|
attachment.id
|
|
1976
2346
|
))
|
|
1977
2347
|
}
|
|
1978
2348
|
),
|
|
1979
|
-
/* @__PURE__ */
|
|
2349
|
+
/* @__PURE__ */ jsxs7(
|
|
1980
2350
|
"div",
|
|
1981
2351
|
{
|
|
1982
2352
|
style: {
|
|
@@ -1988,18 +2358,19 @@ function UseAIChatPanel({
|
|
|
1988
2358
|
},
|
|
1989
2359
|
children: [
|
|
1990
2360
|
slashCommands.AutocompleteComponent,
|
|
1991
|
-
/* @__PURE__ */
|
|
2361
|
+
/* @__PURE__ */ jsx10(
|
|
1992
2362
|
"input",
|
|
1993
2363
|
{
|
|
1994
2364
|
ref: fileInputRef,
|
|
1995
2365
|
type: "file",
|
|
1996
2366
|
multiple: true,
|
|
2367
|
+
"data-testid": "file-input",
|
|
1997
2368
|
style: { display: "none" },
|
|
1998
2369
|
onChange: handleFileInputChange,
|
|
1999
2370
|
accept: acceptedTypes?.join(",")
|
|
2000
2371
|
}
|
|
2001
2372
|
),
|
|
2002
|
-
/* @__PURE__ */
|
|
2373
|
+
/* @__PURE__ */ jsx10(
|
|
2003
2374
|
"textarea",
|
|
2004
2375
|
{
|
|
2005
2376
|
ref: textareaRef,
|
|
@@ -2027,7 +2398,7 @@ function UseAIChatPanel({
|
|
|
2027
2398
|
}
|
|
2028
2399
|
}
|
|
2029
2400
|
),
|
|
2030
|
-
/* @__PURE__ */
|
|
2401
|
+
/* @__PURE__ */ jsxs7(
|
|
2031
2402
|
"div",
|
|
2032
2403
|
{
|
|
2033
2404
|
style: {
|
|
@@ -2037,7 +2408,7 @@ function UseAIChatPanel({
|
|
|
2037
2408
|
padding: "4px 8px"
|
|
2038
2409
|
},
|
|
2039
2410
|
children: [
|
|
2040
|
-
/* @__PURE__ */
|
|
2411
|
+
/* @__PURE__ */ jsx10("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: fileUploadEnabled && /* @__PURE__ */ jsx10(
|
|
2041
2412
|
"button",
|
|
2042
2413
|
{
|
|
2043
2414
|
"data-testid": "file-picker-button",
|
|
@@ -2069,13 +2440,13 @@ function UseAIChatPanel({
|
|
|
2069
2440
|
e.currentTarget.style.borderColor = theme.borderColor;
|
|
2070
2441
|
},
|
|
2071
2442
|
title: strings.fileUpload.attachFiles,
|
|
2072
|
-
children: /* @__PURE__ */
|
|
2073
|
-
/* @__PURE__ */
|
|
2074
|
-
/* @__PURE__ */
|
|
2443
|
+
children: /* @__PURE__ */ jsxs7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2444
|
+
/* @__PURE__ */ jsx10("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
|
|
2445
|
+
/* @__PURE__ */ jsx10("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
|
|
2075
2446
|
] })
|
|
2076
2447
|
}
|
|
2077
2448
|
) }),
|
|
2078
|
-
/* @__PURE__ */
|
|
2449
|
+
/* @__PURE__ */ jsx10(
|
|
2079
2450
|
"button",
|
|
2080
2451
|
{
|
|
2081
2452
|
"data-testid": "chat-send-button",
|
|
@@ -2096,9 +2467,9 @@ function UseAIChatPanel({
|
|
|
2096
2467
|
height: "32px",
|
|
2097
2468
|
transition: "all 0.2s"
|
|
2098
2469
|
},
|
|
2099
|
-
children: /* @__PURE__ */
|
|
2100
|
-
/* @__PURE__ */
|
|
2101
|
-
/* @__PURE__ */
|
|
2470
|
+
children: /* @__PURE__ */ jsxs7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2471
|
+
/* @__PURE__ */ jsx10("line", { x1: "12", y1: "19", x2: "12", y2: "5" }),
|
|
2472
|
+
/* @__PURE__ */ jsx10("polyline", { points: "5 12 12 5 19 12" })
|
|
2102
2473
|
] })
|
|
2103
2474
|
}
|
|
2104
2475
|
)
|
|
@@ -2111,7 +2482,7 @@ function UseAIChatPanel({
|
|
|
2111
2482
|
]
|
|
2112
2483
|
}
|
|
2113
2484
|
),
|
|
2114
|
-
/* @__PURE__ */
|
|
2485
|
+
/* @__PURE__ */ jsx10("style", { children: `
|
|
2115
2486
|
/* Markdown content styles */
|
|
2116
2487
|
.markdown-content > :first-child {
|
|
2117
2488
|
margin-top: 0 !important;
|
|
@@ -2136,7 +2507,7 @@ function UseAIChatPanel({
|
|
|
2136
2507
|
}
|
|
2137
2508
|
|
|
2138
2509
|
// src/components/UseAIFloatingChatWrapper.tsx
|
|
2139
|
-
import { Fragment as Fragment2, jsx as
|
|
2510
|
+
import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2140
2511
|
function UseAIFloatingChatWrapper({
|
|
2141
2512
|
isOpen,
|
|
2142
2513
|
onClose,
|
|
@@ -2144,8 +2515,8 @@ function UseAIFloatingChatWrapper({
|
|
|
2144
2515
|
}) {
|
|
2145
2516
|
const theme = useTheme();
|
|
2146
2517
|
if (!isOpen) return null;
|
|
2147
|
-
return /* @__PURE__ */
|
|
2148
|
-
/* @__PURE__ */
|
|
2518
|
+
return /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
2519
|
+
/* @__PURE__ */ jsx11(
|
|
2149
2520
|
"div",
|
|
2150
2521
|
{
|
|
2151
2522
|
style: {
|
|
@@ -2161,7 +2532,7 @@ function UseAIFloatingChatWrapper({
|
|
|
2161
2532
|
onClick: onClose
|
|
2162
2533
|
}
|
|
2163
2534
|
),
|
|
2164
|
-
/* @__PURE__ */
|
|
2535
|
+
/* @__PURE__ */ jsx11(
|
|
2165
2536
|
"div",
|
|
2166
2537
|
{
|
|
2167
2538
|
style: {
|
|
@@ -2180,7 +2551,7 @@ function UseAIFloatingChatWrapper({
|
|
|
2180
2551
|
children
|
|
2181
2552
|
}
|
|
2182
2553
|
),
|
|
2183
|
-
/* @__PURE__ */
|
|
2554
|
+
/* @__PURE__ */ jsx11("style", { children: `
|
|
2184
2555
|
@keyframes fadeIn {
|
|
2185
2556
|
from { opacity: 0; }
|
|
2186
2557
|
to { opacity: 1; }
|
|
@@ -2200,7 +2571,7 @@ function UseAIFloatingChatWrapper({
|
|
|
2200
2571
|
}
|
|
2201
2572
|
function CloseButton({ onClick }) {
|
|
2202
2573
|
const theme = useTheme();
|
|
2203
|
-
return /* @__PURE__ */
|
|
2574
|
+
return /* @__PURE__ */ jsx11(
|
|
2204
2575
|
"button",
|
|
2205
2576
|
{
|
|
2206
2577
|
"data-testid": "chat-close-button",
|
|
@@ -2235,7 +2606,7 @@ function CloseButton({ onClick }) {
|
|
|
2235
2606
|
|
|
2236
2607
|
// src/components/UseAIChat.tsx
|
|
2237
2608
|
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
2238
|
-
import { jsx as
|
|
2609
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
2239
2610
|
var __UseAIChatContext = createContext3(null);
|
|
2240
2611
|
function useChatUIContext() {
|
|
2241
2612
|
const context = useContext3(__UseAIChatContext);
|
|
@@ -2259,34 +2630,36 @@ function UseAIChat({ floating = false }) {
|
|
|
2259
2630
|
onLoadChat: ctx.history.load,
|
|
2260
2631
|
onDeleteChat: ctx.history.delete,
|
|
2261
2632
|
onListChats: ctx.history.list,
|
|
2633
|
+
onGetChat: ctx.history.get,
|
|
2262
2634
|
suggestions: ctx.suggestions,
|
|
2263
2635
|
availableAgents: ctx.agents.available,
|
|
2264
2636
|
defaultAgent: ctx.agents.default,
|
|
2265
2637
|
selectedAgent: ctx.agents.selected,
|
|
2266
2638
|
onAgentChange: ctx.agents.set,
|
|
2267
2639
|
fileUploadConfig: ctx.fileUploadConfig,
|
|
2640
|
+
fileProcessing: ctx.fileProcessing,
|
|
2268
2641
|
commands: ctx.commands.list,
|
|
2269
2642
|
onSaveCommand: ctx.commands.save,
|
|
2270
2643
|
onRenameCommand: ctx.commands.rename,
|
|
2271
2644
|
onDeleteCommand: ctx.commands.delete
|
|
2272
2645
|
};
|
|
2273
2646
|
if (floating) {
|
|
2274
|
-
return /* @__PURE__ */
|
|
2647
|
+
return /* @__PURE__ */ jsx12(
|
|
2275
2648
|
UseAIFloatingChatWrapper,
|
|
2276
2649
|
{
|
|
2277
2650
|
isOpen: ctx.ui.isOpen,
|
|
2278
2651
|
onClose: () => ctx.ui.setOpen(false),
|
|
2279
|
-
children: /* @__PURE__ */
|
|
2652
|
+
children: /* @__PURE__ */ jsx12(
|
|
2280
2653
|
UseAIChatPanel,
|
|
2281
2654
|
{
|
|
2282
2655
|
...chatPanelProps,
|
|
2283
|
-
closeButton: /* @__PURE__ */
|
|
2656
|
+
closeButton: /* @__PURE__ */ jsx12(CloseButton, { onClick: () => ctx.ui.setOpen(false) })
|
|
2284
2657
|
}
|
|
2285
2658
|
)
|
|
2286
2659
|
}
|
|
2287
2660
|
);
|
|
2288
2661
|
}
|
|
2289
|
-
return /* @__PURE__ */
|
|
2662
|
+
return /* @__PURE__ */ jsx12(UseAIChatPanel, { ...chatPanelProps });
|
|
2290
2663
|
}
|
|
2291
2664
|
|
|
2292
2665
|
// src/client.ts
|
|
@@ -2487,12 +2860,18 @@ var UseAIClient = class {
|
|
|
2487
2860
|
return { type: "text", text: part.text };
|
|
2488
2861
|
} else if (part.type === "image") {
|
|
2489
2862
|
return { type: "image", url: part.url };
|
|
2490
|
-
} else {
|
|
2863
|
+
} else if (part.type === "file") {
|
|
2491
2864
|
return {
|
|
2492
2865
|
type: "file",
|
|
2493
2866
|
url: part.url,
|
|
2494
2867
|
mimeType: part.mimeType
|
|
2495
2868
|
};
|
|
2869
|
+
} else {
|
|
2870
|
+
return {
|
|
2871
|
+
type: "transformed_file",
|
|
2872
|
+
text: part.text,
|
|
2873
|
+
originalFile: part.originalFile
|
|
2874
|
+
};
|
|
2496
2875
|
}
|
|
2497
2876
|
});
|
|
2498
2877
|
}
|
|
@@ -2867,7 +3246,8 @@ var LocalStorageChatRepository = class {
|
|
|
2867
3246
|
title: options?.title,
|
|
2868
3247
|
messages: [],
|
|
2869
3248
|
createdAt: now,
|
|
2870
|
-
updatedAt: now
|
|
3249
|
+
updatedAt: now,
|
|
3250
|
+
metadata: options?.metadata
|
|
2871
3251
|
};
|
|
2872
3252
|
await this.enforceMaxChatsLimit();
|
|
2873
3253
|
await this.saveChat(chat);
|
|
@@ -2951,6 +3331,14 @@ var LocalStorageChatRepository = class {
|
|
|
2951
3331
|
throw new Error(`Failed to clear all chats: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2952
3332
|
}
|
|
2953
3333
|
}
|
|
3334
|
+
async updateMetadata(id, metadata, overwrite = false) {
|
|
3335
|
+
const chat = await this.loadChat(id);
|
|
3336
|
+
if (!chat) {
|
|
3337
|
+
throw new Error(`Chat not found: ${id}`);
|
|
3338
|
+
}
|
|
3339
|
+
chat.metadata = overwrite ? metadata : { ...chat.metadata, ...metadata };
|
|
3340
|
+
await this.saveChat(chat);
|
|
3341
|
+
}
|
|
2954
3342
|
getChatKey(id) {
|
|
2955
3343
|
return `${STORAGE_KEY_PREFIX}${id}`;
|
|
2956
3344
|
}
|
|
@@ -2989,36 +3377,12 @@ var LocalStorageChatRepository = class {
|
|
|
2989
3377
|
}
|
|
2990
3378
|
};
|
|
2991
3379
|
|
|
2992
|
-
// src/fileUpload/EmbedFileUploadBackend.ts
|
|
2993
|
-
var EmbedFileUploadBackend = class {
|
|
2994
|
-
/**
|
|
2995
|
-
* Converts a File to a base64 data URL.
|
|
2996
|
-
*
|
|
2997
|
-
* @param file - The File object to convert
|
|
2998
|
-
* @returns Promise resolving to a base64 data URL (e.g., "data:image/png;base64,...")
|
|
2999
|
-
* @throws Error if file reading fails
|
|
3000
|
-
*/
|
|
3001
|
-
async prepareForSend(file) {
|
|
3002
|
-
return new Promise((resolve, reject) => {
|
|
3003
|
-
const reader = new FileReader();
|
|
3004
|
-
reader.onload = () => {
|
|
3005
|
-
if (typeof reader.result === "string") {
|
|
3006
|
-
resolve(reader.result);
|
|
3007
|
-
} else {
|
|
3008
|
-
reject(new Error("Failed to read file as data URL"));
|
|
3009
|
-
}
|
|
3010
|
-
};
|
|
3011
|
-
reader.onerror = () => {
|
|
3012
|
-
reject(new Error(`Failed to read file: ${file.name}`));
|
|
3013
|
-
};
|
|
3014
|
-
reader.readAsDataURL(file);
|
|
3015
|
-
});
|
|
3016
|
-
}
|
|
3017
|
-
};
|
|
3018
|
-
|
|
3019
3380
|
// src/hooks/useChatManagement.ts
|
|
3020
3381
|
import { useState as useState5, useCallback as useCallback4, useRef as useRef5, useEffect as useEffect5 } from "react";
|
|
3021
3382
|
var CHAT_TITLE_MAX_LENGTH = 50;
|
|
3383
|
+
function deepEquals(a, b) {
|
|
3384
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
3385
|
+
}
|
|
3022
3386
|
function generateChatTitle(message) {
|
|
3023
3387
|
return message.length > CHAT_TITLE_MAX_LENGTH ? message.substring(0, CHAT_TITLE_MAX_LENGTH) + "..." : message;
|
|
3024
3388
|
}
|
|
@@ -3049,7 +3413,11 @@ function transformMessagesToClientFormat(uiMessages) {
|
|
|
3049
3413
|
}
|
|
3050
3414
|
function useChatManagement({
|
|
3051
3415
|
repository,
|
|
3052
|
-
clientRef
|
|
3416
|
+
clientRef,
|
|
3417
|
+
onSendMessage,
|
|
3418
|
+
setOpen,
|
|
3419
|
+
connected,
|
|
3420
|
+
loading
|
|
3053
3421
|
}) {
|
|
3054
3422
|
const [currentChatId, setCurrentChatId] = useState5(null);
|
|
3055
3423
|
const [pendingChatId, setPendingChatId] = useState5(null);
|
|
@@ -3082,18 +3450,18 @@ function useChatManagement({
|
|
|
3082
3450
|
const loadedMessages = await loadChatMessages(chatId);
|
|
3083
3451
|
setMessages(loadedMessages);
|
|
3084
3452
|
}, [loadChatMessages]);
|
|
3085
|
-
const createNewChat = useCallback4(async () => {
|
|
3453
|
+
const createNewChat = useCallback4(async (options) => {
|
|
3086
3454
|
console.log("[ChatManagement] createNewChat called - currentChatId:", currentChatId, "pendingChatId:", pendingChatId, "messages.length:", messages.length);
|
|
3087
3455
|
if (pendingChatId && messages.length === 0) {
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3456
|
+
const existingChat = await repository.loadChat(pendingChatId);
|
|
3457
|
+
const optionsMatch = existingChat && existingChat.title === options?.title && deepEquals(existingChat.metadata, options?.metadata);
|
|
3458
|
+
if (optionsMatch) {
|
|
3459
|
+
console.log("[ChatManagement] Last created chat has matching options, reusing:", pendingChatId);
|
|
3460
|
+
return pendingChatId;
|
|
3461
|
+
}
|
|
3094
3462
|
}
|
|
3095
3463
|
console.log("[ChatManagement] Creating new chat...");
|
|
3096
|
-
const chatId = await repository.createChat();
|
|
3464
|
+
const chatId = await repository.createChat(options);
|
|
3097
3465
|
setPendingChatId(chatId);
|
|
3098
3466
|
setMessages([]);
|
|
3099
3467
|
if (clientRef.current) {
|
|
@@ -3138,6 +3506,22 @@ function useChatManagement({
|
|
|
3138
3506
|
}
|
|
3139
3507
|
}
|
|
3140
3508
|
}, [currentChatId, repository]);
|
|
3509
|
+
const getCurrentChat = useCallback4(async () => {
|
|
3510
|
+
const chatId = pendingChatId || currentChatId;
|
|
3511
|
+
if (!chatId) return null;
|
|
3512
|
+
const chat = await repository.loadChat(chatId);
|
|
3513
|
+
if (chat?.metadata) {
|
|
3514
|
+
chat.metadata = Object.freeze({ ...chat.metadata });
|
|
3515
|
+
}
|
|
3516
|
+
return chat;
|
|
3517
|
+
}, [pendingChatId, currentChatId, repository]);
|
|
3518
|
+
const updateMetadata = useCallback4(async (metadata, overwrite = false) => {
|
|
3519
|
+
const chatId = pendingChatId || currentChatId;
|
|
3520
|
+
if (!chatId) {
|
|
3521
|
+
throw new Error("No active chat");
|
|
3522
|
+
}
|
|
3523
|
+
await repository.updateMetadata(chatId, metadata, overwrite);
|
|
3524
|
+
}, [pendingChatId, currentChatId, repository]);
|
|
3141
3525
|
const activatePendingChat = useCallback4(() => {
|
|
3142
3526
|
if (!pendingChatId) return null;
|
|
3143
3527
|
console.log("[ChatManagement] Activating pending chat:", pendingChatId);
|
|
@@ -3156,7 +3540,7 @@ function useChatManagement({
|
|
|
3156
3540
|
console.error("[ChatManagement] Chat not found:", chatId);
|
|
3157
3541
|
return false;
|
|
3158
3542
|
}
|
|
3159
|
-
const { generateMessageId: generateMessageId2 } = await import("./types-
|
|
3543
|
+
const { generateMessageId: generateMessageId2 } = await import("./types-64CH2HXY.js");
|
|
3160
3544
|
chat.messages.push({
|
|
3161
3545
|
id: generateMessageId2(),
|
|
3162
3546
|
role: "user",
|
|
@@ -3192,7 +3576,7 @@ function useChatManagement({
|
|
|
3192
3576
|
console.error("[ChatManagement] Chat not found:", currentChatIdValue);
|
|
3193
3577
|
return;
|
|
3194
3578
|
}
|
|
3195
|
-
const { generateMessageId: generateMessageId2 } = await import("./types-
|
|
3579
|
+
const { generateMessageId: generateMessageId2 } = await import("./types-64CH2HXY.js");
|
|
3196
3580
|
chat.messages.push({
|
|
3197
3581
|
id: generateMessageId2(),
|
|
3198
3582
|
role: "assistant",
|
|
@@ -3249,6 +3633,70 @@ function useChatManagement({
|
|
|
3249
3633
|
}
|
|
3250
3634
|
}, [currentChatId, pendingChatId, createNewChat, repository, loadChatMessages, clientRef]);
|
|
3251
3635
|
const displayedChatId = pendingChatId || currentChatId;
|
|
3636
|
+
const pendingMessagesRef = useRef5([]);
|
|
3637
|
+
const isProcessingQueueRef = useRef5(false);
|
|
3638
|
+
const loadingRef = useRef5(loading);
|
|
3639
|
+
useEffect5(() => {
|
|
3640
|
+
loadingRef.current = loading;
|
|
3641
|
+
}, [loading]);
|
|
3642
|
+
const processMessageQueue = useCallback4(async () => {
|
|
3643
|
+
if (isProcessingQueueRef.current || pendingMessagesRef.current.length === 0 || !onSendMessage) {
|
|
3644
|
+
return;
|
|
3645
|
+
}
|
|
3646
|
+
isProcessingQueueRef.current = true;
|
|
3647
|
+
while (pendingMessagesRef.current.length > 0) {
|
|
3648
|
+
const { message, options } = pendingMessagesRef.current.shift();
|
|
3649
|
+
const { newChat = false, attachments = [], openChat = true, metadata } = options ?? {};
|
|
3650
|
+
if (newChat) {
|
|
3651
|
+
await createNewChat({ metadata });
|
|
3652
|
+
}
|
|
3653
|
+
const fileAttachments = await Promise.all(
|
|
3654
|
+
attachments.map(async (file) => {
|
|
3655
|
+
let preview;
|
|
3656
|
+
if (file.type.startsWith("image/")) {
|
|
3657
|
+
preview = await new Promise((resolve) => {
|
|
3658
|
+
const reader = new FileReader();
|
|
3659
|
+
reader.onload = () => resolve(typeof reader.result === "string" ? reader.result : void 0);
|
|
3660
|
+
reader.onerror = () => resolve(void 0);
|
|
3661
|
+
reader.readAsDataURL(file);
|
|
3662
|
+
});
|
|
3663
|
+
}
|
|
3664
|
+
return {
|
|
3665
|
+
id: crypto.randomUUID(),
|
|
3666
|
+
file,
|
|
3667
|
+
preview
|
|
3668
|
+
};
|
|
3669
|
+
})
|
|
3670
|
+
);
|
|
3671
|
+
await onSendMessage(message, fileAttachments.length > 0 ? fileAttachments : void 0);
|
|
3672
|
+
if (openChat && setOpen) {
|
|
3673
|
+
setOpen(true);
|
|
3674
|
+
}
|
|
3675
|
+
await new Promise((resolve) => {
|
|
3676
|
+
const checkLoading = () => {
|
|
3677
|
+
setTimeout(() => {
|
|
3678
|
+
if (!loadingRef.current) {
|
|
3679
|
+
resolve();
|
|
3680
|
+
} else {
|
|
3681
|
+
checkLoading();
|
|
3682
|
+
}
|
|
3683
|
+
}, 100);
|
|
3684
|
+
};
|
|
3685
|
+
checkLoading();
|
|
3686
|
+
});
|
|
3687
|
+
}
|
|
3688
|
+
isProcessingQueueRef.current = false;
|
|
3689
|
+
}, [onSendMessage, createNewChat, setOpen]);
|
|
3690
|
+
const sendMessage = useCallback4(async (message, options) => {
|
|
3691
|
+
if (!onSendMessage) {
|
|
3692
|
+
throw new Error("sendMessage is not available (onSendMessage callback not provided)");
|
|
3693
|
+
}
|
|
3694
|
+
if (!connected) {
|
|
3695
|
+
throw new Error("Not connected to UseAI server");
|
|
3696
|
+
}
|
|
3697
|
+
pendingMessagesRef.current.push({ message, options });
|
|
3698
|
+
await processMessageQueue();
|
|
3699
|
+
}, [onSendMessage, connected, processMessageQueue]);
|
|
3252
3700
|
return {
|
|
3253
3701
|
currentChatId,
|
|
3254
3702
|
pendingChatId,
|
|
@@ -3263,6 +3711,9 @@ function useChatManagement({
|
|
|
3263
3711
|
saveUserMessage,
|
|
3264
3712
|
saveAIResponse,
|
|
3265
3713
|
reloadMessages,
|
|
3714
|
+
sendMessage,
|
|
3715
|
+
getCurrentChat,
|
|
3716
|
+
updateMetadata,
|
|
3266
3717
|
currentChatIdSnapshot,
|
|
3267
3718
|
pendingChatIdSnapshot
|
|
3268
3719
|
};
|
|
@@ -3644,7 +4095,7 @@ function usePromptState({
|
|
|
3644
4095
|
}
|
|
3645
4096
|
|
|
3646
4097
|
// src/providers/useAIProvider.tsx
|
|
3647
|
-
import { Fragment as Fragment3, jsx as
|
|
4098
|
+
import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3648
4099
|
var __UseAIContext = createContext4(null);
|
|
3649
4100
|
var hasWarnedAboutMissingProvider = false;
|
|
3650
4101
|
var noOpContextValue = {
|
|
@@ -3674,6 +4125,11 @@ var noOpContextValue = {
|
|
|
3674
4125
|
},
|
|
3675
4126
|
list: async () => [],
|
|
3676
4127
|
clear: async () => {
|
|
4128
|
+
},
|
|
4129
|
+
sendMessage: async () => {
|
|
4130
|
+
},
|
|
4131
|
+
get: async () => null,
|
|
4132
|
+
updateMetadata: async () => {
|
|
3677
4133
|
}
|
|
3678
4134
|
},
|
|
3679
4135
|
agents: {
|
|
@@ -3713,7 +4169,8 @@ function UseAIProvider({
|
|
|
3713
4169
|
renderChat = true,
|
|
3714
4170
|
theme: customTheme,
|
|
3715
4171
|
strings: customStrings,
|
|
3716
|
-
visibleAgentIds
|
|
4172
|
+
visibleAgentIds,
|
|
4173
|
+
onOpenChange
|
|
3717
4174
|
}) {
|
|
3718
4175
|
const fileUploadConfig = fileUploadConfigProp === false ? void 0 : fileUploadConfigProp ?? DEFAULT_FILE_UPLOAD_CONFIG;
|
|
3719
4176
|
const theme = { ...defaultTheme, ...customTheme };
|
|
@@ -3721,12 +4178,18 @@ function UseAIProvider({
|
|
|
3721
4178
|
const [connected, setConnected] = useState10(false);
|
|
3722
4179
|
const [isChatOpen, setIsChatOpen] = useState10(false);
|
|
3723
4180
|
const [loading, setLoading] = useState10(false);
|
|
4181
|
+
const [fileProcessingState, setFileProcessingState] = useState10(null);
|
|
4182
|
+
const handleSetChatOpen = useCallback9((open) => {
|
|
4183
|
+
setIsChatOpen(open);
|
|
4184
|
+
onOpenChange?.(open);
|
|
4185
|
+
}, [onOpenChange]);
|
|
3724
4186
|
const [streamingText, setStreamingText] = useState10("");
|
|
3725
4187
|
const streamingChatIdRef = useRef9(null);
|
|
3726
4188
|
const clientRef = useRef9(null);
|
|
3727
4189
|
const repositoryRef = useRef9(
|
|
3728
4190
|
chatRepository || new LocalStorageChatRepository()
|
|
3729
4191
|
);
|
|
4192
|
+
const handleSendMessageRef = useRef9(null);
|
|
3730
4193
|
const {
|
|
3731
4194
|
registerTools,
|
|
3732
4195
|
unregisterTools,
|
|
@@ -3748,9 +4211,18 @@ function UseAIProvider({
|
|
|
3748
4211
|
clientRef,
|
|
3749
4212
|
connected
|
|
3750
4213
|
});
|
|
4214
|
+
const stableSendMessage = useCallback9(async (message, attachments) => {
|
|
4215
|
+
if (handleSendMessageRef.current) {
|
|
4216
|
+
await handleSendMessageRef.current(message, attachments);
|
|
4217
|
+
}
|
|
4218
|
+
}, []);
|
|
3751
4219
|
const chatManagement = useChatManagement({
|
|
3752
4220
|
repository: repositoryRef.current,
|
|
3753
|
-
clientRef
|
|
4221
|
+
clientRef,
|
|
4222
|
+
onSendMessage: stableSendMessage,
|
|
4223
|
+
setOpen: handleSetChatOpen,
|
|
4224
|
+
connected,
|
|
4225
|
+
loading
|
|
3754
4226
|
});
|
|
3755
4227
|
const {
|
|
3756
4228
|
currentChatId,
|
|
@@ -3764,7 +4236,10 @@ function UseAIProvider({
|
|
|
3764
4236
|
clearCurrentChat,
|
|
3765
4237
|
activatePendingChat,
|
|
3766
4238
|
saveUserMessage,
|
|
3767
|
-
saveAIResponse
|
|
4239
|
+
saveAIResponse,
|
|
4240
|
+
sendMessage,
|
|
4241
|
+
getCurrentChat,
|
|
4242
|
+
updateMetadata
|
|
3768
4243
|
} = chatManagement;
|
|
3769
4244
|
const {
|
|
3770
4245
|
availableAgents,
|
|
@@ -3905,7 +4380,6 @@ function UseAIProvider({
|
|
|
3905
4380
|
let persistedContent = message;
|
|
3906
4381
|
let multimodalContent;
|
|
3907
4382
|
if (attachments && attachments.length > 0) {
|
|
3908
|
-
const backend = fileUploadConfig?.backend ?? new EmbedFileUploadBackend();
|
|
3909
4383
|
const persistedParts = [];
|
|
3910
4384
|
if (message.trim()) {
|
|
3911
4385
|
persistedParts.push({ type: "text", text: message });
|
|
@@ -3921,35 +4395,39 @@ function UseAIProvider({
|
|
|
3921
4395
|
});
|
|
3922
4396
|
}
|
|
3923
4397
|
persistedContent = persistedParts;
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
contentParts.push({ type: "text", text: message });
|
|
4398
|
+
if (activeChatId) {
|
|
4399
|
+
await saveUserMessage(activeChatId, persistedContent);
|
|
3927
4400
|
}
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
url,
|
|
3937
|
-
mimeType: attachment.file.type,
|
|
3938
|
-
name: attachment.file.name
|
|
3939
|
-
});
|
|
4401
|
+
setLoading(true);
|
|
4402
|
+
try {
|
|
4403
|
+
const fileContent = await processAttachments(attachments, {
|
|
4404
|
+
getCurrentChat,
|
|
4405
|
+
backend: fileUploadConfig?.backend,
|
|
4406
|
+
transformers: fileUploadConfig?.transformers,
|
|
4407
|
+
onFileProgress: (_fileId, state) => {
|
|
4408
|
+
setFileProcessingState(state);
|
|
3940
4409
|
}
|
|
3941
|
-
}
|
|
3942
|
-
|
|
4410
|
+
});
|
|
4411
|
+
multimodalContent = [];
|
|
4412
|
+
if (message.trim()) {
|
|
4413
|
+
multimodalContent.push({ type: "text", text: message });
|
|
3943
4414
|
}
|
|
4415
|
+
multimodalContent.push(...fileContent);
|
|
4416
|
+
} catch (error) {
|
|
4417
|
+
setLoading(false);
|
|
4418
|
+
throw error;
|
|
4419
|
+
} finally {
|
|
4420
|
+
setFileProcessingState(null);
|
|
3944
4421
|
}
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
4422
|
+
} else {
|
|
4423
|
+
if (activeChatId) {
|
|
4424
|
+
await saveUserMessage(activeChatId, persistedContent);
|
|
4425
|
+
}
|
|
4426
|
+
setLoading(true);
|
|
3949
4427
|
}
|
|
3950
|
-
setLoading(true);
|
|
3951
4428
|
await clientRef.current.sendPrompt(message, multimodalContent);
|
|
3952
|
-
}, [activatePendingChat, currentChatId, saveUserMessage, fileUploadConfig]);
|
|
4429
|
+
}, [activatePendingChat, currentChatId, saveUserMessage, fileUploadConfig, getCurrentChat]);
|
|
4430
|
+
handleSendMessageRef.current = handleSendMessage;
|
|
3953
4431
|
const value = {
|
|
3954
4432
|
serverUrl,
|
|
3955
4433
|
connected,
|
|
@@ -3969,7 +4447,10 @@ function UseAIProvider({
|
|
|
3969
4447
|
load: loadChat,
|
|
3970
4448
|
delete: deleteChat,
|
|
3971
4449
|
list: listChats,
|
|
3972
|
-
clear: clearCurrentChat
|
|
4450
|
+
clear: clearCurrentChat,
|
|
4451
|
+
sendMessage,
|
|
4452
|
+
get: getCurrentChat,
|
|
4453
|
+
updateMetadata
|
|
3973
4454
|
},
|
|
3974
4455
|
agents: {
|
|
3975
4456
|
available: availableAgents,
|
|
@@ -3994,12 +4475,14 @@ function UseAIProvider({
|
|
|
3994
4475
|
streamingText: effectiveStreamingText,
|
|
3995
4476
|
suggestions: aggregatedSuggestions,
|
|
3996
4477
|
fileUploadConfig,
|
|
4478
|
+
fileProcessing: fileProcessingState,
|
|
3997
4479
|
history: {
|
|
3998
4480
|
currentId: displayedChatId,
|
|
3999
4481
|
create: createNewChat,
|
|
4000
4482
|
load: loadChat,
|
|
4001
4483
|
delete: deleteChat,
|
|
4002
|
-
list: listChats
|
|
4484
|
+
list: listChats,
|
|
4485
|
+
get: getCurrentChat
|
|
4003
4486
|
},
|
|
4004
4487
|
agents: {
|
|
4005
4488
|
available: availableAgents,
|
|
@@ -4015,7 +4498,7 @@ function UseAIProvider({
|
|
|
4015
4498
|
},
|
|
4016
4499
|
ui: {
|
|
4017
4500
|
isOpen: isChatOpen,
|
|
4018
|
-
setOpen:
|
|
4501
|
+
setOpen: handleSetChatOpen
|
|
4019
4502
|
}
|
|
4020
4503
|
};
|
|
4021
4504
|
const isUIDisabled = CustomButton === null || CustomChat === null;
|
|
@@ -4038,6 +4521,7 @@ function UseAIProvider({
|
|
|
4038
4521
|
selectedAgent,
|
|
4039
4522
|
onAgentChange: setAgent,
|
|
4040
4523
|
fileUploadConfig,
|
|
4524
|
+
fileProcessing: fileProcessingState,
|
|
4041
4525
|
commands,
|
|
4042
4526
|
onSaveCommand: saveCommand,
|
|
4043
4527
|
onRenameCommand: renameCommand,
|
|
@@ -4045,21 +4529,21 @@ function UseAIProvider({
|
|
|
4045
4529
|
};
|
|
4046
4530
|
const renderDefaultChat = () => {
|
|
4047
4531
|
if (isUIDisabled) return null;
|
|
4048
|
-
return /* @__PURE__ */
|
|
4532
|
+
return /* @__PURE__ */ jsx13(UseAIFloatingChatWrapper, { isOpen: isChatOpen, onClose: () => handleSetChatOpen(false), children: /* @__PURE__ */ jsx13(
|
|
4049
4533
|
UseAIChatPanel,
|
|
4050
4534
|
{
|
|
4051
4535
|
...chatPanelProps,
|
|
4052
|
-
closeButton: /* @__PURE__ */
|
|
4536
|
+
closeButton: /* @__PURE__ */ jsx13(CloseButton, { onClick: () => handleSetChatOpen(false) })
|
|
4053
4537
|
}
|
|
4054
4538
|
) });
|
|
4055
4539
|
};
|
|
4056
4540
|
const renderCustomChat = () => {
|
|
4057
4541
|
if (!CustomChat) return null;
|
|
4058
|
-
return /* @__PURE__ */
|
|
4542
|
+
return /* @__PURE__ */ jsx13(
|
|
4059
4543
|
CustomChat,
|
|
4060
4544
|
{
|
|
4061
4545
|
isOpen: isChatOpen,
|
|
4062
|
-
onClose: () =>
|
|
4546
|
+
onClose: () => handleSetChatOpen(false),
|
|
4063
4547
|
onSendMessage: handleSendMessage,
|
|
4064
4548
|
messages,
|
|
4065
4549
|
loading,
|
|
@@ -4074,18 +4558,18 @@ function UseAIProvider({
|
|
|
4074
4558
|
};
|
|
4075
4559
|
const renderBuiltInChat = () => {
|
|
4076
4560
|
if (!renderChat) return null;
|
|
4077
|
-
return /* @__PURE__ */
|
|
4078
|
-
ButtonComponent && /* @__PURE__ */
|
|
4561
|
+
return /* @__PURE__ */ jsxs9(Fragment3, { children: [
|
|
4562
|
+
ButtonComponent && /* @__PURE__ */ jsx13(
|
|
4079
4563
|
ButtonComponent,
|
|
4080
4564
|
{
|
|
4081
|
-
onClick: () =>
|
|
4565
|
+
onClick: () => handleSetChatOpen(true),
|
|
4082
4566
|
connected
|
|
4083
4567
|
}
|
|
4084
4568
|
),
|
|
4085
4569
|
hasCustomChat ? renderCustomChat() : renderDefaultChat()
|
|
4086
4570
|
] });
|
|
4087
4571
|
};
|
|
4088
|
-
return /* @__PURE__ */
|
|
4572
|
+
return /* @__PURE__ */ jsx13(ThemeContext.Provider, { value: theme, children: /* @__PURE__ */ jsx13(StringsContext.Provider, { value: strings, children: /* @__PURE__ */ jsx13(__UseAIContext.Provider, { value, children: /* @__PURE__ */ jsxs9(__UseAIChatContext.Provider, { value: chatUIContextValue, children: [
|
|
4089
4573
|
children,
|
|
4090
4574
|
renderBuiltInChat()
|
|
4091
4575
|
] }) }) }) });
|
|
@@ -4488,14 +4972,18 @@ export {
|
|
|
4488
4972
|
UseAIFloatingButton,
|
|
4489
4973
|
UseAIFloatingChatWrapper,
|
|
4490
4974
|
UseAIProvider,
|
|
4975
|
+
clearTransformationCache,
|
|
4491
4976
|
convertToolsToDefinitions,
|
|
4492
4977
|
defaultStrings,
|
|
4493
4978
|
defaultTheme,
|
|
4494
4979
|
defineTool,
|
|
4495
4980
|
executeDefinedTool,
|
|
4981
|
+
findTransformer,
|
|
4496
4982
|
generateChatId,
|
|
4497
4983
|
generateCommandId,
|
|
4498
4984
|
generateMessageId,
|
|
4985
|
+
matchesMimeType,
|
|
4986
|
+
processAttachments,
|
|
4499
4987
|
useAI,
|
|
4500
4988
|
useAIContext,
|
|
4501
4989
|
useAIWorkflow,
|