@meetsmore-oss/use-ai-client 1.2.4 → 1.3.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 +664 -219
- 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 +288 -74
- package/dist/index.js +664 -219
- 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";
|
|
@@ -378,8 +378,131 @@ function MarkdownContent({ content }) {
|
|
|
378
378
|
);
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
-
// src/components/
|
|
381
|
+
// src/components/Spinner.tsx
|
|
382
382
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
383
|
+
function Spinner({
|
|
384
|
+
size = 16,
|
|
385
|
+
color = "currentColor",
|
|
386
|
+
trackColor,
|
|
387
|
+
strokeWidth = 2
|
|
388
|
+
}) {
|
|
389
|
+
const radius = 10;
|
|
390
|
+
const circumference = 2 * Math.PI * radius;
|
|
391
|
+
return /* @__PURE__ */ jsxs2(
|
|
392
|
+
"svg",
|
|
393
|
+
{
|
|
394
|
+
"data-testid": "spinner",
|
|
395
|
+
width: size,
|
|
396
|
+
height: size,
|
|
397
|
+
viewBox: "0 0 24 24",
|
|
398
|
+
style: {
|
|
399
|
+
animation: "use-ai-spin 1s linear infinite"
|
|
400
|
+
},
|
|
401
|
+
children: [
|
|
402
|
+
/* @__PURE__ */ jsx3("style", { children: `
|
|
403
|
+
@keyframes use-ai-spin {
|
|
404
|
+
from { transform: rotate(0deg); }
|
|
405
|
+
to { transform: rotate(360deg); }
|
|
406
|
+
}
|
|
407
|
+
` }),
|
|
408
|
+
/* @__PURE__ */ jsx3(
|
|
409
|
+
"circle",
|
|
410
|
+
{
|
|
411
|
+
cx: "12",
|
|
412
|
+
cy: "12",
|
|
413
|
+
r: radius,
|
|
414
|
+
fill: "none",
|
|
415
|
+
stroke: trackColor || color,
|
|
416
|
+
strokeWidth,
|
|
417
|
+
opacity: trackColor ? 1 : 0.25
|
|
418
|
+
}
|
|
419
|
+
),
|
|
420
|
+
/* @__PURE__ */ jsx3(
|
|
421
|
+
"circle",
|
|
422
|
+
{
|
|
423
|
+
cx: "12",
|
|
424
|
+
cy: "12",
|
|
425
|
+
r: radius,
|
|
426
|
+
fill: "none",
|
|
427
|
+
stroke: color,
|
|
428
|
+
strokeWidth,
|
|
429
|
+
strokeLinecap: "round",
|
|
430
|
+
strokeDasharray: circumference,
|
|
431
|
+
strokeDashoffset: circumference * 0.75,
|
|
432
|
+
style: {
|
|
433
|
+
transformOrigin: "center"
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
)
|
|
437
|
+
]
|
|
438
|
+
}
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// src/components/ProgressBar.tsx
|
|
443
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
444
|
+
function ProgressBar({
|
|
445
|
+
progress,
|
|
446
|
+
size = 16,
|
|
447
|
+
color = "currentColor",
|
|
448
|
+
trackColor,
|
|
449
|
+
strokeWidth = 2
|
|
450
|
+
}) {
|
|
451
|
+
const clampedProgress = Math.min(100, Math.max(0, progress));
|
|
452
|
+
const radius = 10;
|
|
453
|
+
const circumference = 2 * Math.PI * radius;
|
|
454
|
+
const strokeDashoffset = circumference * (1 - clampedProgress / 100);
|
|
455
|
+
return /* @__PURE__ */ jsxs3(
|
|
456
|
+
"svg",
|
|
457
|
+
{
|
|
458
|
+
"data-testid": "progress-bar",
|
|
459
|
+
role: "progressbar",
|
|
460
|
+
"aria-valuenow": clampedProgress,
|
|
461
|
+
"aria-valuemin": 0,
|
|
462
|
+
"aria-valuemax": 100,
|
|
463
|
+
width: size,
|
|
464
|
+
height: size,
|
|
465
|
+
viewBox: "0 0 24 24",
|
|
466
|
+
style: {
|
|
467
|
+
transform: "rotate(-90deg)"
|
|
468
|
+
},
|
|
469
|
+
children: [
|
|
470
|
+
/* @__PURE__ */ jsx4(
|
|
471
|
+
"circle",
|
|
472
|
+
{
|
|
473
|
+
cx: "12",
|
|
474
|
+
cy: "12",
|
|
475
|
+
r: radius,
|
|
476
|
+
fill: "none",
|
|
477
|
+
stroke: trackColor || color,
|
|
478
|
+
strokeWidth,
|
|
479
|
+
opacity: trackColor ? 1 : 0.25
|
|
480
|
+
}
|
|
481
|
+
),
|
|
482
|
+
/* @__PURE__ */ jsx4(
|
|
483
|
+
"circle",
|
|
484
|
+
{
|
|
485
|
+
cx: "12",
|
|
486
|
+
cy: "12",
|
|
487
|
+
r: radius,
|
|
488
|
+
fill: "none",
|
|
489
|
+
stroke: color,
|
|
490
|
+
strokeWidth,
|
|
491
|
+
strokeLinecap: "round",
|
|
492
|
+
strokeDasharray: circumference,
|
|
493
|
+
strokeDashoffset,
|
|
494
|
+
style: {
|
|
495
|
+
transition: "stroke-dashoffset 0.2s ease"
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
]
|
|
500
|
+
}
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// src/components/FileChip.tsx
|
|
505
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
383
506
|
function formatFileSize(bytes) {
|
|
384
507
|
if (bytes < 1024) return `${bytes} B`;
|
|
385
508
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
@@ -394,11 +517,14 @@ function truncateFilename(name, maxLength = 20) {
|
|
|
394
517
|
if (maxBaseLength < 5) return name.substring(0, maxLength - 3) + "...";
|
|
395
518
|
return baseName.substring(0, maxBaseLength) + "..." + ext;
|
|
396
519
|
}
|
|
397
|
-
function FileChip({ attachment, onRemove, disabled }) {
|
|
520
|
+
function FileChip({ attachment, onRemove, disabled, processingState }) {
|
|
398
521
|
const theme = useTheme();
|
|
399
522
|
const { file, preview } = attachment;
|
|
400
523
|
const isImage = file.type.startsWith("image/");
|
|
401
|
-
|
|
524
|
+
const isProcessing = processingState?.status === "processing";
|
|
525
|
+
const hasError = processingState?.status === "error";
|
|
526
|
+
const progress = processingState?.progress;
|
|
527
|
+
return /* @__PURE__ */ jsxs4(
|
|
402
528
|
"div",
|
|
403
529
|
{
|
|
404
530
|
"data-testid": "file-chip",
|
|
@@ -411,10 +537,12 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
411
537
|
borderRadius: "8px",
|
|
412
538
|
fontSize: "13px",
|
|
413
539
|
color: theme.textColor,
|
|
414
|
-
maxWidth: "200px"
|
|
540
|
+
maxWidth: "200px",
|
|
541
|
+
position: "relative",
|
|
542
|
+
opacity: isProcessing ? 0.7 : 1
|
|
415
543
|
},
|
|
416
544
|
children: [
|
|
417
|
-
isImage && preview ? /* @__PURE__ */
|
|
545
|
+
isImage && preview ? /* @__PURE__ */ jsx5(
|
|
418
546
|
"img",
|
|
419
547
|
{
|
|
420
548
|
src: preview,
|
|
@@ -426,7 +554,7 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
426
554
|
objectFit: "cover"
|
|
427
555
|
}
|
|
428
556
|
}
|
|
429
|
-
) : /* @__PURE__ */
|
|
557
|
+
) : /* @__PURE__ */ jsx5(
|
|
430
558
|
"div",
|
|
431
559
|
{
|
|
432
560
|
style: {
|
|
@@ -442,8 +570,8 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
442
570
|
children: "\u{1F4CE}"
|
|
443
571
|
}
|
|
444
572
|
),
|
|
445
|
-
/* @__PURE__ */
|
|
446
|
-
/* @__PURE__ */
|
|
573
|
+
/* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: [
|
|
574
|
+
/* @__PURE__ */ jsx5(
|
|
447
575
|
"div",
|
|
448
576
|
{
|
|
449
577
|
style: {
|
|
@@ -456,28 +584,28 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
456
584
|
children: truncateFilename(file.name)
|
|
457
585
|
}
|
|
458
586
|
),
|
|
459
|
-
/* @__PURE__ */
|
|
587
|
+
/* @__PURE__ */ jsx5("div", { style: { fontSize: "11px", color: theme.secondaryTextColor }, children: formatFileSize(file.size) })
|
|
460
588
|
] }),
|
|
461
|
-
/* @__PURE__ */
|
|
589
|
+
/* @__PURE__ */ jsx5(
|
|
462
590
|
"button",
|
|
463
591
|
{
|
|
464
592
|
"data-testid": "file-chip-remove",
|
|
465
593
|
onClick: onRemove,
|
|
466
|
-
disabled,
|
|
594
|
+
disabled: disabled || isProcessing,
|
|
467
595
|
style: {
|
|
468
596
|
background: "transparent",
|
|
469
597
|
border: "none",
|
|
470
598
|
padding: "2px 4px",
|
|
471
|
-
cursor: disabled ? "not-allowed" : "pointer",
|
|
599
|
+
cursor: disabled || isProcessing ? "not-allowed" : "pointer",
|
|
472
600
|
color: theme.placeholderTextColor,
|
|
473
601
|
fontSize: "16px",
|
|
474
602
|
lineHeight: 1,
|
|
475
603
|
borderRadius: "4px",
|
|
476
604
|
transition: "all 0.15s",
|
|
477
|
-
opacity: disabled ? 0.5 : 1
|
|
605
|
+
opacity: disabled || isProcessing ? 0.5 : 1
|
|
478
606
|
},
|
|
479
607
|
onMouseEnter: (e) => {
|
|
480
|
-
if (!disabled) {
|
|
608
|
+
if (!disabled && !isProcessing) {
|
|
481
609
|
e.currentTarget.style.background = theme.borderColor;
|
|
482
610
|
e.currentTarget.style.color = theme.textColor;
|
|
483
611
|
}
|
|
@@ -488,6 +616,44 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
488
616
|
},
|
|
489
617
|
children: "\xD7"
|
|
490
618
|
}
|
|
619
|
+
),
|
|
620
|
+
isProcessing && /* @__PURE__ */ jsx5(
|
|
621
|
+
"div",
|
|
622
|
+
{
|
|
623
|
+
"data-testid": "file-chip-processing",
|
|
624
|
+
style: {
|
|
625
|
+
position: "absolute",
|
|
626
|
+
inset: 0,
|
|
627
|
+
display: "flex",
|
|
628
|
+
alignItems: "center",
|
|
629
|
+
justifyContent: "center",
|
|
630
|
+
background: "rgba(255, 255, 255, 0.7)",
|
|
631
|
+
borderRadius: "inherit"
|
|
632
|
+
},
|
|
633
|
+
children: progress !== void 0 ? /* @__PURE__ */ jsx5(ProgressBar, { progress, size: 16, color: theme.secondaryTextColor }) : /* @__PURE__ */ jsx5(Spinner, { size: 16, color: theme.secondaryTextColor })
|
|
634
|
+
}
|
|
635
|
+
),
|
|
636
|
+
hasError && /* @__PURE__ */ jsx5(
|
|
637
|
+
"div",
|
|
638
|
+
{
|
|
639
|
+
"data-testid": "file-chip-error",
|
|
640
|
+
style: {
|
|
641
|
+
position: "absolute",
|
|
642
|
+
bottom: "-2px",
|
|
643
|
+
right: "-2px",
|
|
644
|
+
width: "12px",
|
|
645
|
+
height: "12px",
|
|
646
|
+
borderRadius: "50%",
|
|
647
|
+
background: "#ef4444",
|
|
648
|
+
display: "flex",
|
|
649
|
+
alignItems: "center",
|
|
650
|
+
justifyContent: "center",
|
|
651
|
+
fontSize: "8px",
|
|
652
|
+
color: "white",
|
|
653
|
+
fontWeight: "bold"
|
|
654
|
+
},
|
|
655
|
+
children: "!"
|
|
656
|
+
}
|
|
491
657
|
)
|
|
492
658
|
]
|
|
493
659
|
}
|
|
@@ -495,7 +661,7 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
495
661
|
}
|
|
496
662
|
function FilePlaceholder({ name, size }) {
|
|
497
663
|
const theme = useTheme();
|
|
498
|
-
return /* @__PURE__ */
|
|
664
|
+
return /* @__PURE__ */ jsxs4(
|
|
499
665
|
"div",
|
|
500
666
|
{
|
|
501
667
|
"data-testid": "file-placeholder",
|
|
@@ -512,9 +678,9 @@ function FilePlaceholder({ name, size }) {
|
|
|
512
678
|
maxWidth: "200px"
|
|
513
679
|
},
|
|
514
680
|
children: [
|
|
515
|
-
/* @__PURE__ */
|
|
516
|
-
/* @__PURE__ */
|
|
517
|
-
/* @__PURE__ */
|
|
681
|
+
/* @__PURE__ */ jsx5("span", { children: "\u{1F4CE}" }),
|
|
682
|
+
/* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: [
|
|
683
|
+
/* @__PURE__ */ jsx5(
|
|
518
684
|
"div",
|
|
519
685
|
{
|
|
520
686
|
style: {
|
|
@@ -526,7 +692,7 @@ function FilePlaceholder({ name, size }) {
|
|
|
526
692
|
children: truncateFilename(name)
|
|
527
693
|
}
|
|
528
694
|
),
|
|
529
|
-
/* @__PURE__ */
|
|
695
|
+
/* @__PURE__ */ jsx5("div", { style: { fontSize: "11px" }, children: formatFileSize(size) })
|
|
530
696
|
] })
|
|
531
697
|
]
|
|
532
698
|
}
|
|
@@ -555,7 +721,7 @@ function validateCommandName(name) {
|
|
|
555
721
|
|
|
556
722
|
// src/components/CommandAutocomplete.tsx
|
|
557
723
|
import { useEffect, useRef } from "react";
|
|
558
|
-
import { jsx as
|
|
724
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
559
725
|
var MAX_VISIBLE_ITEMS = 8;
|
|
560
726
|
function CommandAutocomplete({
|
|
561
727
|
commands,
|
|
@@ -586,7 +752,7 @@ function CommandAutocomplete({
|
|
|
586
752
|
}
|
|
587
753
|
}, [highlightedIndex]);
|
|
588
754
|
if (filteredCommands.length === 0) {
|
|
589
|
-
return /* @__PURE__ */
|
|
755
|
+
return /* @__PURE__ */ jsx6(
|
|
590
756
|
"div",
|
|
591
757
|
{
|
|
592
758
|
"data-testid": "command-autocomplete",
|
|
@@ -602,7 +768,7 @@ function CommandAutocomplete({
|
|
|
602
768
|
overflow: "hidden",
|
|
603
769
|
zIndex: 1005
|
|
604
770
|
},
|
|
605
|
-
children: /* @__PURE__ */
|
|
771
|
+
children: /* @__PURE__ */ jsx6(
|
|
606
772
|
"div",
|
|
607
773
|
{
|
|
608
774
|
style: {
|
|
@@ -617,7 +783,7 @@ function CommandAutocomplete({
|
|
|
617
783
|
}
|
|
618
784
|
);
|
|
619
785
|
}
|
|
620
|
-
return /* @__PURE__ */
|
|
786
|
+
return /* @__PURE__ */ jsx6(
|
|
621
787
|
"div",
|
|
622
788
|
{
|
|
623
789
|
"data-testid": "command-autocomplete",
|
|
@@ -636,7 +802,7 @@ function CommandAutocomplete({
|
|
|
636
802
|
overflowY: "auto",
|
|
637
803
|
zIndex: 1005
|
|
638
804
|
},
|
|
639
|
-
children: filteredCommands.map((cmd, index) => /* @__PURE__ */
|
|
805
|
+
children: filteredCommands.map((cmd, index) => /* @__PURE__ */ jsxs5(
|
|
640
806
|
"div",
|
|
641
807
|
{
|
|
642
808
|
ref: (el) => {
|
|
@@ -656,8 +822,8 @@ function CommandAutocomplete({
|
|
|
656
822
|
gap: "8px"
|
|
657
823
|
},
|
|
658
824
|
children: [
|
|
659
|
-
/* @__PURE__ */
|
|
660
|
-
/* @__PURE__ */
|
|
825
|
+
/* @__PURE__ */ jsxs5("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
826
|
+
/* @__PURE__ */ jsxs5(
|
|
661
827
|
"div",
|
|
662
828
|
{
|
|
663
829
|
style: {
|
|
@@ -671,7 +837,7 @@ function CommandAutocomplete({
|
|
|
671
837
|
]
|
|
672
838
|
}
|
|
673
839
|
),
|
|
674
|
-
/* @__PURE__ */
|
|
840
|
+
/* @__PURE__ */ jsx6(
|
|
675
841
|
"div",
|
|
676
842
|
{
|
|
677
843
|
style: {
|
|
@@ -686,7 +852,7 @@ function CommandAutocomplete({
|
|
|
686
852
|
}
|
|
687
853
|
)
|
|
688
854
|
] }),
|
|
689
|
-
onDelete && /* @__PURE__ */
|
|
855
|
+
onDelete && /* @__PURE__ */ jsx6(
|
|
690
856
|
"button",
|
|
691
857
|
{
|
|
692
858
|
"data-testid": "command-delete-button",
|
|
@@ -717,7 +883,7 @@ function CommandAutocomplete({
|
|
|
717
883
|
e.currentTarget.style.background = "transparent";
|
|
718
884
|
},
|
|
719
885
|
title: strings.commands.deleteCommand,
|
|
720
|
-
children: /* @__PURE__ */
|
|
886
|
+
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
887
|
}
|
|
722
888
|
)
|
|
723
889
|
]
|
|
@@ -735,7 +901,7 @@ function getFilteredCommandsCount(commands, searchPrefix) {
|
|
|
735
901
|
}
|
|
736
902
|
|
|
737
903
|
// src/hooks/useSlashCommands.tsx
|
|
738
|
-
import { jsx as
|
|
904
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
739
905
|
var MAX_VISIBLE_ITEMS2 = 8;
|
|
740
906
|
function useSlashCommands({
|
|
741
907
|
commands,
|
|
@@ -870,7 +1036,7 @@ function useSlashCommands({
|
|
|
870
1036
|
}
|
|
871
1037
|
}
|
|
872
1038
|
}, [savingMessageId, savingMessageText, commandNameInput, commands, onRenameCommand, onSaveCommand, cancelInlineSave, strings]);
|
|
873
|
-
const AutocompleteComponent = showAutocomplete && commands.length > 0 ? /* @__PURE__ */
|
|
1039
|
+
const AutocompleteComponent = showAutocomplete && commands.length > 0 ? /* @__PURE__ */ jsx7(
|
|
874
1040
|
CommandAutocomplete,
|
|
875
1041
|
{
|
|
876
1042
|
commands,
|
|
@@ -886,7 +1052,7 @@ function useSlashCommands({
|
|
|
886
1052
|
if (savingMessageId !== messageId) {
|
|
887
1053
|
return null;
|
|
888
1054
|
}
|
|
889
|
-
return /* @__PURE__ */
|
|
1055
|
+
return /* @__PURE__ */ jsxs6(
|
|
890
1056
|
"div",
|
|
891
1057
|
{
|
|
892
1058
|
"data-testid": "inline-save-command",
|
|
@@ -900,9 +1066,9 @@ function useSlashCommands({
|
|
|
900
1066
|
gap: "4px"
|
|
901
1067
|
},
|
|
902
1068
|
children: [
|
|
903
|
-
/* @__PURE__ */
|
|
904
|
-
/* @__PURE__ */
|
|
905
|
-
/* @__PURE__ */
|
|
1069
|
+
/* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
|
|
1070
|
+
/* @__PURE__ */ jsx7("span", { style: { color: theme.primaryColor, fontSize: "13px", fontWeight: 500 }, children: "/" }),
|
|
1071
|
+
/* @__PURE__ */ jsx7(
|
|
906
1072
|
"input",
|
|
907
1073
|
{
|
|
908
1074
|
ref: commandNameInputRef,
|
|
@@ -934,7 +1100,7 @@ function useSlashCommands({
|
|
|
934
1100
|
}
|
|
935
1101
|
}
|
|
936
1102
|
),
|
|
937
|
-
/* @__PURE__ */
|
|
1103
|
+
/* @__PURE__ */ jsx7(
|
|
938
1104
|
"button",
|
|
939
1105
|
{
|
|
940
1106
|
"data-testid": "save-command-confirm",
|
|
@@ -952,15 +1118,15 @@ function useSlashCommands({
|
|
|
952
1118
|
justifyContent: "center"
|
|
953
1119
|
},
|
|
954
1120
|
title: strings.commands.saveCommand,
|
|
955
|
-
children: /* @__PURE__ */
|
|
956
|
-
/* @__PURE__ */
|
|
957
|
-
/* @__PURE__ */
|
|
958
|
-
/* @__PURE__ */
|
|
1121
|
+
children: /* @__PURE__ */ jsxs6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1122
|
+
/* @__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" }),
|
|
1123
|
+
/* @__PURE__ */ jsx7("polyline", { points: "17 21 17 13 7 13 7 21" }),
|
|
1124
|
+
/* @__PURE__ */ jsx7("polyline", { points: "7 3 7 8 15 8" })
|
|
959
1125
|
] })
|
|
960
1126
|
}
|
|
961
1127
|
)
|
|
962
1128
|
] }),
|
|
963
|
-
commandSaveError && /* @__PURE__ */
|
|
1129
|
+
commandSaveError && /* @__PURE__ */ jsx7(
|
|
964
1130
|
"div",
|
|
965
1131
|
{
|
|
966
1132
|
"data-testid": "command-save-error",
|
|
@@ -995,9 +1161,151 @@ import { useState as useState2, useRef as useRef3, useCallback as useCallback2,
|
|
|
995
1161
|
// src/fileUpload/types.ts
|
|
996
1162
|
var DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
997
1163
|
|
|
1164
|
+
// src/fileUpload/mimeTypeMatcher.ts
|
|
1165
|
+
function matchesMimeType(mimeType, pattern) {
|
|
1166
|
+
if (!pattern.includes("*")) {
|
|
1167
|
+
return mimeType === pattern;
|
|
1168
|
+
}
|
|
1169
|
+
const regexPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
1170
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
1171
|
+
return regex.test(mimeType);
|
|
1172
|
+
}
|
|
1173
|
+
function findTransformer(mimeType, transformers) {
|
|
1174
|
+
if (!transformers) {
|
|
1175
|
+
return void 0;
|
|
1176
|
+
}
|
|
1177
|
+
let bestMatch;
|
|
1178
|
+
let bestIsExact = false;
|
|
1179
|
+
let bestLength = -1;
|
|
1180
|
+
for (const [pattern, transformer] of Object.entries(transformers)) {
|
|
1181
|
+
if (!matchesMimeType(mimeType, pattern)) {
|
|
1182
|
+
continue;
|
|
1183
|
+
}
|
|
1184
|
+
const isExact = !pattern.includes("*");
|
|
1185
|
+
if (isExact && !bestIsExact) {
|
|
1186
|
+
bestMatch = transformer;
|
|
1187
|
+
bestIsExact = true;
|
|
1188
|
+
bestLength = pattern.length;
|
|
1189
|
+
continue;
|
|
1190
|
+
}
|
|
1191
|
+
if (isExact === bestIsExact && pattern.length > bestLength) {
|
|
1192
|
+
bestMatch = transformer;
|
|
1193
|
+
bestLength = pattern.length;
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
return bestMatch;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
// src/fileUpload/EmbedFileUploadBackend.ts
|
|
1200
|
+
var EmbedFileUploadBackend = class {
|
|
1201
|
+
/**
|
|
1202
|
+
* Converts a File to a base64 data URL.
|
|
1203
|
+
*
|
|
1204
|
+
* @param file - The File object to convert
|
|
1205
|
+
* @returns Promise resolving to a base64 data URL (e.g., "data:image/png;base64,...")
|
|
1206
|
+
* @throws Error if file reading fails
|
|
1207
|
+
*/
|
|
1208
|
+
async prepareForSend(file) {
|
|
1209
|
+
return new Promise((resolve, reject) => {
|
|
1210
|
+
const reader = new FileReader();
|
|
1211
|
+
reader.onload = () => {
|
|
1212
|
+
if (typeof reader.result === "string") {
|
|
1213
|
+
resolve(reader.result);
|
|
1214
|
+
} else {
|
|
1215
|
+
reject(new Error("Failed to read file as data URL"));
|
|
1216
|
+
}
|
|
1217
|
+
};
|
|
1218
|
+
reader.onerror = () => {
|
|
1219
|
+
reject(new Error(`Failed to read file: ${file.name}`));
|
|
1220
|
+
};
|
|
1221
|
+
reader.readAsDataURL(file);
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
};
|
|
1225
|
+
|
|
1226
|
+
// src/fileUpload/processAttachments.ts
|
|
1227
|
+
var transformationCache = /* @__PURE__ */ new Map();
|
|
1228
|
+
function getFileCacheKey(file) {
|
|
1229
|
+
return `${file.name}:${file.size}:${file.lastModified}`;
|
|
1230
|
+
}
|
|
1231
|
+
async function getTransformedContent(file, transformer, context, onProgress) {
|
|
1232
|
+
const cacheKey = getFileCacheKey(file);
|
|
1233
|
+
const cached = transformationCache.get(cacheKey);
|
|
1234
|
+
if (cached !== void 0) {
|
|
1235
|
+
return cached;
|
|
1236
|
+
}
|
|
1237
|
+
const result = await transformer.transform(file, context, onProgress);
|
|
1238
|
+
transformationCache.set(cacheKey, result);
|
|
1239
|
+
return result;
|
|
1240
|
+
}
|
|
1241
|
+
async function processAttachments(attachments, config) {
|
|
1242
|
+
const { getCurrentChat, backend = new EmbedFileUploadBackend(), transformers = {}, onFileProgress } = config;
|
|
1243
|
+
const contentParts = [];
|
|
1244
|
+
const chat = await getCurrentChat();
|
|
1245
|
+
const context = { chat };
|
|
1246
|
+
for (const attachment of attachments) {
|
|
1247
|
+
onFileProgress?.(attachment.id, { status: "processing" });
|
|
1248
|
+
try {
|
|
1249
|
+
if (attachment.transformedContent !== void 0) {
|
|
1250
|
+
contentParts.push({
|
|
1251
|
+
type: "transformed_file",
|
|
1252
|
+
text: attachment.transformedContent,
|
|
1253
|
+
originalFile: {
|
|
1254
|
+
name: attachment.file.name,
|
|
1255
|
+
mimeType: attachment.file.type,
|
|
1256
|
+
size: attachment.file.size
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
onFileProgress?.(attachment.id, { status: "done" });
|
|
1260
|
+
continue;
|
|
1261
|
+
}
|
|
1262
|
+
const transformer = findTransformer(attachment.file.type, transformers);
|
|
1263
|
+
if (transformer) {
|
|
1264
|
+
const transformedText = await getTransformedContent(
|
|
1265
|
+
attachment.file,
|
|
1266
|
+
transformer,
|
|
1267
|
+
context,
|
|
1268
|
+
(progress) => {
|
|
1269
|
+
onFileProgress?.(attachment.id, { status: "processing", progress });
|
|
1270
|
+
}
|
|
1271
|
+
);
|
|
1272
|
+
contentParts.push({
|
|
1273
|
+
type: "transformed_file",
|
|
1274
|
+
text: transformedText,
|
|
1275
|
+
originalFile: {
|
|
1276
|
+
name: attachment.file.name,
|
|
1277
|
+
mimeType: attachment.file.type,
|
|
1278
|
+
size: attachment.file.size
|
|
1279
|
+
}
|
|
1280
|
+
});
|
|
1281
|
+
} else {
|
|
1282
|
+
const url = await backend.prepareForSend(attachment.file);
|
|
1283
|
+
if (attachment.file.type.startsWith("image/")) {
|
|
1284
|
+
contentParts.push({ type: "image", url });
|
|
1285
|
+
} else {
|
|
1286
|
+
contentParts.push({
|
|
1287
|
+
type: "file",
|
|
1288
|
+
url,
|
|
1289
|
+
mimeType: attachment.file.type,
|
|
1290
|
+
name: attachment.file.name
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
onFileProgress?.(attachment.id, { status: "done" });
|
|
1295
|
+
} catch (error) {
|
|
1296
|
+
onFileProgress?.(attachment.id, { status: "error" });
|
|
1297
|
+
throw error;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
return contentParts;
|
|
1301
|
+
}
|
|
1302
|
+
function clearTransformationCache() {
|
|
1303
|
+
transformationCache.clear();
|
|
1304
|
+
}
|
|
1305
|
+
|
|
998
1306
|
// src/hooks/useFileUpload.tsx
|
|
999
1307
|
import { v4 as uuidv4 } from "uuid";
|
|
1000
|
-
import { jsx as
|
|
1308
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1001
1309
|
async function generateImagePreview(file) {
|
|
1002
1310
|
if (!file.type.startsWith("image/")) {
|
|
1003
1311
|
return void 0;
|
|
@@ -1030,18 +1338,21 @@ function isTypeAccepted(mimeType, acceptedTypes) {
|
|
|
1030
1338
|
function useFileUpload({
|
|
1031
1339
|
config,
|
|
1032
1340
|
disabled = false,
|
|
1033
|
-
resetDependency
|
|
1341
|
+
resetDependency,
|
|
1342
|
+
getCurrentChat
|
|
1034
1343
|
}) {
|
|
1035
1344
|
const strings = useStrings();
|
|
1036
1345
|
const theme = useTheme();
|
|
1037
1346
|
const [attachments, setAttachments] = useState2([]);
|
|
1038
1347
|
const [isDragging, setIsDragging] = useState2(false);
|
|
1039
1348
|
const [fileError, setFileError] = useState2(null);
|
|
1349
|
+
const [processingState, setProcessingState] = useState2(/* @__PURE__ */ new Map());
|
|
1040
1350
|
const fileInputRef = useRef3(null);
|
|
1041
1351
|
const dragCounterRef = useRef3(0);
|
|
1042
1352
|
const enabled = config !== void 0;
|
|
1043
1353
|
const maxFileSize = config?.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
|
|
1044
1354
|
const acceptedTypes = config?.acceptedTypes;
|
|
1355
|
+
const transformers = config?.transformers;
|
|
1045
1356
|
useEffect3(() => {
|
|
1046
1357
|
if (fileError) {
|
|
1047
1358
|
const timer = setTimeout(() => setFileError(null), 3e3);
|
|
@@ -1051,7 +1362,28 @@ function useFileUpload({
|
|
|
1051
1362
|
useEffect3(() => {
|
|
1052
1363
|
setAttachments([]);
|
|
1053
1364
|
setFileError(null);
|
|
1365
|
+
setProcessingState(/* @__PURE__ */ new Map());
|
|
1054
1366
|
}, [resetDependency]);
|
|
1367
|
+
const runTransformer = useCallback2(async (attachmentId, file, transformer) => {
|
|
1368
|
+
setProcessingState((prev) => new Map(prev).set(attachmentId, { status: "processing" }));
|
|
1369
|
+
try {
|
|
1370
|
+
const chat = await getCurrentChat();
|
|
1371
|
+
const context = { chat };
|
|
1372
|
+
const transformedContent = await getTransformedContent(file, transformer, context, (progress) => {
|
|
1373
|
+
setProcessingState((prev) => new Map(prev).set(attachmentId, {
|
|
1374
|
+
status: "processing",
|
|
1375
|
+
progress
|
|
1376
|
+
}));
|
|
1377
|
+
});
|
|
1378
|
+
setAttachments((prev) => prev.map(
|
|
1379
|
+
(a) => a.id === attachmentId ? { ...a, transformedContent } : a
|
|
1380
|
+
));
|
|
1381
|
+
setProcessingState((prev) => new Map(prev).set(attachmentId, { status: "done" }));
|
|
1382
|
+
} catch (error) {
|
|
1383
|
+
console.error(`[useFileUpload] Transformation failed for ${file.name}:`, error);
|
|
1384
|
+
setProcessingState((prev) => new Map(prev).set(attachmentId, { status: "error" }));
|
|
1385
|
+
}
|
|
1386
|
+
}, [getCurrentChat]);
|
|
1055
1387
|
const handleFiles = useCallback2(async (files) => {
|
|
1056
1388
|
const fileArray = Array.from(files);
|
|
1057
1389
|
for (const file of fileArray) {
|
|
@@ -1066,21 +1398,30 @@ function useFileUpload({
|
|
|
1066
1398
|
continue;
|
|
1067
1399
|
}
|
|
1068
1400
|
const preview = await generateImagePreview(file);
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1401
|
+
const attachmentId = uuidv4();
|
|
1402
|
+
const attachment = {
|
|
1403
|
+
id: attachmentId,
|
|
1404
|
+
file,
|
|
1405
|
+
preview
|
|
1406
|
+
};
|
|
1407
|
+
setAttachments((prev) => [...prev, attachment]);
|
|
1408
|
+
const transformer = findTransformer(file.type, transformers);
|
|
1409
|
+
if (transformer) {
|
|
1410
|
+
runTransformer(attachmentId, file, transformer);
|
|
1411
|
+
}
|
|
1077
1412
|
}
|
|
1078
|
-
}, [maxFileSize, acceptedTypes, strings]);
|
|
1413
|
+
}, [maxFileSize, acceptedTypes, strings, transformers, runTransformer]);
|
|
1079
1414
|
const removeAttachment = useCallback2((id) => {
|
|
1080
1415
|
setAttachments((prev) => prev.filter((a) => a.id !== id));
|
|
1416
|
+
setProcessingState((prev) => {
|
|
1417
|
+
const next = new Map(prev);
|
|
1418
|
+
next.delete(id);
|
|
1419
|
+
return next;
|
|
1420
|
+
});
|
|
1081
1421
|
}, []);
|
|
1082
1422
|
const clearAttachments = useCallback2(() => {
|
|
1083
1423
|
setAttachments([]);
|
|
1424
|
+
setProcessingState(/* @__PURE__ */ new Map());
|
|
1084
1425
|
}, []);
|
|
1085
1426
|
const openFilePicker = useCallback2(() => {
|
|
1086
1427
|
fileInputRef.current?.click();
|
|
@@ -1133,7 +1474,7 @@ function useFileUpload({
|
|
|
1133
1474
|
}), [handleDragEnter, handleDragOver, handleDragLeave, handleDrop]);
|
|
1134
1475
|
const DropZoneOverlay = useMemo(() => {
|
|
1135
1476
|
if (!isDragging || !enabled) return null;
|
|
1136
|
-
return /* @__PURE__ */
|
|
1477
|
+
return /* @__PURE__ */ jsx8(
|
|
1137
1478
|
"div",
|
|
1138
1479
|
{
|
|
1139
1480
|
style: {
|
|
@@ -1148,7 +1489,7 @@ function useFileUpload({
|
|
|
1148
1489
|
zIndex: 1010,
|
|
1149
1490
|
pointerEvents: "none"
|
|
1150
1491
|
},
|
|
1151
|
-
children: /* @__PURE__ */
|
|
1492
|
+
children: /* @__PURE__ */ jsx8(
|
|
1152
1493
|
"div",
|
|
1153
1494
|
{
|
|
1154
1495
|
style: {
|
|
@@ -1157,7 +1498,7 @@ function useFileUpload({
|
|
|
1157
1498
|
borderRadius: "12px",
|
|
1158
1499
|
boxShadow: theme.buttonShadow
|
|
1159
1500
|
},
|
|
1160
|
-
children: /* @__PURE__ */
|
|
1501
|
+
children: /* @__PURE__ */ jsx8("span", { style: { color: theme.primaryColor, fontWeight: 600, fontSize: "16px" }, children: strings.fileUpload.dropFilesHere })
|
|
1161
1502
|
}
|
|
1162
1503
|
)
|
|
1163
1504
|
}
|
|
@@ -1170,6 +1511,7 @@ function useFileUpload({
|
|
|
1170
1511
|
enabled,
|
|
1171
1512
|
maxFileSize,
|
|
1172
1513
|
acceptedTypes,
|
|
1514
|
+
processingState,
|
|
1173
1515
|
fileInputRef,
|
|
1174
1516
|
handleFiles,
|
|
1175
1517
|
removeAttachment,
|
|
@@ -1187,7 +1529,7 @@ function useFileUpload({
|
|
|
1187
1529
|
|
|
1188
1530
|
// src/hooks/useDropdownState.tsx
|
|
1189
1531
|
import { useState as useState3, useCallback as useCallback3, useMemo as useMemo2 } from "react";
|
|
1190
|
-
import { jsx as
|
|
1532
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1191
1533
|
function useDropdownState(options = {}) {
|
|
1192
1534
|
const { backdropZIndex = 1002, initialOpen = false } = options;
|
|
1193
1535
|
const [isOpen, setIsOpen] = useState3(initialOpen);
|
|
@@ -1202,7 +1544,7 @@ function useDropdownState(options = {}) {
|
|
|
1202
1544
|
}, []);
|
|
1203
1545
|
const Backdrop = useMemo2(() => {
|
|
1204
1546
|
if (!isOpen) return null;
|
|
1205
|
-
return /* @__PURE__ */
|
|
1547
|
+
return /* @__PURE__ */ jsx9(
|
|
1206
1548
|
"div",
|
|
1207
1549
|
{
|
|
1208
1550
|
onClick: close,
|
|
@@ -1227,7 +1569,7 @@ function useDropdownState(options = {}) {
|
|
|
1227
1569
|
}
|
|
1228
1570
|
|
|
1229
1571
|
// src/components/UseAIChatPanel.tsx
|
|
1230
|
-
import { Fragment, jsx as
|
|
1572
|
+
import { Fragment, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1231
1573
|
function getTextContent(content) {
|
|
1232
1574
|
if (typeof content === "string") {
|
|
1233
1575
|
return content;
|
|
@@ -1248,6 +1590,7 @@ function UseAIChatPanel({
|
|
|
1248
1590
|
onLoadChat,
|
|
1249
1591
|
onDeleteChat,
|
|
1250
1592
|
onListChats,
|
|
1593
|
+
onGetChat,
|
|
1251
1594
|
suggestions,
|
|
1252
1595
|
availableAgents,
|
|
1253
1596
|
defaultAgent,
|
|
@@ -1275,6 +1618,7 @@ function UseAIChatPanel({
|
|
|
1275
1618
|
fileError,
|
|
1276
1619
|
enabled: fileUploadEnabled,
|
|
1277
1620
|
acceptedTypes,
|
|
1621
|
+
processingState: fileProcessingState,
|
|
1278
1622
|
fileInputRef,
|
|
1279
1623
|
removeAttachment,
|
|
1280
1624
|
clearAttachments,
|
|
@@ -1283,6 +1627,7 @@ function UseAIChatPanel({
|
|
|
1283
1627
|
getDropZoneProps,
|
|
1284
1628
|
DropZoneOverlay
|
|
1285
1629
|
} = useFileUpload({
|
|
1630
|
+
getCurrentChat: onGetChat ?? (async () => null),
|
|
1286
1631
|
config: fileUploadConfig,
|
|
1287
1632
|
disabled: loading,
|
|
1288
1633
|
resetDependency: currentChatId
|
|
@@ -1354,7 +1699,7 @@ function UseAIChatPanel({
|
|
|
1354
1699
|
chatHistoryDropdown.close();
|
|
1355
1700
|
}
|
|
1356
1701
|
};
|
|
1357
|
-
return /* @__PURE__ */
|
|
1702
|
+
return /* @__PURE__ */ jsxs7(
|
|
1358
1703
|
"div",
|
|
1359
1704
|
{
|
|
1360
1705
|
onClick: () => {
|
|
@@ -1372,7 +1717,7 @@ function UseAIChatPanel({
|
|
|
1372
1717
|
},
|
|
1373
1718
|
children: [
|
|
1374
1719
|
DropZoneOverlay,
|
|
1375
|
-
/* @__PURE__ */
|
|
1720
|
+
/* @__PURE__ */ jsxs7(
|
|
1376
1721
|
"div",
|
|
1377
1722
|
{
|
|
1378
1723
|
style: {
|
|
@@ -1385,7 +1730,7 @@ function UseAIChatPanel({
|
|
|
1385
1730
|
gap: "12px"
|
|
1386
1731
|
},
|
|
1387
1732
|
children: [
|
|
1388
|
-
/* @__PURE__ */
|
|
1733
|
+
/* @__PURE__ */ jsx10("div", { style: { flex: 1, minWidth: 0, position: "relative" }, children: onListChats ? /* @__PURE__ */ jsxs7(
|
|
1389
1734
|
"button",
|
|
1390
1735
|
{
|
|
1391
1736
|
"data-testid": "chat-history-dropdown-button",
|
|
@@ -1418,7 +1763,7 @@ function UseAIChatPanel({
|
|
|
1418
1763
|
e.currentTarget.style.background = "transparent";
|
|
1419
1764
|
},
|
|
1420
1765
|
children: [
|
|
1421
|
-
/* @__PURE__ */
|
|
1766
|
+
/* @__PURE__ */ jsx10("span", { style: {
|
|
1422
1767
|
overflow: "hidden",
|
|
1423
1768
|
textOverflow: "ellipsis",
|
|
1424
1769
|
whiteSpace: "nowrap",
|
|
@@ -1435,13 +1780,13 @@ function UseAIChatPanel({
|
|
|
1435
1780
|
}
|
|
1436
1781
|
return strings.header.newChat;
|
|
1437
1782
|
})() }),
|
|
1438
|
-
/* @__PURE__ */
|
|
1783
|
+
/* @__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
1784
|
]
|
|
1440
1785
|
}
|
|
1441
|
-
) : /* @__PURE__ */
|
|
1442
|
-
/* @__PURE__ */
|
|
1443
|
-
availableAgents && availableAgents.length > 1 && onAgentChange && /* @__PURE__ */
|
|
1444
|
-
/* @__PURE__ */
|
|
1786
|
+
) : /* @__PURE__ */ jsx10("div", { style: { fontSize: "14px", fontWeight: "600", color: theme.textColor, padding: "6px 8px" }, children: strings.header.aiAssistant }) }),
|
|
1787
|
+
/* @__PURE__ */ jsxs7("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
|
|
1788
|
+
availableAgents && availableAgents.length > 1 && onAgentChange && /* @__PURE__ */ jsxs7("div", { style: { position: "relative" }, children: [
|
|
1789
|
+
/* @__PURE__ */ jsxs7(
|
|
1445
1790
|
"button",
|
|
1446
1791
|
{
|
|
1447
1792
|
"data-testid": "agent-selector",
|
|
@@ -1470,7 +1815,7 @@ function UseAIChatPanel({
|
|
|
1470
1815
|
},
|
|
1471
1816
|
title: "Select AI model",
|
|
1472
1817
|
children: [
|
|
1473
|
-
/* @__PURE__ */
|
|
1818
|
+
/* @__PURE__ */ jsx10("span", { style: {
|
|
1474
1819
|
overflow: "hidden",
|
|
1475
1820
|
textOverflow: "ellipsis",
|
|
1476
1821
|
whiteSpace: "nowrap",
|
|
@@ -1479,11 +1824,11 @@ function UseAIChatPanel({
|
|
|
1479
1824
|
const agent = availableAgents.find((a) => a.id === (selectedAgent ?? defaultAgent));
|
|
1480
1825
|
return agent?.name || "AI";
|
|
1481
1826
|
})() }),
|
|
1482
|
-
/* @__PURE__ */
|
|
1827
|
+
/* @__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
1828
|
]
|
|
1484
1829
|
}
|
|
1485
1830
|
),
|
|
1486
|
-
agentDropdown.isOpen && /* @__PURE__ */
|
|
1831
|
+
agentDropdown.isOpen && /* @__PURE__ */ jsx10(
|
|
1487
1832
|
"div",
|
|
1488
1833
|
{
|
|
1489
1834
|
style: {
|
|
@@ -1503,7 +1848,7 @@ function UseAIChatPanel({
|
|
|
1503
1848
|
},
|
|
1504
1849
|
children: availableAgents.map((agent) => {
|
|
1505
1850
|
const isSelected = agent.id === (selectedAgent ?? defaultAgent);
|
|
1506
|
-
return /* @__PURE__ */
|
|
1851
|
+
return /* @__PURE__ */ jsxs7(
|
|
1507
1852
|
"div",
|
|
1508
1853
|
{
|
|
1509
1854
|
"data-testid": "agent-option",
|
|
@@ -1533,13 +1878,13 @@ function UseAIChatPanel({
|
|
|
1533
1878
|
}
|
|
1534
1879
|
},
|
|
1535
1880
|
children: [
|
|
1536
|
-
/* @__PURE__ */
|
|
1537
|
-
/* @__PURE__ */
|
|
1881
|
+
/* @__PURE__ */ jsxs7("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
1882
|
+
/* @__PURE__ */ jsx10("div", { style: {
|
|
1538
1883
|
fontSize: "13px",
|
|
1539
1884
|
fontWeight: isSelected ? "600" : "500",
|
|
1540
1885
|
color: isSelected ? theme.primaryColor : theme.textColor
|
|
1541
1886
|
}, children: agent.name }),
|
|
1542
|
-
agent.annotation && /* @__PURE__ */
|
|
1887
|
+
agent.annotation && /* @__PURE__ */ jsx10("div", { style: {
|
|
1543
1888
|
fontSize: "11px",
|
|
1544
1889
|
color: theme.secondaryTextColor,
|
|
1545
1890
|
marginTop: "2px",
|
|
@@ -1548,7 +1893,7 @@ function UseAIChatPanel({
|
|
|
1548
1893
|
whiteSpace: "nowrap"
|
|
1549
1894
|
}, children: agent.annotation })
|
|
1550
1895
|
] }),
|
|
1551
|
-
isSelected && /* @__PURE__ */
|
|
1896
|
+
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
1897
|
]
|
|
1553
1898
|
},
|
|
1554
1899
|
agent.id
|
|
@@ -1557,7 +1902,7 @@ function UseAIChatPanel({
|
|
|
1557
1902
|
}
|
|
1558
1903
|
)
|
|
1559
1904
|
] }),
|
|
1560
|
-
onNewChat && /* @__PURE__ */
|
|
1905
|
+
onNewChat && /* @__PURE__ */ jsx10(
|
|
1561
1906
|
"button",
|
|
1562
1907
|
{
|
|
1563
1908
|
"data-testid": "new-chat-button",
|
|
@@ -1584,10 +1929,10 @@ function UseAIChatPanel({
|
|
|
1584
1929
|
e.currentTarget.style.color = theme.secondaryTextColor;
|
|
1585
1930
|
},
|
|
1586
1931
|
title: strings.header.newChat,
|
|
1587
|
-
children: /* @__PURE__ */
|
|
1932
|
+
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
1933
|
}
|
|
1589
1934
|
),
|
|
1590
|
-
onDeleteChat && messages.length > 0 && /* @__PURE__ */
|
|
1935
|
+
onDeleteChat && messages.length > 0 && /* @__PURE__ */ jsx10(
|
|
1591
1936
|
"button",
|
|
1592
1937
|
{
|
|
1593
1938
|
"data-testid": "delete-chat-button",
|
|
@@ -1611,7 +1956,7 @@ function UseAIChatPanel({
|
|
|
1611
1956
|
e.currentTarget.style.color = theme.secondaryTextColor;
|
|
1612
1957
|
},
|
|
1613
1958
|
title: strings.header.deleteChat,
|
|
1614
|
-
children: /* @__PURE__ */
|
|
1959
|
+
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
1960
|
}
|
|
1616
1961
|
),
|
|
1617
1962
|
closeButton
|
|
@@ -1619,7 +1964,7 @@ function UseAIChatPanel({
|
|
|
1619
1964
|
]
|
|
1620
1965
|
}
|
|
1621
1966
|
),
|
|
1622
|
-
chatHistoryDropdown.isOpen && onListChats && /* @__PURE__ */
|
|
1967
|
+
chatHistoryDropdown.isOpen && onListChats && /* @__PURE__ */ jsx10(
|
|
1623
1968
|
"div",
|
|
1624
1969
|
{
|
|
1625
1970
|
style: {
|
|
@@ -1636,7 +1981,7 @@ function UseAIChatPanel({
|
|
|
1636
1981
|
flexDirection: "column",
|
|
1637
1982
|
overflow: "hidden"
|
|
1638
1983
|
},
|
|
1639
|
-
children: /* @__PURE__ */
|
|
1984
|
+
children: /* @__PURE__ */ jsx10(
|
|
1640
1985
|
"div",
|
|
1641
1986
|
{
|
|
1642
1987
|
style: {
|
|
@@ -1644,7 +1989,7 @@ function UseAIChatPanel({
|
|
|
1644
1989
|
overflowY: "auto",
|
|
1645
1990
|
padding: "8px"
|
|
1646
1991
|
},
|
|
1647
|
-
children: chatHistory.length === 0 ? /* @__PURE__ */
|
|
1992
|
+
children: chatHistory.length === 0 ? /* @__PURE__ */ jsx10(
|
|
1648
1993
|
"div",
|
|
1649
1994
|
{
|
|
1650
1995
|
style: {
|
|
@@ -1653,9 +1998,9 @@ function UseAIChatPanel({
|
|
|
1653
1998
|
padding: "32px 16px",
|
|
1654
1999
|
fontSize: "13px"
|
|
1655
2000
|
},
|
|
1656
|
-
children: /* @__PURE__ */
|
|
2001
|
+
children: /* @__PURE__ */ jsx10("p", { style: { margin: 0 }, children: strings.chatHistory.noChatHistory })
|
|
1657
2002
|
}
|
|
1658
|
-
) : chatHistory.map((chat) => /* @__PURE__ */
|
|
2003
|
+
) : chatHistory.map((chat) => /* @__PURE__ */ jsxs7(
|
|
1659
2004
|
"div",
|
|
1660
2005
|
{
|
|
1661
2006
|
"data-testid": "chat-history-item",
|
|
@@ -1679,10 +2024,10 @@ function UseAIChatPanel({
|
|
|
1679
2024
|
}
|
|
1680
2025
|
},
|
|
1681
2026
|
children: [
|
|
1682
|
-
/* @__PURE__ */
|
|
1683
|
-
/* @__PURE__ */
|
|
2027
|
+
/* @__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 }),
|
|
2028
|
+
/* @__PURE__ */ jsxs7("div", { style: { fontSize: "11px", color: theme.secondaryTextColor }, children: [
|
|
1684
2029
|
new Date(chat.updatedAt).toLocaleDateString([], { month: "short", day: "numeric" }),
|
|
1685
|
-
currentChatId === chat.id && /* @__PURE__ */
|
|
2030
|
+
currentChatId === chat.id && /* @__PURE__ */ jsxs7("span", { style: {
|
|
1686
2031
|
marginLeft: "8px",
|
|
1687
2032
|
color: theme.primaryColor,
|
|
1688
2033
|
fontWeight: "600"
|
|
@@ -1701,7 +2046,7 @@ function UseAIChatPanel({
|
|
|
1701
2046
|
),
|
|
1702
2047
|
chatHistoryDropdown.Backdrop,
|
|
1703
2048
|
agentDropdown.Backdrop,
|
|
1704
|
-
/* @__PURE__ */
|
|
2049
|
+
/* @__PURE__ */ jsxs7(
|
|
1705
2050
|
"div",
|
|
1706
2051
|
{
|
|
1707
2052
|
style: {
|
|
@@ -1713,7 +2058,7 @@ function UseAIChatPanel({
|
|
|
1713
2058
|
gap: "12px"
|
|
1714
2059
|
},
|
|
1715
2060
|
children: [
|
|
1716
|
-
messages.length === 0 && /* @__PURE__ */
|
|
2061
|
+
messages.length === 0 && /* @__PURE__ */ jsxs7(
|
|
1717
2062
|
"div",
|
|
1718
2063
|
{
|
|
1719
2064
|
style: {
|
|
@@ -1724,12 +2069,12 @@ function UseAIChatPanel({
|
|
|
1724
2069
|
gap: "20px"
|
|
1725
2070
|
},
|
|
1726
2071
|
children: [
|
|
1727
|
-
/* @__PURE__ */
|
|
1728
|
-
/* @__PURE__ */
|
|
1729
|
-
/* @__PURE__ */
|
|
1730
|
-
/* @__PURE__ */
|
|
2072
|
+
/* @__PURE__ */ jsxs7("div", { style: { textAlign: "center", color: theme.secondaryTextColor, fontSize: "14px" }, children: [
|
|
2073
|
+
/* @__PURE__ */ jsx10("p", { style: { margin: 0, fontSize: "32px", marginBottom: "12px" }, children: "\u{1F4AC}" }),
|
|
2074
|
+
/* @__PURE__ */ jsx10("p", { style: { margin: 0 }, children: strings.emptyChat.startConversation }),
|
|
2075
|
+
/* @__PURE__ */ jsx10("p", { style: { margin: "8px 0 0", fontSize: "12px" }, children: strings.emptyChat.askMeToHelp })
|
|
1731
2076
|
] }),
|
|
1732
|
-
displayedSuggestions.length > 0 && /* @__PURE__ */
|
|
2077
|
+
displayedSuggestions.length > 0 && /* @__PURE__ */ jsx10(
|
|
1733
2078
|
"div",
|
|
1734
2079
|
{
|
|
1735
2080
|
style: {
|
|
@@ -1739,7 +2084,7 @@ function UseAIChatPanel({
|
|
|
1739
2084
|
width: "100%",
|
|
1740
2085
|
maxWidth: "320px"
|
|
1741
2086
|
},
|
|
1742
|
-
children: displayedSuggestions.map((suggestion, index) => /* @__PURE__ */
|
|
2087
|
+
children: displayedSuggestions.map((suggestion, index) => /* @__PURE__ */ jsx10(
|
|
1743
2088
|
"button",
|
|
1744
2089
|
{
|
|
1745
2090
|
"data-testid": "chat-suggestion-button",
|
|
@@ -1783,7 +2128,7 @@ function UseAIChatPanel({
|
|
|
1783
2128
|
]
|
|
1784
2129
|
}
|
|
1785
2130
|
),
|
|
1786
|
-
messages.map((message) => /* @__PURE__ */
|
|
2131
|
+
messages.map((message) => /* @__PURE__ */ jsxs7(
|
|
1787
2132
|
"div",
|
|
1788
2133
|
{
|
|
1789
2134
|
"data-testid": `chat-message-${message.role}`,
|
|
@@ -1796,7 +2141,7 @@ function UseAIChatPanel({
|
|
|
1796
2141
|
onMouseEnter: () => message.role === "user" && setHoveredMessageId(message.id),
|
|
1797
2142
|
onMouseLeave: () => setHoveredMessageId(null),
|
|
1798
2143
|
children: [
|
|
1799
|
-
/* @__PURE__ */
|
|
2144
|
+
/* @__PURE__ */ jsxs7(
|
|
1800
2145
|
"div",
|
|
1801
2146
|
{
|
|
1802
2147
|
style: {
|
|
@@ -1804,7 +2149,7 @@ function UseAIChatPanel({
|
|
|
1804
2149
|
maxWidth: "80%"
|
|
1805
2150
|
},
|
|
1806
2151
|
children: [
|
|
1807
|
-
message.role === "user" && hoveredMessageId === message.id && onSaveCommand && !slashCommands.isSavingCommand(message.id) && /* @__PURE__ */
|
|
2152
|
+
message.role === "user" && hoveredMessageId === message.id && onSaveCommand && !slashCommands.isSavingCommand(message.id) && /* @__PURE__ */ jsx10(
|
|
1808
2153
|
"button",
|
|
1809
2154
|
{
|
|
1810
2155
|
"data-testid": "save-command-button",
|
|
@@ -1840,14 +2185,14 @@ function UseAIChatPanel({
|
|
|
1840
2185
|
e.currentTarget.style.transform = "scale(1)";
|
|
1841
2186
|
e.currentTarget.style.boxShadow = "0 2px 6px rgba(0, 0, 0, 0.15)";
|
|
1842
2187
|
},
|
|
1843
|
-
children: /* @__PURE__ */
|
|
1844
|
-
/* @__PURE__ */
|
|
1845
|
-
/* @__PURE__ */
|
|
1846
|
-
/* @__PURE__ */
|
|
2188
|
+
children: /* @__PURE__ */ jsxs7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2189
|
+
/* @__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" }),
|
|
2190
|
+
/* @__PURE__ */ jsx10("polyline", { points: "17 21 17 13 7 13 7 21" }),
|
|
2191
|
+
/* @__PURE__ */ jsx10("polyline", { points: "7 3 7 8 15 8" })
|
|
1847
2192
|
] })
|
|
1848
2193
|
}
|
|
1849
2194
|
),
|
|
1850
|
-
/* @__PURE__ */
|
|
2195
|
+
/* @__PURE__ */ jsxs7(
|
|
1851
2196
|
"div",
|
|
1852
2197
|
{
|
|
1853
2198
|
"data-testid": "chat-message-content",
|
|
@@ -1862,7 +2207,7 @@ function UseAIChatPanel({
|
|
|
1862
2207
|
wordWrap: "break-word"
|
|
1863
2208
|
},
|
|
1864
2209
|
children: [
|
|
1865
|
-
message.role === "user" && hasFileContent(message.content) && /* @__PURE__ */
|
|
2210
|
+
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
2211
|
FilePlaceholder,
|
|
1867
2212
|
{
|
|
1868
2213
|
name: part.file.name,
|
|
@@ -1870,7 +2215,7 @@ function UseAIChatPanel({
|
|
|
1870
2215
|
},
|
|
1871
2216
|
idx
|
|
1872
2217
|
)) }),
|
|
1873
|
-
message.role === "assistant" ? /* @__PURE__ */
|
|
2218
|
+
message.role === "assistant" ? /* @__PURE__ */ jsx10(MarkdownContent, { content: getTextContent(message.content) }) : getTextContent(message.content)
|
|
1874
2219
|
]
|
|
1875
2220
|
}
|
|
1876
2221
|
),
|
|
@@ -1881,7 +2226,7 @@ function UseAIChatPanel({
|
|
|
1881
2226
|
]
|
|
1882
2227
|
}
|
|
1883
2228
|
),
|
|
1884
|
-
/* @__PURE__ */
|
|
2229
|
+
/* @__PURE__ */ jsx10(
|
|
1885
2230
|
"div",
|
|
1886
2231
|
{
|
|
1887
2232
|
style: {
|
|
@@ -1900,14 +2245,14 @@ function UseAIChatPanel({
|
|
|
1900
2245
|
},
|
|
1901
2246
|
message.id
|
|
1902
2247
|
)),
|
|
1903
|
-
loading && /* @__PURE__ */
|
|
2248
|
+
loading && /* @__PURE__ */ jsx10(
|
|
1904
2249
|
"div",
|
|
1905
2250
|
{
|
|
1906
2251
|
style: {
|
|
1907
2252
|
display: "flex",
|
|
1908
2253
|
alignItems: "flex-start"
|
|
1909
2254
|
},
|
|
1910
|
-
children: /* @__PURE__ */
|
|
2255
|
+
children: /* @__PURE__ */ jsx10(
|
|
1911
2256
|
"div",
|
|
1912
2257
|
{
|
|
1913
2258
|
className: "markdown-content",
|
|
@@ -1920,19 +2265,19 @@ function UseAIChatPanel({
|
|
|
1920
2265
|
color: theme.textColor,
|
|
1921
2266
|
maxWidth: "80%"
|
|
1922
2267
|
},
|
|
1923
|
-
children: streamingText ? /* @__PURE__ */
|
|
1924
|
-
/* @__PURE__ */
|
|
1925
|
-
/* @__PURE__ */
|
|
2268
|
+
children: streamingText ? /* @__PURE__ */ jsx10(MarkdownContent, { content: streamingText }) : /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
2269
|
+
/* @__PURE__ */ jsx10("span", { style: { opacity: 0.6 }, children: strings.input.thinking }),
|
|
2270
|
+
/* @__PURE__ */ jsx10("span", { className: "dots", style: { marginLeft: "4px" }, children: "..." })
|
|
1926
2271
|
] })
|
|
1927
2272
|
}
|
|
1928
2273
|
)
|
|
1929
2274
|
}
|
|
1930
2275
|
),
|
|
1931
|
-
/* @__PURE__ */
|
|
2276
|
+
/* @__PURE__ */ jsx10("div", { ref: messagesEndRef })
|
|
1932
2277
|
]
|
|
1933
2278
|
}
|
|
1934
2279
|
),
|
|
1935
|
-
/* @__PURE__ */
|
|
2280
|
+
/* @__PURE__ */ jsxs7(
|
|
1936
2281
|
"div",
|
|
1937
2282
|
{
|
|
1938
2283
|
style: {
|
|
@@ -1940,7 +2285,7 @@ function UseAIChatPanel({
|
|
|
1940
2285
|
borderTop: `1px solid ${theme.borderColor}`
|
|
1941
2286
|
},
|
|
1942
2287
|
children: [
|
|
1943
|
-
fileError && /* @__PURE__ */
|
|
2288
|
+
fileError && /* @__PURE__ */ jsx10(
|
|
1944
2289
|
"div",
|
|
1945
2290
|
{
|
|
1946
2291
|
"data-testid": "file-error",
|
|
@@ -1955,7 +2300,7 @@ function UseAIChatPanel({
|
|
|
1955
2300
|
children: fileError
|
|
1956
2301
|
}
|
|
1957
2302
|
),
|
|
1958
|
-
attachments.length > 0 && /* @__PURE__ */
|
|
2303
|
+
attachments.length > 0 && /* @__PURE__ */ jsx10(
|
|
1959
2304
|
"div",
|
|
1960
2305
|
{
|
|
1961
2306
|
"data-testid": "file-attachments",
|
|
@@ -1965,18 +2310,19 @@ function UseAIChatPanel({
|
|
|
1965
2310
|
gap: "8px",
|
|
1966
2311
|
marginBottom: "8px"
|
|
1967
2312
|
},
|
|
1968
|
-
children: attachments.map((attachment) => /* @__PURE__ */
|
|
2313
|
+
children: attachments.map((attachment) => /* @__PURE__ */ jsx10(
|
|
1969
2314
|
FileChip,
|
|
1970
2315
|
{
|
|
1971
2316
|
attachment,
|
|
1972
2317
|
onRemove: () => removeAttachment(attachment.id),
|
|
1973
|
-
disabled: loading
|
|
2318
|
+
disabled: loading,
|
|
2319
|
+
processingState: fileProcessingState.get(attachment.id)
|
|
1974
2320
|
},
|
|
1975
2321
|
attachment.id
|
|
1976
2322
|
))
|
|
1977
2323
|
}
|
|
1978
2324
|
),
|
|
1979
|
-
/* @__PURE__ */
|
|
2325
|
+
/* @__PURE__ */ jsxs7(
|
|
1980
2326
|
"div",
|
|
1981
2327
|
{
|
|
1982
2328
|
style: {
|
|
@@ -1988,18 +2334,19 @@ function UseAIChatPanel({
|
|
|
1988
2334
|
},
|
|
1989
2335
|
children: [
|
|
1990
2336
|
slashCommands.AutocompleteComponent,
|
|
1991
|
-
/* @__PURE__ */
|
|
2337
|
+
/* @__PURE__ */ jsx10(
|
|
1992
2338
|
"input",
|
|
1993
2339
|
{
|
|
1994
2340
|
ref: fileInputRef,
|
|
1995
2341
|
type: "file",
|
|
1996
2342
|
multiple: true,
|
|
2343
|
+
"data-testid": "file-input",
|
|
1997
2344
|
style: { display: "none" },
|
|
1998
2345
|
onChange: handleFileInputChange,
|
|
1999
2346
|
accept: acceptedTypes?.join(",")
|
|
2000
2347
|
}
|
|
2001
2348
|
),
|
|
2002
|
-
/* @__PURE__ */
|
|
2349
|
+
/* @__PURE__ */ jsx10(
|
|
2003
2350
|
"textarea",
|
|
2004
2351
|
{
|
|
2005
2352
|
ref: textareaRef,
|
|
@@ -2027,7 +2374,7 @@ function UseAIChatPanel({
|
|
|
2027
2374
|
}
|
|
2028
2375
|
}
|
|
2029
2376
|
),
|
|
2030
|
-
/* @__PURE__ */
|
|
2377
|
+
/* @__PURE__ */ jsxs7(
|
|
2031
2378
|
"div",
|
|
2032
2379
|
{
|
|
2033
2380
|
style: {
|
|
@@ -2037,7 +2384,7 @@ function UseAIChatPanel({
|
|
|
2037
2384
|
padding: "4px 8px"
|
|
2038
2385
|
},
|
|
2039
2386
|
children: [
|
|
2040
|
-
/* @__PURE__ */
|
|
2387
|
+
/* @__PURE__ */ jsx10("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: fileUploadEnabled && /* @__PURE__ */ jsx10(
|
|
2041
2388
|
"button",
|
|
2042
2389
|
{
|
|
2043
2390
|
"data-testid": "file-picker-button",
|
|
@@ -2069,13 +2416,13 @@ function UseAIChatPanel({
|
|
|
2069
2416
|
e.currentTarget.style.borderColor = theme.borderColor;
|
|
2070
2417
|
},
|
|
2071
2418
|
title: strings.fileUpload.attachFiles,
|
|
2072
|
-
children: /* @__PURE__ */
|
|
2073
|
-
/* @__PURE__ */
|
|
2074
|
-
/* @__PURE__ */
|
|
2419
|
+
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: [
|
|
2420
|
+
/* @__PURE__ */ jsx10("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
|
|
2421
|
+
/* @__PURE__ */ jsx10("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
|
|
2075
2422
|
] })
|
|
2076
2423
|
}
|
|
2077
2424
|
) }),
|
|
2078
|
-
/* @__PURE__ */
|
|
2425
|
+
/* @__PURE__ */ jsx10(
|
|
2079
2426
|
"button",
|
|
2080
2427
|
{
|
|
2081
2428
|
"data-testid": "chat-send-button",
|
|
@@ -2096,9 +2443,9 @@ function UseAIChatPanel({
|
|
|
2096
2443
|
height: "32px",
|
|
2097
2444
|
transition: "all 0.2s"
|
|
2098
2445
|
},
|
|
2099
|
-
children: /* @__PURE__ */
|
|
2100
|
-
/* @__PURE__ */
|
|
2101
|
-
/* @__PURE__ */
|
|
2446
|
+
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: [
|
|
2447
|
+
/* @__PURE__ */ jsx10("line", { x1: "12", y1: "19", x2: "12", y2: "5" }),
|
|
2448
|
+
/* @__PURE__ */ jsx10("polyline", { points: "5 12 12 5 19 12" })
|
|
2102
2449
|
] })
|
|
2103
2450
|
}
|
|
2104
2451
|
)
|
|
@@ -2111,7 +2458,7 @@ function UseAIChatPanel({
|
|
|
2111
2458
|
]
|
|
2112
2459
|
}
|
|
2113
2460
|
),
|
|
2114
|
-
/* @__PURE__ */
|
|
2461
|
+
/* @__PURE__ */ jsx10("style", { children: `
|
|
2115
2462
|
/* Markdown content styles */
|
|
2116
2463
|
.markdown-content > :first-child {
|
|
2117
2464
|
margin-top: 0 !important;
|
|
@@ -2136,7 +2483,7 @@ function UseAIChatPanel({
|
|
|
2136
2483
|
}
|
|
2137
2484
|
|
|
2138
2485
|
// src/components/UseAIFloatingChatWrapper.tsx
|
|
2139
|
-
import { Fragment as Fragment2, jsx as
|
|
2486
|
+
import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2140
2487
|
function UseAIFloatingChatWrapper({
|
|
2141
2488
|
isOpen,
|
|
2142
2489
|
onClose,
|
|
@@ -2144,8 +2491,8 @@ function UseAIFloatingChatWrapper({
|
|
|
2144
2491
|
}) {
|
|
2145
2492
|
const theme = useTheme();
|
|
2146
2493
|
if (!isOpen) return null;
|
|
2147
|
-
return /* @__PURE__ */
|
|
2148
|
-
/* @__PURE__ */
|
|
2494
|
+
return /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
2495
|
+
/* @__PURE__ */ jsx11(
|
|
2149
2496
|
"div",
|
|
2150
2497
|
{
|
|
2151
2498
|
style: {
|
|
@@ -2161,7 +2508,7 @@ function UseAIFloatingChatWrapper({
|
|
|
2161
2508
|
onClick: onClose
|
|
2162
2509
|
}
|
|
2163
2510
|
),
|
|
2164
|
-
/* @__PURE__ */
|
|
2511
|
+
/* @__PURE__ */ jsx11(
|
|
2165
2512
|
"div",
|
|
2166
2513
|
{
|
|
2167
2514
|
style: {
|
|
@@ -2180,7 +2527,7 @@ function UseAIFloatingChatWrapper({
|
|
|
2180
2527
|
children
|
|
2181
2528
|
}
|
|
2182
2529
|
),
|
|
2183
|
-
/* @__PURE__ */
|
|
2530
|
+
/* @__PURE__ */ jsx11("style", { children: `
|
|
2184
2531
|
@keyframes fadeIn {
|
|
2185
2532
|
from { opacity: 0; }
|
|
2186
2533
|
to { opacity: 1; }
|
|
@@ -2200,7 +2547,7 @@ function UseAIFloatingChatWrapper({
|
|
|
2200
2547
|
}
|
|
2201
2548
|
function CloseButton({ onClick }) {
|
|
2202
2549
|
const theme = useTheme();
|
|
2203
|
-
return /* @__PURE__ */
|
|
2550
|
+
return /* @__PURE__ */ jsx11(
|
|
2204
2551
|
"button",
|
|
2205
2552
|
{
|
|
2206
2553
|
"data-testid": "chat-close-button",
|
|
@@ -2235,7 +2582,7 @@ function CloseButton({ onClick }) {
|
|
|
2235
2582
|
|
|
2236
2583
|
// src/components/UseAIChat.tsx
|
|
2237
2584
|
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
2238
|
-
import { jsx as
|
|
2585
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
2239
2586
|
var __UseAIChatContext = createContext3(null);
|
|
2240
2587
|
function useChatUIContext() {
|
|
2241
2588
|
const context = useContext3(__UseAIChatContext);
|
|
@@ -2259,6 +2606,7 @@ function UseAIChat({ floating = false }) {
|
|
|
2259
2606
|
onLoadChat: ctx.history.load,
|
|
2260
2607
|
onDeleteChat: ctx.history.delete,
|
|
2261
2608
|
onListChats: ctx.history.list,
|
|
2609
|
+
onGetChat: ctx.history.get,
|
|
2262
2610
|
suggestions: ctx.suggestions,
|
|
2263
2611
|
availableAgents: ctx.agents.available,
|
|
2264
2612
|
defaultAgent: ctx.agents.default,
|
|
@@ -2271,22 +2619,22 @@ function UseAIChat({ floating = false }) {
|
|
|
2271
2619
|
onDeleteCommand: ctx.commands.delete
|
|
2272
2620
|
};
|
|
2273
2621
|
if (floating) {
|
|
2274
|
-
return /* @__PURE__ */
|
|
2622
|
+
return /* @__PURE__ */ jsx12(
|
|
2275
2623
|
UseAIFloatingChatWrapper,
|
|
2276
2624
|
{
|
|
2277
2625
|
isOpen: ctx.ui.isOpen,
|
|
2278
2626
|
onClose: () => ctx.ui.setOpen(false),
|
|
2279
|
-
children: /* @__PURE__ */
|
|
2627
|
+
children: /* @__PURE__ */ jsx12(
|
|
2280
2628
|
UseAIChatPanel,
|
|
2281
2629
|
{
|
|
2282
2630
|
...chatPanelProps,
|
|
2283
|
-
closeButton: /* @__PURE__ */
|
|
2631
|
+
closeButton: /* @__PURE__ */ jsx12(CloseButton, { onClick: () => ctx.ui.setOpen(false) })
|
|
2284
2632
|
}
|
|
2285
2633
|
)
|
|
2286
2634
|
}
|
|
2287
2635
|
);
|
|
2288
2636
|
}
|
|
2289
|
-
return /* @__PURE__ */
|
|
2637
|
+
return /* @__PURE__ */ jsx12(UseAIChatPanel, { ...chatPanelProps });
|
|
2290
2638
|
}
|
|
2291
2639
|
|
|
2292
2640
|
// src/client.ts
|
|
@@ -2487,12 +2835,18 @@ var UseAIClient = class {
|
|
|
2487
2835
|
return { type: "text", text: part.text };
|
|
2488
2836
|
} else if (part.type === "image") {
|
|
2489
2837
|
return { type: "image", url: part.url };
|
|
2490
|
-
} else {
|
|
2838
|
+
} else if (part.type === "file") {
|
|
2491
2839
|
return {
|
|
2492
2840
|
type: "file",
|
|
2493
2841
|
url: part.url,
|
|
2494
2842
|
mimeType: part.mimeType
|
|
2495
2843
|
};
|
|
2844
|
+
} else {
|
|
2845
|
+
return {
|
|
2846
|
+
type: "transformed_file",
|
|
2847
|
+
text: part.text,
|
|
2848
|
+
originalFile: part.originalFile
|
|
2849
|
+
};
|
|
2496
2850
|
}
|
|
2497
2851
|
});
|
|
2498
2852
|
}
|
|
@@ -2867,7 +3221,8 @@ var LocalStorageChatRepository = class {
|
|
|
2867
3221
|
title: options?.title,
|
|
2868
3222
|
messages: [],
|
|
2869
3223
|
createdAt: now,
|
|
2870
|
-
updatedAt: now
|
|
3224
|
+
updatedAt: now,
|
|
3225
|
+
metadata: options?.metadata
|
|
2871
3226
|
};
|
|
2872
3227
|
await this.enforceMaxChatsLimit();
|
|
2873
3228
|
await this.saveChat(chat);
|
|
@@ -2951,6 +3306,14 @@ var LocalStorageChatRepository = class {
|
|
|
2951
3306
|
throw new Error(`Failed to clear all chats: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2952
3307
|
}
|
|
2953
3308
|
}
|
|
3309
|
+
async updateMetadata(id, metadata, overwrite = false) {
|
|
3310
|
+
const chat = await this.loadChat(id);
|
|
3311
|
+
if (!chat) {
|
|
3312
|
+
throw new Error(`Chat not found: ${id}`);
|
|
3313
|
+
}
|
|
3314
|
+
chat.metadata = overwrite ? metadata : { ...chat.metadata, ...metadata };
|
|
3315
|
+
await this.saveChat(chat);
|
|
3316
|
+
}
|
|
2954
3317
|
getChatKey(id) {
|
|
2955
3318
|
return `${STORAGE_KEY_PREFIX}${id}`;
|
|
2956
3319
|
}
|
|
@@ -2989,36 +3352,12 @@ var LocalStorageChatRepository = class {
|
|
|
2989
3352
|
}
|
|
2990
3353
|
};
|
|
2991
3354
|
|
|
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
3355
|
// src/hooks/useChatManagement.ts
|
|
3020
3356
|
import { useState as useState5, useCallback as useCallback4, useRef as useRef5, useEffect as useEffect5 } from "react";
|
|
3021
3357
|
var CHAT_TITLE_MAX_LENGTH = 50;
|
|
3358
|
+
function deepEquals(a, b) {
|
|
3359
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
3360
|
+
}
|
|
3022
3361
|
function generateChatTitle(message) {
|
|
3023
3362
|
return message.length > CHAT_TITLE_MAX_LENGTH ? message.substring(0, CHAT_TITLE_MAX_LENGTH) + "..." : message;
|
|
3024
3363
|
}
|
|
@@ -3049,7 +3388,11 @@ function transformMessagesToClientFormat(uiMessages) {
|
|
|
3049
3388
|
}
|
|
3050
3389
|
function useChatManagement({
|
|
3051
3390
|
repository,
|
|
3052
|
-
clientRef
|
|
3391
|
+
clientRef,
|
|
3392
|
+
onSendMessage,
|
|
3393
|
+
setOpen,
|
|
3394
|
+
connected,
|
|
3395
|
+
loading
|
|
3053
3396
|
}) {
|
|
3054
3397
|
const [currentChatId, setCurrentChatId] = useState5(null);
|
|
3055
3398
|
const [pendingChatId, setPendingChatId] = useState5(null);
|
|
@@ -3082,18 +3425,18 @@ function useChatManagement({
|
|
|
3082
3425
|
const loadedMessages = await loadChatMessages(chatId);
|
|
3083
3426
|
setMessages(loadedMessages);
|
|
3084
3427
|
}, [loadChatMessages]);
|
|
3085
|
-
const createNewChat = useCallback4(async () => {
|
|
3428
|
+
const createNewChat = useCallback4(async (options) => {
|
|
3086
3429
|
console.log("[ChatManagement] createNewChat called - currentChatId:", currentChatId, "pendingChatId:", pendingChatId, "messages.length:", messages.length);
|
|
3087
3430
|
if (pendingChatId && messages.length === 0) {
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3431
|
+
const existingChat = await repository.loadChat(pendingChatId);
|
|
3432
|
+
const optionsMatch = existingChat && existingChat.title === options?.title && deepEquals(existingChat.metadata, options?.metadata);
|
|
3433
|
+
if (optionsMatch) {
|
|
3434
|
+
console.log("[ChatManagement] Last created chat has matching options, reusing:", pendingChatId);
|
|
3435
|
+
return pendingChatId;
|
|
3436
|
+
}
|
|
3094
3437
|
}
|
|
3095
3438
|
console.log("[ChatManagement] Creating new chat...");
|
|
3096
|
-
const chatId = await repository.createChat();
|
|
3439
|
+
const chatId = await repository.createChat(options);
|
|
3097
3440
|
setPendingChatId(chatId);
|
|
3098
3441
|
setMessages([]);
|
|
3099
3442
|
if (clientRef.current) {
|
|
@@ -3138,6 +3481,22 @@ function useChatManagement({
|
|
|
3138
3481
|
}
|
|
3139
3482
|
}
|
|
3140
3483
|
}, [currentChatId, repository]);
|
|
3484
|
+
const getCurrentChat = useCallback4(async () => {
|
|
3485
|
+
const chatId = pendingChatId || currentChatId;
|
|
3486
|
+
if (!chatId) return null;
|
|
3487
|
+
const chat = await repository.loadChat(chatId);
|
|
3488
|
+
if (chat?.metadata) {
|
|
3489
|
+
chat.metadata = Object.freeze({ ...chat.metadata });
|
|
3490
|
+
}
|
|
3491
|
+
return chat;
|
|
3492
|
+
}, [pendingChatId, currentChatId, repository]);
|
|
3493
|
+
const updateMetadata = useCallback4(async (metadata, overwrite = false) => {
|
|
3494
|
+
const chatId = pendingChatId || currentChatId;
|
|
3495
|
+
if (!chatId) {
|
|
3496
|
+
throw new Error("No active chat");
|
|
3497
|
+
}
|
|
3498
|
+
await repository.updateMetadata(chatId, metadata, overwrite);
|
|
3499
|
+
}, [pendingChatId, currentChatId, repository]);
|
|
3141
3500
|
const activatePendingChat = useCallback4(() => {
|
|
3142
3501
|
if (!pendingChatId) return null;
|
|
3143
3502
|
console.log("[ChatManagement] Activating pending chat:", pendingChatId);
|
|
@@ -3156,7 +3515,7 @@ function useChatManagement({
|
|
|
3156
3515
|
console.error("[ChatManagement] Chat not found:", chatId);
|
|
3157
3516
|
return false;
|
|
3158
3517
|
}
|
|
3159
|
-
const { generateMessageId: generateMessageId2 } = await import("./types-
|
|
3518
|
+
const { generateMessageId: generateMessageId2 } = await import("./types-64CH2HXY.js");
|
|
3160
3519
|
chat.messages.push({
|
|
3161
3520
|
id: generateMessageId2(),
|
|
3162
3521
|
role: "user",
|
|
@@ -3192,7 +3551,7 @@ function useChatManagement({
|
|
|
3192
3551
|
console.error("[ChatManagement] Chat not found:", currentChatIdValue);
|
|
3193
3552
|
return;
|
|
3194
3553
|
}
|
|
3195
|
-
const { generateMessageId: generateMessageId2 } = await import("./types-
|
|
3554
|
+
const { generateMessageId: generateMessageId2 } = await import("./types-64CH2HXY.js");
|
|
3196
3555
|
chat.messages.push({
|
|
3197
3556
|
id: generateMessageId2(),
|
|
3198
3557
|
role: "assistant",
|
|
@@ -3249,6 +3608,70 @@ function useChatManagement({
|
|
|
3249
3608
|
}
|
|
3250
3609
|
}, [currentChatId, pendingChatId, createNewChat, repository, loadChatMessages, clientRef]);
|
|
3251
3610
|
const displayedChatId = pendingChatId || currentChatId;
|
|
3611
|
+
const pendingMessagesRef = useRef5([]);
|
|
3612
|
+
const isProcessingQueueRef = useRef5(false);
|
|
3613
|
+
const loadingRef = useRef5(loading);
|
|
3614
|
+
useEffect5(() => {
|
|
3615
|
+
loadingRef.current = loading;
|
|
3616
|
+
}, [loading]);
|
|
3617
|
+
const processMessageQueue = useCallback4(async () => {
|
|
3618
|
+
if (isProcessingQueueRef.current || pendingMessagesRef.current.length === 0 || !onSendMessage) {
|
|
3619
|
+
return;
|
|
3620
|
+
}
|
|
3621
|
+
isProcessingQueueRef.current = true;
|
|
3622
|
+
while (pendingMessagesRef.current.length > 0) {
|
|
3623
|
+
const { message, options } = pendingMessagesRef.current.shift();
|
|
3624
|
+
const { newChat = false, attachments = [], openChat = true, metadata } = options ?? {};
|
|
3625
|
+
if (newChat) {
|
|
3626
|
+
await createNewChat({ metadata });
|
|
3627
|
+
}
|
|
3628
|
+
const fileAttachments = await Promise.all(
|
|
3629
|
+
attachments.map(async (file) => {
|
|
3630
|
+
let preview;
|
|
3631
|
+
if (file.type.startsWith("image/")) {
|
|
3632
|
+
preview = await new Promise((resolve) => {
|
|
3633
|
+
const reader = new FileReader();
|
|
3634
|
+
reader.onload = () => resolve(typeof reader.result === "string" ? reader.result : void 0);
|
|
3635
|
+
reader.onerror = () => resolve(void 0);
|
|
3636
|
+
reader.readAsDataURL(file);
|
|
3637
|
+
});
|
|
3638
|
+
}
|
|
3639
|
+
return {
|
|
3640
|
+
id: crypto.randomUUID(),
|
|
3641
|
+
file,
|
|
3642
|
+
preview
|
|
3643
|
+
};
|
|
3644
|
+
})
|
|
3645
|
+
);
|
|
3646
|
+
await onSendMessage(message, fileAttachments.length > 0 ? fileAttachments : void 0);
|
|
3647
|
+
if (openChat && setOpen) {
|
|
3648
|
+
setOpen(true);
|
|
3649
|
+
}
|
|
3650
|
+
await new Promise((resolve) => {
|
|
3651
|
+
const checkLoading = () => {
|
|
3652
|
+
setTimeout(() => {
|
|
3653
|
+
if (!loadingRef.current) {
|
|
3654
|
+
resolve();
|
|
3655
|
+
} else {
|
|
3656
|
+
checkLoading();
|
|
3657
|
+
}
|
|
3658
|
+
}, 100);
|
|
3659
|
+
};
|
|
3660
|
+
checkLoading();
|
|
3661
|
+
});
|
|
3662
|
+
}
|
|
3663
|
+
isProcessingQueueRef.current = false;
|
|
3664
|
+
}, [onSendMessage, createNewChat, setOpen]);
|
|
3665
|
+
const sendMessage = useCallback4(async (message, options) => {
|
|
3666
|
+
if (!onSendMessage) {
|
|
3667
|
+
throw new Error("sendMessage is not available (onSendMessage callback not provided)");
|
|
3668
|
+
}
|
|
3669
|
+
if (!connected) {
|
|
3670
|
+
throw new Error("Not connected to UseAI server");
|
|
3671
|
+
}
|
|
3672
|
+
pendingMessagesRef.current.push({ message, options });
|
|
3673
|
+
await processMessageQueue();
|
|
3674
|
+
}, [onSendMessage, connected, processMessageQueue]);
|
|
3252
3675
|
return {
|
|
3253
3676
|
currentChatId,
|
|
3254
3677
|
pendingChatId,
|
|
@@ -3263,6 +3686,9 @@ function useChatManagement({
|
|
|
3263
3686
|
saveUserMessage,
|
|
3264
3687
|
saveAIResponse,
|
|
3265
3688
|
reloadMessages,
|
|
3689
|
+
sendMessage,
|
|
3690
|
+
getCurrentChat,
|
|
3691
|
+
updateMetadata,
|
|
3266
3692
|
currentChatIdSnapshot,
|
|
3267
3693
|
pendingChatIdSnapshot
|
|
3268
3694
|
};
|
|
@@ -3644,7 +4070,7 @@ function usePromptState({
|
|
|
3644
4070
|
}
|
|
3645
4071
|
|
|
3646
4072
|
// src/providers/useAIProvider.tsx
|
|
3647
|
-
import { Fragment as Fragment3, jsx as
|
|
4073
|
+
import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3648
4074
|
var __UseAIContext = createContext4(null);
|
|
3649
4075
|
var hasWarnedAboutMissingProvider = false;
|
|
3650
4076
|
var noOpContextValue = {
|
|
@@ -3674,6 +4100,11 @@ var noOpContextValue = {
|
|
|
3674
4100
|
},
|
|
3675
4101
|
list: async () => [],
|
|
3676
4102
|
clear: async () => {
|
|
4103
|
+
},
|
|
4104
|
+
sendMessage: async () => {
|
|
4105
|
+
},
|
|
4106
|
+
get: async () => null,
|
|
4107
|
+
updateMetadata: async () => {
|
|
3677
4108
|
}
|
|
3678
4109
|
},
|
|
3679
4110
|
agents: {
|
|
@@ -3713,7 +4144,8 @@ function UseAIProvider({
|
|
|
3713
4144
|
renderChat = true,
|
|
3714
4145
|
theme: customTheme,
|
|
3715
4146
|
strings: customStrings,
|
|
3716
|
-
visibleAgentIds
|
|
4147
|
+
visibleAgentIds,
|
|
4148
|
+
onOpenChange
|
|
3717
4149
|
}) {
|
|
3718
4150
|
const fileUploadConfig = fileUploadConfigProp === false ? void 0 : fileUploadConfigProp ?? DEFAULT_FILE_UPLOAD_CONFIG;
|
|
3719
4151
|
const theme = { ...defaultTheme, ...customTheme };
|
|
@@ -3721,12 +4153,17 @@ function UseAIProvider({
|
|
|
3721
4153
|
const [connected, setConnected] = useState10(false);
|
|
3722
4154
|
const [isChatOpen, setIsChatOpen] = useState10(false);
|
|
3723
4155
|
const [loading, setLoading] = useState10(false);
|
|
4156
|
+
const handleSetChatOpen = useCallback9((open) => {
|
|
4157
|
+
setIsChatOpen(open);
|
|
4158
|
+
onOpenChange?.(open);
|
|
4159
|
+
}, [onOpenChange]);
|
|
3724
4160
|
const [streamingText, setStreamingText] = useState10("");
|
|
3725
4161
|
const streamingChatIdRef = useRef9(null);
|
|
3726
4162
|
const clientRef = useRef9(null);
|
|
3727
4163
|
const repositoryRef = useRef9(
|
|
3728
4164
|
chatRepository || new LocalStorageChatRepository()
|
|
3729
4165
|
);
|
|
4166
|
+
const handleSendMessageRef = useRef9(null);
|
|
3730
4167
|
const {
|
|
3731
4168
|
registerTools,
|
|
3732
4169
|
unregisterTools,
|
|
@@ -3748,9 +4185,18 @@ function UseAIProvider({
|
|
|
3748
4185
|
clientRef,
|
|
3749
4186
|
connected
|
|
3750
4187
|
});
|
|
4188
|
+
const stableSendMessage = useCallback9(async (message, attachments) => {
|
|
4189
|
+
if (handleSendMessageRef.current) {
|
|
4190
|
+
await handleSendMessageRef.current(message, attachments);
|
|
4191
|
+
}
|
|
4192
|
+
}, []);
|
|
3751
4193
|
const chatManagement = useChatManagement({
|
|
3752
4194
|
repository: repositoryRef.current,
|
|
3753
|
-
clientRef
|
|
4195
|
+
clientRef,
|
|
4196
|
+
onSendMessage: stableSendMessage,
|
|
4197
|
+
setOpen: handleSetChatOpen,
|
|
4198
|
+
connected,
|
|
4199
|
+
loading
|
|
3754
4200
|
});
|
|
3755
4201
|
const {
|
|
3756
4202
|
currentChatId,
|
|
@@ -3764,7 +4210,10 @@ function UseAIProvider({
|
|
|
3764
4210
|
clearCurrentChat,
|
|
3765
4211
|
activatePendingChat,
|
|
3766
4212
|
saveUserMessage,
|
|
3767
|
-
saveAIResponse
|
|
4213
|
+
saveAIResponse,
|
|
4214
|
+
sendMessage,
|
|
4215
|
+
getCurrentChat,
|
|
4216
|
+
updateMetadata
|
|
3768
4217
|
} = chatManagement;
|
|
3769
4218
|
const {
|
|
3770
4219
|
availableAgents,
|
|
@@ -3905,7 +4354,6 @@ function UseAIProvider({
|
|
|
3905
4354
|
let persistedContent = message;
|
|
3906
4355
|
let multimodalContent;
|
|
3907
4356
|
if (attachments && attachments.length > 0) {
|
|
3908
|
-
const backend = fileUploadConfig?.backend ?? new EmbedFileUploadBackend();
|
|
3909
4357
|
const persistedParts = [];
|
|
3910
4358
|
if (message.trim()) {
|
|
3911
4359
|
persistedParts.push({ type: "text", text: message });
|
|
@@ -3921,35 +4369,24 @@ function UseAIProvider({
|
|
|
3921
4369
|
});
|
|
3922
4370
|
}
|
|
3923
4371
|
persistedContent = persistedParts;
|
|
3924
|
-
const
|
|
4372
|
+
const fileContent = await processAttachments(attachments, {
|
|
4373
|
+
getCurrentChat,
|
|
4374
|
+
backend: fileUploadConfig?.backend,
|
|
4375
|
+
transformers: fileUploadConfig?.transformers
|
|
4376
|
+
});
|
|
4377
|
+
multimodalContent = [];
|
|
3925
4378
|
if (message.trim()) {
|
|
3926
|
-
|
|
3927
|
-
}
|
|
3928
|
-
for (const attachment of attachments) {
|
|
3929
|
-
try {
|
|
3930
|
-
const url = await backend.prepareForSend(attachment.file);
|
|
3931
|
-
if (attachment.file.type.startsWith("image/")) {
|
|
3932
|
-
contentParts.push({ type: "image", url });
|
|
3933
|
-
} else {
|
|
3934
|
-
contentParts.push({
|
|
3935
|
-
type: "file",
|
|
3936
|
-
url,
|
|
3937
|
-
mimeType: attachment.file.type,
|
|
3938
|
-
name: attachment.file.name
|
|
3939
|
-
});
|
|
3940
|
-
}
|
|
3941
|
-
} catch (error) {
|
|
3942
|
-
console.error("[Provider] Failed to prepare file for send:", error);
|
|
3943
|
-
}
|
|
4379
|
+
multimodalContent.push({ type: "text", text: message });
|
|
3944
4380
|
}
|
|
3945
|
-
multimodalContent
|
|
4381
|
+
multimodalContent.push(...fileContent);
|
|
3946
4382
|
}
|
|
3947
4383
|
if (activeChatId) {
|
|
3948
4384
|
await saveUserMessage(activeChatId, persistedContent);
|
|
3949
4385
|
}
|
|
3950
4386
|
setLoading(true);
|
|
3951
4387
|
await clientRef.current.sendPrompt(message, multimodalContent);
|
|
3952
|
-
}, [activatePendingChat, currentChatId, saveUserMessage, fileUploadConfig]);
|
|
4388
|
+
}, [activatePendingChat, currentChatId, saveUserMessage, fileUploadConfig, getCurrentChat]);
|
|
4389
|
+
handleSendMessageRef.current = handleSendMessage;
|
|
3953
4390
|
const value = {
|
|
3954
4391
|
serverUrl,
|
|
3955
4392
|
connected,
|
|
@@ -3969,7 +4406,10 @@ function UseAIProvider({
|
|
|
3969
4406
|
load: loadChat,
|
|
3970
4407
|
delete: deleteChat,
|
|
3971
4408
|
list: listChats,
|
|
3972
|
-
clear: clearCurrentChat
|
|
4409
|
+
clear: clearCurrentChat,
|
|
4410
|
+
sendMessage,
|
|
4411
|
+
get: getCurrentChat,
|
|
4412
|
+
updateMetadata
|
|
3973
4413
|
},
|
|
3974
4414
|
agents: {
|
|
3975
4415
|
available: availableAgents,
|
|
@@ -3999,7 +4439,8 @@ function UseAIProvider({
|
|
|
3999
4439
|
create: createNewChat,
|
|
4000
4440
|
load: loadChat,
|
|
4001
4441
|
delete: deleteChat,
|
|
4002
|
-
list: listChats
|
|
4442
|
+
list: listChats,
|
|
4443
|
+
get: getCurrentChat
|
|
4003
4444
|
},
|
|
4004
4445
|
agents: {
|
|
4005
4446
|
available: availableAgents,
|
|
@@ -4015,7 +4456,7 @@ function UseAIProvider({
|
|
|
4015
4456
|
},
|
|
4016
4457
|
ui: {
|
|
4017
4458
|
isOpen: isChatOpen,
|
|
4018
|
-
setOpen:
|
|
4459
|
+
setOpen: handleSetChatOpen
|
|
4019
4460
|
}
|
|
4020
4461
|
};
|
|
4021
4462
|
const isUIDisabled = CustomButton === null || CustomChat === null;
|
|
@@ -4045,21 +4486,21 @@ function UseAIProvider({
|
|
|
4045
4486
|
};
|
|
4046
4487
|
const renderDefaultChat = () => {
|
|
4047
4488
|
if (isUIDisabled) return null;
|
|
4048
|
-
return /* @__PURE__ */
|
|
4489
|
+
return /* @__PURE__ */ jsx13(UseAIFloatingChatWrapper, { isOpen: isChatOpen, onClose: () => handleSetChatOpen(false), children: /* @__PURE__ */ jsx13(
|
|
4049
4490
|
UseAIChatPanel,
|
|
4050
4491
|
{
|
|
4051
4492
|
...chatPanelProps,
|
|
4052
|
-
closeButton: /* @__PURE__ */
|
|
4493
|
+
closeButton: /* @__PURE__ */ jsx13(CloseButton, { onClick: () => handleSetChatOpen(false) })
|
|
4053
4494
|
}
|
|
4054
4495
|
) });
|
|
4055
4496
|
};
|
|
4056
4497
|
const renderCustomChat = () => {
|
|
4057
4498
|
if (!CustomChat) return null;
|
|
4058
|
-
return /* @__PURE__ */
|
|
4499
|
+
return /* @__PURE__ */ jsx13(
|
|
4059
4500
|
CustomChat,
|
|
4060
4501
|
{
|
|
4061
4502
|
isOpen: isChatOpen,
|
|
4062
|
-
onClose: () =>
|
|
4503
|
+
onClose: () => handleSetChatOpen(false),
|
|
4063
4504
|
onSendMessage: handleSendMessage,
|
|
4064
4505
|
messages,
|
|
4065
4506
|
loading,
|
|
@@ -4074,18 +4515,18 @@ function UseAIProvider({
|
|
|
4074
4515
|
};
|
|
4075
4516
|
const renderBuiltInChat = () => {
|
|
4076
4517
|
if (!renderChat) return null;
|
|
4077
|
-
return /* @__PURE__ */
|
|
4078
|
-
ButtonComponent && /* @__PURE__ */
|
|
4518
|
+
return /* @__PURE__ */ jsxs9(Fragment3, { children: [
|
|
4519
|
+
ButtonComponent && /* @__PURE__ */ jsx13(
|
|
4079
4520
|
ButtonComponent,
|
|
4080
4521
|
{
|
|
4081
|
-
onClick: () =>
|
|
4522
|
+
onClick: () => handleSetChatOpen(true),
|
|
4082
4523
|
connected
|
|
4083
4524
|
}
|
|
4084
4525
|
),
|
|
4085
4526
|
hasCustomChat ? renderCustomChat() : renderDefaultChat()
|
|
4086
4527
|
] });
|
|
4087
4528
|
};
|
|
4088
|
-
return /* @__PURE__ */
|
|
4529
|
+
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
4530
|
children,
|
|
4090
4531
|
renderBuiltInChat()
|
|
4091
4532
|
] }) }) }) });
|
|
@@ -4488,14 +4929,18 @@ export {
|
|
|
4488
4929
|
UseAIFloatingButton,
|
|
4489
4930
|
UseAIFloatingChatWrapper,
|
|
4490
4931
|
UseAIProvider,
|
|
4932
|
+
clearTransformationCache,
|
|
4491
4933
|
convertToolsToDefinitions,
|
|
4492
4934
|
defaultStrings,
|
|
4493
4935
|
defaultTheme,
|
|
4494
4936
|
defineTool,
|
|
4495
4937
|
executeDefinedTool,
|
|
4938
|
+
findTransformer,
|
|
4496
4939
|
generateChatId,
|
|
4497
4940
|
generateCommandId,
|
|
4498
4941
|
generateMessageId,
|
|
4942
|
+
matchesMimeType,
|
|
4943
|
+
processAttachments,
|
|
4499
4944
|
useAI,
|
|
4500
4945
|
useAIContext,
|
|
4501
4946
|
useAIWorkflow,
|