@qredence/fleet 0.5.1 → 0.5.5
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/CHANGELOG.md +7 -0
- package/bin/fleet-prime.mjs +6 -0
- package/dist/web/client/assets/action-swap-roll-DX5o_33Q.js +1 -0
- package/dist/web/client/assets/artifacts-panel-C3yewUBP.js +1 -0
- package/dist/web/client/assets/{chat-CsepBQwy.js → chat-W-yOMyG_.js} +1 -1
- package/dist/web/client/assets/chat-command-palette-D0xDK1j4.js +1 -0
- package/dist/web/client/assets/command-CQzrtjyj.js +2 -0
- package/dist/web/client/assets/{fleet-pi-tool-renderer-BD_ZAjlG.js → fleet-pi-tool-renderer-B0Y7ou0U.js} +16 -16
- package/dist/web/client/assets/generative-text-renderer-SS9c1kNX.js +6 -0
- package/dist/web/client/assets/globals-D_Hy9bT1.css +2 -0
- package/dist/web/client/assets/{index-DweoFRMs.js → index-C9FloFgj.js} +2 -2
- package/dist/web/client/assets/{ipython-tool-BfeIa0nK.js → ipython-tool-BrMePqD-.js} +1 -1
- package/dist/web/client/assets/{openui-renderer-DlUo6ehT.js → openui-renderer-CCfQqUfE.js} +5 -5
- package/dist/web/client/assets/{prime-agent-artifacts-CHGb5V_j.js → prime-agent-artifacts-C-g1VPiW.js} +1 -1
- package/dist/web/client/assets/range-65lubOFp.js +2 -0
- package/dist/web/client/assets/repl-panel-CCh4ly7J.js +1 -0
- package/dist/web/client/assets/routes-DSTyx_J0.js +16 -0
- package/dist/web/client/assets/session-insights-panel-CQdT90Op.js +1 -0
- package/dist/web/client/assets/subagent-chat-panel-D-qw4uWb.js +1 -0
- package/dist/web/client/assets/subagent-transcript-C7oRwEEP.js +1 -0
- package/dist/web/client/assets/subagents-panel-aSMWZP9p.js +1 -0
- package/dist/web/client/assets/{tool-result-CBzwwUE9.js → tool-result-C2NvnN32.js} +3 -3
- package/dist/web/server/{_tanstack-start-manifest_v-bDUlyKY0-KFW35JRO.js → _tanstack-start-manifest_v-DZc7dwm7-6ZQLGXB7.js} +13 -13
- package/dist/web/server/{artifacts-panel-D9w1DHAN-FGRDCYU2.js → artifacts-panel-Bt7YUzm4-NCBMXJ25.js} +15 -15
- package/dist/web/server/{chat-command-palette-BaenPkCN-BHSOPGU4.js → chat-command-palette-Co1L3rUY-RQLNME4T.js} +33 -12
- package/dist/web/server/{chunk-KPNGZR2R.js → chunk-2V6B62OF.js} +204 -204
- package/dist/web/server/{chunk-44IVTHDV.js → chunk-3HUI75QM.js} +60 -60
- package/dist/web/server/{chunk-5AVQZ4AZ.js → chunk-4UBOIY2S.js} +2 -1
- package/dist/web/server/{chunk-Y6LJ4WBI.js → chunk-56HSKUBD.js} +699 -691
- package/dist/web/server/{chunk-RPROZ2JC.js → chunk-5RQ6QAZX.js} +133 -133
- package/dist/web/server/{chunk-PWK2HJIV.js → chunk-6D524OCJ.js} +175 -175
- package/dist/web/server/{chunk-FBOO3G67.js → chunk-AECEK3K7.js} +6 -6
- package/dist/web/server/{chunk-VHCAD46L.js → chunk-AWFOBHH4.js} +4 -4
- package/dist/web/server/{chunk-FVWDJNXR.js → chunk-BEMDNODD.js} +1 -1
- package/dist/web/server/{chunk-X2TUFLTP.js → chunk-BLVCDQ7E.js} +438 -438
- package/dist/web/server/{chunk-EIVNRYP3.js → chunk-FZRBAPUM.js} +2 -2
- package/dist/web/server/chunk-KOIPYBJF.js +3773 -0
- package/dist/web/server/{chunk-XYYNYFFD.js → chunk-LSIHVSUT.js} +2 -2
- package/dist/web/server/{chunk-H64JLONZ.js → chunk-PDRD2X5G.js} +2 -2
- package/dist/web/server/{chunk-FE4KN6T2.js → chunk-RX62LUDV.js} +4 -4
- package/dist/web/server/chunk-SR65ARVS.js +192 -0
- package/dist/web/server/{chunk-WK7CQS2N.js → chunk-SZ65K4CO.js} +48 -48
- package/dist/web/server/{chunk-DO3TVNGA.js → chunk-TO3YPLNZ.js} +6 -6
- package/dist/web/server/{chunk-3IKSPTYI.js → chunk-UKINNXJY.js} +2 -2
- package/dist/web/server/{chunk-M2FGGPNA.js → chunk-VGDP4YDU.js} +70 -45
- package/dist/web/server/{chunk-PCJ5EKFE.js → chunk-VRLTWOVJ.js} +11 -6
- package/dist/web/server/{chunk-HBZ6YKRB.js → chunk-WN77JNYY.js} +2 -2
- package/dist/web/server/{chunk-2U7PWSJX.js → chunk-WZNZQNI4.js} +231 -3633
- package/dist/web/server/{chunk-B2F6MLVZ.js → chunk-XFVL5ITL.js} +2246 -2228
- package/dist/web/server/{chunk-3GSFXWL5.js → chunk-XLCTCC4W.js} +3 -3
- package/dist/web/server/{chunk-AZZHUVJR.js → chunk-Y4MHIA7B.js} +18 -26
- package/dist/web/server/{fleet-pi-tool-renderer-lJvZWmBJ-4M5YI6VS.js → fleet-pi-tool-renderer-CE45vM6T-2UQN6RJM.js} +11 -9
- package/dist/web/server/{fork-picker-dialog-BZzfxdQd-Y725VJ7G.js → fork-picker-dialog-DCzuGelH-TN2Q5OXI.js} +5 -5
- package/dist/web/server/{openui-renderer-Cg4RSE9k-7BTJIYZJ.js → openui-renderer-c36_GYes-HX46N4M5.js} +11 -11
- package/dist/web/server/{repl-panel-BEQrC2ef-V3YEZ7EO.js → repl-panel-D9E8nkQy-L45ZNG2V.js} +4 -3
- package/dist/web/server/{router-CEahIUpn-SRG7XKIH.js → router-_ZpegqiQ-QIE44PIB.js} +1737 -1370
- package/dist/web/server/{routes-BznemByz-F4DJAYIM.js → routes-Ct81-8Tq-LHRMOS7R.js} +2882 -2330
- package/dist/web/server/server.js +3 -3
- package/dist/web/server/{session-insights-panel-JfeTHE0d-3HZB3ZWI.js → session-insights-panel-BHZyKDTo-LRMAMA3O.js} +4 -2
- package/dist/web/server/{settings-dialog-DgeBMORv-7SRSENPM.js → settings-dialog-B4uUS6f--AZ4I4ZOT.js} +142 -142
- package/dist/web/server/{start-CLAD7RcD-56S4BWMM.js → start-BYVnok_H-IA6TWGA3.js} +1 -1
- package/dist/web/server/subagent-chat-panel-C97S3WID-DLOAD5TG.js +63 -0
- package/dist/web/server/subagents-panel-iHpvMIZy-LI6XK66M.js +181 -0
- package/dist/web/server/{workspace-panel-y54P79_B-VPIYUXF6.js → workspace-panel-CHPoiXEo-YB4WS3MK.js} +2 -2
- package/package.json +5 -5
- package/dist/web/client/assets/artifacts-panel-CX62LQ13.js +0 -1
- package/dist/web/client/assets/chat-command-palette-C4sSf8Kg.js +0 -1
- package/dist/web/client/assets/collapsible-DmyYcezk.js +0 -1
- package/dist/web/client/assets/command-CB6emP8m.js +0 -2
- package/dist/web/client/assets/conversation-turns-ByFoWPXe.js +0 -6
- package/dist/web/client/assets/globals-CqqQdk2S.css +0 -2
- package/dist/web/client/assets/range-vSJ7Ux_5.js +0 -2
- package/dist/web/client/assets/repl-panel-DiGS6uCw.js +0 -1
- package/dist/web/client/assets/routes-CxlNCi_v.js +0 -16
- package/dist/web/client/assets/session-insights-panel-DwmwiikS.js +0 -1
- package/dist/web/client/assets/subagents-panel-DGnsK6Nx.js +0 -1
- package/dist/web/server/chunk-ZEVZFLIY.js +0 -334
- package/dist/web/server/subagents-panel-CzZe3co7-2VZ5JTWF.js +0 -332
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
LazyMarkdown,
|
|
3
3
|
Terminal,
|
|
4
4
|
useHoverCapable
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-3HUI75QM.js";
|
|
6
6
|
import {
|
|
7
7
|
notify
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-FZRBAPUM.js";
|
|
9
9
|
import {
|
|
10
10
|
CircleX,
|
|
11
11
|
Copy,
|
|
12
12
|
Wrench
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-6D524OCJ.js";
|
|
14
14
|
import {
|
|
15
15
|
AnimatePresence,
|
|
16
16
|
EASE_OUT,
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
} from "./chunk-NLIUTTKL.js";
|
|
37
37
|
import {
|
|
38
38
|
X
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-BLVCDQ7E.js";
|
|
40
40
|
import {
|
|
41
41
|
CircleAlert,
|
|
42
42
|
FileText
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
cn
|
|
49
49
|
} from "./chunk-DJMHPJBP.js";
|
|
50
50
|
|
|
51
|
-
// web/app/dist/server/assets/
|
|
51
|
+
// web/app/dist/server/assets/generative-text-renderer-Cn-31rC8.js
|
|
52
52
|
import { Suspense, cloneElement, createContext, lazy, memo, useCallback, useContext, useEffect, useEffectEvent, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
53
53
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
54
54
|
import { createPortal } from "react-dom";
|
|
@@ -151,6 +151,13 @@ var Image = createLucideIcon("image", [
|
|
|
151
151
|
key: "1xmnt7"
|
|
152
152
|
}]
|
|
153
153
|
]);
|
|
154
|
+
var RotateCw = createLucideIcon("rotate-cw", [["path", {
|
|
155
|
+
d: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",
|
|
156
|
+
key: "1p45f6"
|
|
157
|
+
}], ["path", {
|
|
158
|
+
d: "M21 3v5h-5",
|
|
159
|
+
key: "1q7to0"
|
|
160
|
+
}]]);
|
|
154
161
|
var MessageSideContext = createContext(void 0);
|
|
155
162
|
var MessageBubbleContext = createContext({
|
|
156
163
|
animateIn: true,
|
|
@@ -812,175 +819,270 @@ function MessageContent({ className, ...props }) {
|
|
|
812
819
|
...props
|
|
813
820
|
});
|
|
814
821
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
822
|
+
function ImageLightbox({ open, onClose, images, initialIndex = 0 }) {
|
|
823
|
+
const [currentIndex, setCurrentIndex] = useState(initialIndex);
|
|
824
|
+
const hasMultipleImages = images.length > 1;
|
|
825
|
+
useEffect(() => {
|
|
826
|
+
if (open) setCurrentIndex(initialIndex);
|
|
827
|
+
}, [open, initialIndex]);
|
|
828
|
+
const goToPrevious = useCallback((event) => {
|
|
829
|
+
event?.stopPropagation();
|
|
830
|
+
setCurrentIndex((prev) => prev > 0 ? prev - 1 : images.length - 1);
|
|
831
|
+
}, [images.length]);
|
|
832
|
+
const goToNext = useCallback((event) => {
|
|
833
|
+
event?.stopPropagation();
|
|
834
|
+
setCurrentIndex((prev) => prev < images.length - 1 ? prev + 1 : 0);
|
|
835
|
+
}, [images.length]);
|
|
836
|
+
const onLightboxKeyDown = useEffectEvent((event) => {
|
|
837
|
+
switch (event.key) {
|
|
838
|
+
case "ArrowLeft":
|
|
839
|
+
event.preventDefault();
|
|
840
|
+
if (hasMultipleImages) goToPrevious();
|
|
841
|
+
break;
|
|
842
|
+
case "ArrowRight":
|
|
843
|
+
event.preventDefault();
|
|
844
|
+
if (hasMultipleImages) goToNext();
|
|
845
|
+
}
|
|
828
846
|
});
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
847
|
+
useEffect(() => {
|
|
848
|
+
if (!open) return;
|
|
849
|
+
const handler = (event) => onLightboxKeyDown(event);
|
|
850
|
+
window.addEventListener("keydown", handler, true);
|
|
851
|
+
return () => window.removeEventListener("keydown", handler, true);
|
|
852
|
+
}, [open]);
|
|
853
|
+
useEffect(() => {
|
|
854
|
+
if (!open) return;
|
|
855
|
+
const previousOverflow = document.body.style.overflow;
|
|
856
|
+
document.body.style.overflow = "hidden";
|
|
857
|
+
return () => {
|
|
858
|
+
document.body.style.overflow = previousOverflow;
|
|
859
|
+
};
|
|
860
|
+
}, [open]);
|
|
861
|
+
const dialogRef = useRef(null);
|
|
862
|
+
const onLightDismiss = useEffectEvent((event) => {
|
|
863
|
+
if (dialogRef.current && event.target === dialogRef.current) onClose();
|
|
864
|
+
});
|
|
865
|
+
useEffect(() => {
|
|
866
|
+
if (!open) return;
|
|
867
|
+
const dialog = dialogRef.current;
|
|
868
|
+
if (!dialog) return;
|
|
869
|
+
if (!dialog.open) dialog.showModal();
|
|
870
|
+
const handler = (event) => onLightDismiss(event);
|
|
871
|
+
dialog.addEventListener("click", handler);
|
|
872
|
+
return () => {
|
|
873
|
+
dialog.removeEventListener("click", handler);
|
|
874
|
+
if (dialog.open) dialog.close();
|
|
875
|
+
};
|
|
876
|
+
}, [open]);
|
|
877
|
+
if (typeof document === "undefined") return null;
|
|
878
|
+
if (!open) return null;
|
|
879
|
+
const currentImage = images[currentIndex] ?? images[0];
|
|
880
|
+
if (!currentImage?.url) return null;
|
|
881
|
+
return createPortal(/* @__PURE__ */ jsxs("dialog", {
|
|
882
|
+
ref: dialogRef,
|
|
883
|
+
"aria-label": "Image viewer",
|
|
884
|
+
onClose: () => onClose(),
|
|
885
|
+
className: "fixed inset-0 z-50 m-0 flex h-full max-h-none w-full max-w-none items-center justify-center border-0 bg-black/90 p-0 backdrop:bg-transparent",
|
|
844
886
|
children: [
|
|
845
|
-
/* @__PURE__ */ jsx("
|
|
846
|
-
|
|
847
|
-
|
|
887
|
+
/* @__PURE__ */ jsx("button", {
|
|
888
|
+
type: "button",
|
|
889
|
+
onClick: onClose,
|
|
890
|
+
"aria-label": "Close fullscreen (Esc)",
|
|
891
|
+
className: "absolute top-4 right-4 z-10 inline-flex size-9 items-center justify-center rounded-full bg-black/50 text-white transition-colors hover:bg-black/70",
|
|
892
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-5" })
|
|
848
893
|
}),
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
894
|
+
hasMultipleImages && /* @__PURE__ */ jsx("button", {
|
|
895
|
+
type: "button",
|
|
896
|
+
onClick: goToPrevious,
|
|
897
|
+
"aria-label": "Previous image (\u2190)",
|
|
898
|
+
className: "absolute top-1/2 left-4 z-10 inline-flex size-10 -translate-y-1/2 items-center justify-center rounded-full bg-black/50 text-white transition-colors hover:bg-black/70",
|
|
899
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-6" })
|
|
900
|
+
}),
|
|
901
|
+
/* @__PURE__ */ jsx("img", {
|
|
902
|
+
src: currentImage.url,
|
|
903
|
+
alt: currentImage.filename ?? "Image preview",
|
|
904
|
+
className: "max-h-[85vh] max-w-[90vw] object-contain select-none",
|
|
905
|
+
onClick: (event) => event.stopPropagation(),
|
|
906
|
+
draggable: false
|
|
907
|
+
}),
|
|
908
|
+
hasMultipleImages && /* @__PURE__ */ jsx("button", {
|
|
909
|
+
type: "button",
|
|
910
|
+
onClick: goToNext,
|
|
911
|
+
"aria-label": "Next image (\u2192)",
|
|
912
|
+
className: "absolute top-1/2 right-4 z-10 inline-flex size-10 -translate-y-1/2 items-center justify-center rounded-full bg-black/50 text-white transition-colors hover:bg-black/70",
|
|
913
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-6" })
|
|
914
|
+
}),
|
|
915
|
+
hasMultipleImages && /* @__PURE__ */ jsxs("div", {
|
|
916
|
+
className: "absolute bottom-6 left-1/2 flex -translate-x-1/2 flex-col items-center gap-3",
|
|
917
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
918
|
+
className: "flex gap-2",
|
|
919
|
+
children: images.map((image, idx) => /* @__PURE__ */ jsx("button", {
|
|
920
|
+
type: "button",
|
|
921
|
+
onClick: (event) => {
|
|
922
|
+
event.stopPropagation();
|
|
923
|
+
setCurrentIndex(idx);
|
|
924
|
+
},
|
|
925
|
+
"aria-label": `Go to image ${idx + 1}`,
|
|
926
|
+
className: cn("size-2 rounded-full transition-all", idx === currentIndex ? "scale-125 bg-white" : "bg-white/40 hover:bg-white/60")
|
|
927
|
+
}, image.url))
|
|
928
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
929
|
+
className: "text-sm text-white/70",
|
|
930
|
+
children: [
|
|
931
|
+
currentIndex + 1,
|
|
932
|
+
" / ",
|
|
933
|
+
images.length
|
|
934
|
+
]
|
|
862
935
|
})]
|
|
863
|
-
})
|
|
936
|
+
})
|
|
864
937
|
]
|
|
865
|
-
});
|
|
866
|
-
}
|
|
867
|
-
function isRecord$2(value) {
|
|
868
|
-
return typeof value === "object" && value !== null;
|
|
869
|
-
}
|
|
870
|
-
function parseStructuredJson(value) {
|
|
871
|
-
if (typeof value !== "string") return value;
|
|
872
|
-
const trimmed = value.trim();
|
|
873
|
-
if (!trimmed) return value;
|
|
874
|
-
try {
|
|
875
|
-
const parsed = JSON.parse(trimmed);
|
|
876
|
-
return isRecord$2(parsed) || Array.isArray(parsed) ? parsed : value;
|
|
877
|
-
} catch {
|
|
878
|
-
return value;
|
|
879
|
-
}
|
|
938
|
+
}), document.body);
|
|
880
939
|
}
|
|
881
|
-
function
|
|
882
|
-
if (
|
|
883
|
-
if (
|
|
884
|
-
|
|
885
|
-
const normalizedOutput = parseStructuredJson(part.output);
|
|
886
|
-
const normalizedResult = parseStructuredJson(part.result);
|
|
887
|
-
const inputChanged = normalizedInput !== part.input;
|
|
888
|
-
const outputChanged = normalizedOutput !== part.output;
|
|
889
|
-
const resultChanged = normalizedResult !== part.result;
|
|
890
|
-
if (!inputChanged && !outputChanged && !resultChanged) return part;
|
|
891
|
-
const normalizedPart = { ...part };
|
|
892
|
-
if (inputChanged) normalizedPart.input = normalizedInput;
|
|
893
|
-
if (outputChanged) normalizedPart.output = normalizedOutput;
|
|
894
|
-
if (resultChanged) normalizedPart.result = normalizedResult;
|
|
895
|
-
return normalizedPart;
|
|
940
|
+
function formatFileSize(bytes) {
|
|
941
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
942
|
+
if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
943
|
+
return `${(bytes / 1048576).toFixed(1)} MB`;
|
|
896
944
|
}
|
|
897
|
-
function
|
|
898
|
-
|
|
899
|
-
const
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
945
|
+
function getFileIconName(filename, isImage) {
|
|
946
|
+
if (isImage) return "image";
|
|
947
|
+
const ext = filename.split(".").pop()?.toLowerCase();
|
|
948
|
+
if ([
|
|
949
|
+
"js",
|
|
950
|
+
"ts",
|
|
951
|
+
"jsx",
|
|
952
|
+
"tsx",
|
|
953
|
+
"py",
|
|
954
|
+
"rb",
|
|
955
|
+
"go",
|
|
956
|
+
"rs",
|
|
957
|
+
"java",
|
|
958
|
+
"kt",
|
|
959
|
+
"swift",
|
|
960
|
+
"c",
|
|
961
|
+
"cpp",
|
|
962
|
+
"h",
|
|
963
|
+
"hpp",
|
|
964
|
+
"cs",
|
|
965
|
+
"php"
|
|
966
|
+
].includes(ext || "")) return "code";
|
|
967
|
+
if ([
|
|
968
|
+
"json",
|
|
969
|
+
"yaml",
|
|
970
|
+
"yml",
|
|
971
|
+
"xml"
|
|
972
|
+
].includes(ext || "")) return "data";
|
|
973
|
+
return "text";
|
|
905
974
|
}
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
if (date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate()) return timeFormatter.format(date);
|
|
918
|
-
return dateFormatter.format(date);
|
|
975
|
+
function renderFileIcon(iconName) {
|
|
976
|
+
switch (iconName) {
|
|
977
|
+
case "image":
|
|
978
|
+
return /* @__PURE__ */ jsx(Image, { className: "size-4 text-muted-foreground" });
|
|
979
|
+
case "code":
|
|
980
|
+
return /* @__PURE__ */ jsx(FileCode, { className: "size-4 text-muted-foreground" });
|
|
981
|
+
case "data":
|
|
982
|
+
return /* @__PURE__ */ jsx(FileBraces, { className: "size-4 text-muted-foreground" });
|
|
983
|
+
default:
|
|
984
|
+
return /* @__PURE__ */ jsx(FileText, { className: "size-4 text-muted-foreground" });
|
|
985
|
+
}
|
|
919
986
|
}
|
|
920
|
-
function
|
|
921
|
-
const [
|
|
922
|
-
const
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
try {
|
|
930
|
-
await navigator.clipboard.writeText(text);
|
|
931
|
-
setCopied(true);
|
|
932
|
-
if (copiedTimerRef.current) window.clearTimeout(copiedTimerRef.current);
|
|
933
|
-
copiedTimerRef.current = window.setTimeout(() => {
|
|
934
|
-
setCopied(false);
|
|
935
|
-
copiedTimerRef.current = null;
|
|
936
|
-
}, 2e3);
|
|
937
|
-
notify.success("Copied to clipboard");
|
|
938
|
-
onCopied?.();
|
|
939
|
-
} catch {
|
|
940
|
-
notify.error("Failed to copy to clipboard");
|
|
941
|
-
}
|
|
987
|
+
function FileAttachment({ id, filename, size, isImage, url, onRemove, className, display = "chip", enableImagePreview = true }) {
|
|
988
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
989
|
+
const [isLightboxOpen, setIsLightboxOpen] = useState(false);
|
|
990
|
+
const iconName = getFileIconName(filename, isImage);
|
|
991
|
+
const isImageOnly = display === "image-only" && isImage && !!url;
|
|
992
|
+
const canPreview = Boolean(enableImagePreview && isImage && url);
|
|
993
|
+
const openLightbox = (event) => {
|
|
994
|
+
event?.stopPropagation();
|
|
995
|
+
setIsLightboxOpen(true);
|
|
942
996
|
};
|
|
943
|
-
return /* @__PURE__ */ jsx("button", {
|
|
944
|
-
type: "button",
|
|
945
|
-
tabIndex: -1,
|
|
946
|
-
"aria-label": copied ? "Copied" : "Copy message",
|
|
947
|
-
onClick: handleCopy,
|
|
948
|
-
onPointerDown: (event) => {
|
|
949
|
-
event.stopPropagation();
|
|
950
|
-
},
|
|
951
|
-
onMouseDown: (event) => event.stopPropagation(),
|
|
952
|
-
className: cn("flex size-6 items-center justify-center rounded-md transition-[background-color,opacity,transform] duration-150 ease-out active:scale-[0.97]", "bg-transparent opacity-50 hover:bg-an-foreground/10 hover:opacity-100"),
|
|
953
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
954
|
-
className: "relative h-3.5 w-3.5",
|
|
955
|
-
children: [/* @__PURE__ */ jsx(Copy, { className: cn("absolute inset-0 h-3.5 w-3.5 text-an-foreground-muted transition-[opacity,transform] duration-150 ease-out", copied ? "scale-50 opacity-0" : "scale-100 opacity-100") }), /* @__PURE__ */ jsx(Check, { className: cn("absolute inset-0 h-3.5 w-3.5 text-an-foreground-muted transition-[opacity,transform] duration-150 ease-out", copied ? "scale-100 opacity-100" : "scale-50 opacity-0") })]
|
|
956
|
-
})
|
|
957
|
-
});
|
|
958
|
-
}
|
|
959
|
-
function MessageToolbar({ text, timestamp, heightClass, hoverClass, isVisible, alignClass, onCopied }) {
|
|
960
997
|
return /* @__PURE__ */ jsxs("div", {
|
|
961
|
-
className: cn("
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
children: [
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
998
|
+
className: cn("relative rounded-[calc(var(--an-input-border-radius)-var(--an-context-padding))] bg-muted/50", isImageOnly ? "flex size-10 items-center justify-center" : "flex max-w-[200px] min-w-[120px] items-center gap-2 py-1 pr-2 pl-1", className),
|
|
999
|
+
onMouseEnter: () => setIsHovered(true),
|
|
1000
|
+
onMouseLeave: () => setIsHovered(false),
|
|
1001
|
+
children: [
|
|
1002
|
+
isImageOnly ? /* @__PURE__ */ jsx("div", {
|
|
1003
|
+
className: cn("size-8 shrink-0 overflow-hidden rounded-[calc(var(--an-input-border-radius)-var(--an-context-padding)-2px)]", canPreview && "cursor-pointer"),
|
|
1004
|
+
onClick: canPreview ? openLightbox : void 0,
|
|
1005
|
+
role: canPreview ? "button" : void 0,
|
|
1006
|
+
tabIndex: canPreview ? 0 : void 0,
|
|
1007
|
+
"aria-label": canPreview ? `Preview ${filename}` : void 0,
|
|
1008
|
+
onKeyDown: canPreview ? (event) => {
|
|
1009
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1010
|
+
event.preventDefault();
|
|
1011
|
+
openLightbox();
|
|
1012
|
+
}
|
|
1013
|
+
} : void 0,
|
|
1014
|
+
children: /* @__PURE__ */ jsx("img", {
|
|
1015
|
+
src: url,
|
|
1016
|
+
alt: filename,
|
|
1017
|
+
className: "h-full w-full object-cover"
|
|
1018
|
+
})
|
|
1019
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [isImage && url ? /* @__PURE__ */ jsx("div", {
|
|
1020
|
+
className: cn("w-8 shrink-0 self-stretch overflow-hidden rounded-[calc(var(--an-input-border-radius)-var(--an-context-padding)-2px)]", canPreview && "cursor-pointer"),
|
|
1021
|
+
onClick: canPreview ? openLightbox : void 0,
|
|
1022
|
+
role: canPreview ? "button" : void 0,
|
|
1023
|
+
tabIndex: canPreview ? 0 : void 0,
|
|
1024
|
+
"aria-label": canPreview ? `Preview ${filename}` : void 0,
|
|
1025
|
+
onKeyDown: canPreview ? (event) => {
|
|
1026
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1027
|
+
event.preventDefault();
|
|
1028
|
+
openLightbox();
|
|
1029
|
+
}
|
|
1030
|
+
} : void 0,
|
|
1031
|
+
children: /* @__PURE__ */ jsx("img", {
|
|
1032
|
+
src: url,
|
|
1033
|
+
alt: filename,
|
|
1034
|
+
className: "aspect-square h-full w-full object-cover"
|
|
1035
|
+
})
|
|
1036
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
1037
|
+
className: "flex w-8 shrink-0 items-center justify-center self-stretch rounded-[calc(var(--an-input-border-radius)-var(--an-context-padding)-2px)] bg-muted",
|
|
1038
|
+
children: renderFileIcon(iconName)
|
|
1039
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1040
|
+
className: "flex min-w-0 flex-col",
|
|
1041
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1042
|
+
className: "truncate text-sm font-medium text-foreground",
|
|
1043
|
+
title: filename,
|
|
1044
|
+
children: filename
|
|
1045
|
+
}), size !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
1046
|
+
className: "text-[10px] text-muted-foreground",
|
|
1047
|
+
children: formatFileSize(size)
|
|
1048
|
+
})]
|
|
1049
|
+
})] }),
|
|
1050
|
+
onRemove && /* @__PURE__ */ jsx("button", {
|
|
1051
|
+
onClick: (e) => {
|
|
1052
|
+
e.stopPropagation();
|
|
1053
|
+
onRemove();
|
|
1054
|
+
},
|
|
1055
|
+
"aria-label": `Remove ${filename}`,
|
|
1056
|
+
className: `absolute -top-1.5 -right-1.5 z-10 flex size-4 items-center justify-center rounded-full border border-border bg-background text-muted-foreground transition-[opacity,transform] duration-150 ease-out hover:text-foreground active:scale-[0.97] ${isHovered ? "opacity-100" : "opacity-0"}`,
|
|
1057
|
+
type: "button",
|
|
1058
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-3" })
|
|
1059
|
+
}),
|
|
1060
|
+
canPreview && url && /* @__PURE__ */ jsx(ImageLightbox, {
|
|
1061
|
+
open: isLightboxOpen,
|
|
1062
|
+
onClose: () => setIsLightboxOpen(false),
|
|
1063
|
+
images: [{
|
|
1064
|
+
id,
|
|
1065
|
+
url,
|
|
1066
|
+
filename
|
|
1067
|
+
}]
|
|
1068
|
+
})
|
|
1069
|
+
]
|
|
968
1070
|
});
|
|
969
1071
|
}
|
|
970
|
-
function isRecord$
|
|
1072
|
+
function isRecord$2(value) {
|
|
971
1073
|
return typeof value === "object" && value !== null;
|
|
972
1074
|
}
|
|
973
1075
|
function isTextPart(part) {
|
|
974
|
-
return isRecord$
|
|
1076
|
+
return isRecord$2(part) && part.type === "text" && typeof part.text === "string";
|
|
975
1077
|
}
|
|
976
1078
|
function isErrorPart(part) {
|
|
977
|
-
return isRecord$
|
|
1079
|
+
return isRecord$2(part) && part.type === "error" && typeof part.message === "string";
|
|
978
1080
|
}
|
|
979
1081
|
function isPayloadPart(part) {
|
|
980
|
-
return isRecord$
|
|
1082
|
+
return isRecord$2(part) && part.type === "payload" && typeof part.kind === "string" && typeof part.title === "string";
|
|
981
1083
|
}
|
|
982
1084
|
function isV5ToolPart(part) {
|
|
983
|
-
if (!isRecord$
|
|
1085
|
+
if (!isRecord$2(part)) return false;
|
|
984
1086
|
const partType = part.type;
|
|
985
1087
|
return partType === "dynamic-tool" || typeof partType === "string" && partType.startsWith("tool-");
|
|
986
1088
|
}
|
|
@@ -989,564 +1091,449 @@ function getTextFromParts(parts, joiner) {
|
|
|
989
1091
|
for (const part of parts) if (isTextPart(part)) texts.push(part.text);
|
|
990
1092
|
return texts.join(joiner);
|
|
991
1093
|
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
const { enableImagePreview, showCopyToolbar, isMounted, isCopyVisible } = display;
|
|
995
|
-
const text = getTextFromParts(message.parts ?? [], "");
|
|
996
|
-
const hasParts = (message.parts ?? []).length > 0;
|
|
997
|
-
if (!text && !hasParts) return null;
|
|
998
|
-
const userCreatedAt = message?.createdAt;
|
|
999
|
-
const userCopyKey = `user-${message.id}`;
|
|
1000
|
-
const userTimestamp = isMounted && userCreatedAt ? formatTimestamp(new Date(userCreatedAt)) : void 0;
|
|
1001
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
1002
|
-
className: "group/user-message",
|
|
1003
|
-
children: [/* @__PURE__ */ jsx(UserMessageComponent, {
|
|
1004
|
-
message,
|
|
1005
|
-
className: userMessageClassName,
|
|
1006
|
-
enableImagePreview
|
|
1007
|
-
}), (showCopyToolbar && Boolean(text) || Boolean(userTimestamp)) && /* @__PURE__ */ jsx(MessageToolbar, {
|
|
1008
|
-
text: showCopyToolbar ? text : "",
|
|
1009
|
-
timestamp: userTimestamp,
|
|
1010
|
-
heightClass: "h-[28px]",
|
|
1011
|
-
hoverClass: "group-hover/user-message:opacity-100 group-hover/user-message:pointer-events-auto",
|
|
1012
|
-
isVisible: isCopyVisible,
|
|
1013
|
-
alignClass: "justify-end",
|
|
1014
|
-
onCopied: () => onCopied(userCopyKey)
|
|
1015
|
-
})]
|
|
1016
|
-
});
|
|
1017
|
-
});
|
|
1018
|
-
memo(function AssistantTurn(props) {
|
|
1019
|
-
const { assistantMsgs, turnKey, ToolRendererComponent, TextRendererComponent, toolRenderers, onOpenUIAction, onOpenUIArtifactReady, onOpenArtifact, onCopied, stream, copy, display } = props;
|
|
1020
|
-
const { isLast: isLastTurn, isStreaming } = stream;
|
|
1021
|
-
const { enabled: showCopyToolbar, isVisible: isCopyVisible } = copy;
|
|
1022
|
-
const { suppressQuestionTool } = display;
|
|
1023
|
-
const assistantText = getTextFromParts(assistantMsgs.flatMap((msg) => msg.parts ?? []), "\n\n");
|
|
1024
|
-
const isTurnStreaming = isStreaming && isLastTurn;
|
|
1025
|
-
const showToolbar = showCopyToolbar && Boolean(assistantText.trim()) && !isTurnStreaming;
|
|
1026
|
-
const copyKey = `assistant-${turnKey}-all`;
|
|
1027
|
-
const toolbarText = showCopyToolbar ? assistantText : "";
|
|
1028
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
1029
|
-
className: "group/assistant-turn",
|
|
1030
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
1031
|
-
className: "flex flex-col gap-3",
|
|
1032
|
-
children: assistantMsgs.map((msg, i) => {
|
|
1033
|
-
const isLastMsg = isLastTurn && i === assistantMsgs.length - 1;
|
|
1034
|
-
return /* @__PURE__ */ jsx(AssistantParts, {
|
|
1035
|
-
msg,
|
|
1036
|
-
isLast: isLastMsg,
|
|
1037
|
-
isStreaming,
|
|
1038
|
-
suppressQuestionTool,
|
|
1039
|
-
ToolRendererComponent,
|
|
1040
|
-
TextRendererComponent,
|
|
1041
|
-
toolRenderers,
|
|
1042
|
-
onOpenUIAction,
|
|
1043
|
-
onOpenUIArtifactReady,
|
|
1044
|
-
onOpenArtifact
|
|
1045
|
-
}, msg.id);
|
|
1046
|
-
})
|
|
1047
|
-
}), (showToolbar || isCopyVisible) && /* @__PURE__ */ jsx(MessageToolbar, {
|
|
1048
|
-
text: toolbarText,
|
|
1049
|
-
heightClass: "h-[48px] flex items-start w-full",
|
|
1050
|
-
hoverClass: "group-hover/assistant-turn:opacity-100 group-hover/assistant-turn:pointer-events-auto",
|
|
1051
|
-
isVisible: isCopyVisible,
|
|
1052
|
-
alignClass: "justify-start",
|
|
1053
|
-
onCopied: () => onCopied(copyKey)
|
|
1054
|
-
})]
|
|
1055
|
-
});
|
|
1056
|
-
});
|
|
1057
|
-
var TOOL_CALL_KEY_PREFIX = "tool-call:";
|
|
1058
|
-
var UNKEYED_TOOL_KEY_PREFIX = "unkeyed-tool:";
|
|
1059
|
-
function getAssistantToolElementKey(messageId, part, occurrence) {
|
|
1060
|
-
if (part.toolCallId) return `${TOOL_CALL_KEY_PREFIX}${part.toolCallId}`;
|
|
1061
|
-
return `${UNKEYED_TOOL_KEY_PREFIX}${messageId}:${part.type}:${occurrence}`;
|
|
1094
|
+
function isRecord$1(value) {
|
|
1095
|
+
return typeof value === "object" && value !== null;
|
|
1062
1096
|
}
|
|
1063
|
-
function
|
|
1064
|
-
|
|
1065
|
-
const
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
const nestedToolIds = /* @__PURE__ */ new Set();
|
|
1071
|
-
const unkeyedToolOccurrences = /* @__PURE__ */ new Map();
|
|
1072
|
-
for (const part of parts) {
|
|
1073
|
-
if (!isV5ToolPart(part)) continue;
|
|
1074
|
-
if (part.type === "tool-TaskOutput") continue;
|
|
1075
|
-
if (!part.toolCallId || !part.toolCallId.includes(":")) continue;
|
|
1076
|
-
const parentId = part.toolCallId.split(":")[0];
|
|
1077
|
-
if (!taskPartIds.has(parentId)) continue;
|
|
1078
|
-
if (!nestedToolsMap.has(parentId)) nestedToolsMap.set(parentId, []);
|
|
1079
|
-
nestedToolsMap.get(parentId).push(part);
|
|
1080
|
-
nestedToolIds.add(part.toolCallId);
|
|
1097
|
+
function getImageUrlFromPart(part) {
|
|
1098
|
+
if (!isRecord$1(part)) return null;
|
|
1099
|
+
const type = part.type;
|
|
1100
|
+
if (typeof type !== "string") return null;
|
|
1101
|
+
if (type === "image") {
|
|
1102
|
+
const imagePart = part;
|
|
1103
|
+
return imagePart.url ?? imagePart.image ?? null;
|
|
1081
1104
|
}
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
const
|
|
1085
|
-
if (
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
}
|
|
1089
|
-
if (isTextPart(part)) {
|
|
1090
|
-
const text2 = part.text;
|
|
1091
|
-
if (text2 && !hasPlanWritePresentation) textChunks.push(text2);
|
|
1092
|
-
i++;
|
|
1093
|
-
continue;
|
|
1094
|
-
}
|
|
1095
|
-
if (isErrorPart(part)) {
|
|
1096
|
-
elems.push(/* @__PURE__ */ jsx(ErrorMessage, {
|
|
1097
|
-
title: part.title,
|
|
1098
|
-
message: part.message
|
|
1099
|
-
}, `${messageId}-error-${part.title}-${part.message}`));
|
|
1100
|
-
i++;
|
|
1101
|
-
continue;
|
|
1102
|
-
}
|
|
1103
|
-
if (isPayloadPart(part)) {
|
|
1104
|
-
elems.push(/* @__PURE__ */ jsx(PayloadPart, { part }, `${messageId}-payload-${i}`));
|
|
1105
|
-
i++;
|
|
1106
|
-
continue;
|
|
1105
|
+
if (type === "data-image") return part.data?.url ?? null;
|
|
1106
|
+
if (type === "file") {
|
|
1107
|
+
const filePart = part;
|
|
1108
|
+
if (filePart.mimeType?.startsWith("image/")) {
|
|
1109
|
+
if (filePart.url) return filePart.url;
|
|
1110
|
+
if (filePart.data) return `data:${filePart.mimeType};base64,${filePart.data}`;
|
|
1107
1111
|
}
|
|
1108
|
-
if (isV5ToolPart(part)) {
|
|
1109
|
-
if (suppressQuestionTool && part.type === "tool-Question") {
|
|
1110
|
-
i++;
|
|
1111
|
-
continue;
|
|
1112
|
-
}
|
|
1113
|
-
if (part.toolCallId && nestedToolIds.has(part.toolCallId)) {
|
|
1114
|
-
i++;
|
|
1115
|
-
continue;
|
|
1116
|
-
}
|
|
1117
|
-
const chatStreamingStatus = isLast && isStreaming ? "streaming" : void 0;
|
|
1118
|
-
const toolCallId = part.toolCallId;
|
|
1119
|
-
const nestedTools = (part.type === "tool-Task" || part.type === "tool-Agent") && toolCallId ? nestedToolsMap.get(toolCallId) || [] : void 0;
|
|
1120
|
-
const occurrence = part.toolCallId ? 0 : unkeyedToolOccurrences.get(part.type) ?? 0;
|
|
1121
|
-
if (!part.toolCallId) unkeyedToolOccurrences.set(part.type, occurrence + 1);
|
|
1122
|
-
elems.push(/* @__PURE__ */ jsx(ToolRendererComponent, {
|
|
1123
|
-
part,
|
|
1124
|
-
nestedTools,
|
|
1125
|
-
chatStatus: chatStreamingStatus,
|
|
1126
|
-
toolRenderers
|
|
1127
|
-
}, getAssistantToolElementKey(messageId, part, occurrence)));
|
|
1128
|
-
i++;
|
|
1129
|
-
continue;
|
|
1130
|
-
}
|
|
1131
|
-
i++;
|
|
1132
1112
|
}
|
|
1133
|
-
|
|
1134
|
-
if (text) elems.push(/* @__PURE__ */ jsx("div", {
|
|
1135
|
-
className: "group/assistant-text text-[14px]",
|
|
1136
|
-
children: /* @__PURE__ */ jsx(TextRendererComponent, {
|
|
1137
|
-
content: text,
|
|
1138
|
-
isStreaming,
|
|
1139
|
-
messageId,
|
|
1140
|
-
onOpenUIAction,
|
|
1141
|
-
onOpenUIArtifactReady,
|
|
1142
|
-
onOpenArtifact,
|
|
1143
|
-
className: "leading-relaxed [&_p]:leading-relaxed"
|
|
1144
|
-
})
|
|
1145
|
-
}, `${messageId}-text-final`));
|
|
1146
|
-
return elems;
|
|
1113
|
+
return null;
|
|
1147
1114
|
}
|
|
1148
|
-
function
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
onOpenUIAction,
|
|
1159
|
-
onOpenUIArtifactReady,
|
|
1160
|
-
onOpenArtifact
|
|
1161
|
-
}), [
|
|
1162
|
-
parts,
|
|
1163
|
-
msg.id,
|
|
1164
|
-
isLast,
|
|
1165
|
-
isStreaming,
|
|
1166
|
-
suppressQuestionTool,
|
|
1167
|
-
ToolRendererComponent,
|
|
1168
|
-
TextRendererComponent,
|
|
1169
|
-
toolRenderers,
|
|
1170
|
-
onOpenUIAction,
|
|
1171
|
-
onOpenUIArtifactReady,
|
|
1172
|
-
onOpenArtifact
|
|
1173
|
-
]);
|
|
1174
|
-
if (elements.length > 1) return /* @__PURE__ */ jsx("div", {
|
|
1175
|
-
className: "group/assistant-turn flex flex-col gap-3",
|
|
1176
|
-
children: elements
|
|
1177
|
-
});
|
|
1178
|
-
return /* @__PURE__ */ jsx("div", {
|
|
1179
|
-
className: "group/assistant-turn",
|
|
1180
|
-
children: elements
|
|
1181
|
-
});
|
|
1115
|
+
function getFileFromPart(part) {
|
|
1116
|
+
if (!isRecord$1(part)) return null;
|
|
1117
|
+
if (part.type !== "file") return null;
|
|
1118
|
+
const filePart = part;
|
|
1119
|
+
const filename = filePart.filename || filePart.name || filePart.fileName || "Attachment";
|
|
1120
|
+
if (filePart.mimeType?.startsWith("image/") ?? false) return null;
|
|
1121
|
+
return {
|
|
1122
|
+
filename,
|
|
1123
|
+
size: filePart.size
|
|
1124
|
+
};
|
|
1182
1125
|
}
|
|
1183
|
-
function
|
|
1184
|
-
const [
|
|
1185
|
-
const
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
}
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
if (hasMultipleImages) goToNext();
|
|
1206
|
-
}
|
|
1207
|
-
});
|
|
1208
|
-
useEffect(() => {
|
|
1209
|
-
if (!open) return;
|
|
1210
|
-
const handler = (event) => onLightboxKeyDown(event);
|
|
1211
|
-
window.addEventListener("keydown", handler, true);
|
|
1212
|
-
return () => window.removeEventListener("keydown", handler, true);
|
|
1213
|
-
}, [open]);
|
|
1214
|
-
useEffect(() => {
|
|
1215
|
-
if (!open) return;
|
|
1216
|
-
const previousOverflow = document.body.style.overflow;
|
|
1217
|
-
document.body.style.overflow = "hidden";
|
|
1218
|
-
return () => {
|
|
1219
|
-
document.body.style.overflow = previousOverflow;
|
|
1220
|
-
};
|
|
1221
|
-
}, [open]);
|
|
1222
|
-
const dialogRef = useRef(null);
|
|
1223
|
-
const onLightDismiss = useEffectEvent((event) => {
|
|
1224
|
-
if (dialogRef.current && event.target === dialogRef.current) onClose();
|
|
1225
|
-
});
|
|
1226
|
-
useEffect(() => {
|
|
1227
|
-
if (!open) return;
|
|
1228
|
-
const dialog = dialogRef.current;
|
|
1229
|
-
if (!dialog) return;
|
|
1230
|
-
if (!dialog.open) dialog.showModal();
|
|
1231
|
-
const handler = (event) => onLightDismiss(event);
|
|
1232
|
-
dialog.addEventListener("click", handler);
|
|
1233
|
-
return () => {
|
|
1234
|
-
dialog.removeEventListener("click", handler);
|
|
1235
|
-
if (dialog.open) dialog.close();
|
|
1236
|
-
};
|
|
1237
|
-
}, [open]);
|
|
1238
|
-
if (typeof document === "undefined") return null;
|
|
1239
|
-
if (!open) return null;
|
|
1240
|
-
const currentImage = images[currentIndex] ?? images[0];
|
|
1241
|
-
if (!currentImage?.url) return null;
|
|
1242
|
-
return createPortal(/* @__PURE__ */ jsxs("dialog", {
|
|
1243
|
-
ref: dialogRef,
|
|
1244
|
-
"aria-label": "Image viewer",
|
|
1245
|
-
onClose: () => onClose(),
|
|
1246
|
-
className: "fixed inset-0 z-50 m-0 flex h-full max-h-none w-full max-w-none items-center justify-center border-0 bg-black/90 p-0 backdrop:bg-transparent",
|
|
1126
|
+
var UserMessage = memo(function UserMessage2({ message, className, enableImagePreview = true }) {
|
|
1127
|
+
const [lightboxIndex, setLightboxIndex] = useState(null);
|
|
1128
|
+
const text = (message.parts?.filter(isTextPart) ?? []).map((p) => p.text).join("");
|
|
1129
|
+
const images = [];
|
|
1130
|
+
const files = [];
|
|
1131
|
+
for (const part of message.parts ?? []) {
|
|
1132
|
+
const imageUrl = getImageUrlFromPart(part);
|
|
1133
|
+
if (imageUrl) images.push(imageUrl);
|
|
1134
|
+
const file = getFileFromPart(part);
|
|
1135
|
+
if (file) files.push(file);
|
|
1136
|
+
}
|
|
1137
|
+
if (isRecord$1(message) && Array.isArray(message.experimental_attachments)) {
|
|
1138
|
+
for (const att of message.experimental_attachments) if (att.contentType?.startsWith("image/") && att.url) images.push(att.url);
|
|
1139
|
+
}
|
|
1140
|
+
if (!text && images.length === 0 && files.length === 0) return null;
|
|
1141
|
+
const lightboxImages = images.map((url, i) => ({
|
|
1142
|
+
id: `${message.id}-img-${i}`,
|
|
1143
|
+
url,
|
|
1144
|
+
filename: `image-${i + 1}`
|
|
1145
|
+
}));
|
|
1146
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1147
|
+
className: cn("flex flex-col items-end gap-1", className),
|
|
1247
1148
|
children: [
|
|
1248
|
-
/* @__PURE__ */ jsx("
|
|
1249
|
-
|
|
1250
|
-
onClick:
|
|
1251
|
-
"
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1149
|
+
images.length > 0 && images.map((url, i) => /* @__PURE__ */ jsx("div", {
|
|
1150
|
+
className: cn("max-w-[200px] rounded-an-message bg-an-foreground/4 p-1.5", enableImagePreview && "cursor-pointer"),
|
|
1151
|
+
onClick: enableImagePreview ? () => setLightboxIndex(i) : void 0,
|
|
1152
|
+
role: enableImagePreview ? "button" : void 0,
|
|
1153
|
+
tabIndex: enableImagePreview ? 0 : void 0,
|
|
1154
|
+
onKeyDown: enableImagePreview ? (event) => {
|
|
1155
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1156
|
+
event.preventDefault();
|
|
1157
|
+
setLightboxIndex(i);
|
|
1158
|
+
}
|
|
1159
|
+
} : void 0,
|
|
1160
|
+
children: /* @__PURE__ */ jsx("img", {
|
|
1161
|
+
src: url,
|
|
1162
|
+
alt: "attachment",
|
|
1163
|
+
className: "block max-h-[120px] max-w-[184px] rounded-an-message-inner object-cover"
|
|
1164
|
+
})
|
|
1165
|
+
}, url)),
|
|
1166
|
+
enableImagePreview && lightboxImages.length > 0 && /* @__PURE__ */ jsx(ImageLightbox, {
|
|
1167
|
+
open: lightboxIndex !== null,
|
|
1168
|
+
onClose: () => setLightboxIndex(null),
|
|
1169
|
+
images: lightboxImages,
|
|
1170
|
+
initialIndex: lightboxIndex ?? 0
|
|
1268
1171
|
}),
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1172
|
+
files.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
1173
|
+
className: "flex flex-col items-end gap-2",
|
|
1174
|
+
children: files.map((file, i) => /* @__PURE__ */ jsx(FileAttachment, {
|
|
1175
|
+
id: `${file.filename}-${i}`,
|
|
1176
|
+
filename: file.filename,
|
|
1177
|
+
size: file.size
|
|
1178
|
+
}, `${file.filename}-${file.size}`))
|
|
1275
1179
|
}),
|
|
1276
|
-
|
|
1277
|
-
className: "
|
|
1278
|
-
children:
|
|
1279
|
-
className: "
|
|
1280
|
-
children:
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
},
|
|
1286
|
-
"aria-label": `Go to image ${idx + 1}`,
|
|
1287
|
-
className: cn("size-2 rounded-full transition-all", idx === currentIndex ? "scale-125 bg-white" : "bg-white/40 hover:bg-white/60")
|
|
1288
|
-
}, image.url))
|
|
1289
|
-
}), /* @__PURE__ */ jsxs("span", {
|
|
1290
|
-
className: "text-sm text-white/70",
|
|
1291
|
-
children: [
|
|
1292
|
-
currentIndex + 1,
|
|
1293
|
-
" / ",
|
|
1294
|
-
images.length
|
|
1295
|
-
]
|
|
1296
|
-
})]
|
|
1180
|
+
text && /* @__PURE__ */ jsx("div", {
|
|
1181
|
+
className: "ms-[70px] max-w-[calc(95%-40px)]",
|
|
1182
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1183
|
+
className: "rounded-an-message bg-an-user-message-bg px-3.5 py-1.5 text-sm text-an-user-message-text transition-colors",
|
|
1184
|
+
children: /* @__PURE__ */ jsx("p", {
|
|
1185
|
+
className: "leading-5 wrap-break-word whitespace-pre-wrap",
|
|
1186
|
+
children: text
|
|
1187
|
+
})
|
|
1188
|
+
})
|
|
1297
1189
|
})
|
|
1298
1190
|
]
|
|
1299
|
-
})
|
|
1300
|
-
}
|
|
1301
|
-
function
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
"
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
"hpp",
|
|
1325
|
-
"cs",
|
|
1326
|
-
"php"
|
|
1327
|
-
].includes(ext || "")) return "code";
|
|
1328
|
-
if ([
|
|
1329
|
-
"json",
|
|
1330
|
-
"yaml",
|
|
1331
|
-
"yml",
|
|
1332
|
-
"xml"
|
|
1333
|
-
].includes(ext || "")) return "data";
|
|
1334
|
-
return "text";
|
|
1191
|
+
});
|
|
1192
|
+
});
|
|
1193
|
+
var ErrorMessage = memo(function ErrorMessage2({ title = "Something went wrong", message, className }) {
|
|
1194
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1195
|
+
className: cn("flex justify-start", className),
|
|
1196
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1197
|
+
className: "rounded-[8px] border border-red-500/30 bg-red-500/10 px-4 py-2.5 text-sm text-an-foreground",
|
|
1198
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1199
|
+
className: "font-medium text-an-foreground",
|
|
1200
|
+
children: title
|
|
1201
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1202
|
+
className: "mt-0.5 text-an-foreground-muted",
|
|
1203
|
+
children: message
|
|
1204
|
+
})]
|
|
1205
|
+
})
|
|
1206
|
+
});
|
|
1207
|
+
});
|
|
1208
|
+
function formatPayload(value) {
|
|
1209
|
+
if (typeof value === "string") return value;
|
|
1210
|
+
if (value === void 0) return "";
|
|
1211
|
+
try {
|
|
1212
|
+
return JSON.stringify(value, null, 2) ?? "";
|
|
1213
|
+
} catch {
|
|
1214
|
+
return String(value);
|
|
1215
|
+
}
|
|
1335
1216
|
}
|
|
1336
|
-
function
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1217
|
+
function PayloadPart({ part }) {
|
|
1218
|
+
const payload = formatPayload(part.payload);
|
|
1219
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
1220
|
+
"data-payload-kind": part.kind,
|
|
1221
|
+
className: "w-full min-w-0 overflow-hidden rounded-xl border border-border/60 bg-muted/40 text-sm",
|
|
1222
|
+
children: [
|
|
1223
|
+
/* @__PURE__ */ jsx("div", {
|
|
1224
|
+
className: "border-b border-border/50 px-3 py-2 text-xs font-medium text-muted-foreground",
|
|
1225
|
+
children: part.title
|
|
1226
|
+
}),
|
|
1227
|
+
part.text ? /* @__PURE__ */ jsx("pre", {
|
|
1228
|
+
className: "m-0 whitespace-pre-wrap break-words px-3 py-3 font-mono text-xs leading-5 text-foreground/80",
|
|
1229
|
+
children: part.text
|
|
1230
|
+
}) : null,
|
|
1231
|
+
payload ? /* @__PURE__ */ jsxs("details", {
|
|
1232
|
+
open: true,
|
|
1233
|
+
className: "border-t border-border/50 px-3 py-2",
|
|
1234
|
+
children: [/* @__PURE__ */ jsx("summary", {
|
|
1235
|
+
className: "cursor-pointer text-xs font-medium text-muted-foreground",
|
|
1236
|
+
children: "Payload"
|
|
1237
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
1238
|
+
className: "m-0 mt-2 max-w-full whitespace-pre-wrap break-words font-mono text-xs leading-5 text-foreground/70",
|
|
1239
|
+
children: payload
|
|
1240
|
+
})]
|
|
1241
|
+
}) : null
|
|
1242
|
+
]
|
|
1243
|
+
});
|
|
1244
|
+
}
|
|
1245
|
+
function isRecord(value) {
|
|
1246
|
+
return typeof value === "object" && value !== null;
|
|
1247
|
+
}
|
|
1248
|
+
function parseStructuredJson(value) {
|
|
1249
|
+
if (typeof value !== "string") return value;
|
|
1250
|
+
const trimmed = value.trim();
|
|
1251
|
+
if (!trimmed) return value;
|
|
1252
|
+
try {
|
|
1253
|
+
const parsed = JSON.parse(trimmed);
|
|
1254
|
+
return isRecord(parsed) || Array.isArray(parsed) ? parsed : value;
|
|
1255
|
+
} catch {
|
|
1256
|
+
return value;
|
|
1346
1257
|
}
|
|
1347
1258
|
}
|
|
1348
|
-
function
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
const
|
|
1352
|
-
const
|
|
1353
|
-
const
|
|
1354
|
-
const
|
|
1355
|
-
|
|
1356
|
-
|
|
1259
|
+
function normalizeToolPart(part) {
|
|
1260
|
+
if (!isRecord(part)) return part;
|
|
1261
|
+
if (typeof part.type !== "string" || !part.type.startsWith("tool-")) return part;
|
|
1262
|
+
const normalizedInput = parseStructuredJson(part.input);
|
|
1263
|
+
const normalizedOutput = parseStructuredJson(part.output);
|
|
1264
|
+
const normalizedResult = parseStructuredJson(part.result);
|
|
1265
|
+
const inputChanged = normalizedInput !== part.input;
|
|
1266
|
+
const outputChanged = normalizedOutput !== part.output;
|
|
1267
|
+
const resultChanged = normalizedResult !== part.result;
|
|
1268
|
+
if (!inputChanged && !outputChanged && !resultChanged) return part;
|
|
1269
|
+
const normalizedPart = { ...part };
|
|
1270
|
+
if (inputChanged) normalizedPart.input = normalizedInput;
|
|
1271
|
+
if (outputChanged) normalizedPart.output = normalizedOutput;
|
|
1272
|
+
if (resultChanged) normalizedPart.result = normalizedResult;
|
|
1273
|
+
return normalizedPart;
|
|
1274
|
+
}
|
|
1275
|
+
function normalizeAssistantToolParts(parts) {
|
|
1276
|
+
let changed = false;
|
|
1277
|
+
const normalizedParts = parts.map((part) => {
|
|
1278
|
+
const normalizedPart = normalizeToolPart(part);
|
|
1279
|
+
if (normalizedPart !== part) changed = true;
|
|
1280
|
+
return normalizedPart;
|
|
1281
|
+
});
|
|
1282
|
+
return changed ? normalizedParts : parts;
|
|
1283
|
+
}
|
|
1284
|
+
var timeFormatter = new Intl.DateTimeFormat("en-US", {
|
|
1285
|
+
hour: "numeric",
|
|
1286
|
+
minute: "2-digit",
|
|
1287
|
+
hour12: true
|
|
1288
|
+
});
|
|
1289
|
+
var dateFormatter = new Intl.DateTimeFormat("en-US", {
|
|
1290
|
+
month: "short",
|
|
1291
|
+
day: "numeric"
|
|
1292
|
+
});
|
|
1293
|
+
function formatTimestamp(date) {
|
|
1294
|
+
const now = /* @__PURE__ */ new Date();
|
|
1295
|
+
if (date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate()) return timeFormatter.format(date);
|
|
1296
|
+
return dateFormatter.format(date);
|
|
1297
|
+
}
|
|
1298
|
+
function CopyButton({ text, onCopied }) {
|
|
1299
|
+
const [copied, setCopied] = useState(false);
|
|
1300
|
+
const copiedTimerRef = useRef(null);
|
|
1301
|
+
useEffect(() => {
|
|
1302
|
+
return () => {
|
|
1303
|
+
if (copiedTimerRef.current) window.clearTimeout(copiedTimerRef.current);
|
|
1304
|
+
};
|
|
1305
|
+
}, []);
|
|
1306
|
+
const handleCopy = async () => {
|
|
1307
|
+
try {
|
|
1308
|
+
await navigator.clipboard.writeText(text);
|
|
1309
|
+
setCopied(true);
|
|
1310
|
+
if (copiedTimerRef.current) window.clearTimeout(copiedTimerRef.current);
|
|
1311
|
+
copiedTimerRef.current = window.setTimeout(() => {
|
|
1312
|
+
setCopied(false);
|
|
1313
|
+
copiedTimerRef.current = null;
|
|
1314
|
+
}, 2e3);
|
|
1315
|
+
notify.success("Copied to clipboard");
|
|
1316
|
+
onCopied?.();
|
|
1317
|
+
} catch {
|
|
1318
|
+
notify.error("Failed to copy to clipboard");
|
|
1319
|
+
}
|
|
1357
1320
|
};
|
|
1321
|
+
return /* @__PURE__ */ jsx("button", {
|
|
1322
|
+
type: "button",
|
|
1323
|
+
tabIndex: -1,
|
|
1324
|
+
"aria-label": copied ? "Copied" : "Copy message",
|
|
1325
|
+
onClick: handleCopy,
|
|
1326
|
+
onPointerDown: (event) => {
|
|
1327
|
+
event.stopPropagation();
|
|
1328
|
+
},
|
|
1329
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
1330
|
+
className: cn("flex size-6 items-center justify-center rounded-md transition-[background-color,opacity,transform] duration-150 ease-out active:scale-[0.97]", "bg-transparent opacity-50 hover:bg-an-foreground/10 hover:opacity-100"),
|
|
1331
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1332
|
+
className: "relative h-3.5 w-3.5",
|
|
1333
|
+
children: [/* @__PURE__ */ jsx(Copy, { className: cn("absolute inset-0 h-3.5 w-3.5 text-an-foreground-muted transition-[opacity,transform] duration-150 ease-out", copied ? "scale-50 opacity-0" : "scale-100 opacity-100") }), /* @__PURE__ */ jsx(Check, { className: cn("absolute inset-0 h-3.5 w-3.5 text-an-foreground-muted transition-[opacity,transform] duration-150 ease-out", copied ? "scale-100 opacity-100" : "scale-50 opacity-0") })]
|
|
1334
|
+
})
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
function MessageToolbar({ text, timestamp, heightClass, hoverClass, isVisible, alignClass, onCopied }) {
|
|
1358
1338
|
return /* @__PURE__ */ jsxs("div", {
|
|
1359
|
-
className: cn("
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
children: [
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
open: isLightboxOpen,
|
|
1423
|
-
onClose: () => setIsLightboxOpen(false),
|
|
1424
|
-
images: [{
|
|
1425
|
-
id,
|
|
1426
|
-
url,
|
|
1427
|
-
filename
|
|
1428
|
-
}]
|
|
1339
|
+
className: cn("pointer-events-none flex items-center gap-1 pt-1 text-xs text-an-foreground-muted/70 opacity-0 transition-opacity duration-100", heightClass, alignClass, hoverClass, isVisible && "pointer-events-auto opacity-100"),
|
|
1340
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
1341
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
1342
|
+
children: [timestamp && /* @__PURE__ */ jsx("span", { children: timestamp }), text && /* @__PURE__ */ jsx(CopyButton, {
|
|
1343
|
+
text,
|
|
1344
|
+
onCopied
|
|
1345
|
+
})]
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
memo(function UserTurn(props) {
|
|
1349
|
+
const { message, UserMessageComponent, userMessageClassName, onCopied, display } = props;
|
|
1350
|
+
const { enableImagePreview, showCopyToolbar, isMounted, isCopyVisible } = display;
|
|
1351
|
+
const text = getTextFromParts(message.parts ?? [], "");
|
|
1352
|
+
const hasParts = (message.parts ?? []).length > 0;
|
|
1353
|
+
if (!text && !hasParts) return null;
|
|
1354
|
+
const userCreatedAt = message?.createdAt;
|
|
1355
|
+
const userCopyKey = `user-${message.id}`;
|
|
1356
|
+
const userTimestamp = isMounted && userCreatedAt ? formatTimestamp(new Date(userCreatedAt)) : void 0;
|
|
1357
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1358
|
+
className: "group/user-message",
|
|
1359
|
+
children: [/* @__PURE__ */ jsx(UserMessageComponent, {
|
|
1360
|
+
message,
|
|
1361
|
+
className: userMessageClassName,
|
|
1362
|
+
enableImagePreview
|
|
1363
|
+
}), (showCopyToolbar && Boolean(text) || Boolean(userTimestamp)) && /* @__PURE__ */ jsx(MessageToolbar, {
|
|
1364
|
+
text: showCopyToolbar ? text : "",
|
|
1365
|
+
timestamp: userTimestamp,
|
|
1366
|
+
heightClass: "h-[28px]",
|
|
1367
|
+
hoverClass: "group-hover/user-message:opacity-100 group-hover/user-message:pointer-events-auto",
|
|
1368
|
+
isVisible: isCopyVisible,
|
|
1369
|
+
alignClass: "justify-end",
|
|
1370
|
+
onCopied: () => onCopied(userCopyKey)
|
|
1371
|
+
})]
|
|
1372
|
+
});
|
|
1373
|
+
});
|
|
1374
|
+
memo(function AssistantTurn(props) {
|
|
1375
|
+
const { assistantMsgs, turnKey, ToolRendererComponent, TextRendererComponent, toolRenderers, onOpenUIAction, onOpenUIArtifactReady, onOpenArtifact, onCopied, stream, copy, display } = props;
|
|
1376
|
+
const { isLast: isLastTurn, isStreaming } = stream;
|
|
1377
|
+
const { enabled: showCopyToolbar, isVisible: isCopyVisible } = copy;
|
|
1378
|
+
const { suppressQuestionTool } = display;
|
|
1379
|
+
const assistantText = getTextFromParts(assistantMsgs.flatMap((msg) => msg.parts ?? []), "\n\n");
|
|
1380
|
+
const isTurnStreaming = isStreaming && isLastTurn;
|
|
1381
|
+
const showToolbar = showCopyToolbar && Boolean(assistantText.trim()) && !isTurnStreaming;
|
|
1382
|
+
const copyKey = `assistant-${turnKey}-all`;
|
|
1383
|
+
const toolbarText = showCopyToolbar ? assistantText : "";
|
|
1384
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1385
|
+
className: "group/assistant-turn",
|
|
1386
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1387
|
+
className: "flex flex-col gap-3",
|
|
1388
|
+
children: assistantMsgs.map((msg, i) => {
|
|
1389
|
+
const isLastMsg = isLastTurn && i === assistantMsgs.length - 1;
|
|
1390
|
+
return /* @__PURE__ */ jsx(AssistantParts, {
|
|
1391
|
+
msg,
|
|
1392
|
+
isLast: isLastMsg,
|
|
1393
|
+
isStreaming,
|
|
1394
|
+
suppressQuestionTool,
|
|
1395
|
+
ToolRendererComponent,
|
|
1396
|
+
TextRendererComponent,
|
|
1397
|
+
toolRenderers,
|
|
1398
|
+
onOpenUIAction,
|
|
1399
|
+
onOpenUIArtifactReady,
|
|
1400
|
+
onOpenArtifact
|
|
1401
|
+
}, msg.id);
|
|
1429
1402
|
})
|
|
1430
|
-
|
|
1403
|
+
}), (showToolbar || isCopyVisible) && /* @__PURE__ */ jsx(MessageToolbar, {
|
|
1404
|
+
text: toolbarText,
|
|
1405
|
+
heightClass: "h-[48px] flex items-start w-full",
|
|
1406
|
+
hoverClass: "group-hover/assistant-turn:opacity-100 group-hover/assistant-turn:pointer-events-auto",
|
|
1407
|
+
isVisible: isCopyVisible,
|
|
1408
|
+
alignClass: "justify-start",
|
|
1409
|
+
onCopied: () => onCopied(copyKey)
|
|
1410
|
+
})]
|
|
1431
1411
|
});
|
|
1412
|
+
});
|
|
1413
|
+
var TOOL_CALL_KEY_PREFIX = "tool-call:";
|
|
1414
|
+
var UNKEYED_TOOL_KEY_PREFIX = "unkeyed-tool:";
|
|
1415
|
+
function getAssistantToolElementKey(messageId, part, occurrence) {
|
|
1416
|
+
if (part.toolCallId) return `${TOOL_CALL_KEY_PREFIX}${part.toolCallId}`;
|
|
1417
|
+
return `${UNKEYED_TOOL_KEY_PREFIX}${messageId}:${part.type}:${occurrence}`;
|
|
1432
1418
|
}
|
|
1433
|
-
function
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
const
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1419
|
+
function buildAssistantElements(parts, opts) {
|
|
1420
|
+
const { messageId, isLast, isStreaming, suppressQuestionTool, suppressTextWhenPlanWrite = false, ToolRendererComponent, TextRendererComponent, toolRenderers, onOpenUIAction, onOpenUIArtifactReady, onOpenArtifact } = opts;
|
|
1421
|
+
const elems = [];
|
|
1422
|
+
const textChunks = [];
|
|
1423
|
+
const hasPlanWritePresentation = suppressTextWhenPlanWrite && parts.some((part) => isV5ToolPart(part) && part.type === "tool-PlanWrite");
|
|
1424
|
+
const taskPartIds = new Set(parts.filter((p) => isV5ToolPart(p) && (p.type === "tool-Task" || p.type === "tool-Agent") && typeof p.toolCallId === "string").map((p) => p.toolCallId));
|
|
1425
|
+
const nestedToolsMap = /* @__PURE__ */ new Map();
|
|
1426
|
+
const nestedToolIds = /* @__PURE__ */ new Set();
|
|
1427
|
+
const unkeyedToolOccurrences = /* @__PURE__ */ new Map();
|
|
1428
|
+
for (const part of parts) {
|
|
1429
|
+
if (!isV5ToolPart(part)) continue;
|
|
1430
|
+
if (part.type === "tool-TaskOutput") continue;
|
|
1431
|
+
if (!part.toolCallId || !part.toolCallId.includes(":")) continue;
|
|
1432
|
+
const parentId = part.toolCallId.split(":")[0];
|
|
1433
|
+
if (!taskPartIds.has(parentId)) continue;
|
|
1434
|
+
if (!nestedToolsMap.has(parentId)) nestedToolsMap.set(parentId, []);
|
|
1435
|
+
nestedToolsMap.get(parentId).push(part);
|
|
1436
|
+
nestedToolIds.add(part.toolCallId);
|
|
1443
1437
|
}
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
const
|
|
1447
|
-
if (
|
|
1448
|
-
|
|
1449
|
-
|
|
1438
|
+
let i = 0;
|
|
1439
|
+
while (i < parts.length) {
|
|
1440
|
+
const part = parts[i];
|
|
1441
|
+
if (isV5ToolPart(part) && part.type === "tool-TaskOutput") {
|
|
1442
|
+
i++;
|
|
1443
|
+
continue;
|
|
1444
|
+
}
|
|
1445
|
+
if (isTextPart(part)) {
|
|
1446
|
+
const text2 = part.text;
|
|
1447
|
+
if (text2 && !hasPlanWritePresentation) textChunks.push(text2);
|
|
1448
|
+
i++;
|
|
1449
|
+
continue;
|
|
1450
|
+
}
|
|
1451
|
+
if (isErrorPart(part)) {
|
|
1452
|
+
elems.push(/* @__PURE__ */ jsx(ErrorMessage, {
|
|
1453
|
+
title: part.title,
|
|
1454
|
+
message: part.message
|
|
1455
|
+
}, `${messageId}-error-${part.title}-${part.message}`));
|
|
1456
|
+
i++;
|
|
1457
|
+
continue;
|
|
1458
|
+
}
|
|
1459
|
+
if (isPayloadPart(part)) {
|
|
1460
|
+
elems.push(/* @__PURE__ */ jsx(PayloadPart, { part }, `${messageId}-payload-${i}`));
|
|
1461
|
+
i++;
|
|
1462
|
+
continue;
|
|
1463
|
+
}
|
|
1464
|
+
if (isV5ToolPart(part)) {
|
|
1465
|
+
if (suppressQuestionTool && part.type === "tool-Question") {
|
|
1466
|
+
i++;
|
|
1467
|
+
continue;
|
|
1468
|
+
}
|
|
1469
|
+
if (part.toolCallId && nestedToolIds.has(part.toolCallId)) {
|
|
1470
|
+
i++;
|
|
1471
|
+
continue;
|
|
1472
|
+
}
|
|
1473
|
+
const chatStreamingStatus = isLast && isStreaming ? "streaming" : void 0;
|
|
1474
|
+
const toolCallId = part.toolCallId;
|
|
1475
|
+
const nestedTools = (part.type === "tool-Task" || part.type === "tool-Agent") && toolCallId ? nestedToolsMap.get(toolCallId) || [] : void 0;
|
|
1476
|
+
const occurrence = part.toolCallId ? 0 : unkeyedToolOccurrences.get(part.type) ?? 0;
|
|
1477
|
+
if (!part.toolCallId) unkeyedToolOccurrences.set(part.type, occurrence + 1);
|
|
1478
|
+
elems.push(/* @__PURE__ */ jsx(ToolRendererComponent, {
|
|
1479
|
+
part,
|
|
1480
|
+
nestedTools,
|
|
1481
|
+
chatStatus: chatStreamingStatus,
|
|
1482
|
+
toolRenderers
|
|
1483
|
+
}, getAssistantToolElementKey(messageId, part, occurrence)));
|
|
1484
|
+
i++;
|
|
1485
|
+
continue;
|
|
1450
1486
|
}
|
|
1487
|
+
i++;
|
|
1451
1488
|
}
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1489
|
+
const text = textChunks.join("\n\n");
|
|
1490
|
+
if (text) elems.push(/* @__PURE__ */ jsx("div", {
|
|
1491
|
+
className: "group/assistant-text text-[14px]",
|
|
1492
|
+
children: /* @__PURE__ */ jsx(TextRendererComponent, {
|
|
1493
|
+
content: text,
|
|
1494
|
+
isStreaming,
|
|
1495
|
+
messageId,
|
|
1496
|
+
onOpenUIAction,
|
|
1497
|
+
onOpenUIArtifactReady,
|
|
1498
|
+
onOpenArtifact,
|
|
1499
|
+
className: "leading-relaxed [&_p]:leading-relaxed"
|
|
1500
|
+
})
|
|
1501
|
+
}, `${messageId}-text-final`));
|
|
1502
|
+
return elems;
|
|
1464
1503
|
}
|
|
1465
|
-
|
|
1466
|
-
const
|
|
1467
|
-
const
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
}
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
1495
|
-
event.preventDefault();
|
|
1496
|
-
setLightboxIndex(i);
|
|
1497
|
-
}
|
|
1498
|
-
} : void 0,
|
|
1499
|
-
children: /* @__PURE__ */ jsx("img", {
|
|
1500
|
-
src: url,
|
|
1501
|
-
alt: "attachment",
|
|
1502
|
-
className: "block max-h-[120px] max-w-[184px] rounded-an-message-inner object-cover"
|
|
1503
|
-
})
|
|
1504
|
-
}, url)),
|
|
1505
|
-
enableImagePreview && lightboxImages.length > 0 && /* @__PURE__ */ jsx(ImageLightbox, {
|
|
1506
|
-
open: lightboxIndex !== null,
|
|
1507
|
-
onClose: () => setLightboxIndex(null),
|
|
1508
|
-
images: lightboxImages,
|
|
1509
|
-
initialIndex: lightboxIndex ?? 0
|
|
1510
|
-
}),
|
|
1511
|
-
files.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
1512
|
-
className: "flex flex-col items-end gap-2",
|
|
1513
|
-
children: files.map((file, i) => /* @__PURE__ */ jsx(FileAttachment, {
|
|
1514
|
-
id: `${file.filename}-${i}`,
|
|
1515
|
-
filename: file.filename,
|
|
1516
|
-
size: file.size
|
|
1517
|
-
}, `${file.filename}-${file.size}`))
|
|
1518
|
-
}),
|
|
1519
|
-
text && /* @__PURE__ */ jsx("div", {
|
|
1520
|
-
className: "ms-[70px] max-w-[calc(95%-40px)]",
|
|
1521
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
1522
|
-
className: "rounded-an-message bg-an-user-message-bg px-3.5 py-1.5 text-sm text-an-user-message-text transition-colors",
|
|
1523
|
-
children: /* @__PURE__ */ jsx("p", {
|
|
1524
|
-
className: "leading-5 wrap-break-word whitespace-pre-wrap",
|
|
1525
|
-
children: text
|
|
1526
|
-
})
|
|
1527
|
-
})
|
|
1528
|
-
})
|
|
1529
|
-
]
|
|
1504
|
+
function AssistantParts({ msg, isLast, isStreaming, suppressQuestionTool, ToolRendererComponent, TextRendererComponent, toolRenderers, onOpenUIAction, onOpenUIArtifactReady, onOpenArtifact }) {
|
|
1505
|
+
const parts = useMemo(() => normalizeAssistantToolParts(msg.parts ?? []), [msg.parts]);
|
|
1506
|
+
const elements = useMemo(() => buildAssistantElements(parts, {
|
|
1507
|
+
messageId: msg.id,
|
|
1508
|
+
isLast,
|
|
1509
|
+
isStreaming,
|
|
1510
|
+
suppressQuestionTool,
|
|
1511
|
+
ToolRendererComponent,
|
|
1512
|
+
TextRendererComponent,
|
|
1513
|
+
toolRenderers,
|
|
1514
|
+
onOpenUIAction,
|
|
1515
|
+
onOpenUIArtifactReady,
|
|
1516
|
+
onOpenArtifact
|
|
1517
|
+
}), [
|
|
1518
|
+
parts,
|
|
1519
|
+
msg.id,
|
|
1520
|
+
isLast,
|
|
1521
|
+
isStreaming,
|
|
1522
|
+
suppressQuestionTool,
|
|
1523
|
+
ToolRendererComponent,
|
|
1524
|
+
TextRendererComponent,
|
|
1525
|
+
toolRenderers,
|
|
1526
|
+
onOpenUIAction,
|
|
1527
|
+
onOpenUIArtifactReady,
|
|
1528
|
+
onOpenArtifact
|
|
1529
|
+
]);
|
|
1530
|
+
if (elements.length > 1) return /* @__PURE__ */ jsx("div", {
|
|
1531
|
+
className: "group/assistant-turn flex flex-col gap-3",
|
|
1532
|
+
children: elements
|
|
1530
1533
|
});
|
|
1531
|
-
});
|
|
1532
|
-
var LazyGenerativeTextRenderer = lazy(() => import("./openui-renderer-Cg4RSE9k-7BTJIYZJ.js").then((n) => n.n).then(({ GenerativeTextRenderer }) => ({ default: GenerativeTextRenderer })));
|
|
1533
|
-
function PlainTextFallback({ className, content }) {
|
|
1534
1534
|
return /* @__PURE__ */ jsx("div", {
|
|
1535
|
-
className:
|
|
1536
|
-
children:
|
|
1537
|
-
});
|
|
1538
|
-
}
|
|
1539
|
-
function FleetGenerativeTextRenderer(props) {
|
|
1540
|
-
if (!useMemo(() => segmentOpenUIContent(props.content).some((segment) => segment.type === "openui"), [props.content])) return /* @__PURE__ */ jsx(LazyMarkdown, {
|
|
1541
|
-
className: props.className,
|
|
1542
|
-
content: props.content
|
|
1543
|
-
});
|
|
1544
|
-
return /* @__PURE__ */ jsx(Suspense, {
|
|
1545
|
-
fallback: /* @__PURE__ */ jsx(PlainTextFallback, {
|
|
1546
|
-
className: props.className,
|
|
1547
|
-
content: props.content
|
|
1548
|
-
}),
|
|
1549
|
-
children: /* @__PURE__ */ jsx(LazyGenerativeTextRenderer, { ...props })
|
|
1535
|
+
className: "group/assistant-turn",
|
|
1536
|
+
children: elements
|
|
1550
1537
|
});
|
|
1551
1538
|
}
|
|
1552
1539
|
function orderedRlmChildren(children, tree) {
|
|
@@ -1566,13 +1553,14 @@ function orderedRlmChildren(children, tree) {
|
|
|
1566
1553
|
}
|
|
1567
1554
|
function rlmStatusIcon(status2) {
|
|
1568
1555
|
if (status2 === "done") return /* @__PURE__ */ jsx(CircleCheck, { className: "size-3.5 text-emerald-600 dark:text-emerald-400" });
|
|
1569
|
-
if (status2 === "error") return /* @__PURE__ */ jsx(CircleAlert, { className: "size-3.5 text-destructive" });
|
|
1556
|
+
if (status2 === "error" || status2 === "failed") return /* @__PURE__ */ jsx(CircleAlert, { className: "size-3.5 text-destructive" });
|
|
1570
1557
|
if (status2 === "cancelled") return /* @__PURE__ */ jsx(CircleX, { className: "size-3.5 text-muted-foreground" });
|
|
1558
|
+
if (status2 === "recovering") return /* @__PURE__ */ jsx(RotateCw, { className: "size-3.5 animate-spin text-amber-500 dark:text-amber-400" });
|
|
1571
1559
|
return /* @__PURE__ */ jsx(LoaderCircle, { className: "size-3.5 animate-spin text-blue-600 dark:text-blue-400" });
|
|
1572
1560
|
}
|
|
1573
1561
|
function FleetSubagentList({ children, tree, className }) {
|
|
1574
1562
|
const agents = useMemo(() => orderedRlmChildren(children, tree), [children, tree]);
|
|
1575
|
-
const active = agents.some((child) => child.status === "queued" || child.status === "running");
|
|
1563
|
+
const active = agents.some((child) => child.status === "queued" || child.status === "running" || child.status === "recovering");
|
|
1576
1564
|
const [open, setOpen] = useState(active);
|
|
1577
1565
|
if (agents.length === 0) return null;
|
|
1578
1566
|
return /* @__PURE__ */ jsxs("section", {
|
|
@@ -1769,6 +1757,26 @@ function groupMessages(messages) {
|
|
|
1769
1757
|
if (current) turns.push(current);
|
|
1770
1758
|
return turns;
|
|
1771
1759
|
}
|
|
1760
|
+
var LazyGenerativeTextRenderer = lazy(() => import("./openui-renderer-c36_GYes-HX46N4M5.js").then((n) => n.n).then(({ GenerativeTextRenderer }) => ({ default: GenerativeTextRenderer })));
|
|
1761
|
+
function PlainTextFallback({ className, content }) {
|
|
1762
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1763
|
+
className: className ? `${className} whitespace-pre-wrap` : "whitespace-pre-wrap",
|
|
1764
|
+
children: content
|
|
1765
|
+
});
|
|
1766
|
+
}
|
|
1767
|
+
function FleetGenerativeTextRenderer(props) {
|
|
1768
|
+
if (!useMemo(() => segmentOpenUIContent(props.content).some((segment) => segment.type === "openui"), [props.content])) return /* @__PURE__ */ jsx(LazyMarkdown, {
|
|
1769
|
+
className: props.className,
|
|
1770
|
+
content: props.content
|
|
1771
|
+
});
|
|
1772
|
+
return /* @__PURE__ */ jsx(Suspense, {
|
|
1773
|
+
fallback: /* @__PURE__ */ jsx(PlainTextFallback, {
|
|
1774
|
+
className: props.className,
|
|
1775
|
+
content: props.content
|
|
1776
|
+
}),
|
|
1777
|
+
children: /* @__PURE__ */ jsx(LazyGenerativeTextRenderer, { ...props })
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1772
1780
|
|
|
1773
1781
|
export {
|
|
1774
1782
|
ChevronLeft,
|
|
@@ -1778,16 +1786,16 @@ export {
|
|
|
1778
1786
|
MessageScroller,
|
|
1779
1787
|
Message,
|
|
1780
1788
|
MessageContent,
|
|
1781
|
-
normalizeAssistantToolParts,
|
|
1782
|
-
buildAssistantElements,
|
|
1783
1789
|
FileAttachment,
|
|
1784
1790
|
UserMessage,
|
|
1785
|
-
|
|
1791
|
+
normalizeAssistantToolParts,
|
|
1792
|
+
buildAssistantElements,
|
|
1786
1793
|
orderedRlmChildren,
|
|
1787
1794
|
rlmStatusIcon,
|
|
1788
1795
|
FleetSubagentList,
|
|
1789
1796
|
FleetToolTimeline,
|
|
1790
|
-
groupMessages
|
|
1797
|
+
groupMessages,
|
|
1798
|
+
FleetGenerativeTextRenderer
|
|
1791
1799
|
};
|
|
1792
1800
|
/**
|
|
1793
1801
|
* @license lucide-react v1.33.0 - ISC
|