@usecrow/ui 0.1.43 → 0.1.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +419 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +89 -65
- package/dist/index.d.ts +89 -65
- package/dist/index.js +419 -51
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -879,11 +879,44 @@ function useCrowAPI({ onIdentified, onReset } = {}) {
|
|
|
879
879
|
window.__crow_page_context = void 0;
|
|
880
880
|
console.log("[Crow] Context cleared");
|
|
881
881
|
break;
|
|
882
|
+
case "setIdentityTokenFetcher":
|
|
883
|
+
if (typeof opts !== "function") {
|
|
884
|
+
console.error("[Crow] setIdentityTokenFetcher() requires a function");
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
window.__crow_identity_token_fetcher = opts;
|
|
888
|
+
console.log("[Crow] Identity token fetcher registered");
|
|
889
|
+
break;
|
|
890
|
+
case "onToolResult":
|
|
891
|
+
if (typeof opts !== "function") {
|
|
892
|
+
console.error("[Crow] onToolResult() requires a function");
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
window.__crow_on_tool_result = opts;
|
|
896
|
+
console.log("[Crow] onToolResult callback registered");
|
|
897
|
+
break;
|
|
898
|
+
case "registerToolRenderers":
|
|
899
|
+
if (!opts || typeof opts !== "object") {
|
|
900
|
+
console.error("[Crow] registerToolRenderers() requires an object");
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
window.__crow_tool_renderers = {
|
|
904
|
+
...window.__crow_tool_renderers || {},
|
|
905
|
+
...opts
|
|
906
|
+
};
|
|
907
|
+
console.log("[Crow] Tool renderers registered");
|
|
908
|
+
break;
|
|
882
909
|
default:
|
|
883
910
|
console.warn(`[Crow] Unknown command: ${command}`);
|
|
884
911
|
}
|
|
885
912
|
};
|
|
886
913
|
console.log("[Crow] API ready");
|
|
914
|
+
const queue = window.__crow_queue;
|
|
915
|
+
if (queue?.length) {
|
|
916
|
+
console.log(`[Crow] Replaying ${queue.length} queued command(s)`);
|
|
917
|
+
queue.forEach(([cmd, opts]) => window.crow(cmd, opts));
|
|
918
|
+
window.__crow_queue = void 0;
|
|
919
|
+
}
|
|
887
920
|
const handleIdentified = () => onIdentifiedRef.current?.();
|
|
888
921
|
const handleReset = () => onResetRef.current?.();
|
|
889
922
|
window.addEventListener("crow:identified", handleIdentified);
|
|
@@ -1915,6 +1948,23 @@ function ThinkingBlock({
|
|
|
1915
1948
|
) })
|
|
1916
1949
|
] });
|
|
1917
1950
|
}
|
|
1951
|
+
function RenderedToolResult({ renderer, result, status }) {
|
|
1952
|
+
const domRef = useRef(null);
|
|
1953
|
+
const rendered = renderer({ result, status });
|
|
1954
|
+
useEffect(() => {
|
|
1955
|
+
if (domRef.current && rendered instanceof HTMLElement) {
|
|
1956
|
+
domRef.current.innerHTML = "";
|
|
1957
|
+
domRef.current.appendChild(rendered);
|
|
1958
|
+
}
|
|
1959
|
+
}, [rendered]);
|
|
1960
|
+
if (rendered instanceof HTMLElement) {
|
|
1961
|
+
return /* @__PURE__ */ jsx("div", { className: "crow-mt-1.5 crow-mb-0.5", ref: domRef });
|
|
1962
|
+
}
|
|
1963
|
+
if (typeof rendered === "string") {
|
|
1964
|
+
return /* @__PURE__ */ jsx("div", { className: "crow-mt-1.5 crow-mb-0.5", dangerouslySetInnerHTML: { __html: rendered } });
|
|
1965
|
+
}
|
|
1966
|
+
return /* @__PURE__ */ jsx("div", { className: "crow-mt-1.5 crow-mb-0.5", children: rendered });
|
|
1967
|
+
}
|
|
1918
1968
|
function ToolCallBlock({
|
|
1919
1969
|
toolCall,
|
|
1920
1970
|
toolRenderers
|
|
@@ -1954,7 +2004,7 @@ function ToolCallBlock({
|
|
|
1954
2004
|
]
|
|
1955
2005
|
}
|
|
1956
2006
|
),
|
|
1957
|
-
hasCustomRender && /* @__PURE__ */ jsx(
|
|
2007
|
+
hasCustomRender && /* @__PURE__ */ jsx(RenderedToolResult, { renderer: customRenderer, result: toolCall.result, status: toolCall.status }),
|
|
1958
2008
|
/* @__PURE__ */ jsx(AnimatePresence, { children: expanded && hasArgs && /* @__PURE__ */ jsx(
|
|
1959
2009
|
motion.div,
|
|
1960
2010
|
{
|
|
@@ -2913,8 +2963,12 @@ function CrowWidget({
|
|
|
2913
2963
|
navigate,
|
|
2914
2964
|
onToolResult,
|
|
2915
2965
|
getIdentityToken,
|
|
2916
|
-
context
|
|
2966
|
+
context,
|
|
2967
|
+
toolRenderers
|
|
2917
2968
|
}) {
|
|
2969
|
+
const effectiveGetIdentityToken = getIdentityToken || window.__crow_identity_token_fetcher;
|
|
2970
|
+
const effectiveOnToolResult = onToolResult || window.__crow_on_tool_result;
|
|
2971
|
+
const effectiveToolRenderers = toolRenderers || window.__crow_tool_renderers;
|
|
2918
2972
|
const {
|
|
2919
2973
|
styles,
|
|
2920
2974
|
isLoading: isLoadingStyles,
|
|
@@ -2993,7 +3047,7 @@ function CrowWidget({
|
|
|
2993
3047
|
break;
|
|
2994
3048
|
}
|
|
2995
3049
|
},
|
|
2996
|
-
onToolResult,
|
|
3050
|
+
onToolResult: effectiveOnToolResult,
|
|
2997
3051
|
onToolCall: async (event) => {
|
|
2998
3052
|
if (event.type === "client_call" && event.toolName && event.toolCallId) {
|
|
2999
3053
|
try {
|
|
@@ -3092,11 +3146,11 @@ function CrowWidget({
|
|
|
3092
3146
|
}
|
|
3093
3147
|
}, [isLoadingStyles, onIdentify]);
|
|
3094
3148
|
useEffect(() => {
|
|
3095
|
-
if (!
|
|
3149
|
+
if (!effectiveGetIdentityToken || isLoadingStyles) return;
|
|
3096
3150
|
let cancelled = false;
|
|
3097
3151
|
const identify = async () => {
|
|
3098
3152
|
try {
|
|
3099
|
-
const token = await
|
|
3153
|
+
const token = await effectiveGetIdentityToken();
|
|
3100
3154
|
if (!cancelled && token) {
|
|
3101
3155
|
window.crow?.("identify", { token });
|
|
3102
3156
|
}
|
|
@@ -3111,7 +3165,7 @@ function CrowWidget({
|
|
|
3111
3165
|
cancelled = true;
|
|
3112
3166
|
window.removeEventListener("crow:token-refresh-needed", handleRefresh);
|
|
3113
3167
|
};
|
|
3114
|
-
}, [
|
|
3168
|
+
}, [effectiveGetIdentityToken, isLoadingStyles]);
|
|
3115
3169
|
useEffect(() => {
|
|
3116
3170
|
if (typeof window === "undefined") return;
|
|
3117
3171
|
if (context && Object.keys(context).length > 0) {
|
|
@@ -3298,7 +3352,8 @@ function CrowWidget({
|
|
|
3298
3352
|
messages: chat.messages,
|
|
3299
3353
|
activeToolCalls: chat.activeToolCalls,
|
|
3300
3354
|
isLoadingHistory: conversations.isLoadingHistory,
|
|
3301
|
-
isGenerating: chat.isLoading
|
|
3355
|
+
isGenerating: chat.isLoading,
|
|
3356
|
+
toolRenderers: effectiveToolRenderers
|
|
3302
3357
|
}
|
|
3303
3358
|
),
|
|
3304
3359
|
pendingConfirmation && /* @__PURE__ */ jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsx(
|
|
@@ -3402,40 +3457,88 @@ function MessageIcon() {
|
|
|
3402
3457
|
}
|
|
3403
3458
|
);
|
|
3404
3459
|
}
|
|
3405
|
-
|
|
3406
|
-
isOpen,
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
}
|
|
3460
|
+
var CopilotToggleButton = forwardRef(
|
|
3461
|
+
function CopilotToggleButton2({ isOpen, position, onClick, onMouseDown, isDragging }, ref) {
|
|
3462
|
+
const renderIcon = () => {
|
|
3463
|
+
if (!isOpen) return /* @__PURE__ */ jsx(MessageIcon, {});
|
|
3464
|
+
if (position === "right") return /* @__PURE__ */ jsx(ChevronRight2, {});
|
|
3465
|
+
return /* @__PURE__ */ jsx(ChevronLeft, {});
|
|
3466
|
+
};
|
|
3467
|
+
return /* @__PURE__ */ jsx(
|
|
3468
|
+
"button",
|
|
3469
|
+
{
|
|
3470
|
+
ref,
|
|
3471
|
+
onClick,
|
|
3472
|
+
onMouseDown,
|
|
3473
|
+
className: `crow-copilot-toggle crow-copilot-toggle-${position} ${isOpen ? "open" : ""} ${isDragging ? "dragging" : ""}`,
|
|
3474
|
+
style: {
|
|
3475
|
+
cursor: isOpen ? "col-resize" : void 0
|
|
3476
|
+
},
|
|
3477
|
+
"aria-label": isOpen ? "Close Copilot" : "Open Copilot",
|
|
3478
|
+
title: isOpen ? "Close Copilot" : "Open Copilot",
|
|
3479
|
+
children: renderIcon()
|
|
3480
|
+
}
|
|
3481
|
+
);
|
|
3482
|
+
}
|
|
3483
|
+
);
|
|
3484
|
+
var DRAG_THRESHOLD = 5;
|
|
3485
|
+
var MIN_WIDTH = 280;
|
|
3486
|
+
var MAX_WIDTH = 800;
|
|
3426
3487
|
function CopilotContainer({
|
|
3427
3488
|
position,
|
|
3428
|
-
width,
|
|
3489
|
+
width: initialWidth,
|
|
3429
3490
|
defaultOpen,
|
|
3430
3491
|
children
|
|
3431
3492
|
}) {
|
|
3432
|
-
const [isOpen, setIsOpen] = useState(
|
|
3493
|
+
const [isOpen, setIsOpen] = useState(() => {
|
|
3494
|
+
try {
|
|
3495
|
+
const stored = sessionStorage.getItem("crow_copilot_open");
|
|
3496
|
+
if (stored !== null) return stored === "true";
|
|
3497
|
+
} catch {
|
|
3498
|
+
}
|
|
3499
|
+
return defaultOpen;
|
|
3500
|
+
});
|
|
3501
|
+
const [currentWidth, setCurrentWidth] = useState(() => {
|
|
3502
|
+
try {
|
|
3503
|
+
const stored = sessionStorage.getItem("crow_copilot_width");
|
|
3504
|
+
if (stored) {
|
|
3505
|
+
const parsed = parseInt(stored, 10);
|
|
3506
|
+
if (parsed >= MIN_WIDTH && parsed <= MAX_WIDTH) return parsed;
|
|
3507
|
+
}
|
|
3508
|
+
} catch {
|
|
3509
|
+
}
|
|
3510
|
+
return initialWidth;
|
|
3511
|
+
});
|
|
3512
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
3513
|
+
useEffect(() => {
|
|
3514
|
+
try {
|
|
3515
|
+
sessionStorage.setItem("crow_copilot_open", String(isOpen));
|
|
3516
|
+
} catch {
|
|
3517
|
+
}
|
|
3518
|
+
}, [isOpen]);
|
|
3519
|
+
useEffect(() => {
|
|
3520
|
+
try {
|
|
3521
|
+
sessionStorage.setItem("crow_copilot_width", String(currentWidth));
|
|
3522
|
+
} catch {
|
|
3523
|
+
}
|
|
3524
|
+
}, [currentWidth]);
|
|
3525
|
+
const sidebarRef = useRef(null);
|
|
3526
|
+
const toggleRef = useRef(null);
|
|
3527
|
+
const dragStartXRef = useRef(0);
|
|
3528
|
+
const dragStartWidthRef = useRef(0);
|
|
3529
|
+
const hasDraggedRef = useRef(false);
|
|
3530
|
+
const liveWidthRef = useRef(initialWidth);
|
|
3531
|
+
const positionRef = useRef(position);
|
|
3532
|
+
positionRef.current = position;
|
|
3533
|
+
useEffect(() => {
|
|
3534
|
+
liveWidthRef.current = currentWidth;
|
|
3535
|
+
}, [currentWidth]);
|
|
3433
3536
|
useEffect(() => {
|
|
3434
3537
|
document.documentElement.style.setProperty(
|
|
3435
3538
|
"--crow-copilot-width",
|
|
3436
|
-
`${
|
|
3539
|
+
`${currentWidth}px`
|
|
3437
3540
|
);
|
|
3438
|
-
}, [
|
|
3541
|
+
}, [currentWidth]);
|
|
3439
3542
|
useEffect(() => {
|
|
3440
3543
|
const className = `crow-copilot-open-${position}`;
|
|
3441
3544
|
if (isOpen) {
|
|
@@ -3457,21 +3560,97 @@ function CopilotContainer({
|
|
|
3457
3560
|
delete window.crowCopilot;
|
|
3458
3561
|
};
|
|
3459
3562
|
}, []);
|
|
3563
|
+
const handleMouseMove = useCallback(
|
|
3564
|
+
(e) => {
|
|
3565
|
+
const deltaX = e.clientX - dragStartXRef.current;
|
|
3566
|
+
if (!hasDraggedRef.current && Math.abs(deltaX) >= DRAG_THRESHOLD) {
|
|
3567
|
+
hasDraggedRef.current = true;
|
|
3568
|
+
document.body.style.transition = "none";
|
|
3569
|
+
document.body.style.cursor = "col-resize";
|
|
3570
|
+
document.body.style.userSelect = "none";
|
|
3571
|
+
document.body.classList.add("crow-copilot-resizing");
|
|
3572
|
+
if (sidebarRef.current) {
|
|
3573
|
+
sidebarRef.current.style.transition = "none";
|
|
3574
|
+
}
|
|
3575
|
+
if (toggleRef.current) {
|
|
3576
|
+
toggleRef.current.style.transition = "none";
|
|
3577
|
+
}
|
|
3578
|
+
setIsDragging(true);
|
|
3579
|
+
}
|
|
3580
|
+
if (!hasDraggedRef.current) return;
|
|
3581
|
+
const widthDelta = positionRef.current === "right" ? -deltaX : deltaX;
|
|
3582
|
+
const newWidth = Math.min(
|
|
3583
|
+
MAX_WIDTH,
|
|
3584
|
+
Math.max(MIN_WIDTH, dragStartWidthRef.current + widthDelta)
|
|
3585
|
+
);
|
|
3586
|
+
liveWidthRef.current = newWidth;
|
|
3587
|
+
const px = `${newWidth}px`;
|
|
3588
|
+
document.documentElement.style.setProperty("--crow-copilot-width", px);
|
|
3589
|
+
if (sidebarRef.current) {
|
|
3590
|
+
sidebarRef.current.style.width = px;
|
|
3591
|
+
}
|
|
3592
|
+
},
|
|
3593
|
+
[]
|
|
3594
|
+
// no deps — we use refs for everything to avoid stale closures
|
|
3595
|
+
);
|
|
3596
|
+
const handleMouseUp = useCallback(() => {
|
|
3597
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
3598
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
3599
|
+
document.body.style.transition = "";
|
|
3600
|
+
document.body.style.cursor = "";
|
|
3601
|
+
document.body.style.userSelect = "";
|
|
3602
|
+
document.body.classList.remove("crow-copilot-resizing");
|
|
3603
|
+
if (sidebarRef.current) {
|
|
3604
|
+
sidebarRef.current.style.transition = "";
|
|
3605
|
+
}
|
|
3606
|
+
if (toggleRef.current) {
|
|
3607
|
+
toggleRef.current.style.transition = "";
|
|
3608
|
+
}
|
|
3609
|
+
if (hasDraggedRef.current) {
|
|
3610
|
+
setCurrentWidth(liveWidthRef.current);
|
|
3611
|
+
setIsDragging(false);
|
|
3612
|
+
} else {
|
|
3613
|
+
setIsDragging(false);
|
|
3614
|
+
setIsOpen((prev) => !prev);
|
|
3615
|
+
}
|
|
3616
|
+
}, [handleMouseMove]);
|
|
3617
|
+
const handleToggleMouseDown = useCallback(
|
|
3618
|
+
(e) => {
|
|
3619
|
+
if (e.button !== 0 || !isOpen) return;
|
|
3620
|
+
e.preventDefault();
|
|
3621
|
+
e.stopPropagation();
|
|
3622
|
+
dragStartXRef.current = e.clientX;
|
|
3623
|
+
dragStartWidthRef.current = liveWidthRef.current;
|
|
3624
|
+
hasDraggedRef.current = false;
|
|
3625
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
3626
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
3627
|
+
},
|
|
3628
|
+
[isOpen, handleMouseMove, handleMouseUp]
|
|
3629
|
+
);
|
|
3630
|
+
const handleToggleClick = useCallback(() => {
|
|
3631
|
+
if (!isOpen) {
|
|
3632
|
+
setIsOpen(true);
|
|
3633
|
+
}
|
|
3634
|
+
}, [isOpen]);
|
|
3460
3635
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3461
3636
|
/* @__PURE__ */ jsx(
|
|
3462
3637
|
CopilotToggleButton,
|
|
3463
3638
|
{
|
|
3639
|
+
ref: toggleRef,
|
|
3464
3640
|
isOpen,
|
|
3465
3641
|
position,
|
|
3466
|
-
onClick:
|
|
3642
|
+
onClick: handleToggleClick,
|
|
3643
|
+
onMouseDown: handleToggleMouseDown,
|
|
3644
|
+
isDragging
|
|
3467
3645
|
}
|
|
3468
3646
|
),
|
|
3469
3647
|
/* @__PURE__ */ jsx(
|
|
3470
3648
|
"div",
|
|
3471
3649
|
{
|
|
3650
|
+
ref: sidebarRef,
|
|
3472
3651
|
className: `crow-copilot-sidebar crow-copilot-sidebar-${position} ${isOpen ? "" : "closed"}`,
|
|
3473
|
-
style: { width: `${
|
|
3474
|
-
children: children({ close: () => setIsOpen(false) })
|
|
3652
|
+
style: { width: `${currentWidth}px` },
|
|
3653
|
+
children: children({ close: () => setIsOpen(false), currentWidth })
|
|
3475
3654
|
}
|
|
3476
3655
|
)
|
|
3477
3656
|
] });
|
|
@@ -3498,6 +3677,9 @@ function CrowCopilot({
|
|
|
3498
3677
|
getIdentityToken,
|
|
3499
3678
|
context
|
|
3500
3679
|
}) {
|
|
3680
|
+
const effectiveGetIdentityToken = getIdentityToken || window.__crow_identity_token_fetcher;
|
|
3681
|
+
const effectiveOnToolResult = onToolResult || window.__crow_on_tool_result;
|
|
3682
|
+
const effectiveToolRenderers = toolRenderers || window.__crow_tool_renderers;
|
|
3501
3683
|
const {
|
|
3502
3684
|
styles,
|
|
3503
3685
|
isLoading: isLoadingStyles,
|
|
@@ -3551,6 +3733,93 @@ function CrowCopilot({
|
|
|
3551
3733
|
window.crow?.("registerTools", autoTools);
|
|
3552
3734
|
}
|
|
3553
3735
|
}, [autoTools]);
|
|
3736
|
+
const embeddedInitialWidth = typeof width === "number" ? width : parseInt(String(width), 10) || 400;
|
|
3737
|
+
const [embeddedWidth, setEmbeddedWidth] = useState(() => {
|
|
3738
|
+
try {
|
|
3739
|
+
const stored = sessionStorage.getItem("crow_embedded_width");
|
|
3740
|
+
if (stored) {
|
|
3741
|
+
const parsed = parseInt(stored, 10);
|
|
3742
|
+
if (parsed >= 280 && parsed <= 800) return parsed;
|
|
3743
|
+
}
|
|
3744
|
+
} catch {
|
|
3745
|
+
}
|
|
3746
|
+
return embeddedInitialWidth;
|
|
3747
|
+
});
|
|
3748
|
+
const [isCollapsed, setIsCollapsed] = useState(() => {
|
|
3749
|
+
try {
|
|
3750
|
+
return sessionStorage.getItem("crow_embedded_collapsed") === "true";
|
|
3751
|
+
} catch {
|
|
3752
|
+
return false;
|
|
3753
|
+
}
|
|
3754
|
+
});
|
|
3755
|
+
useEffect(() => {
|
|
3756
|
+
try {
|
|
3757
|
+
sessionStorage.setItem("crow_embedded_width", String(embeddedWidth));
|
|
3758
|
+
} catch {
|
|
3759
|
+
}
|
|
3760
|
+
}, [embeddedWidth]);
|
|
3761
|
+
useEffect(() => {
|
|
3762
|
+
try {
|
|
3763
|
+
sessionStorage.setItem("crow_embedded_collapsed", String(isCollapsed));
|
|
3764
|
+
} catch {
|
|
3765
|
+
}
|
|
3766
|
+
}, [isCollapsed]);
|
|
3767
|
+
const embeddedContentRef = useRef(null);
|
|
3768
|
+
const embeddedToggleRef = useRef(null);
|
|
3769
|
+
const embeddedDragStartX = useRef(0);
|
|
3770
|
+
const embeddedDragStartW = useRef(0);
|
|
3771
|
+
const embeddedHasDragged = useRef(false);
|
|
3772
|
+
const embeddedLiveWidth = useRef(embeddedInitialWidth);
|
|
3773
|
+
const positionRef = useRef(position);
|
|
3774
|
+
positionRef.current = position;
|
|
3775
|
+
useEffect(() => {
|
|
3776
|
+
embeddedLiveWidth.current = embeddedWidth;
|
|
3777
|
+
}, [embeddedWidth]);
|
|
3778
|
+
const embeddedMouseMove = useCallback((e) => {
|
|
3779
|
+
const dx = e.clientX - embeddedDragStartX.current;
|
|
3780
|
+
if (!embeddedHasDragged.current && Math.abs(dx) >= 5) {
|
|
3781
|
+
embeddedHasDragged.current = true;
|
|
3782
|
+
document.body.style.cursor = "col-resize";
|
|
3783
|
+
document.body.style.userSelect = "none";
|
|
3784
|
+
}
|
|
3785
|
+
if (!embeddedHasDragged.current) return;
|
|
3786
|
+
const delta = positionRef.current === "right" ? -dx : dx;
|
|
3787
|
+
const newW = Math.min(800, Math.max(280, embeddedDragStartW.current + delta));
|
|
3788
|
+
embeddedLiveWidth.current = newW;
|
|
3789
|
+
if (embeddedContentRef.current) {
|
|
3790
|
+
embeddedContentRef.current.style.width = `${newW}px`;
|
|
3791
|
+
}
|
|
3792
|
+
}, []);
|
|
3793
|
+
const embeddedMouseUp = useCallback(() => {
|
|
3794
|
+
document.removeEventListener("mousemove", embeddedMouseMove);
|
|
3795
|
+
document.removeEventListener("mouseup", embeddedMouseUp);
|
|
3796
|
+
document.body.style.cursor = "";
|
|
3797
|
+
document.body.style.userSelect = "";
|
|
3798
|
+
if (embeddedHasDragged.current) {
|
|
3799
|
+
setEmbeddedWidth(embeddedLiveWidth.current);
|
|
3800
|
+
} else {
|
|
3801
|
+
setIsCollapsed((prev) => !prev);
|
|
3802
|
+
}
|
|
3803
|
+
}, [embeddedMouseMove]);
|
|
3804
|
+
const embeddedHandleMouseDown = useCallback(
|
|
3805
|
+
(e) => {
|
|
3806
|
+
if (e.button !== 0) return;
|
|
3807
|
+
if (isCollapsed) return;
|
|
3808
|
+
e.preventDefault();
|
|
3809
|
+
e.stopPropagation();
|
|
3810
|
+
embeddedDragStartX.current = e.clientX;
|
|
3811
|
+
embeddedDragStartW.current = embeddedLiveWidth.current;
|
|
3812
|
+
embeddedHasDragged.current = false;
|
|
3813
|
+
document.addEventListener("mousemove", embeddedMouseMove);
|
|
3814
|
+
document.addEventListener("mouseup", embeddedMouseUp);
|
|
3815
|
+
},
|
|
3816
|
+
[isCollapsed, embeddedMouseMove, embeddedMouseUp]
|
|
3817
|
+
);
|
|
3818
|
+
const embeddedHandleClick = useCallback(() => {
|
|
3819
|
+
if (isCollapsed) {
|
|
3820
|
+
setIsCollapsed(false);
|
|
3821
|
+
}
|
|
3822
|
+
}, [isCollapsed]);
|
|
3554
3823
|
const messagesContainerRef = useRef(null);
|
|
3555
3824
|
const tabsScrollRef = useRef(null);
|
|
3556
3825
|
const executeClientToolRef = useRef(null);
|
|
@@ -3570,6 +3839,16 @@ function CrowCopilot({
|
|
|
3570
3839
|
const conversations = useConversations({ productId, apiUrl });
|
|
3571
3840
|
const [shouldRestoreHistory, setShouldRestoreHistory] = useState(false);
|
|
3572
3841
|
const hasRestoredHistoryRef = useRef(false);
|
|
3842
|
+
const activeConvStorageKey = `crow_active_conv_${productId}`;
|
|
3843
|
+
const pendingRestoreConvId = useRef(null);
|
|
3844
|
+
const hasRestoredActiveConvRef = useRef(false);
|
|
3845
|
+
if (pendingRestoreConvId.current === null) {
|
|
3846
|
+
try {
|
|
3847
|
+
pendingRestoreConvId.current = localStorage.getItem(activeConvStorageKey) || "";
|
|
3848
|
+
} catch {
|
|
3849
|
+
pendingRestoreConvId.current = "";
|
|
3850
|
+
}
|
|
3851
|
+
}
|
|
3573
3852
|
const chat = useChat({
|
|
3574
3853
|
productId,
|
|
3575
3854
|
apiUrl,
|
|
@@ -3601,7 +3880,7 @@ function CrowCopilot({
|
|
|
3601
3880
|
break;
|
|
3602
3881
|
}
|
|
3603
3882
|
},
|
|
3604
|
-
onToolResult,
|
|
3883
|
+
onToolResult: effectiveOnToolResult,
|
|
3605
3884
|
onToolCall: async (event) => {
|
|
3606
3885
|
if (event.type === "client_call" && event.toolName && event.toolCallId) {
|
|
3607
3886
|
try {
|
|
@@ -3656,6 +3935,32 @@ function CrowCopilot({
|
|
|
3656
3935
|
});
|
|
3657
3936
|
}
|
|
3658
3937
|
}, [shouldRestoreHistory, chat.conversationId, conversations, chat]);
|
|
3938
|
+
useEffect(() => {
|
|
3939
|
+
if (isLoadingStyles || hasRestoredActiveConvRef.current) return;
|
|
3940
|
+
const timer = setTimeout(() => {
|
|
3941
|
+
if (hasRestoredActiveConvRef.current || isVerifiedUser) return;
|
|
3942
|
+
const savedId = pendingRestoreConvId.current;
|
|
3943
|
+
if (!savedId) return;
|
|
3944
|
+
hasRestoredActiveConvRef.current = true;
|
|
3945
|
+
pendingRestoreConvId.current = "";
|
|
3946
|
+
conversations.loadAnonymousConversationHistory(savedId).then((historyMessages) => {
|
|
3947
|
+
if (historyMessages.length > 0) {
|
|
3948
|
+
chat.loadMessages(historyMessages);
|
|
3949
|
+
chat.setConversationId(savedId);
|
|
3950
|
+
}
|
|
3951
|
+
}).catch(() => {
|
|
3952
|
+
});
|
|
3953
|
+
}, 500);
|
|
3954
|
+
return () => clearTimeout(timer);
|
|
3955
|
+
}, [isLoadingStyles]);
|
|
3956
|
+
useEffect(() => {
|
|
3957
|
+
try {
|
|
3958
|
+
if (chat.conversationId) {
|
|
3959
|
+
localStorage.setItem(activeConvStorageKey, chat.conversationId);
|
|
3960
|
+
}
|
|
3961
|
+
} catch {
|
|
3962
|
+
}
|
|
3963
|
+
}, [chat.conversationId, activeConvStorageKey]);
|
|
3659
3964
|
useEffect(() => {
|
|
3660
3965
|
if (variant === "floating") {
|
|
3661
3966
|
injectCopilotBodyStyles();
|
|
@@ -3689,6 +3994,19 @@ function CrowCopilot({
|
|
|
3689
3994
|
onIdentified: async () => {
|
|
3690
3995
|
setIsVerifiedUser(true);
|
|
3691
3996
|
await conversations.loadConversations();
|
|
3997
|
+
const savedId = pendingRestoreConvId.current;
|
|
3998
|
+
if (savedId && !hasRestoredActiveConvRef.current) {
|
|
3999
|
+
hasRestoredActiveConvRef.current = true;
|
|
4000
|
+
pendingRestoreConvId.current = "";
|
|
4001
|
+
try {
|
|
4002
|
+
const historyMessages = await conversations.loadConversationHistory(savedId);
|
|
4003
|
+
if (historyMessages.length > 0) {
|
|
4004
|
+
chat.loadMessages(historyMessages);
|
|
4005
|
+
chat.setConversationId(savedId);
|
|
4006
|
+
}
|
|
4007
|
+
} catch {
|
|
4008
|
+
}
|
|
4009
|
+
}
|
|
3692
4010
|
},
|
|
3693
4011
|
onReset: () => {
|
|
3694
4012
|
setIsVerifiedUser(false);
|
|
@@ -3747,11 +4065,11 @@ function CrowCopilot({
|
|
|
3747
4065
|
}
|
|
3748
4066
|
}, [isLoadingStyles, onReady]);
|
|
3749
4067
|
useEffect(() => {
|
|
3750
|
-
if (!
|
|
4068
|
+
if (!effectiveGetIdentityToken || isLoadingStyles) return;
|
|
3751
4069
|
let cancelled = false;
|
|
3752
4070
|
const identify = async () => {
|
|
3753
4071
|
try {
|
|
3754
|
-
const token = await
|
|
4072
|
+
const token = await effectiveGetIdentityToken();
|
|
3755
4073
|
if (!cancelled && token) {
|
|
3756
4074
|
window.crow?.("identify", { token });
|
|
3757
4075
|
}
|
|
@@ -3766,7 +4084,7 @@ function CrowCopilot({
|
|
|
3766
4084
|
cancelled = true;
|
|
3767
4085
|
window.removeEventListener("crow:token-refresh-needed", handleRefresh);
|
|
3768
4086
|
};
|
|
3769
|
-
}, [
|
|
4087
|
+
}, [effectiveGetIdentityToken, isLoadingStyles]);
|
|
3770
4088
|
useEffect(() => {
|
|
3771
4089
|
if (typeof window === "undefined") return;
|
|
3772
4090
|
if (context && Object.keys(context).length > 0) {
|
|
@@ -3940,7 +4258,7 @@ function CrowCopilot({
|
|
|
3940
4258
|
checkTabsOverflow();
|
|
3941
4259
|
}, [tabs.length, checkTabsOverflow]);
|
|
3942
4260
|
const widthStyle = typeof width === "number" ? `${width}px` : width;
|
|
3943
|
-
const renderCopilotContent = (overrideOnClose, forceShowClose) => /* @__PURE__ */ jsx(
|
|
4261
|
+
const renderCopilotContent = (overrideOnClose, forceShowClose, overrideWidth) => /* @__PURE__ */ jsx(
|
|
3944
4262
|
CopilotStyleProvider,
|
|
3945
4263
|
{
|
|
3946
4264
|
styles,
|
|
@@ -3951,7 +4269,7 @@ function CrowCopilot({
|
|
|
3951
4269
|
{
|
|
3952
4270
|
className: `crow-flex crow-flex-col crow-h-full ${position === "left" ? "crow-border-r" : "crow-border-l"} ${className || ""}`,
|
|
3953
4271
|
style: {
|
|
3954
|
-
width: widthStyle,
|
|
4272
|
+
width: overrideWidth ? typeof overrideWidth === "number" ? `${overrideWidth}px` : overrideWidth : widthStyle,
|
|
3955
4273
|
fontFamily: styles.typography.fontFamily,
|
|
3956
4274
|
fontSize: styles.typography.fontSize,
|
|
3957
4275
|
fontWeight: styles.typography.fontWeight,
|
|
@@ -4129,7 +4447,7 @@ function CrowCopilot({
|
|
|
4129
4447
|
activeToolCalls: chat.activeToolCalls,
|
|
4130
4448
|
isLoadingHistory: conversations.isLoadingHistory,
|
|
4131
4449
|
isGenerating: chat.isLoading,
|
|
4132
|
-
toolRenderers
|
|
4450
|
+
toolRenderers: effectiveToolRenderers
|
|
4133
4451
|
}
|
|
4134
4452
|
),
|
|
4135
4453
|
pendingConfirmation && /* @__PURE__ */ jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsx(
|
|
@@ -4183,15 +4501,65 @@ function CrowCopilot({
|
|
|
4183
4501
|
}
|
|
4184
4502
|
);
|
|
4185
4503
|
const floatingWidth = typeof width === "number" ? width : parseInt(String(width), 10) || 400;
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4504
|
+
if (variant === "floating") {
|
|
4505
|
+
return /* @__PURE__ */ jsx(ShadowContainer, { styles: WIDGET_CSS, children: /* @__PURE__ */ jsx(
|
|
4506
|
+
CopilotContainer,
|
|
4507
|
+
{
|
|
4508
|
+
position,
|
|
4509
|
+
width: floatingWidth,
|
|
4510
|
+
defaultOpen,
|
|
4511
|
+
children: ({ close, currentWidth: resizedWidth }) => renderCopilotContent(close, true, resizedWidth)
|
|
4512
|
+
}
|
|
4513
|
+
) });
|
|
4514
|
+
}
|
|
4515
|
+
const isRight = position === "right";
|
|
4516
|
+
const edgeSide = isRight ? "left" : "right";
|
|
4517
|
+
const toggleIcon = isCollapsed ? /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#6b7280", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z" }) }) : /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#6b7280", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: isRight ? /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" }) : /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" }) });
|
|
4518
|
+
return /* @__PURE__ */ jsxs("div", { style: { position: "relative", flexShrink: 0, height: "100%" }, children: [
|
|
4519
|
+
/* @__PURE__ */ jsx(
|
|
4520
|
+
"button",
|
|
4521
|
+
{
|
|
4522
|
+
ref: embeddedToggleRef,
|
|
4523
|
+
onMouseDown: embeddedHandleMouseDown,
|
|
4524
|
+
onClick: embeddedHandleClick,
|
|
4525
|
+
style: {
|
|
4526
|
+
position: "absolute",
|
|
4527
|
+
[edgeSide]: "-12px",
|
|
4528
|
+
top: "50%",
|
|
4529
|
+
transform: "translateY(-50%)",
|
|
4530
|
+
zIndex: 10,
|
|
4531
|
+
width: "24px",
|
|
4532
|
+
height: "64px",
|
|
4533
|
+
display: "flex",
|
|
4534
|
+
alignItems: "center",
|
|
4535
|
+
justifyContent: "center",
|
|
4536
|
+
background: "#fff",
|
|
4537
|
+
border: "1px solid #e5e7eb",
|
|
4538
|
+
[isRight ? "borderRight" : "borderLeft"]: "none",
|
|
4539
|
+
borderRadius: isRight ? "8px 0 0 8px" : "0 8px 8px 0",
|
|
4540
|
+
cursor: isCollapsed ? "pointer" : "col-resize",
|
|
4541
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
|
|
4542
|
+
padding: 0,
|
|
4543
|
+
outline: "none"
|
|
4544
|
+
},
|
|
4545
|
+
"aria-label": isCollapsed ? "Open Copilot" : "Resize or close Copilot",
|
|
4546
|
+
children: toggleIcon
|
|
4547
|
+
}
|
|
4548
|
+
),
|
|
4549
|
+
/* @__PURE__ */ jsx(
|
|
4550
|
+
"div",
|
|
4551
|
+
{
|
|
4552
|
+
ref: embeddedContentRef,
|
|
4553
|
+
style: {
|
|
4554
|
+
width: `${embeddedWidth}px`,
|
|
4555
|
+
height: "100%",
|
|
4556
|
+
display: isCollapsed ? "none" : "block",
|
|
4557
|
+
overflow: "hidden"
|
|
4558
|
+
},
|
|
4559
|
+
children: /* @__PURE__ */ jsx(ShadowContainer, { styles: WIDGET_CSS, children: renderCopilotContent(void 0, false, "100%") })
|
|
4560
|
+
}
|
|
4561
|
+
)
|
|
4562
|
+
] });
|
|
4195
4563
|
}
|
|
4196
4564
|
function PlusIcon({ className }) {
|
|
4197
4565
|
return /* @__PURE__ */ jsxs(
|