@meetsmore-oss/use-ai-client 1.2.3 → 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 +736 -277
- 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 -76
- package/dist/index.js +736 -277
- 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";
|
|
@@ -50,8 +50,6 @@ var defaultStrings = {
|
|
|
50
50
|
placeholder: "Type a message...",
|
|
51
51
|
/** Input placeholder when connecting */
|
|
52
52
|
connectingPlaceholder: "Connecting...",
|
|
53
|
-
/** Send button text */
|
|
54
|
-
send: "Send",
|
|
55
53
|
/** Loading indicator text */
|
|
56
54
|
thinking: "Thinking"
|
|
57
55
|
},
|
|
@@ -380,8 +378,131 @@ function MarkdownContent({ content }) {
|
|
|
380
378
|
);
|
|
381
379
|
}
|
|
382
380
|
|
|
383
|
-
// src/components/
|
|
381
|
+
// src/components/Spinner.tsx
|
|
384
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";
|
|
385
506
|
function formatFileSize(bytes) {
|
|
386
507
|
if (bytes < 1024) return `${bytes} B`;
|
|
387
508
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
@@ -396,11 +517,14 @@ function truncateFilename(name, maxLength = 20) {
|
|
|
396
517
|
if (maxBaseLength < 5) return name.substring(0, maxLength - 3) + "...";
|
|
397
518
|
return baseName.substring(0, maxBaseLength) + "..." + ext;
|
|
398
519
|
}
|
|
399
|
-
function FileChip({ attachment, onRemove, disabled }) {
|
|
520
|
+
function FileChip({ attachment, onRemove, disabled, processingState }) {
|
|
400
521
|
const theme = useTheme();
|
|
401
522
|
const { file, preview } = attachment;
|
|
402
523
|
const isImage = file.type.startsWith("image/");
|
|
403
|
-
|
|
524
|
+
const isProcessing = processingState?.status === "processing";
|
|
525
|
+
const hasError = processingState?.status === "error";
|
|
526
|
+
const progress = processingState?.progress;
|
|
527
|
+
return /* @__PURE__ */ jsxs4(
|
|
404
528
|
"div",
|
|
405
529
|
{
|
|
406
530
|
"data-testid": "file-chip",
|
|
@@ -413,10 +537,12 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
413
537
|
borderRadius: "8px",
|
|
414
538
|
fontSize: "13px",
|
|
415
539
|
color: theme.textColor,
|
|
416
|
-
maxWidth: "200px"
|
|
540
|
+
maxWidth: "200px",
|
|
541
|
+
position: "relative",
|
|
542
|
+
opacity: isProcessing ? 0.7 : 1
|
|
417
543
|
},
|
|
418
544
|
children: [
|
|
419
|
-
isImage && preview ? /* @__PURE__ */
|
|
545
|
+
isImage && preview ? /* @__PURE__ */ jsx5(
|
|
420
546
|
"img",
|
|
421
547
|
{
|
|
422
548
|
src: preview,
|
|
@@ -428,7 +554,7 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
428
554
|
objectFit: "cover"
|
|
429
555
|
}
|
|
430
556
|
}
|
|
431
|
-
) : /* @__PURE__ */
|
|
557
|
+
) : /* @__PURE__ */ jsx5(
|
|
432
558
|
"div",
|
|
433
559
|
{
|
|
434
560
|
style: {
|
|
@@ -444,8 +570,8 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
444
570
|
children: "\u{1F4CE}"
|
|
445
571
|
}
|
|
446
572
|
),
|
|
447
|
-
/* @__PURE__ */
|
|
448
|
-
/* @__PURE__ */
|
|
573
|
+
/* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: [
|
|
574
|
+
/* @__PURE__ */ jsx5(
|
|
449
575
|
"div",
|
|
450
576
|
{
|
|
451
577
|
style: {
|
|
@@ -458,28 +584,28 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
458
584
|
children: truncateFilename(file.name)
|
|
459
585
|
}
|
|
460
586
|
),
|
|
461
|
-
/* @__PURE__ */
|
|
587
|
+
/* @__PURE__ */ jsx5("div", { style: { fontSize: "11px", color: theme.secondaryTextColor }, children: formatFileSize(file.size) })
|
|
462
588
|
] }),
|
|
463
|
-
/* @__PURE__ */
|
|
589
|
+
/* @__PURE__ */ jsx5(
|
|
464
590
|
"button",
|
|
465
591
|
{
|
|
466
592
|
"data-testid": "file-chip-remove",
|
|
467
593
|
onClick: onRemove,
|
|
468
|
-
disabled,
|
|
594
|
+
disabled: disabled || isProcessing,
|
|
469
595
|
style: {
|
|
470
596
|
background: "transparent",
|
|
471
597
|
border: "none",
|
|
472
598
|
padding: "2px 4px",
|
|
473
|
-
cursor: disabled ? "not-allowed" : "pointer",
|
|
599
|
+
cursor: disabled || isProcessing ? "not-allowed" : "pointer",
|
|
474
600
|
color: theme.placeholderTextColor,
|
|
475
601
|
fontSize: "16px",
|
|
476
602
|
lineHeight: 1,
|
|
477
603
|
borderRadius: "4px",
|
|
478
604
|
transition: "all 0.15s",
|
|
479
|
-
opacity: disabled ? 0.5 : 1
|
|
605
|
+
opacity: disabled || isProcessing ? 0.5 : 1
|
|
480
606
|
},
|
|
481
607
|
onMouseEnter: (e) => {
|
|
482
|
-
if (!disabled) {
|
|
608
|
+
if (!disabled && !isProcessing) {
|
|
483
609
|
e.currentTarget.style.background = theme.borderColor;
|
|
484
610
|
e.currentTarget.style.color = theme.textColor;
|
|
485
611
|
}
|
|
@@ -490,6 +616,44 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
490
616
|
},
|
|
491
617
|
children: "\xD7"
|
|
492
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
|
+
}
|
|
493
657
|
)
|
|
494
658
|
]
|
|
495
659
|
}
|
|
@@ -497,7 +661,7 @@ function FileChip({ attachment, onRemove, disabled }) {
|
|
|
497
661
|
}
|
|
498
662
|
function FilePlaceholder({ name, size }) {
|
|
499
663
|
const theme = useTheme();
|
|
500
|
-
return /* @__PURE__ */
|
|
664
|
+
return /* @__PURE__ */ jsxs4(
|
|
501
665
|
"div",
|
|
502
666
|
{
|
|
503
667
|
"data-testid": "file-placeholder",
|
|
@@ -514,9 +678,9 @@ function FilePlaceholder({ name, size }) {
|
|
|
514
678
|
maxWidth: "200px"
|
|
515
679
|
},
|
|
516
680
|
children: [
|
|
517
|
-
/* @__PURE__ */
|
|
518
|
-
/* @__PURE__ */
|
|
519
|
-
/* @__PURE__ */
|
|
681
|
+
/* @__PURE__ */ jsx5("span", { children: "\u{1F4CE}" }),
|
|
682
|
+
/* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: [
|
|
683
|
+
/* @__PURE__ */ jsx5(
|
|
520
684
|
"div",
|
|
521
685
|
{
|
|
522
686
|
style: {
|
|
@@ -528,7 +692,7 @@ function FilePlaceholder({ name, size }) {
|
|
|
528
692
|
children: truncateFilename(name)
|
|
529
693
|
}
|
|
530
694
|
),
|
|
531
|
-
/* @__PURE__ */
|
|
695
|
+
/* @__PURE__ */ jsx5("div", { style: { fontSize: "11px" }, children: formatFileSize(size) })
|
|
532
696
|
] })
|
|
533
697
|
]
|
|
534
698
|
}
|
|
@@ -557,7 +721,7 @@ function validateCommandName(name) {
|
|
|
557
721
|
|
|
558
722
|
// src/components/CommandAutocomplete.tsx
|
|
559
723
|
import { useEffect, useRef } from "react";
|
|
560
|
-
import { jsx as
|
|
724
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
561
725
|
var MAX_VISIBLE_ITEMS = 8;
|
|
562
726
|
function CommandAutocomplete({
|
|
563
727
|
commands,
|
|
@@ -588,7 +752,7 @@ function CommandAutocomplete({
|
|
|
588
752
|
}
|
|
589
753
|
}, [highlightedIndex]);
|
|
590
754
|
if (filteredCommands.length === 0) {
|
|
591
|
-
return /* @__PURE__ */
|
|
755
|
+
return /* @__PURE__ */ jsx6(
|
|
592
756
|
"div",
|
|
593
757
|
{
|
|
594
758
|
"data-testid": "command-autocomplete",
|
|
@@ -604,7 +768,7 @@ function CommandAutocomplete({
|
|
|
604
768
|
overflow: "hidden",
|
|
605
769
|
zIndex: 1005
|
|
606
770
|
},
|
|
607
|
-
children: /* @__PURE__ */
|
|
771
|
+
children: /* @__PURE__ */ jsx6(
|
|
608
772
|
"div",
|
|
609
773
|
{
|
|
610
774
|
style: {
|
|
@@ -619,7 +783,7 @@ function CommandAutocomplete({
|
|
|
619
783
|
}
|
|
620
784
|
);
|
|
621
785
|
}
|
|
622
|
-
return /* @__PURE__ */
|
|
786
|
+
return /* @__PURE__ */ jsx6(
|
|
623
787
|
"div",
|
|
624
788
|
{
|
|
625
789
|
"data-testid": "command-autocomplete",
|
|
@@ -638,7 +802,7 @@ function CommandAutocomplete({
|
|
|
638
802
|
overflowY: "auto",
|
|
639
803
|
zIndex: 1005
|
|
640
804
|
},
|
|
641
|
-
children: filteredCommands.map((cmd, index) => /* @__PURE__ */
|
|
805
|
+
children: filteredCommands.map((cmd, index) => /* @__PURE__ */ jsxs5(
|
|
642
806
|
"div",
|
|
643
807
|
{
|
|
644
808
|
ref: (el) => {
|
|
@@ -658,8 +822,8 @@ function CommandAutocomplete({
|
|
|
658
822
|
gap: "8px"
|
|
659
823
|
},
|
|
660
824
|
children: [
|
|
661
|
-
/* @__PURE__ */
|
|
662
|
-
/* @__PURE__ */
|
|
825
|
+
/* @__PURE__ */ jsxs5("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
826
|
+
/* @__PURE__ */ jsxs5(
|
|
663
827
|
"div",
|
|
664
828
|
{
|
|
665
829
|
style: {
|
|
@@ -673,7 +837,7 @@ function CommandAutocomplete({
|
|
|
673
837
|
]
|
|
674
838
|
}
|
|
675
839
|
),
|
|
676
|
-
/* @__PURE__ */
|
|
840
|
+
/* @__PURE__ */ jsx6(
|
|
677
841
|
"div",
|
|
678
842
|
{
|
|
679
843
|
style: {
|
|
@@ -688,7 +852,7 @@ function CommandAutocomplete({
|
|
|
688
852
|
}
|
|
689
853
|
)
|
|
690
854
|
] }),
|
|
691
|
-
onDelete && /* @__PURE__ */
|
|
855
|
+
onDelete && /* @__PURE__ */ jsx6(
|
|
692
856
|
"button",
|
|
693
857
|
{
|
|
694
858
|
"data-testid": "command-delete-button",
|
|
@@ -719,7 +883,7 @@ function CommandAutocomplete({
|
|
|
719
883
|
e.currentTarget.style.background = "transparent";
|
|
720
884
|
},
|
|
721
885
|
title: strings.commands.deleteCommand,
|
|
722
|
-
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" }) })
|
|
723
887
|
}
|
|
724
888
|
)
|
|
725
889
|
]
|
|
@@ -737,7 +901,7 @@ function getFilteredCommandsCount(commands, searchPrefix) {
|
|
|
737
901
|
}
|
|
738
902
|
|
|
739
903
|
// src/hooks/useSlashCommands.tsx
|
|
740
|
-
import { jsx as
|
|
904
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
741
905
|
var MAX_VISIBLE_ITEMS2 = 8;
|
|
742
906
|
function useSlashCommands({
|
|
743
907
|
commands,
|
|
@@ -872,7 +1036,7 @@ function useSlashCommands({
|
|
|
872
1036
|
}
|
|
873
1037
|
}
|
|
874
1038
|
}, [savingMessageId, savingMessageText, commandNameInput, commands, onRenameCommand, onSaveCommand, cancelInlineSave, strings]);
|
|
875
|
-
const AutocompleteComponent = showAutocomplete && commands.length > 0 ? /* @__PURE__ */
|
|
1039
|
+
const AutocompleteComponent = showAutocomplete && commands.length > 0 ? /* @__PURE__ */ jsx7(
|
|
876
1040
|
CommandAutocomplete,
|
|
877
1041
|
{
|
|
878
1042
|
commands,
|
|
@@ -888,7 +1052,7 @@ function useSlashCommands({
|
|
|
888
1052
|
if (savingMessageId !== messageId) {
|
|
889
1053
|
return null;
|
|
890
1054
|
}
|
|
891
|
-
return /* @__PURE__ */
|
|
1055
|
+
return /* @__PURE__ */ jsxs6(
|
|
892
1056
|
"div",
|
|
893
1057
|
{
|
|
894
1058
|
"data-testid": "inline-save-command",
|
|
@@ -902,9 +1066,9 @@ function useSlashCommands({
|
|
|
902
1066
|
gap: "4px"
|
|
903
1067
|
},
|
|
904
1068
|
children: [
|
|
905
|
-
/* @__PURE__ */
|
|
906
|
-
/* @__PURE__ */
|
|
907
|
-
/* @__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(
|
|
908
1072
|
"input",
|
|
909
1073
|
{
|
|
910
1074
|
ref: commandNameInputRef,
|
|
@@ -936,7 +1100,7 @@ function useSlashCommands({
|
|
|
936
1100
|
}
|
|
937
1101
|
}
|
|
938
1102
|
),
|
|
939
|
-
/* @__PURE__ */
|
|
1103
|
+
/* @__PURE__ */ jsx7(
|
|
940
1104
|
"button",
|
|
941
1105
|
{
|
|
942
1106
|
"data-testid": "save-command-confirm",
|
|
@@ -954,15 +1118,15 @@ function useSlashCommands({
|
|
|
954
1118
|
justifyContent: "center"
|
|
955
1119
|
},
|
|
956
1120
|
title: strings.commands.saveCommand,
|
|
957
|
-
children: /* @__PURE__ */
|
|
958
|
-
/* @__PURE__ */
|
|
959
|
-
/* @__PURE__ */
|
|
960
|
-
/* @__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" })
|
|
961
1125
|
] })
|
|
962
1126
|
}
|
|
963
1127
|
)
|
|
964
1128
|
] }),
|
|
965
|
-
commandSaveError && /* @__PURE__ */
|
|
1129
|
+
commandSaveError && /* @__PURE__ */ jsx7(
|
|
966
1130
|
"div",
|
|
967
1131
|
{
|
|
968
1132
|
"data-testid": "command-save-error",
|
|
@@ -997,9 +1161,151 @@ import { useState as useState2, useRef as useRef3, useCallback as useCallback2,
|
|
|
997
1161
|
// src/fileUpload/types.ts
|
|
998
1162
|
var DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
999
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
|
+
|
|
1000
1306
|
// src/hooks/useFileUpload.tsx
|
|
1001
1307
|
import { v4 as uuidv4 } from "uuid";
|
|
1002
|
-
import { jsx as
|
|
1308
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1003
1309
|
async function generateImagePreview(file) {
|
|
1004
1310
|
if (!file.type.startsWith("image/")) {
|
|
1005
1311
|
return void 0;
|
|
@@ -1032,18 +1338,21 @@ function isTypeAccepted(mimeType, acceptedTypes) {
|
|
|
1032
1338
|
function useFileUpload({
|
|
1033
1339
|
config,
|
|
1034
1340
|
disabled = false,
|
|
1035
|
-
resetDependency
|
|
1341
|
+
resetDependency,
|
|
1342
|
+
getCurrentChat
|
|
1036
1343
|
}) {
|
|
1037
1344
|
const strings = useStrings();
|
|
1038
1345
|
const theme = useTheme();
|
|
1039
1346
|
const [attachments, setAttachments] = useState2([]);
|
|
1040
1347
|
const [isDragging, setIsDragging] = useState2(false);
|
|
1041
1348
|
const [fileError, setFileError] = useState2(null);
|
|
1349
|
+
const [processingState, setProcessingState] = useState2(/* @__PURE__ */ new Map());
|
|
1042
1350
|
const fileInputRef = useRef3(null);
|
|
1043
1351
|
const dragCounterRef = useRef3(0);
|
|
1044
1352
|
const enabled = config !== void 0;
|
|
1045
1353
|
const maxFileSize = config?.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
|
|
1046
1354
|
const acceptedTypes = config?.acceptedTypes;
|
|
1355
|
+
const transformers = config?.transformers;
|
|
1047
1356
|
useEffect3(() => {
|
|
1048
1357
|
if (fileError) {
|
|
1049
1358
|
const timer = setTimeout(() => setFileError(null), 3e3);
|
|
@@ -1053,7 +1362,28 @@ function useFileUpload({
|
|
|
1053
1362
|
useEffect3(() => {
|
|
1054
1363
|
setAttachments([]);
|
|
1055
1364
|
setFileError(null);
|
|
1365
|
+
setProcessingState(/* @__PURE__ */ new Map());
|
|
1056
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]);
|
|
1057
1387
|
const handleFiles = useCallback2(async (files) => {
|
|
1058
1388
|
const fileArray = Array.from(files);
|
|
1059
1389
|
for (const file of fileArray) {
|
|
@@ -1068,21 +1398,30 @@ function useFileUpload({
|
|
|
1068
1398
|
continue;
|
|
1069
1399
|
}
|
|
1070
1400
|
const preview = await generateImagePreview(file);
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
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
|
+
}
|
|
1079
1412
|
}
|
|
1080
|
-
}, [maxFileSize, acceptedTypes, strings]);
|
|
1413
|
+
}, [maxFileSize, acceptedTypes, strings, transformers, runTransformer]);
|
|
1081
1414
|
const removeAttachment = useCallback2((id) => {
|
|
1082
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
|
+
});
|
|
1083
1421
|
}, []);
|
|
1084
1422
|
const clearAttachments = useCallback2(() => {
|
|
1085
1423
|
setAttachments([]);
|
|
1424
|
+
setProcessingState(/* @__PURE__ */ new Map());
|
|
1086
1425
|
}, []);
|
|
1087
1426
|
const openFilePicker = useCallback2(() => {
|
|
1088
1427
|
fileInputRef.current?.click();
|
|
@@ -1135,7 +1474,7 @@ function useFileUpload({
|
|
|
1135
1474
|
}), [handleDragEnter, handleDragOver, handleDragLeave, handleDrop]);
|
|
1136
1475
|
const DropZoneOverlay = useMemo(() => {
|
|
1137
1476
|
if (!isDragging || !enabled) return null;
|
|
1138
|
-
return /* @__PURE__ */
|
|
1477
|
+
return /* @__PURE__ */ jsx8(
|
|
1139
1478
|
"div",
|
|
1140
1479
|
{
|
|
1141
1480
|
style: {
|
|
@@ -1150,7 +1489,7 @@ function useFileUpload({
|
|
|
1150
1489
|
zIndex: 1010,
|
|
1151
1490
|
pointerEvents: "none"
|
|
1152
1491
|
},
|
|
1153
|
-
children: /* @__PURE__ */
|
|
1492
|
+
children: /* @__PURE__ */ jsx8(
|
|
1154
1493
|
"div",
|
|
1155
1494
|
{
|
|
1156
1495
|
style: {
|
|
@@ -1159,7 +1498,7 @@ function useFileUpload({
|
|
|
1159
1498
|
borderRadius: "12px",
|
|
1160
1499
|
boxShadow: theme.buttonShadow
|
|
1161
1500
|
},
|
|
1162
|
-
children: /* @__PURE__ */
|
|
1501
|
+
children: /* @__PURE__ */ jsx8("span", { style: { color: theme.primaryColor, fontWeight: 600, fontSize: "16px" }, children: strings.fileUpload.dropFilesHere })
|
|
1163
1502
|
}
|
|
1164
1503
|
)
|
|
1165
1504
|
}
|
|
@@ -1172,6 +1511,7 @@ function useFileUpload({
|
|
|
1172
1511
|
enabled,
|
|
1173
1512
|
maxFileSize,
|
|
1174
1513
|
acceptedTypes,
|
|
1514
|
+
processingState,
|
|
1175
1515
|
fileInputRef,
|
|
1176
1516
|
handleFiles,
|
|
1177
1517
|
removeAttachment,
|
|
@@ -1189,7 +1529,7 @@ function useFileUpload({
|
|
|
1189
1529
|
|
|
1190
1530
|
// src/hooks/useDropdownState.tsx
|
|
1191
1531
|
import { useState as useState3, useCallback as useCallback3, useMemo as useMemo2 } from "react";
|
|
1192
|
-
import { jsx as
|
|
1532
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1193
1533
|
function useDropdownState(options = {}) {
|
|
1194
1534
|
const { backdropZIndex = 1002, initialOpen = false } = options;
|
|
1195
1535
|
const [isOpen, setIsOpen] = useState3(initialOpen);
|
|
@@ -1204,7 +1544,7 @@ function useDropdownState(options = {}) {
|
|
|
1204
1544
|
}, []);
|
|
1205
1545
|
const Backdrop = useMemo2(() => {
|
|
1206
1546
|
if (!isOpen) return null;
|
|
1207
|
-
return /* @__PURE__ */
|
|
1547
|
+
return /* @__PURE__ */ jsx9(
|
|
1208
1548
|
"div",
|
|
1209
1549
|
{
|
|
1210
1550
|
onClick: close,
|
|
@@ -1229,7 +1569,7 @@ function useDropdownState(options = {}) {
|
|
|
1229
1569
|
}
|
|
1230
1570
|
|
|
1231
1571
|
// src/components/UseAIChatPanel.tsx
|
|
1232
|
-
import { Fragment, jsx as
|
|
1572
|
+
import { Fragment, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1233
1573
|
function getTextContent(content) {
|
|
1234
1574
|
if (typeof content === "string") {
|
|
1235
1575
|
return content;
|
|
@@ -1250,6 +1590,7 @@ function UseAIChatPanel({
|
|
|
1250
1590
|
onLoadChat,
|
|
1251
1591
|
onDeleteChat,
|
|
1252
1592
|
onListChats,
|
|
1593
|
+
onGetChat,
|
|
1253
1594
|
suggestions,
|
|
1254
1595
|
availableAgents,
|
|
1255
1596
|
defaultAgent,
|
|
@@ -1270,12 +1611,14 @@ function UseAIChatPanel({
|
|
|
1270
1611
|
const [chatHistory, setChatHistory] = useState4([]);
|
|
1271
1612
|
const messagesEndRef = useRef4(null);
|
|
1272
1613
|
const [displayedSuggestions, setDisplayedSuggestions] = useState4([]);
|
|
1614
|
+
const textareaRef = useRef4(null);
|
|
1273
1615
|
const [hoveredMessageId, setHoveredMessageId] = useState4(null);
|
|
1274
1616
|
const {
|
|
1275
1617
|
attachments,
|
|
1276
1618
|
fileError,
|
|
1277
1619
|
enabled: fileUploadEnabled,
|
|
1278
1620
|
acceptedTypes,
|
|
1621
|
+
processingState: fileProcessingState,
|
|
1279
1622
|
fileInputRef,
|
|
1280
1623
|
removeAttachment,
|
|
1281
1624
|
clearAttachments,
|
|
@@ -1284,6 +1627,7 @@ function UseAIChatPanel({
|
|
|
1284
1627
|
getDropZoneProps,
|
|
1285
1628
|
DropZoneOverlay
|
|
1286
1629
|
} = useFileUpload({
|
|
1630
|
+
getCurrentChat: onGetChat ?? (async () => null),
|
|
1287
1631
|
config: fileUploadConfig,
|
|
1288
1632
|
disabled: loading,
|
|
1289
1633
|
resetDependency: currentChatId
|
|
@@ -1298,6 +1642,14 @@ function UseAIChatPanel({
|
|
|
1298
1642
|
useEffect4(() => {
|
|
1299
1643
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
1300
1644
|
}, [messages]);
|
|
1645
|
+
const maxTextareaHeight = 160;
|
|
1646
|
+
useEffect4(() => {
|
|
1647
|
+
const textarea = textareaRef.current;
|
|
1648
|
+
if (!textarea) return;
|
|
1649
|
+
textarea.style.height = "auto";
|
|
1650
|
+
const newHeight = Math.min(textarea.scrollHeight, maxTextareaHeight);
|
|
1651
|
+
textarea.style.height = `${newHeight}px`;
|
|
1652
|
+
}, [input]);
|
|
1301
1653
|
useEffect4(() => {
|
|
1302
1654
|
if (!suggestions || suggestions.length === 0) {
|
|
1303
1655
|
setDisplayedSuggestions([]);
|
|
@@ -1347,7 +1699,7 @@ function UseAIChatPanel({
|
|
|
1347
1699
|
chatHistoryDropdown.close();
|
|
1348
1700
|
}
|
|
1349
1701
|
};
|
|
1350
|
-
return /* @__PURE__ */
|
|
1702
|
+
return /* @__PURE__ */ jsxs7(
|
|
1351
1703
|
"div",
|
|
1352
1704
|
{
|
|
1353
1705
|
onClick: () => {
|
|
@@ -1365,7 +1717,7 @@ function UseAIChatPanel({
|
|
|
1365
1717
|
},
|
|
1366
1718
|
children: [
|
|
1367
1719
|
DropZoneOverlay,
|
|
1368
|
-
/* @__PURE__ */
|
|
1720
|
+
/* @__PURE__ */ jsxs7(
|
|
1369
1721
|
"div",
|
|
1370
1722
|
{
|
|
1371
1723
|
style: {
|
|
@@ -1378,7 +1730,7 @@ function UseAIChatPanel({
|
|
|
1378
1730
|
gap: "12px"
|
|
1379
1731
|
},
|
|
1380
1732
|
children: [
|
|
1381
|
-
/* @__PURE__ */
|
|
1733
|
+
/* @__PURE__ */ jsx10("div", { style: { flex: 1, minWidth: 0, position: "relative" }, children: onListChats ? /* @__PURE__ */ jsxs7(
|
|
1382
1734
|
"button",
|
|
1383
1735
|
{
|
|
1384
1736
|
"data-testid": "chat-history-dropdown-button",
|
|
@@ -1411,7 +1763,7 @@ function UseAIChatPanel({
|
|
|
1411
1763
|
e.currentTarget.style.background = "transparent";
|
|
1412
1764
|
},
|
|
1413
1765
|
children: [
|
|
1414
|
-
/* @__PURE__ */
|
|
1766
|
+
/* @__PURE__ */ jsx10("span", { style: {
|
|
1415
1767
|
overflow: "hidden",
|
|
1416
1768
|
textOverflow: "ellipsis",
|
|
1417
1769
|
whiteSpace: "nowrap",
|
|
@@ -1428,13 +1780,13 @@ function UseAIChatPanel({
|
|
|
1428
1780
|
}
|
|
1429
1781
|
return strings.header.newChat;
|
|
1430
1782
|
})() }),
|
|
1431
|
-
/* @__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" }) })
|
|
1432
1784
|
]
|
|
1433
1785
|
}
|
|
1434
|
-
) : /* @__PURE__ */
|
|
1435
|
-
/* @__PURE__ */
|
|
1436
|
-
availableAgents && availableAgents.length > 1 && onAgentChange && /* @__PURE__ */
|
|
1437
|
-
/* @__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(
|
|
1438
1790
|
"button",
|
|
1439
1791
|
{
|
|
1440
1792
|
"data-testid": "agent-selector",
|
|
@@ -1463,7 +1815,7 @@ function UseAIChatPanel({
|
|
|
1463
1815
|
},
|
|
1464
1816
|
title: "Select AI model",
|
|
1465
1817
|
children: [
|
|
1466
|
-
/* @__PURE__ */
|
|
1818
|
+
/* @__PURE__ */ jsx10("span", { style: {
|
|
1467
1819
|
overflow: "hidden",
|
|
1468
1820
|
textOverflow: "ellipsis",
|
|
1469
1821
|
whiteSpace: "nowrap",
|
|
@@ -1472,11 +1824,11 @@ function UseAIChatPanel({
|
|
|
1472
1824
|
const agent = availableAgents.find((a) => a.id === (selectedAgent ?? defaultAgent));
|
|
1473
1825
|
return agent?.name || "AI";
|
|
1474
1826
|
})() }),
|
|
1475
|
-
/* @__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" }) })
|
|
1476
1828
|
]
|
|
1477
1829
|
}
|
|
1478
1830
|
),
|
|
1479
|
-
agentDropdown.isOpen && /* @__PURE__ */
|
|
1831
|
+
agentDropdown.isOpen && /* @__PURE__ */ jsx10(
|
|
1480
1832
|
"div",
|
|
1481
1833
|
{
|
|
1482
1834
|
style: {
|
|
@@ -1496,7 +1848,7 @@ function UseAIChatPanel({
|
|
|
1496
1848
|
},
|
|
1497
1849
|
children: availableAgents.map((agent) => {
|
|
1498
1850
|
const isSelected = agent.id === (selectedAgent ?? defaultAgent);
|
|
1499
|
-
return /* @__PURE__ */
|
|
1851
|
+
return /* @__PURE__ */ jsxs7(
|
|
1500
1852
|
"div",
|
|
1501
1853
|
{
|
|
1502
1854
|
"data-testid": "agent-option",
|
|
@@ -1526,13 +1878,13 @@ function UseAIChatPanel({
|
|
|
1526
1878
|
}
|
|
1527
1879
|
},
|
|
1528
1880
|
children: [
|
|
1529
|
-
/* @__PURE__ */
|
|
1530
|
-
/* @__PURE__ */
|
|
1881
|
+
/* @__PURE__ */ jsxs7("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
1882
|
+
/* @__PURE__ */ jsx10("div", { style: {
|
|
1531
1883
|
fontSize: "13px",
|
|
1532
1884
|
fontWeight: isSelected ? "600" : "500",
|
|
1533
1885
|
color: isSelected ? theme.primaryColor : theme.textColor
|
|
1534
1886
|
}, children: agent.name }),
|
|
1535
|
-
agent.annotation && /* @__PURE__ */
|
|
1887
|
+
agent.annotation && /* @__PURE__ */ jsx10("div", { style: {
|
|
1536
1888
|
fontSize: "11px",
|
|
1537
1889
|
color: theme.secondaryTextColor,
|
|
1538
1890
|
marginTop: "2px",
|
|
@@ -1541,7 +1893,7 @@ function UseAIChatPanel({
|
|
|
1541
1893
|
whiteSpace: "nowrap"
|
|
1542
1894
|
}, children: agent.annotation })
|
|
1543
1895
|
] }),
|
|
1544
|
-
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" }) })
|
|
1545
1897
|
]
|
|
1546
1898
|
},
|
|
1547
1899
|
agent.id
|
|
@@ -1550,7 +1902,7 @@ function UseAIChatPanel({
|
|
|
1550
1902
|
}
|
|
1551
1903
|
)
|
|
1552
1904
|
] }),
|
|
1553
|
-
onNewChat && /* @__PURE__ */
|
|
1905
|
+
onNewChat && /* @__PURE__ */ jsx10(
|
|
1554
1906
|
"button",
|
|
1555
1907
|
{
|
|
1556
1908
|
"data-testid": "new-chat-button",
|
|
@@ -1577,10 +1929,10 @@ function UseAIChatPanel({
|
|
|
1577
1929
|
e.currentTarget.style.color = theme.secondaryTextColor;
|
|
1578
1930
|
},
|
|
1579
1931
|
title: strings.header.newChat,
|
|
1580
|
-
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" }) })
|
|
1581
1933
|
}
|
|
1582
1934
|
),
|
|
1583
|
-
onDeleteChat && messages.length > 0 && /* @__PURE__ */
|
|
1935
|
+
onDeleteChat && messages.length > 0 && /* @__PURE__ */ jsx10(
|
|
1584
1936
|
"button",
|
|
1585
1937
|
{
|
|
1586
1938
|
"data-testid": "delete-chat-button",
|
|
@@ -1604,7 +1956,7 @@ function UseAIChatPanel({
|
|
|
1604
1956
|
e.currentTarget.style.color = theme.secondaryTextColor;
|
|
1605
1957
|
},
|
|
1606
1958
|
title: strings.header.deleteChat,
|
|
1607
|
-
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" }) })
|
|
1608
1960
|
}
|
|
1609
1961
|
),
|
|
1610
1962
|
closeButton
|
|
@@ -1612,7 +1964,7 @@ function UseAIChatPanel({
|
|
|
1612
1964
|
]
|
|
1613
1965
|
}
|
|
1614
1966
|
),
|
|
1615
|
-
chatHistoryDropdown.isOpen && onListChats && /* @__PURE__ */
|
|
1967
|
+
chatHistoryDropdown.isOpen && onListChats && /* @__PURE__ */ jsx10(
|
|
1616
1968
|
"div",
|
|
1617
1969
|
{
|
|
1618
1970
|
style: {
|
|
@@ -1629,7 +1981,7 @@ function UseAIChatPanel({
|
|
|
1629
1981
|
flexDirection: "column",
|
|
1630
1982
|
overflow: "hidden"
|
|
1631
1983
|
},
|
|
1632
|
-
children: /* @__PURE__ */
|
|
1984
|
+
children: /* @__PURE__ */ jsx10(
|
|
1633
1985
|
"div",
|
|
1634
1986
|
{
|
|
1635
1987
|
style: {
|
|
@@ -1637,7 +1989,7 @@ function UseAIChatPanel({
|
|
|
1637
1989
|
overflowY: "auto",
|
|
1638
1990
|
padding: "8px"
|
|
1639
1991
|
},
|
|
1640
|
-
children: chatHistory.length === 0 ? /* @__PURE__ */
|
|
1992
|
+
children: chatHistory.length === 0 ? /* @__PURE__ */ jsx10(
|
|
1641
1993
|
"div",
|
|
1642
1994
|
{
|
|
1643
1995
|
style: {
|
|
@@ -1646,9 +1998,9 @@ function UseAIChatPanel({
|
|
|
1646
1998
|
padding: "32px 16px",
|
|
1647
1999
|
fontSize: "13px"
|
|
1648
2000
|
},
|
|
1649
|
-
children: /* @__PURE__ */
|
|
2001
|
+
children: /* @__PURE__ */ jsx10("p", { style: { margin: 0 }, children: strings.chatHistory.noChatHistory })
|
|
1650
2002
|
}
|
|
1651
|
-
) : chatHistory.map((chat) => /* @__PURE__ */
|
|
2003
|
+
) : chatHistory.map((chat) => /* @__PURE__ */ jsxs7(
|
|
1652
2004
|
"div",
|
|
1653
2005
|
{
|
|
1654
2006
|
"data-testid": "chat-history-item",
|
|
@@ -1672,10 +2024,10 @@ function UseAIChatPanel({
|
|
|
1672
2024
|
}
|
|
1673
2025
|
},
|
|
1674
2026
|
children: [
|
|
1675
|
-
/* @__PURE__ */
|
|
1676
|
-
/* @__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: [
|
|
1677
2029
|
new Date(chat.updatedAt).toLocaleDateString([], { month: "short", day: "numeric" }),
|
|
1678
|
-
currentChatId === chat.id && /* @__PURE__ */
|
|
2030
|
+
currentChatId === chat.id && /* @__PURE__ */ jsxs7("span", { style: {
|
|
1679
2031
|
marginLeft: "8px",
|
|
1680
2032
|
color: theme.primaryColor,
|
|
1681
2033
|
fontWeight: "600"
|
|
@@ -1694,7 +2046,7 @@ function UseAIChatPanel({
|
|
|
1694
2046
|
),
|
|
1695
2047
|
chatHistoryDropdown.Backdrop,
|
|
1696
2048
|
agentDropdown.Backdrop,
|
|
1697
|
-
/* @__PURE__ */
|
|
2049
|
+
/* @__PURE__ */ jsxs7(
|
|
1698
2050
|
"div",
|
|
1699
2051
|
{
|
|
1700
2052
|
style: {
|
|
@@ -1706,7 +2058,7 @@ function UseAIChatPanel({
|
|
|
1706
2058
|
gap: "12px"
|
|
1707
2059
|
},
|
|
1708
2060
|
children: [
|
|
1709
|
-
messages.length === 0 && /* @__PURE__ */
|
|
2061
|
+
messages.length === 0 && /* @__PURE__ */ jsxs7(
|
|
1710
2062
|
"div",
|
|
1711
2063
|
{
|
|
1712
2064
|
style: {
|
|
@@ -1717,12 +2069,12 @@ function UseAIChatPanel({
|
|
|
1717
2069
|
gap: "20px"
|
|
1718
2070
|
},
|
|
1719
2071
|
children: [
|
|
1720
|
-
/* @__PURE__ */
|
|
1721
|
-
/* @__PURE__ */
|
|
1722
|
-
/* @__PURE__ */
|
|
1723
|
-
/* @__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 })
|
|
1724
2076
|
] }),
|
|
1725
|
-
displayedSuggestions.length > 0 && /* @__PURE__ */
|
|
2077
|
+
displayedSuggestions.length > 0 && /* @__PURE__ */ jsx10(
|
|
1726
2078
|
"div",
|
|
1727
2079
|
{
|
|
1728
2080
|
style: {
|
|
@@ -1732,7 +2084,7 @@ function UseAIChatPanel({
|
|
|
1732
2084
|
width: "100%",
|
|
1733
2085
|
maxWidth: "320px"
|
|
1734
2086
|
},
|
|
1735
|
-
children: displayedSuggestions.map((suggestion, index) => /* @__PURE__ */
|
|
2087
|
+
children: displayedSuggestions.map((suggestion, index) => /* @__PURE__ */ jsx10(
|
|
1736
2088
|
"button",
|
|
1737
2089
|
{
|
|
1738
2090
|
"data-testid": "chat-suggestion-button",
|
|
@@ -1776,7 +2128,7 @@ function UseAIChatPanel({
|
|
|
1776
2128
|
]
|
|
1777
2129
|
}
|
|
1778
2130
|
),
|
|
1779
|
-
messages.map((message) => /* @__PURE__ */
|
|
2131
|
+
messages.map((message) => /* @__PURE__ */ jsxs7(
|
|
1780
2132
|
"div",
|
|
1781
2133
|
{
|
|
1782
2134
|
"data-testid": `chat-message-${message.role}`,
|
|
@@ -1789,7 +2141,7 @@ function UseAIChatPanel({
|
|
|
1789
2141
|
onMouseEnter: () => message.role === "user" && setHoveredMessageId(message.id),
|
|
1790
2142
|
onMouseLeave: () => setHoveredMessageId(null),
|
|
1791
2143
|
children: [
|
|
1792
|
-
/* @__PURE__ */
|
|
2144
|
+
/* @__PURE__ */ jsxs7(
|
|
1793
2145
|
"div",
|
|
1794
2146
|
{
|
|
1795
2147
|
style: {
|
|
@@ -1797,7 +2149,7 @@ function UseAIChatPanel({
|
|
|
1797
2149
|
maxWidth: "80%"
|
|
1798
2150
|
},
|
|
1799
2151
|
children: [
|
|
1800
|
-
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(
|
|
1801
2153
|
"button",
|
|
1802
2154
|
{
|
|
1803
2155
|
"data-testid": "save-command-button",
|
|
@@ -1833,14 +2185,14 @@ function UseAIChatPanel({
|
|
|
1833
2185
|
e.currentTarget.style.transform = "scale(1)";
|
|
1834
2186
|
e.currentTarget.style.boxShadow = "0 2px 6px rgba(0, 0, 0, 0.15)";
|
|
1835
2187
|
},
|
|
1836
|
-
children: /* @__PURE__ */
|
|
1837
|
-
/* @__PURE__ */
|
|
1838
|
-
/* @__PURE__ */
|
|
1839
|
-
/* @__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" })
|
|
1840
2192
|
] })
|
|
1841
2193
|
}
|
|
1842
2194
|
),
|
|
1843
|
-
/* @__PURE__ */
|
|
2195
|
+
/* @__PURE__ */ jsxs7(
|
|
1844
2196
|
"div",
|
|
1845
2197
|
{
|
|
1846
2198
|
"data-testid": "chat-message-content",
|
|
@@ -1855,7 +2207,7 @@ function UseAIChatPanel({
|
|
|
1855
2207
|
wordWrap: "break-word"
|
|
1856
2208
|
},
|
|
1857
2209
|
children: [
|
|
1858
|
-
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(
|
|
1859
2211
|
FilePlaceholder,
|
|
1860
2212
|
{
|
|
1861
2213
|
name: part.file.name,
|
|
@@ -1863,7 +2215,7 @@ function UseAIChatPanel({
|
|
|
1863
2215
|
},
|
|
1864
2216
|
idx
|
|
1865
2217
|
)) }),
|
|
1866
|
-
message.role === "assistant" ? /* @__PURE__ */
|
|
2218
|
+
message.role === "assistant" ? /* @__PURE__ */ jsx10(MarkdownContent, { content: getTextContent(message.content) }) : getTextContent(message.content)
|
|
1867
2219
|
]
|
|
1868
2220
|
}
|
|
1869
2221
|
),
|
|
@@ -1874,7 +2226,7 @@ function UseAIChatPanel({
|
|
|
1874
2226
|
]
|
|
1875
2227
|
}
|
|
1876
2228
|
),
|
|
1877
|
-
/* @__PURE__ */
|
|
2229
|
+
/* @__PURE__ */ jsx10(
|
|
1878
2230
|
"div",
|
|
1879
2231
|
{
|
|
1880
2232
|
style: {
|
|
@@ -1893,14 +2245,14 @@ function UseAIChatPanel({
|
|
|
1893
2245
|
},
|
|
1894
2246
|
message.id
|
|
1895
2247
|
)),
|
|
1896
|
-
loading && /* @__PURE__ */
|
|
2248
|
+
loading && /* @__PURE__ */ jsx10(
|
|
1897
2249
|
"div",
|
|
1898
2250
|
{
|
|
1899
2251
|
style: {
|
|
1900
2252
|
display: "flex",
|
|
1901
2253
|
alignItems: "flex-start"
|
|
1902
2254
|
},
|
|
1903
|
-
children: /* @__PURE__ */
|
|
2255
|
+
children: /* @__PURE__ */ jsx10(
|
|
1904
2256
|
"div",
|
|
1905
2257
|
{
|
|
1906
2258
|
className: "markdown-content",
|
|
@@ -1913,19 +2265,19 @@ function UseAIChatPanel({
|
|
|
1913
2265
|
color: theme.textColor,
|
|
1914
2266
|
maxWidth: "80%"
|
|
1915
2267
|
},
|
|
1916
|
-
children: streamingText ? /* @__PURE__ */
|
|
1917
|
-
/* @__PURE__ */
|
|
1918
|
-
/* @__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: "..." })
|
|
1919
2271
|
] })
|
|
1920
2272
|
}
|
|
1921
2273
|
)
|
|
1922
2274
|
}
|
|
1923
2275
|
),
|
|
1924
|
-
/* @__PURE__ */
|
|
2276
|
+
/* @__PURE__ */ jsx10("div", { ref: messagesEndRef })
|
|
1925
2277
|
]
|
|
1926
2278
|
}
|
|
1927
2279
|
),
|
|
1928
|
-
/* @__PURE__ */
|
|
2280
|
+
/* @__PURE__ */ jsxs7(
|
|
1929
2281
|
"div",
|
|
1930
2282
|
{
|
|
1931
2283
|
style: {
|
|
@@ -1933,7 +2285,7 @@ function UseAIChatPanel({
|
|
|
1933
2285
|
borderTop: `1px solid ${theme.borderColor}`
|
|
1934
2286
|
},
|
|
1935
2287
|
children: [
|
|
1936
|
-
fileError && /* @__PURE__ */
|
|
2288
|
+
fileError && /* @__PURE__ */ jsx10(
|
|
1937
2289
|
"div",
|
|
1938
2290
|
{
|
|
1939
2291
|
"data-testid": "file-error",
|
|
@@ -1948,7 +2300,7 @@ function UseAIChatPanel({
|
|
|
1948
2300
|
children: fileError
|
|
1949
2301
|
}
|
|
1950
2302
|
),
|
|
1951
|
-
attachments.length > 0 && /* @__PURE__ */
|
|
2303
|
+
attachments.length > 0 && /* @__PURE__ */ jsx10(
|
|
1952
2304
|
"div",
|
|
1953
2305
|
{
|
|
1954
2306
|
"data-testid": "file-attachments",
|
|
@@ -1958,138 +2310,147 @@ function UseAIChatPanel({
|
|
|
1958
2310
|
gap: "8px",
|
|
1959
2311
|
marginBottom: "8px"
|
|
1960
2312
|
},
|
|
1961
|
-
children: attachments.map((attachment) => /* @__PURE__ */
|
|
2313
|
+
children: attachments.map((attachment) => /* @__PURE__ */ jsx10(
|
|
1962
2314
|
FileChip,
|
|
1963
2315
|
{
|
|
1964
2316
|
attachment,
|
|
1965
2317
|
onRemove: () => removeAttachment(attachment.id),
|
|
1966
|
-
disabled: loading
|
|
2318
|
+
disabled: loading,
|
|
2319
|
+
processingState: fileProcessingState.get(attachment.id)
|
|
1967
2320
|
},
|
|
1968
2321
|
attachment.id
|
|
1969
2322
|
))
|
|
1970
2323
|
}
|
|
1971
2324
|
),
|
|
1972
|
-
/* @__PURE__ */
|
|
2325
|
+
/* @__PURE__ */ jsxs7(
|
|
1973
2326
|
"div",
|
|
1974
2327
|
{
|
|
1975
2328
|
style: {
|
|
1976
|
-
|
|
1977
|
-
|
|
2329
|
+
border: `1px solid ${theme.borderColor}`,
|
|
2330
|
+
borderRadius: "12px",
|
|
2331
|
+
background: theme.backgroundColor,
|
|
2332
|
+
overflow: "hidden",
|
|
1978
2333
|
position: "relative"
|
|
1979
2334
|
},
|
|
1980
2335
|
children: [
|
|
1981
2336
|
slashCommands.AutocompleteComponent,
|
|
1982
|
-
/* @__PURE__ */
|
|
2337
|
+
/* @__PURE__ */ jsx10(
|
|
1983
2338
|
"input",
|
|
1984
2339
|
{
|
|
1985
2340
|
ref: fileInputRef,
|
|
1986
2341
|
type: "file",
|
|
1987
2342
|
multiple: true,
|
|
2343
|
+
"data-testid": "file-input",
|
|
1988
2344
|
style: { display: "none" },
|
|
1989
2345
|
onChange: handleFileInputChange,
|
|
1990
2346
|
accept: acceptedTypes?.join(",")
|
|
1991
2347
|
}
|
|
1992
2348
|
),
|
|
1993
|
-
/* @__PURE__ */
|
|
2349
|
+
/* @__PURE__ */ jsx10(
|
|
2350
|
+
"textarea",
|
|
2351
|
+
{
|
|
2352
|
+
ref: textareaRef,
|
|
2353
|
+
"data-testid": "chat-input",
|
|
2354
|
+
className: "chat-input",
|
|
2355
|
+
value: input,
|
|
2356
|
+
onChange: handleInputChange,
|
|
2357
|
+
onKeyDown: handleKeyDown,
|
|
2358
|
+
placeholder: connected ? strings.input.placeholder : strings.input.connectingPlaceholder,
|
|
2359
|
+
disabled: !connected || loading,
|
|
2360
|
+
rows: 1,
|
|
2361
|
+
style: {
|
|
2362
|
+
width: "100%",
|
|
2363
|
+
padding: "10px 14px 6px",
|
|
2364
|
+
border: "none",
|
|
2365
|
+
fontSize: "14px",
|
|
2366
|
+
lineHeight: "1.4",
|
|
2367
|
+
resize: "none",
|
|
2368
|
+
maxHeight: `${maxTextareaHeight}px`,
|
|
2369
|
+
fontFamily: "inherit",
|
|
2370
|
+
outline: "none",
|
|
2371
|
+
background: "transparent",
|
|
2372
|
+
overflowY: "auto",
|
|
2373
|
+
boxSizing: "border-box"
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
),
|
|
2377
|
+
/* @__PURE__ */ jsxs7(
|
|
1994
2378
|
"div",
|
|
1995
2379
|
{
|
|
1996
2380
|
style: {
|
|
1997
|
-
flex: 1,
|
|
1998
2381
|
display: "flex",
|
|
1999
2382
|
alignItems: "center",
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
background: theme.backgroundColor,
|
|
2003
|
-
overflow: "hidden"
|
|
2383
|
+
justifyContent: "space-between",
|
|
2384
|
+
padding: "4px 8px"
|
|
2004
2385
|
},
|
|
2005
2386
|
children: [
|
|
2006
|
-
/* @__PURE__ */
|
|
2007
|
-
"textarea",
|
|
2008
|
-
{
|
|
2009
|
-
"data-testid": "chat-input",
|
|
2010
|
-
className: "chat-input",
|
|
2011
|
-
value: input,
|
|
2012
|
-
onChange: handleInputChange,
|
|
2013
|
-
onKeyDown: handleKeyDown,
|
|
2014
|
-
placeholder: connected ? strings.input.placeholder : strings.input.connectingPlaceholder,
|
|
2015
|
-
disabled: !connected || loading,
|
|
2016
|
-
style: {
|
|
2017
|
-
flex: 1,
|
|
2018
|
-
padding: "10px 12px",
|
|
2019
|
-
border: "none",
|
|
2020
|
-
fontSize: "14px",
|
|
2021
|
-
resize: "none",
|
|
2022
|
-
minHeight: "44px",
|
|
2023
|
-
maxHeight: "120px",
|
|
2024
|
-
fontFamily: "inherit",
|
|
2025
|
-
outline: "none",
|
|
2026
|
-
background: "transparent"
|
|
2027
|
-
},
|
|
2028
|
-
rows: 1
|
|
2029
|
-
}
|
|
2030
|
-
),
|
|
2031
|
-
fileUploadEnabled && /* @__PURE__ */ jsx8(
|
|
2387
|
+
/* @__PURE__ */ jsx10("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: fileUploadEnabled && /* @__PURE__ */ jsx10(
|
|
2032
2388
|
"button",
|
|
2033
2389
|
{
|
|
2034
2390
|
"data-testid": "file-picker-button",
|
|
2035
2391
|
onClick: openFilePicker,
|
|
2036
2392
|
disabled: !connected || loading,
|
|
2037
2393
|
style: {
|
|
2038
|
-
padding: "
|
|
2039
|
-
marginRight: "6px",
|
|
2394
|
+
padding: "4px",
|
|
2040
2395
|
background: "transparent",
|
|
2041
|
-
border:
|
|
2042
|
-
borderRadius: "
|
|
2396
|
+
border: `1px solid ${theme.borderColor}`,
|
|
2397
|
+
borderRadius: "50%",
|
|
2043
2398
|
cursor: connected && !loading ? "pointer" : "not-allowed",
|
|
2044
2399
|
color: theme.secondaryTextColor,
|
|
2045
2400
|
display: "flex",
|
|
2046
2401
|
alignItems: "center",
|
|
2047
2402
|
justifyContent: "center",
|
|
2403
|
+
width: "28px",
|
|
2404
|
+
height: "28px",
|
|
2048
2405
|
transition: "all 0.15s",
|
|
2049
2406
|
opacity: connected && !loading ? 1 : 0.5
|
|
2050
2407
|
},
|
|
2051
2408
|
onMouseEnter: (e) => {
|
|
2052
2409
|
if (connected && !loading) {
|
|
2053
2410
|
e.currentTarget.style.color = theme.primaryColor;
|
|
2054
|
-
e.currentTarget.style.
|
|
2411
|
+
e.currentTarget.style.borderColor = theme.primaryColor;
|
|
2055
2412
|
}
|
|
2056
2413
|
},
|
|
2057
2414
|
onMouseLeave: (e) => {
|
|
2058
2415
|
e.currentTarget.style.color = theme.secondaryTextColor;
|
|
2059
|
-
e.currentTarget.style.
|
|
2416
|
+
e.currentTarget.style.borderColor = theme.borderColor;
|
|
2060
2417
|
},
|
|
2061
2418
|
title: strings.fileUpload.attachFiles,
|
|
2062
|
-
children: /* @__PURE__ */
|
|
2063
|
-
/* @__PURE__ */
|
|
2064
|
-
/* @__PURE__ */
|
|
2065
|
-
|
|
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" })
|
|
2422
|
+
] })
|
|
2423
|
+
}
|
|
2424
|
+
) }),
|
|
2425
|
+
/* @__PURE__ */ jsx10(
|
|
2426
|
+
"button",
|
|
2427
|
+
{
|
|
2428
|
+
"data-testid": "chat-send-button",
|
|
2429
|
+
className: "chat-send-button",
|
|
2430
|
+
onClick: handleSend,
|
|
2431
|
+
disabled: !connected || loading || !input.trim() && attachments.length === 0,
|
|
2432
|
+
style: {
|
|
2433
|
+
padding: "6px",
|
|
2434
|
+
background: connected && !loading && (input.trim() || attachments.length > 0) ? theme.primaryGradient : theme.buttonDisabledBackground,
|
|
2435
|
+
color: connected && !loading && (input.trim() || attachments.length > 0) ? "white" : theme.secondaryTextColor,
|
|
2436
|
+
border: "none",
|
|
2437
|
+
borderRadius: "50%",
|
|
2438
|
+
cursor: connected && !loading && (input.trim() || attachments.length > 0) ? "pointer" : "not-allowed",
|
|
2439
|
+
display: "flex",
|
|
2440
|
+
alignItems: "center",
|
|
2441
|
+
justifyContent: "center",
|
|
2442
|
+
width: "32px",
|
|
2443
|
+
height: "32px",
|
|
2444
|
+
transition: "all 0.2s"
|
|
2445
|
+
},
|
|
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" })
|
|
2066
2449
|
] })
|
|
2067
2450
|
}
|
|
2068
2451
|
)
|
|
2069
2452
|
]
|
|
2070
2453
|
}
|
|
2071
|
-
),
|
|
2072
|
-
/* @__PURE__ */ jsx8(
|
|
2073
|
-
"button",
|
|
2074
|
-
{
|
|
2075
|
-
"data-testid": "chat-send-button",
|
|
2076
|
-
className: "chat-send-button",
|
|
2077
|
-
onClick: handleSend,
|
|
2078
|
-
disabled: !connected || loading || !input.trim() && attachments.length === 0,
|
|
2079
|
-
style: {
|
|
2080
|
-
padding: "10px 16px",
|
|
2081
|
-
background: connected && !loading && (input.trim() || attachments.length > 0) ? theme.primaryGradient : theme.buttonDisabledBackground,
|
|
2082
|
-
color: connected && !loading && (input.trim() || attachments.length > 0) ? "white" : theme.secondaryTextColor,
|
|
2083
|
-
border: "none",
|
|
2084
|
-
borderRadius: "8px",
|
|
2085
|
-
cursor: connected && !loading && (input.trim() || attachments.length > 0) ? "pointer" : "not-allowed",
|
|
2086
|
-
fontSize: "14px",
|
|
2087
|
-
fontWeight: "600",
|
|
2088
|
-
minWidth: "60px",
|
|
2089
|
-
transition: "all 0.2s"
|
|
2090
|
-
},
|
|
2091
|
-
children: strings.input.send
|
|
2092
|
-
}
|
|
2093
2454
|
)
|
|
2094
2455
|
]
|
|
2095
2456
|
}
|
|
@@ -2097,7 +2458,7 @@ function UseAIChatPanel({
|
|
|
2097
2458
|
]
|
|
2098
2459
|
}
|
|
2099
2460
|
),
|
|
2100
|
-
/* @__PURE__ */
|
|
2461
|
+
/* @__PURE__ */ jsx10("style", { children: `
|
|
2101
2462
|
/* Markdown content styles */
|
|
2102
2463
|
.markdown-content > :first-child {
|
|
2103
2464
|
margin-top: 0 !important;
|
|
@@ -2122,7 +2483,7 @@ function UseAIChatPanel({
|
|
|
2122
2483
|
}
|
|
2123
2484
|
|
|
2124
2485
|
// src/components/UseAIFloatingChatWrapper.tsx
|
|
2125
|
-
import { Fragment as Fragment2, jsx as
|
|
2486
|
+
import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2126
2487
|
function UseAIFloatingChatWrapper({
|
|
2127
2488
|
isOpen,
|
|
2128
2489
|
onClose,
|
|
@@ -2130,8 +2491,8 @@ function UseAIFloatingChatWrapper({
|
|
|
2130
2491
|
}) {
|
|
2131
2492
|
const theme = useTheme();
|
|
2132
2493
|
if (!isOpen) return null;
|
|
2133
|
-
return /* @__PURE__ */
|
|
2134
|
-
/* @__PURE__ */
|
|
2494
|
+
return /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
2495
|
+
/* @__PURE__ */ jsx11(
|
|
2135
2496
|
"div",
|
|
2136
2497
|
{
|
|
2137
2498
|
style: {
|
|
@@ -2147,7 +2508,7 @@ function UseAIFloatingChatWrapper({
|
|
|
2147
2508
|
onClick: onClose
|
|
2148
2509
|
}
|
|
2149
2510
|
),
|
|
2150
|
-
/* @__PURE__ */
|
|
2511
|
+
/* @__PURE__ */ jsx11(
|
|
2151
2512
|
"div",
|
|
2152
2513
|
{
|
|
2153
2514
|
style: {
|
|
@@ -2166,7 +2527,7 @@ function UseAIFloatingChatWrapper({
|
|
|
2166
2527
|
children
|
|
2167
2528
|
}
|
|
2168
2529
|
),
|
|
2169
|
-
/* @__PURE__ */
|
|
2530
|
+
/* @__PURE__ */ jsx11("style", { children: `
|
|
2170
2531
|
@keyframes fadeIn {
|
|
2171
2532
|
from { opacity: 0; }
|
|
2172
2533
|
to { opacity: 1; }
|
|
@@ -2186,7 +2547,7 @@ function UseAIFloatingChatWrapper({
|
|
|
2186
2547
|
}
|
|
2187
2548
|
function CloseButton({ onClick }) {
|
|
2188
2549
|
const theme = useTheme();
|
|
2189
|
-
return /* @__PURE__ */
|
|
2550
|
+
return /* @__PURE__ */ jsx11(
|
|
2190
2551
|
"button",
|
|
2191
2552
|
{
|
|
2192
2553
|
"data-testid": "chat-close-button",
|
|
@@ -2221,7 +2582,7 @@ function CloseButton({ onClick }) {
|
|
|
2221
2582
|
|
|
2222
2583
|
// src/components/UseAIChat.tsx
|
|
2223
2584
|
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
2224
|
-
import { jsx as
|
|
2585
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
2225
2586
|
var __UseAIChatContext = createContext3(null);
|
|
2226
2587
|
function useChatUIContext() {
|
|
2227
2588
|
const context = useContext3(__UseAIChatContext);
|
|
@@ -2245,6 +2606,7 @@ function UseAIChat({ floating = false }) {
|
|
|
2245
2606
|
onLoadChat: ctx.history.load,
|
|
2246
2607
|
onDeleteChat: ctx.history.delete,
|
|
2247
2608
|
onListChats: ctx.history.list,
|
|
2609
|
+
onGetChat: ctx.history.get,
|
|
2248
2610
|
suggestions: ctx.suggestions,
|
|
2249
2611
|
availableAgents: ctx.agents.available,
|
|
2250
2612
|
defaultAgent: ctx.agents.default,
|
|
@@ -2257,22 +2619,22 @@ function UseAIChat({ floating = false }) {
|
|
|
2257
2619
|
onDeleteCommand: ctx.commands.delete
|
|
2258
2620
|
};
|
|
2259
2621
|
if (floating) {
|
|
2260
|
-
return /* @__PURE__ */
|
|
2622
|
+
return /* @__PURE__ */ jsx12(
|
|
2261
2623
|
UseAIFloatingChatWrapper,
|
|
2262
2624
|
{
|
|
2263
2625
|
isOpen: ctx.ui.isOpen,
|
|
2264
2626
|
onClose: () => ctx.ui.setOpen(false),
|
|
2265
|
-
children: /* @__PURE__ */
|
|
2627
|
+
children: /* @__PURE__ */ jsx12(
|
|
2266
2628
|
UseAIChatPanel,
|
|
2267
2629
|
{
|
|
2268
2630
|
...chatPanelProps,
|
|
2269
|
-
closeButton: /* @__PURE__ */
|
|
2631
|
+
closeButton: /* @__PURE__ */ jsx12(CloseButton, { onClick: () => ctx.ui.setOpen(false) })
|
|
2270
2632
|
}
|
|
2271
2633
|
)
|
|
2272
2634
|
}
|
|
2273
2635
|
);
|
|
2274
2636
|
}
|
|
2275
|
-
return /* @__PURE__ */
|
|
2637
|
+
return /* @__PURE__ */ jsx12(UseAIChatPanel, { ...chatPanelProps });
|
|
2276
2638
|
}
|
|
2277
2639
|
|
|
2278
2640
|
// src/client.ts
|
|
@@ -2473,12 +2835,18 @@ var UseAIClient = class {
|
|
|
2473
2835
|
return { type: "text", text: part.text };
|
|
2474
2836
|
} else if (part.type === "image") {
|
|
2475
2837
|
return { type: "image", url: part.url };
|
|
2476
|
-
} else {
|
|
2838
|
+
} else if (part.type === "file") {
|
|
2477
2839
|
return {
|
|
2478
2840
|
type: "file",
|
|
2479
2841
|
url: part.url,
|
|
2480
2842
|
mimeType: part.mimeType
|
|
2481
2843
|
};
|
|
2844
|
+
} else {
|
|
2845
|
+
return {
|
|
2846
|
+
type: "transformed_file",
|
|
2847
|
+
text: part.text,
|
|
2848
|
+
originalFile: part.originalFile
|
|
2849
|
+
};
|
|
2482
2850
|
}
|
|
2483
2851
|
});
|
|
2484
2852
|
}
|
|
@@ -2853,7 +3221,8 @@ var LocalStorageChatRepository = class {
|
|
|
2853
3221
|
title: options?.title,
|
|
2854
3222
|
messages: [],
|
|
2855
3223
|
createdAt: now,
|
|
2856
|
-
updatedAt: now
|
|
3224
|
+
updatedAt: now,
|
|
3225
|
+
metadata: options?.metadata
|
|
2857
3226
|
};
|
|
2858
3227
|
await this.enforceMaxChatsLimit();
|
|
2859
3228
|
await this.saveChat(chat);
|
|
@@ -2937,6 +3306,14 @@ var LocalStorageChatRepository = class {
|
|
|
2937
3306
|
throw new Error(`Failed to clear all chats: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2938
3307
|
}
|
|
2939
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
|
+
}
|
|
2940
3317
|
getChatKey(id) {
|
|
2941
3318
|
return `${STORAGE_KEY_PREFIX}${id}`;
|
|
2942
3319
|
}
|
|
@@ -2975,36 +3352,12 @@ var LocalStorageChatRepository = class {
|
|
|
2975
3352
|
}
|
|
2976
3353
|
};
|
|
2977
3354
|
|
|
2978
|
-
// src/fileUpload/EmbedFileUploadBackend.ts
|
|
2979
|
-
var EmbedFileUploadBackend = class {
|
|
2980
|
-
/**
|
|
2981
|
-
* Converts a File to a base64 data URL.
|
|
2982
|
-
*
|
|
2983
|
-
* @param file - The File object to convert
|
|
2984
|
-
* @returns Promise resolving to a base64 data URL (e.g., "data:image/png;base64,...")
|
|
2985
|
-
* @throws Error if file reading fails
|
|
2986
|
-
*/
|
|
2987
|
-
async prepareForSend(file) {
|
|
2988
|
-
return new Promise((resolve, reject) => {
|
|
2989
|
-
const reader = new FileReader();
|
|
2990
|
-
reader.onload = () => {
|
|
2991
|
-
if (typeof reader.result === "string") {
|
|
2992
|
-
resolve(reader.result);
|
|
2993
|
-
} else {
|
|
2994
|
-
reject(new Error("Failed to read file as data URL"));
|
|
2995
|
-
}
|
|
2996
|
-
};
|
|
2997
|
-
reader.onerror = () => {
|
|
2998
|
-
reject(new Error(`Failed to read file: ${file.name}`));
|
|
2999
|
-
};
|
|
3000
|
-
reader.readAsDataURL(file);
|
|
3001
|
-
});
|
|
3002
|
-
}
|
|
3003
|
-
};
|
|
3004
|
-
|
|
3005
3355
|
// src/hooks/useChatManagement.ts
|
|
3006
3356
|
import { useState as useState5, useCallback as useCallback4, useRef as useRef5, useEffect as useEffect5 } from "react";
|
|
3007
3357
|
var CHAT_TITLE_MAX_LENGTH = 50;
|
|
3358
|
+
function deepEquals(a, b) {
|
|
3359
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
3360
|
+
}
|
|
3008
3361
|
function generateChatTitle(message) {
|
|
3009
3362
|
return message.length > CHAT_TITLE_MAX_LENGTH ? message.substring(0, CHAT_TITLE_MAX_LENGTH) + "..." : message;
|
|
3010
3363
|
}
|
|
@@ -3035,7 +3388,11 @@ function transformMessagesToClientFormat(uiMessages) {
|
|
|
3035
3388
|
}
|
|
3036
3389
|
function useChatManagement({
|
|
3037
3390
|
repository,
|
|
3038
|
-
clientRef
|
|
3391
|
+
clientRef,
|
|
3392
|
+
onSendMessage,
|
|
3393
|
+
setOpen,
|
|
3394
|
+
connected,
|
|
3395
|
+
loading
|
|
3039
3396
|
}) {
|
|
3040
3397
|
const [currentChatId, setCurrentChatId] = useState5(null);
|
|
3041
3398
|
const [pendingChatId, setPendingChatId] = useState5(null);
|
|
@@ -3068,18 +3425,18 @@ function useChatManagement({
|
|
|
3068
3425
|
const loadedMessages = await loadChatMessages(chatId);
|
|
3069
3426
|
setMessages(loadedMessages);
|
|
3070
3427
|
}, [loadChatMessages]);
|
|
3071
|
-
const createNewChat = useCallback4(async () => {
|
|
3428
|
+
const createNewChat = useCallback4(async (options) => {
|
|
3072
3429
|
console.log("[ChatManagement] createNewChat called - currentChatId:", currentChatId, "pendingChatId:", pendingChatId, "messages.length:", messages.length);
|
|
3073
3430
|
if (pendingChatId && messages.length === 0) {
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
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
|
+
}
|
|
3080
3437
|
}
|
|
3081
3438
|
console.log("[ChatManagement] Creating new chat...");
|
|
3082
|
-
const chatId = await repository.createChat();
|
|
3439
|
+
const chatId = await repository.createChat(options);
|
|
3083
3440
|
setPendingChatId(chatId);
|
|
3084
3441
|
setMessages([]);
|
|
3085
3442
|
if (clientRef.current) {
|
|
@@ -3124,6 +3481,22 @@ function useChatManagement({
|
|
|
3124
3481
|
}
|
|
3125
3482
|
}
|
|
3126
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]);
|
|
3127
3500
|
const activatePendingChat = useCallback4(() => {
|
|
3128
3501
|
if (!pendingChatId) return null;
|
|
3129
3502
|
console.log("[ChatManagement] Activating pending chat:", pendingChatId);
|
|
@@ -3142,7 +3515,7 @@ function useChatManagement({
|
|
|
3142
3515
|
console.error("[ChatManagement] Chat not found:", chatId);
|
|
3143
3516
|
return false;
|
|
3144
3517
|
}
|
|
3145
|
-
const { generateMessageId: generateMessageId2 } = await import("./types-
|
|
3518
|
+
const { generateMessageId: generateMessageId2 } = await import("./types-64CH2HXY.js");
|
|
3146
3519
|
chat.messages.push({
|
|
3147
3520
|
id: generateMessageId2(),
|
|
3148
3521
|
role: "user",
|
|
@@ -3178,7 +3551,7 @@ function useChatManagement({
|
|
|
3178
3551
|
console.error("[ChatManagement] Chat not found:", currentChatIdValue);
|
|
3179
3552
|
return;
|
|
3180
3553
|
}
|
|
3181
|
-
const { generateMessageId: generateMessageId2 } = await import("./types-
|
|
3554
|
+
const { generateMessageId: generateMessageId2 } = await import("./types-64CH2HXY.js");
|
|
3182
3555
|
chat.messages.push({
|
|
3183
3556
|
id: generateMessageId2(),
|
|
3184
3557
|
role: "assistant",
|
|
@@ -3235,6 +3608,70 @@ function useChatManagement({
|
|
|
3235
3608
|
}
|
|
3236
3609
|
}, [currentChatId, pendingChatId, createNewChat, repository, loadChatMessages, clientRef]);
|
|
3237
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]);
|
|
3238
3675
|
return {
|
|
3239
3676
|
currentChatId,
|
|
3240
3677
|
pendingChatId,
|
|
@@ -3249,6 +3686,9 @@ function useChatManagement({
|
|
|
3249
3686
|
saveUserMessage,
|
|
3250
3687
|
saveAIResponse,
|
|
3251
3688
|
reloadMessages,
|
|
3689
|
+
sendMessage,
|
|
3690
|
+
getCurrentChat,
|
|
3691
|
+
updateMetadata,
|
|
3252
3692
|
currentChatIdSnapshot,
|
|
3253
3693
|
pendingChatIdSnapshot
|
|
3254
3694
|
};
|
|
@@ -3630,7 +4070,7 @@ function usePromptState({
|
|
|
3630
4070
|
}
|
|
3631
4071
|
|
|
3632
4072
|
// src/providers/useAIProvider.tsx
|
|
3633
|
-
import { Fragment as Fragment3, jsx as
|
|
4073
|
+
import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3634
4074
|
var __UseAIContext = createContext4(null);
|
|
3635
4075
|
var hasWarnedAboutMissingProvider = false;
|
|
3636
4076
|
var noOpContextValue = {
|
|
@@ -3660,6 +4100,11 @@ var noOpContextValue = {
|
|
|
3660
4100
|
},
|
|
3661
4101
|
list: async () => [],
|
|
3662
4102
|
clear: async () => {
|
|
4103
|
+
},
|
|
4104
|
+
sendMessage: async () => {
|
|
4105
|
+
},
|
|
4106
|
+
get: async () => null,
|
|
4107
|
+
updateMetadata: async () => {
|
|
3663
4108
|
}
|
|
3664
4109
|
},
|
|
3665
4110
|
agents: {
|
|
@@ -3699,7 +4144,8 @@ function UseAIProvider({
|
|
|
3699
4144
|
renderChat = true,
|
|
3700
4145
|
theme: customTheme,
|
|
3701
4146
|
strings: customStrings,
|
|
3702
|
-
visibleAgentIds
|
|
4147
|
+
visibleAgentIds,
|
|
4148
|
+
onOpenChange
|
|
3703
4149
|
}) {
|
|
3704
4150
|
const fileUploadConfig = fileUploadConfigProp === false ? void 0 : fileUploadConfigProp ?? DEFAULT_FILE_UPLOAD_CONFIG;
|
|
3705
4151
|
const theme = { ...defaultTheme, ...customTheme };
|
|
@@ -3707,12 +4153,17 @@ function UseAIProvider({
|
|
|
3707
4153
|
const [connected, setConnected] = useState10(false);
|
|
3708
4154
|
const [isChatOpen, setIsChatOpen] = useState10(false);
|
|
3709
4155
|
const [loading, setLoading] = useState10(false);
|
|
4156
|
+
const handleSetChatOpen = useCallback9((open) => {
|
|
4157
|
+
setIsChatOpen(open);
|
|
4158
|
+
onOpenChange?.(open);
|
|
4159
|
+
}, [onOpenChange]);
|
|
3710
4160
|
const [streamingText, setStreamingText] = useState10("");
|
|
3711
4161
|
const streamingChatIdRef = useRef9(null);
|
|
3712
4162
|
const clientRef = useRef9(null);
|
|
3713
4163
|
const repositoryRef = useRef9(
|
|
3714
4164
|
chatRepository || new LocalStorageChatRepository()
|
|
3715
4165
|
);
|
|
4166
|
+
const handleSendMessageRef = useRef9(null);
|
|
3716
4167
|
const {
|
|
3717
4168
|
registerTools,
|
|
3718
4169
|
unregisterTools,
|
|
@@ -3734,9 +4185,18 @@ function UseAIProvider({
|
|
|
3734
4185
|
clientRef,
|
|
3735
4186
|
connected
|
|
3736
4187
|
});
|
|
4188
|
+
const stableSendMessage = useCallback9(async (message, attachments) => {
|
|
4189
|
+
if (handleSendMessageRef.current) {
|
|
4190
|
+
await handleSendMessageRef.current(message, attachments);
|
|
4191
|
+
}
|
|
4192
|
+
}, []);
|
|
3737
4193
|
const chatManagement = useChatManagement({
|
|
3738
4194
|
repository: repositoryRef.current,
|
|
3739
|
-
clientRef
|
|
4195
|
+
clientRef,
|
|
4196
|
+
onSendMessage: stableSendMessage,
|
|
4197
|
+
setOpen: handleSetChatOpen,
|
|
4198
|
+
connected,
|
|
4199
|
+
loading
|
|
3740
4200
|
});
|
|
3741
4201
|
const {
|
|
3742
4202
|
currentChatId,
|
|
@@ -3750,7 +4210,10 @@ function UseAIProvider({
|
|
|
3750
4210
|
clearCurrentChat,
|
|
3751
4211
|
activatePendingChat,
|
|
3752
4212
|
saveUserMessage,
|
|
3753
|
-
saveAIResponse
|
|
4213
|
+
saveAIResponse,
|
|
4214
|
+
sendMessage,
|
|
4215
|
+
getCurrentChat,
|
|
4216
|
+
updateMetadata
|
|
3754
4217
|
} = chatManagement;
|
|
3755
4218
|
const {
|
|
3756
4219
|
availableAgents,
|
|
@@ -3891,7 +4354,6 @@ function UseAIProvider({
|
|
|
3891
4354
|
let persistedContent = message;
|
|
3892
4355
|
let multimodalContent;
|
|
3893
4356
|
if (attachments && attachments.length > 0) {
|
|
3894
|
-
const backend = fileUploadConfig?.backend ?? new EmbedFileUploadBackend();
|
|
3895
4357
|
const persistedParts = [];
|
|
3896
4358
|
if (message.trim()) {
|
|
3897
4359
|
persistedParts.push({ type: "text", text: message });
|
|
@@ -3907,35 +4369,24 @@ function UseAIProvider({
|
|
|
3907
4369
|
});
|
|
3908
4370
|
}
|
|
3909
4371
|
persistedContent = persistedParts;
|
|
3910
|
-
const
|
|
4372
|
+
const fileContent = await processAttachments(attachments, {
|
|
4373
|
+
getCurrentChat,
|
|
4374
|
+
backend: fileUploadConfig?.backend,
|
|
4375
|
+
transformers: fileUploadConfig?.transformers
|
|
4376
|
+
});
|
|
4377
|
+
multimodalContent = [];
|
|
3911
4378
|
if (message.trim()) {
|
|
3912
|
-
|
|
4379
|
+
multimodalContent.push({ type: "text", text: message });
|
|
3913
4380
|
}
|
|
3914
|
-
|
|
3915
|
-
try {
|
|
3916
|
-
const url = await backend.prepareForSend(attachment.file);
|
|
3917
|
-
if (attachment.file.type.startsWith("image/")) {
|
|
3918
|
-
contentParts.push({ type: "image", url });
|
|
3919
|
-
} else {
|
|
3920
|
-
contentParts.push({
|
|
3921
|
-
type: "file",
|
|
3922
|
-
url,
|
|
3923
|
-
mimeType: attachment.file.type,
|
|
3924
|
-
name: attachment.file.name
|
|
3925
|
-
});
|
|
3926
|
-
}
|
|
3927
|
-
} catch (error) {
|
|
3928
|
-
console.error("[Provider] Failed to prepare file for send:", error);
|
|
3929
|
-
}
|
|
3930
|
-
}
|
|
3931
|
-
multimodalContent = contentParts;
|
|
4381
|
+
multimodalContent.push(...fileContent);
|
|
3932
4382
|
}
|
|
3933
4383
|
if (activeChatId) {
|
|
3934
4384
|
await saveUserMessage(activeChatId, persistedContent);
|
|
3935
4385
|
}
|
|
3936
4386
|
setLoading(true);
|
|
3937
4387
|
await clientRef.current.sendPrompt(message, multimodalContent);
|
|
3938
|
-
}, [activatePendingChat, currentChatId, saveUserMessage, fileUploadConfig]);
|
|
4388
|
+
}, [activatePendingChat, currentChatId, saveUserMessage, fileUploadConfig, getCurrentChat]);
|
|
4389
|
+
handleSendMessageRef.current = handleSendMessage;
|
|
3939
4390
|
const value = {
|
|
3940
4391
|
serverUrl,
|
|
3941
4392
|
connected,
|
|
@@ -3955,7 +4406,10 @@ function UseAIProvider({
|
|
|
3955
4406
|
load: loadChat,
|
|
3956
4407
|
delete: deleteChat,
|
|
3957
4408
|
list: listChats,
|
|
3958
|
-
clear: clearCurrentChat
|
|
4409
|
+
clear: clearCurrentChat,
|
|
4410
|
+
sendMessage,
|
|
4411
|
+
get: getCurrentChat,
|
|
4412
|
+
updateMetadata
|
|
3959
4413
|
},
|
|
3960
4414
|
agents: {
|
|
3961
4415
|
available: availableAgents,
|
|
@@ -3985,7 +4439,8 @@ function UseAIProvider({
|
|
|
3985
4439
|
create: createNewChat,
|
|
3986
4440
|
load: loadChat,
|
|
3987
4441
|
delete: deleteChat,
|
|
3988
|
-
list: listChats
|
|
4442
|
+
list: listChats,
|
|
4443
|
+
get: getCurrentChat
|
|
3989
4444
|
},
|
|
3990
4445
|
agents: {
|
|
3991
4446
|
available: availableAgents,
|
|
@@ -4001,7 +4456,7 @@ function UseAIProvider({
|
|
|
4001
4456
|
},
|
|
4002
4457
|
ui: {
|
|
4003
4458
|
isOpen: isChatOpen,
|
|
4004
|
-
setOpen:
|
|
4459
|
+
setOpen: handleSetChatOpen
|
|
4005
4460
|
}
|
|
4006
4461
|
};
|
|
4007
4462
|
const isUIDisabled = CustomButton === null || CustomChat === null;
|
|
@@ -4031,21 +4486,21 @@ function UseAIProvider({
|
|
|
4031
4486
|
};
|
|
4032
4487
|
const renderDefaultChat = () => {
|
|
4033
4488
|
if (isUIDisabled) return null;
|
|
4034
|
-
return /* @__PURE__ */
|
|
4489
|
+
return /* @__PURE__ */ jsx13(UseAIFloatingChatWrapper, { isOpen: isChatOpen, onClose: () => handleSetChatOpen(false), children: /* @__PURE__ */ jsx13(
|
|
4035
4490
|
UseAIChatPanel,
|
|
4036
4491
|
{
|
|
4037
4492
|
...chatPanelProps,
|
|
4038
|
-
closeButton: /* @__PURE__ */
|
|
4493
|
+
closeButton: /* @__PURE__ */ jsx13(CloseButton, { onClick: () => handleSetChatOpen(false) })
|
|
4039
4494
|
}
|
|
4040
4495
|
) });
|
|
4041
4496
|
};
|
|
4042
4497
|
const renderCustomChat = () => {
|
|
4043
4498
|
if (!CustomChat) return null;
|
|
4044
|
-
return /* @__PURE__ */
|
|
4499
|
+
return /* @__PURE__ */ jsx13(
|
|
4045
4500
|
CustomChat,
|
|
4046
4501
|
{
|
|
4047
4502
|
isOpen: isChatOpen,
|
|
4048
|
-
onClose: () =>
|
|
4503
|
+
onClose: () => handleSetChatOpen(false),
|
|
4049
4504
|
onSendMessage: handleSendMessage,
|
|
4050
4505
|
messages,
|
|
4051
4506
|
loading,
|
|
@@ -4060,18 +4515,18 @@ function UseAIProvider({
|
|
|
4060
4515
|
};
|
|
4061
4516
|
const renderBuiltInChat = () => {
|
|
4062
4517
|
if (!renderChat) return null;
|
|
4063
|
-
return /* @__PURE__ */
|
|
4064
|
-
ButtonComponent && /* @__PURE__ */
|
|
4518
|
+
return /* @__PURE__ */ jsxs9(Fragment3, { children: [
|
|
4519
|
+
ButtonComponent && /* @__PURE__ */ jsx13(
|
|
4065
4520
|
ButtonComponent,
|
|
4066
4521
|
{
|
|
4067
|
-
onClick: () =>
|
|
4522
|
+
onClick: () => handleSetChatOpen(true),
|
|
4068
4523
|
connected
|
|
4069
4524
|
}
|
|
4070
4525
|
),
|
|
4071
4526
|
hasCustomChat ? renderCustomChat() : renderDefaultChat()
|
|
4072
4527
|
] });
|
|
4073
4528
|
};
|
|
4074
|
-
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: [
|
|
4075
4530
|
children,
|
|
4076
4531
|
renderBuiltInChat()
|
|
4077
4532
|
] }) }) }) });
|
|
@@ -4474,14 +4929,18 @@ export {
|
|
|
4474
4929
|
UseAIFloatingButton,
|
|
4475
4930
|
UseAIFloatingChatWrapper,
|
|
4476
4931
|
UseAIProvider,
|
|
4932
|
+
clearTransformationCache,
|
|
4477
4933
|
convertToolsToDefinitions,
|
|
4478
4934
|
defaultStrings,
|
|
4479
4935
|
defaultTheme,
|
|
4480
4936
|
defineTool,
|
|
4481
4937
|
executeDefinedTool,
|
|
4938
|
+
findTransformer,
|
|
4482
4939
|
generateChatId,
|
|
4483
4940
|
generateCommandId,
|
|
4484
4941
|
generateMessageId,
|
|
4942
|
+
matchesMimeType,
|
|
4943
|
+
processAttachments,
|
|
4485
4944
|
useAI,
|
|
4486
4945
|
useAIContext,
|
|
4487
4946
|
useAIWorkflow,
|