@qredence/fleet 0.5.11 → 0.6.1
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 +14 -0
- package/dist/web/client/assets/action-swap-roll-COzQ86wm.js +1 -0
- package/dist/web/client/assets/agent-activity-svETLf_5.js +1 -0
- package/dist/web/client/assets/agent-disclosure-DAMuuGcM.js +1 -0
- package/dist/web/client/assets/analytics-stub-B6zGMuSV.js +1 -0
- package/dist/web/client/assets/{artifacts-panel-CQmFEF_H.js → artifacts-panel-HVjqBMyx.js} +1 -1
- package/dist/web/client/assets/button-C5wFDY5_.js +1 -0
- package/dist/web/client/assets/card-DA3Vnqay.js +1 -0
- package/dist/web/client/assets/{chat-yh02zgA7.js → chat-BhYseKd6.js} +7 -7
- package/dist/web/client/assets/{chat-command-palette-CmHTS3rs.js → chat-command-palette-LILDO_vG.js} +1 -1
- package/dist/web/client/assets/{citations-C_tPOJE_.js → citations-BPv8HIpf.js} +2 -2
- package/dist/web/client/assets/command-PhicLCoO.js +1 -0
- package/dist/web/client/assets/dialog-pBGUjAQ7.js +1 -0
- package/dist/web/client/assets/fleet-message-queue-fbYYwMj0.js +1 -0
- package/dist/web/client/assets/{fleet-pi-tool-renderer-BEDIO3al.js → fleet-pi-tool-renderer-BRgNnmaJ.js} +28 -28
- package/dist/web/client/assets/fleet-reasoning-panel-CjA2dwUJ.js +1 -0
- package/dist/web/client/assets/{fork-picker-dialog-ByBOGVsa.js → fork-picker-dialog-B7NNpVmW.js} +1 -1
- package/dist/web/client/assets/globals-CuIiqOTg.css +2 -0
- package/dist/web/client/assets/horizontal-resize-Cp3iHMH7.js +1 -0
- package/dist/web/client/assets/index-CSGplyr_.js +12 -0
- package/dist/web/client/assets/{input-0wwjWjKq.js → input-PcdubeKn.js} +1 -1
- package/dist/web/client/assets/input-group-C2HJEZvl.js +1 -0
- package/dist/web/client/assets/ipython-tool-CyuMOxz1.js +3 -0
- package/dist/web/client/assets/{markdown-code-CuQcR3UO.js → markdown-code-xNyjdZ4g.js} +1 -1
- package/dist/web/client/assets/{markdown-DInPmRUG.js → markdown-lvexwooo.js} +2 -2
- package/dist/web/client/assets/{model-selector-list-DsKTuAgS.js → model-selector-list-CoXX358G.js} +1 -1
- package/dist/web/client/assets/{notify-DgMKgZZW.js → notify-DxL0VD7Z.js} +1 -1
- package/dist/web/client/assets/openui-renderer-TLNe5e_Q.js +378 -0
- package/dist/web/client/assets/pencil-DcUwsKLn.js +1 -0
- package/dist/web/client/assets/prompt-input-fwP8TsgQ.js +1 -0
- package/dist/web/client/assets/{prompt-suggestions-Cc--lSNR.js → prompt-suggestions-BlGXmWS7.js} +1 -1
- package/dist/web/client/assets/provider-catalog-DYMFdbKc.js +1 -0
- package/dist/web/client/assets/provider-label-B4q5mI65.js +1 -0
- package/dist/web/client/assets/{repl-panel-DsPX04Xr.js → repl-panel-C5om8MGU.js} +1 -1
- package/dist/web/client/assets/{right-panel-registry-DewpBWHM.js → right-panel-registry-BBlxLxnx.js} +2 -2
- package/dist/web/client/assets/routes-XGsAIqBJ.js +16 -0
- package/dist/web/client/assets/settings-dialog-BSBasR3o.js +2 -0
- package/dist/web/client/assets/{subagent-chat-panel-DkVUumrP.js → subagent-chat-panel-oeLDPDAK.js} +1 -1
- package/dist/web/client/assets/{subagent-transcript-D8wmQxXe.js → subagent-transcript-DaVHjNUH.js} +1 -1
- package/dist/web/client/assets/{subagents-panel-BMp2Ego0.js → subagents-panel-D_aVgSCi.js} +1 -1
- package/dist/web/client/assets/surfaces-BhAXz9So.js +1 -0
- package/dist/web/client/assets/{switch-9rTeg6J6.js → switch-WhXeJNNY.js} +1 -1
- package/dist/web/client/assets/{toast-Bt9p2OL4.js → toast-D3c9XeGe.js} +1 -1
- package/dist/web/client/assets/{tool-result-DfnPN0FQ.js → tool-result-Cki8WUNc.js} +3 -3
- package/dist/web/client/assets/virtualized-turn-list-CdMa-ydT.js +6 -0
- package/dist/web/client/assets/workspace-panel-77bDbprs.js +1 -0
- package/dist/web/client/bundle-budget.json +6 -6
- package/dist/web/launcher.mjs +10 -1
- package/dist/web/server/{_tanstack-start-manifest_v-po4woX6g-AUGCOEZ2.js → _tanstack-start-manifest_v-0L7fqnH4-KMVGUFE4.js} +25 -24
- package/dist/web/server/{agent-activity-CS2rbF_C-A3R26CYH.js → agent-activity-BuEE6iVw-CDZLK4D2.js} +4 -4
- package/dist/web/server/{artifacts-panel-8GGUCtOd-X5TNKTY2.js → artifacts-panel-D3ySO--V-XSL53CXL.js} +18 -18
- package/dist/web/server/{chat-command-palette-Dgl5tqWn-72LLEWUD.js → chat-command-palette-kAbXhWVg-TJWXH2WW.js} +9 -9
- package/dist/web/server/{chunk-O4OTWWPF.js → chunk-2DDWXTVG.js} +5 -5
- package/dist/web/server/{chunk-MIW4LJTV.js → chunk-2JHTYWD5.js} +15 -23
- package/dist/web/server/{chunk-7MDZVLIY.js → chunk-3TIMGWWI.js} +1 -2
- package/dist/web/server/{chunk-AGFRJQZ7.js → chunk-4WBFCB4O.js} +257 -257
- package/dist/web/server/{chunk-P6UMR32I.js → chunk-5UCAJBAH.js} +4 -4
- package/dist/web/server/{chunk-BXWAUTTH.js → chunk-D27LRYVT.js} +42 -42
- package/dist/web/server/{chunk-YXXRP3NS.js → chunk-DLUZFOG3.js} +5 -5
- package/dist/web/server/{chunk-K3BXQG3N.js → chunk-EBG3XFGQ.js} +60 -60
- package/dist/web/server/{chunk-2ATMSG7U.js → chunk-EJEPDVK6.js} +3 -3
- package/dist/web/server/{chunk-IJPCV6DH.js → chunk-FYDQK6UX.js} +1 -1
- package/dist/web/server/{chunk-WKV2Z4KO.js → chunk-HF7DG7PC.js} +74 -74
- package/dist/web/server/{chunk-WYL2DW5R.js → chunk-JTCCQZLN.js} +2 -2
- package/dist/web/server/{chunk-UAPNEWCA.js → chunk-KP2PNDGL.js} +6 -6
- package/dist/web/server/chunk-M5RSPNYN.js +22 -0
- package/dist/web/server/{chunk-7SR6WDM2.js → chunk-MNBGB2SP.js} +2 -2
- package/dist/web/server/{chunk-HSJMLO36.js → chunk-MNPHMZU7.js} +3 -3
- package/dist/web/server/{chunk-JQDLJ7KI.js → chunk-NGCQJ33Y.js} +1134 -1134
- package/dist/web/server/{chunk-7SD2ZSEA.js → chunk-NIDBN7BQ.js} +1 -1
- package/dist/web/server/{chunk-ZJFA4F5X.js → chunk-NIZBFVJF.js} +2 -2
- package/dist/web/server/{chunk-P7H2OPKF.js → chunk-NJ4QEZHK.js} +11 -4
- package/dist/web/server/{chunk-WM4PUT6M.js → chunk-NNKJTKOQ.js} +234 -234
- package/dist/web/server/{chunk-N6NOTURM.js → chunk-NWDI3OWB.js} +4 -4
- package/dist/web/server/{chunk-ABBWBBSS.js → chunk-O3HDELZ2.js} +74826 -74825
- package/dist/web/server/{chunk-GGT2ZKDB.js → chunk-PLYZ7P2Y.js} +11 -155
- package/dist/web/server/chunk-PTCKOR23.js +39 -0
- package/dist/web/server/{chunk-RNOJACWQ.js → chunk-QFRCJWQQ.js} +7 -7
- package/dist/web/server/{chunk-NXJ32VFR.js → chunk-QIULBRTU.js} +13 -13
- package/dist/web/server/{chunk-XKKXXG6N.js → chunk-RIP3PBWT.js} +3 -3
- package/dist/web/server/{chunk-YKVGQBZA.js → chunk-S5LFXXDY.js} +625 -622
- package/dist/web/server/{chunk-XLNCWZMZ.js → chunk-UCUFC553.js} +3 -1
- package/dist/web/server/{chunk-KOUEJ3NU.js → chunk-UL2725KQ.js} +3 -3
- package/dist/web/server/{chunk-HFQTI7AX.js → chunk-VPKX7QRU.js} +3 -3
- package/dist/web/server/{chunk-LZ4Q5KUJ.js → chunk-WNCAL4HN.js} +133 -133
- package/dist/web/server/{chunk-C5X6G26O.js → chunk-XIB6XNUX.js} +436 -436
- package/dist/web/server/{chunk-JUROEEWM.js → chunk-YGYOBX7G.js} +82 -4
- package/dist/web/server/{chunk-WILCIZYU.js → chunk-ZIFSJ3HQ.js} +626 -626
- package/dist/web/server/fleet-message-queue-D_w8lSeY-T3HB7HVQ.js +152 -0
- package/dist/web/server/{fleet-pi-tool-renderer-umKunT3K-O4GBH35V.js → fleet-pi-tool-renderer-qwc-qZFq-4U556N5Q.js} +12 -12
- package/dist/web/server/{fleet-reasoning-panel-BxC2COxi-GPLMQSTT.js → fleet-reasoning-panel-DG_vuvv0-NCZWEEIT.js} +26 -26
- package/dist/web/server/{fleet-subagent-list-CpSYzCIq-JDH2LHSS.js → fleet-subagent-list-BGb0PjhF-2X67FMUV.js} +1 -1
- package/dist/web/server/{fleet-tool-timeline-IB36_PB2-XJENTO6I.js → fleet-tool-timeline-D6yM4ZMz-ZSFVRRRI.js} +1 -1
- package/dist/web/server/{fork-picker-dialog-DlINz9UQ-UWIXFDJX.js → fork-picker-dialog-Ds6Tgtu3-DIBWN7MV.js} +5 -5
- package/dist/web/server/{model-selector-list-OYnzNbyu-HBGCNF2L.js → model-selector-list-DxeGZoD2-P6S6FSJH.js} +9 -9
- package/dist/web/server/{openui-renderer-Cj7kfqyL-EKJ6JTTQ.js → openui-renderer-MKFv6LlH-MDRSVFEY.js} +11 -11
- package/dist/web/server/{prompt-suggestions-D4AEEY7K-RZSP7PWV.js → prompt-suggestions-BOItmGnD-YQA7RHLG.js} +2 -2
- package/dist/web/server/{repl-panel-D5KsoJik-BQKO53JO.js → repl-panel-CuyF8wt5-CHDT2Q3N.js} +2 -2
- package/dist/web/server/{router-Ci1wxI7I-E2AYMNON.js → router-Dg72SESP-PCWKLFRG.js} +1239 -470
- package/dist/web/server/{routes-CRpm9-Sa-IYK6MUJO.js → routes-BGrVtPYF-SURPAJN6.js} +5781 -5588
- package/dist/web/server/server.js +2 -2
- package/dist/web/server/{settings-dialog-BvkgNflv-GPJ6COQO.js → settings-dialog-CK0FJlTg-HZRBAXDZ.js} +1577 -1264
- package/dist/web/server/{subagent-chat-panel-CMuvW9Sd-M5TEEGQW.js → subagent-chat-panel-gzamnTgK-PQ2TLLJF.js} +21 -21
- package/dist/web/server/{subagents-panel-DgfB6_Yy-4INEPE3Y.js → subagents-panel-Berjd7HJ-EI5ZKC6V.js} +20 -20
- package/dist/web/server/{workspace-panel-bpwj-Veu-Q2CEJMN4.js → workspace-panel-CBBa_3UO-B4PPFPMA.js} +46 -21
- package/package.json +1 -1
- package/dist/web/client/assets/action-swap-roll-BB8DFMuf.js +0 -1
- package/dist/web/client/assets/agent-activity-CwMDU7aP.js +0 -1
- package/dist/web/client/assets/agent-disclosure-B8SnhQXL.js +0 -1
- package/dist/web/client/assets/analytics-stub-Cas1He0w.js +0 -1
- package/dist/web/client/assets/button-BR2WWrFo.js +0 -1
- package/dist/web/client/assets/card-BKl76a3R.js +0 -1
- package/dist/web/client/assets/command-DPfiaYUL.js +0 -1
- package/dist/web/client/assets/dialog-BEZuZhzk.js +0 -1
- package/dist/web/client/assets/fleet-message-queue-DUz6Hfrf.js +0 -1
- package/dist/web/client/assets/fleet-reasoning-panel-CbkO7u-v.js +0 -1
- package/dist/web/client/assets/globals-B_I1Eq1u.css +0 -2
- package/dist/web/client/assets/horizontal-resize-qK6eRhIG.js +0 -1
- package/dist/web/client/assets/index-C1zOjrMK.js +0 -12
- package/dist/web/client/assets/input-group-BFDsCVS9.js +0 -1
- package/dist/web/client/assets/ipython-tool-ldJ9F1Cw.js +0 -3
- package/dist/web/client/assets/openui-renderer-J3dhPpL4.js +0 -378
- package/dist/web/client/assets/prompt-input-qPIXZ-Rb.js +0 -1
- package/dist/web/client/assets/provider-catalog-D8G66gwc.js +0 -1
- package/dist/web/client/assets/provider-label-Dpr7djG9.js +0 -1
- package/dist/web/client/assets/routes-vNkVToAF.js +0 -16
- package/dist/web/client/assets/settings-dialog-B-v4me3Y.js +0 -1
- package/dist/web/client/assets/surfaces-DI-U-_2a.js +0 -1
- package/dist/web/client/assets/virtualized-turn-list-DMJENRY0.js +0 -6
- package/dist/web/client/assets/workspace-panel-G6yMpKJ8.js +0 -1
- package/dist/web/server/chunk-QK4CHLVV.js +0 -17
- package/dist/web/server/fleet-message-queue-j0DCU5Xy-5HKBHMPV.js +0 -75
|
@@ -3,18 +3,18 @@ import {
|
|
|
3
3
|
} from "./chunk-FJV6EQDW.js";
|
|
4
4
|
import {
|
|
5
5
|
notify
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JTCCQZLN.js";
|
|
7
7
|
import {
|
|
8
8
|
LazyMarkdown,
|
|
9
9
|
useHoverCapable
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NWDI3OWB.js";
|
|
11
11
|
import {
|
|
12
12
|
Copy
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-EJEPDVK6.js";
|
|
14
14
|
import {
|
|
15
15
|
AnimatePresence,
|
|
16
16
|
useReducedMotion
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-NIZBFVJF.js";
|
|
18
18
|
import {
|
|
19
19
|
ChevronRight
|
|
20
20
|
} from "./chunk-3C4CFCIS.js";
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
EASE_OUT,
|
|
23
23
|
SPRING_LAYOUT,
|
|
24
24
|
m
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-EBG3XFGQ.js";
|
|
26
26
|
import {
|
|
27
27
|
segmentOpenUIContent
|
|
28
28
|
} from "./chunk-NFRJDPB3.js";
|
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
cn
|
|
43
43
|
} from "./chunk-DJMHPJBP.js";
|
|
44
44
|
|
|
45
|
-
// web/app/dist/server/assets/virtualized-turn-list-
|
|
45
|
+
// web/app/dist/server/assets/virtualized-turn-list-DNo8CDwR.js
|
|
46
46
|
import { Fragment, Suspense, cloneElement, createContext, lazy, memo, useCallback, useContext, useEffect, useEffectEvent, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
47
47
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
48
48
|
import { createPortal } from "react-dom";
|
|
@@ -86,6 +86,29 @@ var FileCode = createLucideIcon("file-code", [
|
|
|
86
86
|
key: "yinavb"
|
|
87
87
|
}]
|
|
88
88
|
]);
|
|
89
|
+
function groupMessages(messages) {
|
|
90
|
+
const turns = [];
|
|
91
|
+
let current;
|
|
92
|
+
for (const message of messages) {
|
|
93
|
+
if (message.role === "user") {
|
|
94
|
+
if (current) turns.push(current);
|
|
95
|
+
current = {
|
|
96
|
+
user: message,
|
|
97
|
+
assistants: []
|
|
98
|
+
};
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (message.role !== "assistant") continue;
|
|
102
|
+
if (!current || message.source === "local") {
|
|
103
|
+
if (current) turns.push(current);
|
|
104
|
+
current = { assistants: [message] };
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
current.assistants.push(message);
|
|
108
|
+
}
|
|
109
|
+
if (current) turns.push(current);
|
|
110
|
+
return turns;
|
|
111
|
+
}
|
|
89
112
|
var MessageSideContext = createContext(void 0);
|
|
90
113
|
var MessageBubbleContext = createContext({
|
|
91
114
|
animateIn: true,
|
|
@@ -747,258 +770,124 @@ function MessageContent({ className, ...props }) {
|
|
|
747
770
|
...props
|
|
748
771
|
});
|
|
749
772
|
}
|
|
750
|
-
function
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
}, [images.length]);
|
|
764
|
-
const onLightboxKeyDown = useEffectEvent((event) => {
|
|
765
|
-
switch (event.key) {
|
|
766
|
-
case "ArrowLeft":
|
|
767
|
-
event.preventDefault();
|
|
768
|
-
if (hasMultipleImages) goToPrevious();
|
|
769
|
-
break;
|
|
770
|
-
case "ArrowRight":
|
|
771
|
-
event.preventDefault();
|
|
772
|
-
if (hasMultipleImages) goToNext();
|
|
773
|
-
}
|
|
773
|
+
var ErrorMessage = memo(function ErrorMessage2({ title = "Something went wrong", message, className }) {
|
|
774
|
+
return /* @__PURE__ */ jsx("div", {
|
|
775
|
+
className: cn("flex justify-start", className),
|
|
776
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
777
|
+
className: "rounded-[8px] border border-red-500/30 bg-red-500/10 px-4 py-2.5 text-sm text-an-foreground",
|
|
778
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
779
|
+
className: "font-medium text-an-foreground",
|
|
780
|
+
children: title
|
|
781
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
782
|
+
className: "mt-0.5 text-an-foreground-muted",
|
|
783
|
+
children: message
|
|
784
|
+
})]
|
|
785
|
+
})
|
|
774
786
|
});
|
|
787
|
+
});
|
|
788
|
+
var timeFormatter = new Intl.DateTimeFormat("en-US", {
|
|
789
|
+
hour: "numeric",
|
|
790
|
+
minute: "2-digit",
|
|
791
|
+
hour12: true
|
|
792
|
+
});
|
|
793
|
+
var dateFormatter = new Intl.DateTimeFormat("en-US", {
|
|
794
|
+
month: "short",
|
|
795
|
+
day: "numeric"
|
|
796
|
+
});
|
|
797
|
+
function formatTimestamp(date) {
|
|
798
|
+
const now = /* @__PURE__ */ new Date();
|
|
799
|
+
if (date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate()) return timeFormatter.format(date);
|
|
800
|
+
return dateFormatter.format(date);
|
|
801
|
+
}
|
|
802
|
+
function CopyButton({ text, onCopied }) {
|
|
803
|
+
const [copied, setCopied] = useState(false);
|
|
804
|
+
const copiedTimerRef = useRef(null);
|
|
775
805
|
useEffect(() => {
|
|
776
|
-
if (!open) return;
|
|
777
|
-
const handler = (event) => onLightboxKeyDown(event);
|
|
778
|
-
window.addEventListener("keydown", handler, true);
|
|
779
|
-
return () => window.removeEventListener("keydown", handler, true);
|
|
780
|
-
}, [open]);
|
|
781
|
-
useEffect(() => {
|
|
782
|
-
if (!open) return;
|
|
783
|
-
const previousOverflow = document.body.style.overflow;
|
|
784
|
-
document.body.style.overflow = "hidden";
|
|
785
806
|
return () => {
|
|
786
|
-
|
|
807
|
+
if (copiedTimerRef.current) window.clearTimeout(copiedTimerRef.current);
|
|
787
808
|
};
|
|
788
|
-
}, [
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
|
|
809
|
+
}, []);
|
|
810
|
+
const handleCopy = async () => {
|
|
811
|
+
try {
|
|
812
|
+
await navigator.clipboard.writeText(text);
|
|
813
|
+
setCopied(true);
|
|
814
|
+
if (copiedTimerRef.current) window.clearTimeout(copiedTimerRef.current);
|
|
815
|
+
copiedTimerRef.current = window.setTimeout(() => {
|
|
816
|
+
setCopied(false);
|
|
817
|
+
copiedTimerRef.current = null;
|
|
818
|
+
}, 2e3);
|
|
819
|
+
notify.success("Copied to clipboard");
|
|
820
|
+
onCopied?.();
|
|
821
|
+
} catch {
|
|
822
|
+
notify.error("Failed to copy to clipboard");
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
return /* @__PURE__ */ jsx("button", {
|
|
826
|
+
type: "button",
|
|
827
|
+
tabIndex: -1,
|
|
828
|
+
"aria-label": copied ? "Copied" : "Copy message",
|
|
829
|
+
onClick: handleCopy,
|
|
830
|
+
onPointerDown: (event) => {
|
|
831
|
+
event.stopPropagation();
|
|
832
|
+
},
|
|
833
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
834
|
+
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"),
|
|
835
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
836
|
+
className: "relative size-3.5",
|
|
837
|
+
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") })]
|
|
838
|
+
})
|
|
792
839
|
});
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
if (
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
840
|
+
}
|
|
841
|
+
function MessageToolbar({ text, timestamp, heightClass, hoverClass, isVisible, alignClass, onCopied }) {
|
|
842
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
843
|
+
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"),
|
|
844
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
845
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
846
|
+
children: [timestamp && /* @__PURE__ */ jsx("span", { children: timestamp }), text && /* @__PURE__ */ jsx(CopyButton, {
|
|
847
|
+
text,
|
|
848
|
+
onCopied
|
|
849
|
+
})]
|
|
850
|
+
});
|
|
851
|
+
}
|
|
852
|
+
function formatPayload(value) {
|
|
853
|
+
if (typeof value === "string") return value;
|
|
854
|
+
if (value === void 0) return "";
|
|
855
|
+
try {
|
|
856
|
+
return JSON.stringify(value, null, 2) ?? "";
|
|
857
|
+
} catch {
|
|
858
|
+
return String(value);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
function PayloadPart({ part }) {
|
|
862
|
+
const payload = formatPayload(part.payload);
|
|
863
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
864
|
+
"data-payload-kind": part.kind,
|
|
865
|
+
className: "w-full min-w-0 overflow-hidden rounded-xl border border-border/60 bg-muted/40 text-sm",
|
|
814
866
|
children: [
|
|
815
|
-
/* @__PURE__ */ jsx("
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
"aria-label": "Close fullscreen (Esc)",
|
|
819
|
-
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",
|
|
820
|
-
children: /* @__PURE__ */ jsx(X, { className: "size-5" })
|
|
821
|
-
}),
|
|
822
|
-
hasMultipleImages && /* @__PURE__ */ jsx("button", {
|
|
823
|
-
type: "button",
|
|
824
|
-
onClick: goToPrevious,
|
|
825
|
-
"aria-label": "Previous image (\u2190)",
|
|
826
|
-
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",
|
|
827
|
-
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-6" })
|
|
828
|
-
}),
|
|
829
|
-
/* @__PURE__ */ jsx("img", {
|
|
830
|
-
src: currentImage.url,
|
|
831
|
-
alt: currentImage.filename ?? "Image preview",
|
|
832
|
-
className: "max-h-[85vh] max-w-[90vw] object-contain select-none",
|
|
833
|
-
onClick: (event) => event.stopPropagation(),
|
|
834
|
-
draggable: false
|
|
835
|
-
}),
|
|
836
|
-
hasMultipleImages && /* @__PURE__ */ jsx("button", {
|
|
837
|
-
type: "button",
|
|
838
|
-
onClick: goToNext,
|
|
839
|
-
"aria-label": "Next image (\u2192)",
|
|
840
|
-
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",
|
|
841
|
-
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-6" })
|
|
867
|
+
/* @__PURE__ */ jsx("div", {
|
|
868
|
+
className: "border-b border-border/50 px-3 py-2 text-xs font-medium text-muted-foreground",
|
|
869
|
+
children: part.title
|
|
842
870
|
}),
|
|
843
|
-
|
|
844
|
-
className: "
|
|
845
|
-
children:
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
}), /* @__PURE__ */ jsxs("span", {
|
|
857
|
-
className: "text-sm text-white/70",
|
|
858
|
-
children: [
|
|
859
|
-
currentIndex + 1,
|
|
860
|
-
" / ",
|
|
861
|
-
images.length
|
|
862
|
-
]
|
|
871
|
+
part.text ? /* @__PURE__ */ jsx("pre", {
|
|
872
|
+
className: "m-0 whitespace-pre-wrap break-words p-3 font-mono text-xs leading-5 text-foreground/80",
|
|
873
|
+
children: part.text
|
|
874
|
+
}) : null,
|
|
875
|
+
payload ? /* @__PURE__ */ jsxs("details", {
|
|
876
|
+
open: true,
|
|
877
|
+
className: "border-t border-border/50 px-3 py-2",
|
|
878
|
+
children: [/* @__PURE__ */ jsx("summary", {
|
|
879
|
+
className: "cursor-pointer text-xs font-medium text-muted-foreground",
|
|
880
|
+
children: "Payload"
|
|
881
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
882
|
+
className: "m-0 mt-2 max-w-full whitespace-pre-wrap break-words font-mono text-xs leading-5 text-foreground/70",
|
|
883
|
+
children: payload
|
|
863
884
|
})]
|
|
864
|
-
})
|
|
885
|
+
}) : null
|
|
865
886
|
]
|
|
866
|
-
})
|
|
887
|
+
});
|
|
867
888
|
}
|
|
868
|
-
function
|
|
869
|
-
|
|
870
|
-
if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
871
|
-
return `${(bytes / 1048576).toFixed(1)} MB`;
|
|
872
|
-
}
|
|
873
|
-
function getFileIconName(filename, isImage) {
|
|
874
|
-
if (isImage) return "image";
|
|
875
|
-
const ext = filename.split(".").pop()?.toLowerCase();
|
|
876
|
-
if ([
|
|
877
|
-
"js",
|
|
878
|
-
"ts",
|
|
879
|
-
"jsx",
|
|
880
|
-
"tsx",
|
|
881
|
-
"py",
|
|
882
|
-
"rb",
|
|
883
|
-
"go",
|
|
884
|
-
"rs",
|
|
885
|
-
"java",
|
|
886
|
-
"kt",
|
|
887
|
-
"swift",
|
|
888
|
-
"c",
|
|
889
|
-
"cpp",
|
|
890
|
-
"h",
|
|
891
|
-
"hpp",
|
|
892
|
-
"cs",
|
|
893
|
-
"php"
|
|
894
|
-
].includes(ext || "")) return "code";
|
|
895
|
-
if ([
|
|
896
|
-
"json",
|
|
897
|
-
"yaml",
|
|
898
|
-
"yml",
|
|
899
|
-
"xml"
|
|
900
|
-
].includes(ext || "")) return "data";
|
|
901
|
-
return "text";
|
|
902
|
-
}
|
|
903
|
-
function renderFileIcon(iconName) {
|
|
904
|
-
switch (iconName) {
|
|
905
|
-
case "image":
|
|
906
|
-
return /* @__PURE__ */ jsx(Image, { className: "size-4 text-muted-foreground" });
|
|
907
|
-
case "code":
|
|
908
|
-
return /* @__PURE__ */ jsx(FileCode, { className: "size-4 text-muted-foreground" });
|
|
909
|
-
case "data":
|
|
910
|
-
return /* @__PURE__ */ jsx(FileBraces, { className: "size-4 text-muted-foreground" });
|
|
911
|
-
default:
|
|
912
|
-
return /* @__PURE__ */ jsx(FileText, { className: "size-4 text-muted-foreground" });
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
function FileAttachment({ id, filename, size, isImage, url, onRemove, className, display = "chip", enableImagePreview = true }) {
|
|
916
|
-
const [isHovered, setIsHovered] = useState(false);
|
|
917
|
-
const [isLightboxOpen, setIsLightboxOpen] = useState(false);
|
|
918
|
-
const iconName = getFileIconName(filename, isImage);
|
|
919
|
-
const isImageOnly = display === "image-only" && isImage && !!url;
|
|
920
|
-
const canPreview = Boolean(enableImagePreview && isImage && url);
|
|
921
|
-
const openLightbox = (event) => {
|
|
922
|
-
event?.stopPropagation();
|
|
923
|
-
setIsLightboxOpen(true);
|
|
924
|
-
};
|
|
925
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
926
|
-
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),
|
|
927
|
-
onMouseEnter: () => setIsHovered(true),
|
|
928
|
-
onMouseLeave: () => setIsHovered(false),
|
|
929
|
-
children: [
|
|
930
|
-
isImageOnly ? /* @__PURE__ */ jsx("div", {
|
|
931
|
-
className: cn("size-8 shrink-0 overflow-hidden rounded-[calc(var(--an-input-border-radius)-var(--an-context-padding)-2px)]", canPreview && "cursor-pointer"),
|
|
932
|
-
onClick: canPreview ? openLightbox : void 0,
|
|
933
|
-
role: canPreview ? "button" : void 0,
|
|
934
|
-
tabIndex: canPreview ? 0 : void 0,
|
|
935
|
-
"aria-label": canPreview ? `Preview ${filename}` : void 0,
|
|
936
|
-
onKeyDown: canPreview ? (event) => {
|
|
937
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
938
|
-
event.preventDefault();
|
|
939
|
-
openLightbox();
|
|
940
|
-
}
|
|
941
|
-
} : void 0,
|
|
942
|
-
children: /* @__PURE__ */ jsx("img", {
|
|
943
|
-
src: url,
|
|
944
|
-
alt: filename,
|
|
945
|
-
className: "h-full w-full object-cover"
|
|
946
|
-
})
|
|
947
|
-
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [isImage && url ? /* @__PURE__ */ jsx("div", {
|
|
948
|
-
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"),
|
|
949
|
-
onClick: canPreview ? openLightbox : void 0,
|
|
950
|
-
role: canPreview ? "button" : void 0,
|
|
951
|
-
tabIndex: canPreview ? 0 : void 0,
|
|
952
|
-
"aria-label": canPreview ? `Preview ${filename}` : void 0,
|
|
953
|
-
onKeyDown: canPreview ? (event) => {
|
|
954
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
955
|
-
event.preventDefault();
|
|
956
|
-
openLightbox();
|
|
957
|
-
}
|
|
958
|
-
} : void 0,
|
|
959
|
-
children: /* @__PURE__ */ jsx("img", {
|
|
960
|
-
src: url,
|
|
961
|
-
alt: filename,
|
|
962
|
-
className: "aspect-square h-full w-full object-cover"
|
|
963
|
-
})
|
|
964
|
-
}) : /* @__PURE__ */ jsx("div", {
|
|
965
|
-
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",
|
|
966
|
-
children: renderFileIcon(iconName)
|
|
967
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
968
|
-
className: "flex min-w-0 flex-col",
|
|
969
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
970
|
-
className: "truncate text-sm font-medium text-foreground",
|
|
971
|
-
title: filename,
|
|
972
|
-
children: filename
|
|
973
|
-
}), size !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
974
|
-
className: "text-[0.625rem] text-muted-foreground",
|
|
975
|
-
children: formatFileSize(size)
|
|
976
|
-
})]
|
|
977
|
-
})] }),
|
|
978
|
-
onRemove && /* @__PURE__ */ jsx("button", {
|
|
979
|
-
onClick: (e) => {
|
|
980
|
-
e.stopPropagation();
|
|
981
|
-
onRemove();
|
|
982
|
-
},
|
|
983
|
-
"aria-label": `Remove ${filename}`,
|
|
984
|
-
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"}`,
|
|
985
|
-
type: "button",
|
|
986
|
-
children: /* @__PURE__ */ jsx(X, { className: "size-3" })
|
|
987
|
-
}),
|
|
988
|
-
canPreview && url && /* @__PURE__ */ jsx(ImageLightbox, {
|
|
989
|
-
open: isLightboxOpen,
|
|
990
|
-
onClose: () => setIsLightboxOpen(false),
|
|
991
|
-
images: [{
|
|
992
|
-
id,
|
|
993
|
-
url,
|
|
994
|
-
filename
|
|
995
|
-
}]
|
|
996
|
-
})
|
|
997
|
-
]
|
|
998
|
-
});
|
|
999
|
-
}
|
|
1000
|
-
function isRecord$2(value) {
|
|
1001
|
-
return typeof value === "object" && value !== null;
|
|
889
|
+
function isRecord$2(value) {
|
|
890
|
+
return typeof value === "object" && value !== null;
|
|
1002
891
|
}
|
|
1003
892
|
function isTextPart(part) {
|
|
1004
893
|
return isRecord$2(part) && part.type === "text" && typeof part.text === "string";
|
|
@@ -1022,170 +911,19 @@ function getTextFromParts(parts, joiner) {
|
|
|
1022
911
|
function isRecord$1(value) {
|
|
1023
912
|
return typeof value === "object" && value !== null;
|
|
1024
913
|
}
|
|
1025
|
-
function
|
|
1026
|
-
if (
|
|
1027
|
-
const
|
|
1028
|
-
if (
|
|
1029
|
-
if (type === "image") {
|
|
1030
|
-
const imagePart = part;
|
|
1031
|
-
return imagePart.url ?? imagePart.image ?? null;
|
|
1032
|
-
}
|
|
1033
|
-
if (type === "data-image") return part.data?.url ?? null;
|
|
1034
|
-
if (type === "file") {
|
|
1035
|
-
const filePart = part;
|
|
1036
|
-
if (filePart.mimeType?.startsWith("image/")) {
|
|
1037
|
-
if (filePart.url) return filePart.url;
|
|
1038
|
-
if (filePart.data) return `data:${filePart.mimeType};base64,${filePart.data}`;
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
return null;
|
|
1042
|
-
}
|
|
1043
|
-
function getFileFromPart(part) {
|
|
1044
|
-
if (!isRecord$1(part)) return null;
|
|
1045
|
-
if (part.type !== "file") return null;
|
|
1046
|
-
const filePart = part;
|
|
1047
|
-
const filename = filePart.filename || filePart.name || filePart.fileName || "Attachment";
|
|
1048
|
-
if (filePart.mimeType?.startsWith("image/") ?? false) return null;
|
|
1049
|
-
return {
|
|
1050
|
-
filename,
|
|
1051
|
-
size: filePart.size
|
|
1052
|
-
};
|
|
1053
|
-
}
|
|
1054
|
-
var UserMessage = memo(function UserMessage2({ message, className, enableImagePreview = true }) {
|
|
1055
|
-
const [lightboxIndex, setLightboxIndex] = useState(null);
|
|
1056
|
-
const text = (message.parts?.filter(isTextPart) ?? []).map((p) => p.text).join("");
|
|
1057
|
-
const images = [];
|
|
1058
|
-
const files = [];
|
|
1059
|
-
for (const part of message.parts ?? []) {
|
|
1060
|
-
const imageUrl = getImageUrlFromPart(part);
|
|
1061
|
-
if (imageUrl) images.push(imageUrl);
|
|
1062
|
-
const file = getFileFromPart(part);
|
|
1063
|
-
if (file) files.push(file);
|
|
1064
|
-
}
|
|
1065
|
-
if (isRecord$1(message) && Array.isArray(message.experimental_attachments)) {
|
|
1066
|
-
for (const att of message.experimental_attachments) if (att.contentType?.startsWith("image/") && att.url) images.push(att.url);
|
|
1067
|
-
}
|
|
1068
|
-
if (!text && images.length === 0 && files.length === 0) return null;
|
|
1069
|
-
const lightboxImages = images.map((url, i) => ({
|
|
1070
|
-
id: `${message.id}-img-${i}`,
|
|
1071
|
-
url,
|
|
1072
|
-
filename: `image-${i + 1}`
|
|
1073
|
-
}));
|
|
1074
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
1075
|
-
className: cn("flex flex-col items-end gap-1", className),
|
|
1076
|
-
children: [
|
|
1077
|
-
images.length > 0 && images.map((url, i) => /* @__PURE__ */ jsx("div", {
|
|
1078
|
-
className: cn("max-w-[200px] rounded-an-message bg-an-foreground/4 p-1.5", enableImagePreview && "cursor-pointer"),
|
|
1079
|
-
onClick: enableImagePreview ? () => setLightboxIndex(i) : void 0,
|
|
1080
|
-
role: enableImagePreview ? "button" : void 0,
|
|
1081
|
-
tabIndex: enableImagePreview ? 0 : void 0,
|
|
1082
|
-
onKeyDown: enableImagePreview ? (event) => {
|
|
1083
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
1084
|
-
event.preventDefault();
|
|
1085
|
-
setLightboxIndex(i);
|
|
1086
|
-
}
|
|
1087
|
-
} : void 0,
|
|
1088
|
-
children: /* @__PURE__ */ jsx("img", {
|
|
1089
|
-
src: url,
|
|
1090
|
-
alt: "attachment",
|
|
1091
|
-
className: "block max-h-[120px] max-w-[184px] rounded-an-message-inner object-cover"
|
|
1092
|
-
})
|
|
1093
|
-
}, url)),
|
|
1094
|
-
enableImagePreview && lightboxImages.length > 0 && /* @__PURE__ */ jsx(ImageLightbox, {
|
|
1095
|
-
open: lightboxIndex !== null,
|
|
1096
|
-
onClose: () => setLightboxIndex(null),
|
|
1097
|
-
images: lightboxImages,
|
|
1098
|
-
initialIndex: lightboxIndex ?? 0
|
|
1099
|
-
}),
|
|
1100
|
-
files.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
1101
|
-
className: "flex flex-col items-end gap-2",
|
|
1102
|
-
children: files.map((file, i) => /* @__PURE__ */ jsx(FileAttachment, {
|
|
1103
|
-
id: `${file.filename}-${i}`,
|
|
1104
|
-
filename: file.filename,
|
|
1105
|
-
size: file.size
|
|
1106
|
-
}, `${file.filename}-${file.size}`))
|
|
1107
|
-
}),
|
|
1108
|
-
text && /* @__PURE__ */ jsx("div", {
|
|
1109
|
-
className: "ms-[70px] max-w-[calc(95%-40px)]",
|
|
1110
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
1111
|
-
className: "rounded-an-message bg-an-user-message-bg px-3.5 py-1.5 text-sm text-an-user-message-text transition-colors",
|
|
1112
|
-
children: /* @__PURE__ */ jsx("p", {
|
|
1113
|
-
className: "leading-5 wrap-break-word whitespace-pre-wrap",
|
|
1114
|
-
children: text
|
|
1115
|
-
})
|
|
1116
|
-
})
|
|
1117
|
-
})
|
|
1118
|
-
]
|
|
1119
|
-
});
|
|
1120
|
-
});
|
|
1121
|
-
var ErrorMessage = memo(function ErrorMessage2({ title = "Something went wrong", message, className }) {
|
|
1122
|
-
return /* @__PURE__ */ jsx("div", {
|
|
1123
|
-
className: cn("flex justify-start", className),
|
|
1124
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
1125
|
-
className: "rounded-[8px] border border-red-500/30 bg-red-500/10 px-4 py-2.5 text-sm text-an-foreground",
|
|
1126
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
1127
|
-
className: "font-medium text-an-foreground",
|
|
1128
|
-
children: title
|
|
1129
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
1130
|
-
className: "mt-0.5 text-an-foreground-muted",
|
|
1131
|
-
children: message
|
|
1132
|
-
})]
|
|
1133
|
-
})
|
|
1134
|
-
});
|
|
1135
|
-
});
|
|
1136
|
-
function formatPayload(value) {
|
|
1137
|
-
if (typeof value === "string") return value;
|
|
1138
|
-
if (value === void 0) return "";
|
|
914
|
+
function parseStructuredJson(value) {
|
|
915
|
+
if (typeof value !== "string") return value;
|
|
916
|
+
const trimmed = value.trim();
|
|
917
|
+
if (!trimmed) return value;
|
|
1139
918
|
try {
|
|
1140
|
-
|
|
919
|
+
const parsed = JSON.parse(trimmed);
|
|
920
|
+
return isRecord$1(parsed) || Array.isArray(parsed) ? parsed : value;
|
|
1141
921
|
} catch {
|
|
1142
|
-
return
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
function PayloadPart({ part }) {
|
|
1146
|
-
const payload = formatPayload(part.payload);
|
|
1147
|
-
return /* @__PURE__ */ jsxs("section", {
|
|
1148
|
-
"data-payload-kind": part.kind,
|
|
1149
|
-
className: "w-full min-w-0 overflow-hidden rounded-xl border border-border/60 bg-muted/40 text-sm",
|
|
1150
|
-
children: [
|
|
1151
|
-
/* @__PURE__ */ jsx("div", {
|
|
1152
|
-
className: "border-b border-border/50 px-3 py-2 text-xs font-medium text-muted-foreground",
|
|
1153
|
-
children: part.title
|
|
1154
|
-
}),
|
|
1155
|
-
part.text ? /* @__PURE__ */ jsx("pre", {
|
|
1156
|
-
className: "m-0 whitespace-pre-wrap break-words p-3 font-mono text-xs leading-5 text-foreground/80",
|
|
1157
|
-
children: part.text
|
|
1158
|
-
}) : null,
|
|
1159
|
-
payload ? /* @__PURE__ */ jsxs("details", {
|
|
1160
|
-
open: true,
|
|
1161
|
-
className: "border-t border-border/50 px-3 py-2",
|
|
1162
|
-
children: [/* @__PURE__ */ jsx("summary", {
|
|
1163
|
-
className: "cursor-pointer text-xs font-medium text-muted-foreground",
|
|
1164
|
-
children: "Payload"
|
|
1165
|
-
}), /* @__PURE__ */ jsx("pre", {
|
|
1166
|
-
className: "m-0 mt-2 max-w-full whitespace-pre-wrap break-words font-mono text-xs leading-5 text-foreground/70",
|
|
1167
|
-
children: payload
|
|
1168
|
-
})]
|
|
1169
|
-
}) : null
|
|
1170
|
-
]
|
|
1171
|
-
});
|
|
1172
|
-
}
|
|
1173
|
-
function isRecord(value) {
|
|
1174
|
-
return typeof value === "object" && value !== null;
|
|
1175
|
-
}
|
|
1176
|
-
function parseStructuredJson(value) {
|
|
1177
|
-
if (typeof value !== "string") return value;
|
|
1178
|
-
const trimmed = value.trim();
|
|
1179
|
-
if (!trimmed) return value;
|
|
1180
|
-
try {
|
|
1181
|
-
const parsed = JSON.parse(trimmed);
|
|
1182
|
-
return isRecord(parsed) || Array.isArray(parsed) ? parsed : value;
|
|
1183
|
-
} catch {
|
|
1184
|
-
return value;
|
|
922
|
+
return value;
|
|
1185
923
|
}
|
|
1186
924
|
}
|
|
1187
925
|
function normalizeToolPart(part) {
|
|
1188
|
-
if (!isRecord(part)) return part;
|
|
926
|
+
if (!isRecord$1(part)) return part;
|
|
1189
927
|
if (typeof part.type !== "string" || !part.type.startsWith("tool-")) return part;
|
|
1190
928
|
const normalizedInput = parseStructuredJson(part.input);
|
|
1191
929
|
const normalizedOutput = parseStructuredJson(part.output);
|
|
@@ -1209,70 +947,6 @@ function normalizeAssistantToolParts(parts) {
|
|
|
1209
947
|
});
|
|
1210
948
|
return changed ? normalizedParts : parts;
|
|
1211
949
|
}
|
|
1212
|
-
var timeFormatter = new Intl.DateTimeFormat("en-US", {
|
|
1213
|
-
hour: "numeric",
|
|
1214
|
-
minute: "2-digit",
|
|
1215
|
-
hour12: true
|
|
1216
|
-
});
|
|
1217
|
-
var dateFormatter = new Intl.DateTimeFormat("en-US", {
|
|
1218
|
-
month: "short",
|
|
1219
|
-
day: "numeric"
|
|
1220
|
-
});
|
|
1221
|
-
function formatTimestamp(date) {
|
|
1222
|
-
const now = /* @__PURE__ */ new Date();
|
|
1223
|
-
if (date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate()) return timeFormatter.format(date);
|
|
1224
|
-
return dateFormatter.format(date);
|
|
1225
|
-
}
|
|
1226
|
-
function CopyButton({ text, onCopied }) {
|
|
1227
|
-
const [copied, setCopied] = useState(false);
|
|
1228
|
-
const copiedTimerRef = useRef(null);
|
|
1229
|
-
useEffect(() => {
|
|
1230
|
-
return () => {
|
|
1231
|
-
if (copiedTimerRef.current) window.clearTimeout(copiedTimerRef.current);
|
|
1232
|
-
};
|
|
1233
|
-
}, []);
|
|
1234
|
-
const handleCopy = async () => {
|
|
1235
|
-
try {
|
|
1236
|
-
await navigator.clipboard.writeText(text);
|
|
1237
|
-
setCopied(true);
|
|
1238
|
-
if (copiedTimerRef.current) window.clearTimeout(copiedTimerRef.current);
|
|
1239
|
-
copiedTimerRef.current = window.setTimeout(() => {
|
|
1240
|
-
setCopied(false);
|
|
1241
|
-
copiedTimerRef.current = null;
|
|
1242
|
-
}, 2e3);
|
|
1243
|
-
notify.success("Copied to clipboard");
|
|
1244
|
-
onCopied?.();
|
|
1245
|
-
} catch {
|
|
1246
|
-
notify.error("Failed to copy to clipboard");
|
|
1247
|
-
}
|
|
1248
|
-
};
|
|
1249
|
-
return /* @__PURE__ */ jsx("button", {
|
|
1250
|
-
type: "button",
|
|
1251
|
-
tabIndex: -1,
|
|
1252
|
-
"aria-label": copied ? "Copied" : "Copy message",
|
|
1253
|
-
onClick: handleCopy,
|
|
1254
|
-
onPointerDown: (event) => {
|
|
1255
|
-
event.stopPropagation();
|
|
1256
|
-
},
|
|
1257
|
-
onMouseDown: (event) => event.stopPropagation(),
|
|
1258
|
-
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"),
|
|
1259
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
1260
|
-
className: "relative size-3.5",
|
|
1261
|
-
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") })]
|
|
1262
|
-
})
|
|
1263
|
-
});
|
|
1264
|
-
}
|
|
1265
|
-
function MessageToolbar({ text, timestamp, heightClass, hoverClass, isVisible, alignClass, onCopied }) {
|
|
1266
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
1267
|
-
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"),
|
|
1268
|
-
onMouseDown: (event) => event.stopPropagation(),
|
|
1269
|
-
onPointerDown: (event) => event.stopPropagation(),
|
|
1270
|
-
children: [timestamp && /* @__PURE__ */ jsx("span", { children: timestamp }), text && /* @__PURE__ */ jsx(CopyButton, {
|
|
1271
|
-
text,
|
|
1272
|
-
onCopied
|
|
1273
|
-
})]
|
|
1274
|
-
});
|
|
1275
|
-
}
|
|
1276
950
|
memo(function UserTurn(props) {
|
|
1277
951
|
const { message, UserMessageComponent, userMessageClassName, onCopied, display } = props;
|
|
1278
952
|
const { enableImagePreview, showCopyToolbar, isMounted, isCopyVisible } = display;
|
|
@@ -1328,166 +1002,492 @@ memo(function AssistantTurn(props) {
|
|
|
1328
1002
|
onOpenArtifact
|
|
1329
1003
|
}, msg.id);
|
|
1330
1004
|
})
|
|
1331
|
-
}), (showToolbar || isCopyVisible) && /* @__PURE__ */ jsx(MessageToolbar, {
|
|
1332
|
-
text: toolbarText,
|
|
1333
|
-
heightClass: "h-[48px] flex items-start w-full",
|
|
1334
|
-
hoverClass: "group-hover/assistant-turn:opacity-100 group-hover/assistant-turn:pointer-events-auto",
|
|
1335
|
-
isVisible: isCopyVisible,
|
|
1336
|
-
alignClass: "justify-start",
|
|
1337
|
-
onCopied: () => onCopied(copyKey)
|
|
1338
|
-
})]
|
|
1005
|
+
}), (showToolbar || isCopyVisible) && /* @__PURE__ */ jsx(MessageToolbar, {
|
|
1006
|
+
text: toolbarText,
|
|
1007
|
+
heightClass: "h-[48px] flex items-start w-full",
|
|
1008
|
+
hoverClass: "group-hover/assistant-turn:opacity-100 group-hover/assistant-turn:pointer-events-auto",
|
|
1009
|
+
isVisible: isCopyVisible,
|
|
1010
|
+
alignClass: "justify-start",
|
|
1011
|
+
onCopied: () => onCopied(copyKey)
|
|
1012
|
+
})]
|
|
1013
|
+
});
|
|
1014
|
+
});
|
|
1015
|
+
var TOOL_CALL_KEY_PREFIX = "tool-call:";
|
|
1016
|
+
var UNKEYED_TOOL_KEY_PREFIX = "unkeyed-tool:";
|
|
1017
|
+
function getAssistantToolElementKey(messageId, part, occurrence) {
|
|
1018
|
+
if (part.toolCallId) return `${TOOL_CALL_KEY_PREFIX}${part.toolCallId}`;
|
|
1019
|
+
return `${UNKEYED_TOOL_KEY_PREFIX}${messageId}:${part.type}:${occurrence}`;
|
|
1020
|
+
}
|
|
1021
|
+
function buildAssistantElements(parts, opts) {
|
|
1022
|
+
const { messageId, isLast, isStreaming, suppressQuestionTool, suppressTextWhenPlanWrite = false, ToolRendererComponent, TextRendererComponent, toolRenderers, onOpenUIAction, onOpenUIArtifactReady, onOpenArtifact } = opts;
|
|
1023
|
+
const elems = [];
|
|
1024
|
+
const textChunks = [];
|
|
1025
|
+
const hasPlanWritePresentation = suppressTextWhenPlanWrite && parts.some((part) => isV5ToolPart(part) && part.type === "tool-PlanWrite");
|
|
1026
|
+
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));
|
|
1027
|
+
const nestedToolsMap = /* @__PURE__ */ new Map();
|
|
1028
|
+
const nestedToolIds = /* @__PURE__ */ new Set();
|
|
1029
|
+
const unkeyedToolOccurrences = /* @__PURE__ */ new Map();
|
|
1030
|
+
for (const part of parts) {
|
|
1031
|
+
if (!isV5ToolPart(part)) continue;
|
|
1032
|
+
if (part.type === "tool-TaskOutput") continue;
|
|
1033
|
+
if (!part.toolCallId || !part.toolCallId.includes(":")) continue;
|
|
1034
|
+
const parentId = part.toolCallId.split(":")[0];
|
|
1035
|
+
if (!taskPartIds.has(parentId)) continue;
|
|
1036
|
+
if (!nestedToolsMap.has(parentId)) nestedToolsMap.set(parentId, []);
|
|
1037
|
+
nestedToolsMap.get(parentId).push(part);
|
|
1038
|
+
nestedToolIds.add(part.toolCallId);
|
|
1039
|
+
}
|
|
1040
|
+
let i = 0;
|
|
1041
|
+
while (i < parts.length) {
|
|
1042
|
+
const part = parts[i];
|
|
1043
|
+
if (isV5ToolPart(part) && part.type === "tool-TaskOutput") {
|
|
1044
|
+
i++;
|
|
1045
|
+
continue;
|
|
1046
|
+
}
|
|
1047
|
+
if (isTextPart(part)) {
|
|
1048
|
+
const text2 = part.text;
|
|
1049
|
+
if (text2 && !hasPlanWritePresentation) textChunks.push(text2);
|
|
1050
|
+
i++;
|
|
1051
|
+
continue;
|
|
1052
|
+
}
|
|
1053
|
+
if (isErrorPart(part)) {
|
|
1054
|
+
elems.push(/* @__PURE__ */ jsx(ErrorMessage, {
|
|
1055
|
+
title: part.title,
|
|
1056
|
+
message: part.message
|
|
1057
|
+
}, `${messageId}-error-${part.title}-${part.message}`));
|
|
1058
|
+
i++;
|
|
1059
|
+
continue;
|
|
1060
|
+
}
|
|
1061
|
+
if (isPayloadPart(part)) {
|
|
1062
|
+
elems.push(/* @__PURE__ */ jsx(PayloadPart, { part }, `${messageId}-payload-${i}`));
|
|
1063
|
+
i++;
|
|
1064
|
+
continue;
|
|
1065
|
+
}
|
|
1066
|
+
if (isV5ToolPart(part)) {
|
|
1067
|
+
if (suppressQuestionTool && part.type === "tool-Question") {
|
|
1068
|
+
i++;
|
|
1069
|
+
continue;
|
|
1070
|
+
}
|
|
1071
|
+
if (part.toolCallId && nestedToolIds.has(part.toolCallId)) {
|
|
1072
|
+
i++;
|
|
1073
|
+
continue;
|
|
1074
|
+
}
|
|
1075
|
+
const chatStreamingStatus = isLast && isStreaming ? "streaming" : void 0;
|
|
1076
|
+
const toolCallId = part.toolCallId;
|
|
1077
|
+
const nestedTools = (part.type === "tool-Task" || part.type === "tool-Agent") && toolCallId ? nestedToolsMap.get(toolCallId) || [] : void 0;
|
|
1078
|
+
const occurrence = part.toolCallId ? 0 : unkeyedToolOccurrences.get(part.type) ?? 0;
|
|
1079
|
+
if (!part.toolCallId) unkeyedToolOccurrences.set(part.type, occurrence + 1);
|
|
1080
|
+
elems.push(/* @__PURE__ */ jsx(ToolRendererComponent, {
|
|
1081
|
+
part,
|
|
1082
|
+
nestedTools,
|
|
1083
|
+
chatStatus: chatStreamingStatus,
|
|
1084
|
+
toolRenderers
|
|
1085
|
+
}, getAssistantToolElementKey(messageId, part, occurrence)));
|
|
1086
|
+
i++;
|
|
1087
|
+
continue;
|
|
1088
|
+
}
|
|
1089
|
+
i++;
|
|
1090
|
+
}
|
|
1091
|
+
const text = textChunks.join("\n\n");
|
|
1092
|
+
if (text) elems.push(/* @__PURE__ */ jsx("div", {
|
|
1093
|
+
className: "group/assistant-text text-[0.875rem]",
|
|
1094
|
+
children: /* @__PURE__ */ jsx(TextRendererComponent, {
|
|
1095
|
+
content: text,
|
|
1096
|
+
isStreaming,
|
|
1097
|
+
messageId,
|
|
1098
|
+
onOpenUIAction,
|
|
1099
|
+
onOpenUIArtifactReady,
|
|
1100
|
+
onOpenArtifact,
|
|
1101
|
+
className: "leading-relaxed [&_p]:leading-relaxed"
|
|
1102
|
+
})
|
|
1103
|
+
}, `${messageId}-text-final`));
|
|
1104
|
+
return elems;
|
|
1105
|
+
}
|
|
1106
|
+
function AssistantParts({ msg, isLast, isStreaming, suppressQuestionTool, ToolRendererComponent, TextRendererComponent, toolRenderers, onOpenUIAction, onOpenUIArtifactReady, onOpenArtifact }) {
|
|
1107
|
+
const parts = useMemo(() => normalizeAssistantToolParts(msg.parts ?? []), [msg.parts]);
|
|
1108
|
+
const elements = useMemo(() => buildAssistantElements(parts, {
|
|
1109
|
+
messageId: msg.id,
|
|
1110
|
+
isLast,
|
|
1111
|
+
isStreaming,
|
|
1112
|
+
suppressQuestionTool,
|
|
1113
|
+
ToolRendererComponent,
|
|
1114
|
+
TextRendererComponent,
|
|
1115
|
+
toolRenderers,
|
|
1116
|
+
onOpenUIAction,
|
|
1117
|
+
onOpenUIArtifactReady,
|
|
1118
|
+
onOpenArtifact
|
|
1119
|
+
}), [
|
|
1120
|
+
parts,
|
|
1121
|
+
msg.id,
|
|
1122
|
+
isLast,
|
|
1123
|
+
isStreaming,
|
|
1124
|
+
suppressQuestionTool,
|
|
1125
|
+
ToolRendererComponent,
|
|
1126
|
+
TextRendererComponent,
|
|
1127
|
+
toolRenderers,
|
|
1128
|
+
onOpenUIAction,
|
|
1129
|
+
onOpenUIArtifactReady,
|
|
1130
|
+
onOpenArtifact
|
|
1131
|
+
]);
|
|
1132
|
+
if (elements.length > 1) return /* @__PURE__ */ jsx("div", {
|
|
1133
|
+
className: "group/assistant-turn flex flex-col gap-3",
|
|
1134
|
+
children: elements
|
|
1135
|
+
});
|
|
1136
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1137
|
+
className: "group/assistant-turn",
|
|
1138
|
+
children: elements
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1141
|
+
function ImageLightbox({ open, onClose, images, initialIndex = 0 }) {
|
|
1142
|
+
const [currentIndex, setCurrentIndex] = useState(initialIndex);
|
|
1143
|
+
const hasMultipleImages = images.length > 1;
|
|
1144
|
+
useEffect(() => {
|
|
1145
|
+
if (open) setCurrentIndex(initialIndex);
|
|
1146
|
+
}, [open, initialIndex]);
|
|
1147
|
+
const goToPrevious = useCallback((event) => {
|
|
1148
|
+
event?.stopPropagation();
|
|
1149
|
+
setCurrentIndex((prev) => prev > 0 ? prev - 1 : images.length - 1);
|
|
1150
|
+
}, [images.length]);
|
|
1151
|
+
const goToNext = useCallback((event) => {
|
|
1152
|
+
event?.stopPropagation();
|
|
1153
|
+
setCurrentIndex((prev) => prev < images.length - 1 ? prev + 1 : 0);
|
|
1154
|
+
}, [images.length]);
|
|
1155
|
+
const onLightboxKeyDown = useEffectEvent((event) => {
|
|
1156
|
+
switch (event.key) {
|
|
1157
|
+
case "ArrowLeft":
|
|
1158
|
+
event.preventDefault();
|
|
1159
|
+
if (hasMultipleImages) goToPrevious();
|
|
1160
|
+
break;
|
|
1161
|
+
case "ArrowRight":
|
|
1162
|
+
event.preventDefault();
|
|
1163
|
+
if (hasMultipleImages) goToNext();
|
|
1164
|
+
}
|
|
1165
|
+
});
|
|
1166
|
+
useEffect(() => {
|
|
1167
|
+
if (!open) return;
|
|
1168
|
+
const handler = (event) => onLightboxKeyDown(event);
|
|
1169
|
+
window.addEventListener("keydown", handler, true);
|
|
1170
|
+
return () => window.removeEventListener("keydown", handler, true);
|
|
1171
|
+
}, [open]);
|
|
1172
|
+
useEffect(() => {
|
|
1173
|
+
if (!open) return;
|
|
1174
|
+
const previousOverflow = document.body.style.overflow;
|
|
1175
|
+
document.body.style.overflow = "hidden";
|
|
1176
|
+
return () => {
|
|
1177
|
+
document.body.style.overflow = previousOverflow;
|
|
1178
|
+
};
|
|
1179
|
+
}, [open]);
|
|
1180
|
+
const dialogRef = useRef(null);
|
|
1181
|
+
const onLightDismiss = useEffectEvent((event) => {
|
|
1182
|
+
if (dialogRef.current && event.target === dialogRef.current) onClose();
|
|
1183
|
+
});
|
|
1184
|
+
useEffect(() => {
|
|
1185
|
+
if (!open) return;
|
|
1186
|
+
const dialog = dialogRef.current;
|
|
1187
|
+
if (!dialog) return;
|
|
1188
|
+
if (!dialog.open) dialog.showModal();
|
|
1189
|
+
const handler = (event) => onLightDismiss(event);
|
|
1190
|
+
dialog.addEventListener("click", handler);
|
|
1191
|
+
return () => {
|
|
1192
|
+
dialog.removeEventListener("click", handler);
|
|
1193
|
+
if (dialog.open) dialog.close();
|
|
1194
|
+
};
|
|
1195
|
+
}, [open]);
|
|
1196
|
+
if (typeof document === "undefined") return null;
|
|
1197
|
+
if (!open) return null;
|
|
1198
|
+
const currentImage = images[currentIndex] ?? images[0];
|
|
1199
|
+
if (!currentImage?.url) return null;
|
|
1200
|
+
return createPortal(/* @__PURE__ */ jsxs("dialog", {
|
|
1201
|
+
ref: dialogRef,
|
|
1202
|
+
"aria-label": "Image viewer",
|
|
1203
|
+
onClose: () => onClose(),
|
|
1204
|
+
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",
|
|
1205
|
+
children: [
|
|
1206
|
+
/* @__PURE__ */ jsx("button", {
|
|
1207
|
+
type: "button",
|
|
1208
|
+
onClick: onClose,
|
|
1209
|
+
"aria-label": "Close fullscreen (Esc)",
|
|
1210
|
+
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",
|
|
1211
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-5" })
|
|
1212
|
+
}),
|
|
1213
|
+
hasMultipleImages && /* @__PURE__ */ jsx("button", {
|
|
1214
|
+
type: "button",
|
|
1215
|
+
onClick: goToPrevious,
|
|
1216
|
+
"aria-label": "Previous image (\u2190)",
|
|
1217
|
+
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",
|
|
1218
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-6" })
|
|
1219
|
+
}),
|
|
1220
|
+
/* @__PURE__ */ jsx("img", {
|
|
1221
|
+
src: currentImage.url,
|
|
1222
|
+
alt: currentImage.filename ?? "Image preview",
|
|
1223
|
+
className: "max-h-[85vh] max-w-[90vw] object-contain select-none",
|
|
1224
|
+
onClick: (event) => event.stopPropagation(),
|
|
1225
|
+
draggable: false
|
|
1226
|
+
}),
|
|
1227
|
+
hasMultipleImages && /* @__PURE__ */ jsx("button", {
|
|
1228
|
+
type: "button",
|
|
1229
|
+
onClick: goToNext,
|
|
1230
|
+
"aria-label": "Next image (\u2192)",
|
|
1231
|
+
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",
|
|
1232
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-6" })
|
|
1233
|
+
}),
|
|
1234
|
+
hasMultipleImages && /* @__PURE__ */ jsxs("div", {
|
|
1235
|
+
className: "absolute bottom-6 left-1/2 flex -translate-x-1/2 flex-col items-center gap-3",
|
|
1236
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1237
|
+
className: "flex gap-2",
|
|
1238
|
+
children: images.map((image, idx) => /* @__PURE__ */ jsx("button", {
|
|
1239
|
+
type: "button",
|
|
1240
|
+
onClick: (event) => {
|
|
1241
|
+
event.stopPropagation();
|
|
1242
|
+
setCurrentIndex(idx);
|
|
1243
|
+
},
|
|
1244
|
+
"aria-label": `Go to image ${idx + 1}`,
|
|
1245
|
+
className: cn("size-2 rounded-full transition-all", idx === currentIndex ? "scale-125 bg-white" : "bg-white/40 hover:bg-white/60")
|
|
1246
|
+
}, image.url))
|
|
1247
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
1248
|
+
className: "text-sm text-white/70",
|
|
1249
|
+
children: [
|
|
1250
|
+
currentIndex + 1,
|
|
1251
|
+
" / ",
|
|
1252
|
+
images.length
|
|
1253
|
+
]
|
|
1254
|
+
})]
|
|
1255
|
+
})
|
|
1256
|
+
]
|
|
1257
|
+
}), document.body);
|
|
1258
|
+
}
|
|
1259
|
+
function formatFileSize(bytes) {
|
|
1260
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
1261
|
+
if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1262
|
+
return `${(bytes / 1048576).toFixed(1)} MB`;
|
|
1263
|
+
}
|
|
1264
|
+
function getFileIconName(filename, isImage) {
|
|
1265
|
+
if (isImage) return "image";
|
|
1266
|
+
const ext = filename.split(".").pop()?.toLowerCase();
|
|
1267
|
+
if ([
|
|
1268
|
+
"js",
|
|
1269
|
+
"ts",
|
|
1270
|
+
"jsx",
|
|
1271
|
+
"tsx",
|
|
1272
|
+
"py",
|
|
1273
|
+
"rb",
|
|
1274
|
+
"go",
|
|
1275
|
+
"rs",
|
|
1276
|
+
"java",
|
|
1277
|
+
"kt",
|
|
1278
|
+
"swift",
|
|
1279
|
+
"c",
|
|
1280
|
+
"cpp",
|
|
1281
|
+
"h",
|
|
1282
|
+
"hpp",
|
|
1283
|
+
"cs",
|
|
1284
|
+
"php"
|
|
1285
|
+
].includes(ext || "")) return "code";
|
|
1286
|
+
if ([
|
|
1287
|
+
"json",
|
|
1288
|
+
"yaml",
|
|
1289
|
+
"yml",
|
|
1290
|
+
"xml"
|
|
1291
|
+
].includes(ext || "")) return "data";
|
|
1292
|
+
return "text";
|
|
1293
|
+
}
|
|
1294
|
+
function renderFileIcon(iconName) {
|
|
1295
|
+
switch (iconName) {
|
|
1296
|
+
case "image":
|
|
1297
|
+
return /* @__PURE__ */ jsx(Image, { className: "size-4 text-muted-foreground" });
|
|
1298
|
+
case "code":
|
|
1299
|
+
return /* @__PURE__ */ jsx(FileCode, { className: "size-4 text-muted-foreground" });
|
|
1300
|
+
case "data":
|
|
1301
|
+
return /* @__PURE__ */ jsx(FileBraces, { className: "size-4 text-muted-foreground" });
|
|
1302
|
+
default:
|
|
1303
|
+
return /* @__PURE__ */ jsx(FileText, { className: "size-4 text-muted-foreground" });
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
function FileAttachment({ id, filename, size, isImage, url, onRemove, className, display = "chip", enableImagePreview = true }) {
|
|
1307
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
1308
|
+
const [isLightboxOpen, setIsLightboxOpen] = useState(false);
|
|
1309
|
+
const iconName = getFileIconName(filename, isImage);
|
|
1310
|
+
const isImageOnly = display === "image-only" && isImage && !!url;
|
|
1311
|
+
const canPreview = Boolean(enableImagePreview && isImage && url);
|
|
1312
|
+
const openLightbox = (event) => {
|
|
1313
|
+
event?.stopPropagation();
|
|
1314
|
+
setIsLightboxOpen(true);
|
|
1315
|
+
};
|
|
1316
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1317
|
+
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),
|
|
1318
|
+
onMouseEnter: () => setIsHovered(true),
|
|
1319
|
+
onMouseLeave: () => setIsHovered(false),
|
|
1320
|
+
children: [
|
|
1321
|
+
isImageOnly ? /* @__PURE__ */ jsx("div", {
|
|
1322
|
+
className: cn("size-8 shrink-0 overflow-hidden rounded-[calc(var(--an-input-border-radius)-var(--an-context-padding)-2px)]", canPreview && "cursor-pointer"),
|
|
1323
|
+
onClick: canPreview ? openLightbox : void 0,
|
|
1324
|
+
role: canPreview ? "button" : void 0,
|
|
1325
|
+
tabIndex: canPreview ? 0 : void 0,
|
|
1326
|
+
"aria-label": canPreview ? `Preview ${filename}` : void 0,
|
|
1327
|
+
onKeyDown: canPreview ? (event) => {
|
|
1328
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1329
|
+
event.preventDefault();
|
|
1330
|
+
openLightbox();
|
|
1331
|
+
}
|
|
1332
|
+
} : void 0,
|
|
1333
|
+
children: /* @__PURE__ */ jsx("img", {
|
|
1334
|
+
src: url,
|
|
1335
|
+
alt: filename,
|
|
1336
|
+
className: "h-full w-full object-cover"
|
|
1337
|
+
})
|
|
1338
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [isImage && url ? /* @__PURE__ */ jsx("div", {
|
|
1339
|
+
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"),
|
|
1340
|
+
onClick: canPreview ? openLightbox : void 0,
|
|
1341
|
+
role: canPreview ? "button" : void 0,
|
|
1342
|
+
tabIndex: canPreview ? 0 : void 0,
|
|
1343
|
+
"aria-label": canPreview ? `Preview ${filename}` : void 0,
|
|
1344
|
+
onKeyDown: canPreview ? (event) => {
|
|
1345
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1346
|
+
event.preventDefault();
|
|
1347
|
+
openLightbox();
|
|
1348
|
+
}
|
|
1349
|
+
} : void 0,
|
|
1350
|
+
children: /* @__PURE__ */ jsx("img", {
|
|
1351
|
+
src: url,
|
|
1352
|
+
alt: filename,
|
|
1353
|
+
className: "aspect-square h-full w-full object-cover"
|
|
1354
|
+
})
|
|
1355
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
1356
|
+
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",
|
|
1357
|
+
children: renderFileIcon(iconName)
|
|
1358
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1359
|
+
className: "flex min-w-0 flex-col",
|
|
1360
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1361
|
+
className: "truncate text-sm font-medium text-foreground",
|
|
1362
|
+
title: filename,
|
|
1363
|
+
children: filename
|
|
1364
|
+
}), size !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
1365
|
+
className: "text-[0.625rem] text-muted-foreground",
|
|
1366
|
+
children: formatFileSize(size)
|
|
1367
|
+
})]
|
|
1368
|
+
})] }),
|
|
1369
|
+
onRemove && /* @__PURE__ */ jsx("button", {
|
|
1370
|
+
onClick: (e) => {
|
|
1371
|
+
e.stopPropagation();
|
|
1372
|
+
onRemove();
|
|
1373
|
+
},
|
|
1374
|
+
"aria-label": `Remove ${filename}`,
|
|
1375
|
+
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"}`,
|
|
1376
|
+
type: "button",
|
|
1377
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-3" })
|
|
1378
|
+
}),
|
|
1379
|
+
canPreview && url && /* @__PURE__ */ jsx(ImageLightbox, {
|
|
1380
|
+
open: isLightboxOpen,
|
|
1381
|
+
onClose: () => setIsLightboxOpen(false),
|
|
1382
|
+
images: [{
|
|
1383
|
+
id,
|
|
1384
|
+
url,
|
|
1385
|
+
filename
|
|
1386
|
+
}]
|
|
1387
|
+
})
|
|
1388
|
+
]
|
|
1339
1389
|
});
|
|
1340
|
-
});
|
|
1341
|
-
var TOOL_CALL_KEY_PREFIX = "tool-call:";
|
|
1342
|
-
var UNKEYED_TOOL_KEY_PREFIX = "unkeyed-tool:";
|
|
1343
|
-
function getAssistantToolElementKey(messageId, part, occurrence) {
|
|
1344
|
-
if (part.toolCallId) return `${TOOL_CALL_KEY_PREFIX}${part.toolCallId}`;
|
|
1345
|
-
return `${UNKEYED_TOOL_KEY_PREFIX}${messageId}:${part.type}:${occurrence}`;
|
|
1346
1390
|
}
|
|
1347
|
-
function
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
const
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
if (!isV5ToolPart(part)) continue;
|
|
1358
|
-
if (part.type === "tool-TaskOutput") continue;
|
|
1359
|
-
if (!part.toolCallId || !part.toolCallId.includes(":")) continue;
|
|
1360
|
-
const parentId = part.toolCallId.split(":")[0];
|
|
1361
|
-
if (!taskPartIds.has(parentId)) continue;
|
|
1362
|
-
if (!nestedToolsMap.has(parentId)) nestedToolsMap.set(parentId, []);
|
|
1363
|
-
nestedToolsMap.get(parentId).push(part);
|
|
1364
|
-
nestedToolIds.add(part.toolCallId);
|
|
1391
|
+
function isRecord(value) {
|
|
1392
|
+
return typeof value === "object" && value !== null;
|
|
1393
|
+
}
|
|
1394
|
+
function getImageUrlFromPart(part) {
|
|
1395
|
+
if (!isRecord(part)) return null;
|
|
1396
|
+
const type = part.type;
|
|
1397
|
+
if (typeof type !== "string") return null;
|
|
1398
|
+
if (type === "image") {
|
|
1399
|
+
const imagePart = part;
|
|
1400
|
+
return imagePart.url ?? imagePart.image ?? null;
|
|
1365
1401
|
}
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
const
|
|
1369
|
-
if (
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
}
|
|
1373
|
-
if (isTextPart(part)) {
|
|
1374
|
-
const text2 = part.text;
|
|
1375
|
-
if (text2 && !hasPlanWritePresentation) textChunks.push(text2);
|
|
1376
|
-
i++;
|
|
1377
|
-
continue;
|
|
1378
|
-
}
|
|
1379
|
-
if (isErrorPart(part)) {
|
|
1380
|
-
elems.push(/* @__PURE__ */ jsx(ErrorMessage, {
|
|
1381
|
-
title: part.title,
|
|
1382
|
-
message: part.message
|
|
1383
|
-
}, `${messageId}-error-${part.title}-${part.message}`));
|
|
1384
|
-
i++;
|
|
1385
|
-
continue;
|
|
1386
|
-
}
|
|
1387
|
-
if (isPayloadPart(part)) {
|
|
1388
|
-
elems.push(/* @__PURE__ */ jsx(PayloadPart, { part }, `${messageId}-payload-${i}`));
|
|
1389
|
-
i++;
|
|
1390
|
-
continue;
|
|
1391
|
-
}
|
|
1392
|
-
if (isV5ToolPart(part)) {
|
|
1393
|
-
if (suppressQuestionTool && part.type === "tool-Question") {
|
|
1394
|
-
i++;
|
|
1395
|
-
continue;
|
|
1396
|
-
}
|
|
1397
|
-
if (part.toolCallId && nestedToolIds.has(part.toolCallId)) {
|
|
1398
|
-
i++;
|
|
1399
|
-
continue;
|
|
1400
|
-
}
|
|
1401
|
-
const chatStreamingStatus = isLast && isStreaming ? "streaming" : void 0;
|
|
1402
|
-
const toolCallId = part.toolCallId;
|
|
1403
|
-
const nestedTools = (part.type === "tool-Task" || part.type === "tool-Agent") && toolCallId ? nestedToolsMap.get(toolCallId) || [] : void 0;
|
|
1404
|
-
const occurrence = part.toolCallId ? 0 : unkeyedToolOccurrences.get(part.type) ?? 0;
|
|
1405
|
-
if (!part.toolCallId) unkeyedToolOccurrences.set(part.type, occurrence + 1);
|
|
1406
|
-
elems.push(/* @__PURE__ */ jsx(ToolRendererComponent, {
|
|
1407
|
-
part,
|
|
1408
|
-
nestedTools,
|
|
1409
|
-
chatStatus: chatStreamingStatus,
|
|
1410
|
-
toolRenderers
|
|
1411
|
-
}, getAssistantToolElementKey(messageId, part, occurrence)));
|
|
1412
|
-
i++;
|
|
1413
|
-
continue;
|
|
1402
|
+
if (type === "data-image") return part.data?.url ?? null;
|
|
1403
|
+
if (type === "file") {
|
|
1404
|
+
const filePart = part;
|
|
1405
|
+
if (filePart.mimeType?.startsWith("image/")) {
|
|
1406
|
+
if (filePart.url) return filePart.url;
|
|
1407
|
+
if (filePart.data) return `data:${filePart.mimeType};base64,${filePart.data}`;
|
|
1414
1408
|
}
|
|
1415
|
-
i++;
|
|
1416
1409
|
}
|
|
1417
|
-
|
|
1418
|
-
if (text) elems.push(/* @__PURE__ */ jsx("div", {
|
|
1419
|
-
className: "group/assistant-text text-[0.875rem]",
|
|
1420
|
-
children: /* @__PURE__ */ jsx(TextRendererComponent, {
|
|
1421
|
-
content: text,
|
|
1422
|
-
isStreaming,
|
|
1423
|
-
messageId,
|
|
1424
|
-
onOpenUIAction,
|
|
1425
|
-
onOpenUIArtifactReady,
|
|
1426
|
-
onOpenArtifact,
|
|
1427
|
-
className: "leading-relaxed [&_p]:leading-relaxed"
|
|
1428
|
-
})
|
|
1429
|
-
}, `${messageId}-text-final`));
|
|
1430
|
-
return elems;
|
|
1410
|
+
return null;
|
|
1431
1411
|
}
|
|
1432
|
-
function
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
onOpenUIAction,
|
|
1443
|
-
onOpenUIArtifactReady,
|
|
1444
|
-
onOpenArtifact
|
|
1445
|
-
}), [
|
|
1446
|
-
parts,
|
|
1447
|
-
msg.id,
|
|
1448
|
-
isLast,
|
|
1449
|
-
isStreaming,
|
|
1450
|
-
suppressQuestionTool,
|
|
1451
|
-
ToolRendererComponent,
|
|
1452
|
-
TextRendererComponent,
|
|
1453
|
-
toolRenderers,
|
|
1454
|
-
onOpenUIAction,
|
|
1455
|
-
onOpenUIArtifactReady,
|
|
1456
|
-
onOpenArtifact
|
|
1457
|
-
]);
|
|
1458
|
-
if (elements.length > 1) return /* @__PURE__ */ jsx("div", {
|
|
1459
|
-
className: "group/assistant-turn flex flex-col gap-3",
|
|
1460
|
-
children: elements
|
|
1461
|
-
});
|
|
1462
|
-
return /* @__PURE__ */ jsx("div", {
|
|
1463
|
-
className: "group/assistant-turn",
|
|
1464
|
-
children: elements
|
|
1465
|
-
});
|
|
1412
|
+
function getFileFromPart(part) {
|
|
1413
|
+
if (!isRecord(part)) return null;
|
|
1414
|
+
if (part.type !== "file") return null;
|
|
1415
|
+
const filePart = part;
|
|
1416
|
+
const filename = filePart.filename || filePart.name || filePart.fileName || "Attachment";
|
|
1417
|
+
if (filePart.mimeType?.startsWith("image/") ?? false) return null;
|
|
1418
|
+
return {
|
|
1419
|
+
filename,
|
|
1420
|
+
size: filePart.size
|
|
1421
|
+
};
|
|
1466
1422
|
}
|
|
1467
|
-
function
|
|
1468
|
-
const
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
continue;
|
|
1478
|
-
}
|
|
1479
|
-
if (message.role !== "assistant") continue;
|
|
1480
|
-
if (!current || message.source === "local") {
|
|
1481
|
-
if (current) turns.push(current);
|
|
1482
|
-
current = { assistants: [message] };
|
|
1483
|
-
continue;
|
|
1484
|
-
}
|
|
1485
|
-
current.assistants.push(message);
|
|
1423
|
+
var UserMessage = memo(function UserMessage2({ message, className, enableImagePreview = true }) {
|
|
1424
|
+
const [lightboxIndex, setLightboxIndex] = useState(null);
|
|
1425
|
+
const text = (message.parts?.filter(isTextPart) ?? []).map((p) => p.text).join("");
|
|
1426
|
+
const images = [];
|
|
1427
|
+
const files = [];
|
|
1428
|
+
for (const part of message.parts ?? []) {
|
|
1429
|
+
const imageUrl = getImageUrlFromPart(part);
|
|
1430
|
+
if (imageUrl) images.push(imageUrl);
|
|
1431
|
+
const file = getFileFromPart(part);
|
|
1432
|
+
if (file) files.push(file);
|
|
1486
1433
|
}
|
|
1487
|
-
if (
|
|
1488
|
-
|
|
1489
|
-
}
|
|
1490
|
-
|
|
1434
|
+
if (isRecord(message) && Array.isArray(message.experimental_attachments)) {
|
|
1435
|
+
for (const att of message.experimental_attachments) if (att.contentType?.startsWith("image/") && att.url) images.push(att.url);
|
|
1436
|
+
}
|
|
1437
|
+
if (!text && images.length === 0 && files.length === 0) return null;
|
|
1438
|
+
const lightboxImages = images.map((url, i) => ({
|
|
1439
|
+
id: `${message.id}-img-${i}`,
|
|
1440
|
+
url,
|
|
1441
|
+
filename: `image-${i + 1}`
|
|
1442
|
+
}));
|
|
1443
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1444
|
+
className: cn("flex flex-col items-end gap-1", className),
|
|
1445
|
+
children: [
|
|
1446
|
+
images.length > 0 && images.map((url, i) => /* @__PURE__ */ jsx("div", {
|
|
1447
|
+
className: cn("max-w-[200px] rounded-an-message bg-an-foreground/4 p-1.5", enableImagePreview && "cursor-pointer"),
|
|
1448
|
+
onClick: enableImagePreview ? () => setLightboxIndex(i) : void 0,
|
|
1449
|
+
role: enableImagePreview ? "button" : void 0,
|
|
1450
|
+
tabIndex: enableImagePreview ? 0 : void 0,
|
|
1451
|
+
onKeyDown: enableImagePreview ? (event) => {
|
|
1452
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1453
|
+
event.preventDefault();
|
|
1454
|
+
setLightboxIndex(i);
|
|
1455
|
+
}
|
|
1456
|
+
} : void 0,
|
|
1457
|
+
children: /* @__PURE__ */ jsx("img", {
|
|
1458
|
+
src: url,
|
|
1459
|
+
alt: "attachment",
|
|
1460
|
+
className: "block max-h-[120px] max-w-[184px] rounded-an-message-inner object-cover"
|
|
1461
|
+
})
|
|
1462
|
+
}, url)),
|
|
1463
|
+
enableImagePreview && lightboxImages.length > 0 && /* @__PURE__ */ jsx(ImageLightbox, {
|
|
1464
|
+
open: lightboxIndex !== null,
|
|
1465
|
+
onClose: () => setLightboxIndex(null),
|
|
1466
|
+
images: lightboxImages,
|
|
1467
|
+
initialIndex: lightboxIndex ?? 0
|
|
1468
|
+
}),
|
|
1469
|
+
files.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
1470
|
+
className: "flex flex-col items-end gap-2",
|
|
1471
|
+
children: files.map((file, i) => /* @__PURE__ */ jsx(FileAttachment, {
|
|
1472
|
+
id: `${file.filename}-${i}`,
|
|
1473
|
+
filename: file.filename,
|
|
1474
|
+
size: file.size
|
|
1475
|
+
}, `${file.filename}-${file.size}`))
|
|
1476
|
+
}),
|
|
1477
|
+
text && /* @__PURE__ */ jsx("div", {
|
|
1478
|
+
className: "ms-[70px] max-w-[calc(95%-40px)]",
|
|
1479
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1480
|
+
className: "rounded-an-message bg-an-user-message-bg px-3.5 py-1.5 text-sm text-an-user-message-text transition-colors",
|
|
1481
|
+
children: /* @__PURE__ */ jsx("p", {
|
|
1482
|
+
className: "leading-5 wrap-break-word whitespace-pre-wrap",
|
|
1483
|
+
children: text
|
|
1484
|
+
})
|
|
1485
|
+
})
|
|
1486
|
+
})
|
|
1487
|
+
]
|
|
1488
|
+
});
|
|
1489
|
+
});
|
|
1490
|
+
var LazyGenerativeTextRenderer = lazy(() => import("./openui-renderer-MKFv6LlH-MDRSVFEY.js").then((n) => n.n).then(({ GenerativeTextRenderer }) => ({ default: GenerativeTextRenderer })));
|
|
1491
1491
|
function PlainTextFallback({ className, content }) {
|
|
1492
1492
|
return /* @__PURE__ */ jsx("div", {
|
|
1493
1493
|
className: className ? `${className} whitespace-pre-wrap` : "whitespace-pre-wrap",
|
|
@@ -1693,16 +1693,16 @@ function VirtualizedTurnList({ estimateSize, getItemKey, itemGap = 0, items, ove
|
|
|
1693
1693
|
|
|
1694
1694
|
export {
|
|
1695
1695
|
ChevronLeft,
|
|
1696
|
+
groupMessages,
|
|
1696
1697
|
MessageBubble,
|
|
1697
1698
|
MessageBubbleContent,
|
|
1698
1699
|
MessageScroller,
|
|
1699
1700
|
Message,
|
|
1700
1701
|
MessageContent,
|
|
1701
|
-
FileAttachment,
|
|
1702
|
-
UserMessage,
|
|
1703
1702
|
normalizeAssistantToolParts,
|
|
1704
1703
|
buildAssistantElements,
|
|
1705
|
-
|
|
1704
|
+
FileAttachment,
|
|
1705
|
+
UserMessage,
|
|
1706
1706
|
FleetGenerativeTextRenderer,
|
|
1707
1707
|
VirtualizedTurnList
|
|
1708
1708
|
};
|