@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.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("div", { className: "crow-mt-1.5 crow-mb-0.5", children: customRenderer({ result: toolCall.result, status: toolCall.status }) }),
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 (!getIdentityToken || isLoadingStyles) return;
3149
+ if (!effectiveGetIdentityToken || isLoadingStyles) return;
3096
3150
  let cancelled = false;
3097
3151
  const identify = async () => {
3098
3152
  try {
3099
- const token = await getIdentityToken();
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
- }, [getIdentityToken, isLoadingStyles]);
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
- function CopilotToggleButton({
3406
- isOpen,
3407
- position,
3408
- onClick
3409
- }) {
3410
- const renderIcon = () => {
3411
- if (!isOpen) return /* @__PURE__ */ jsx(MessageIcon, {});
3412
- if (position === "right") return /* @__PURE__ */ jsx(ChevronRight2, {});
3413
- return /* @__PURE__ */ jsx(ChevronLeft, {});
3414
- };
3415
- return /* @__PURE__ */ jsx(
3416
- "button",
3417
- {
3418
- onClick,
3419
- className: `crow-copilot-toggle crow-copilot-toggle-${position} ${isOpen ? "open" : ""}`,
3420
- "aria-label": isOpen ? "Close Copilot" : "Open Copilot",
3421
- title: isOpen ? "Close Copilot" : "Open Copilot",
3422
- children: renderIcon()
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(defaultOpen);
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
- `${width}px`
3539
+ `${currentWidth}px`
3437
3540
  );
3438
- }, [width]);
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: () => setIsOpen((prev) => !prev)
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: `${width}px` },
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 (!getIdentityToken || isLoadingStyles) return;
4068
+ if (!effectiveGetIdentityToken || isLoadingStyles) return;
3751
4069
  let cancelled = false;
3752
4070
  const identify = async () => {
3753
4071
  try {
3754
- const token = await getIdentityToken();
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
- }, [getIdentityToken, isLoadingStyles]);
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
- return /* @__PURE__ */ jsx(ShadowContainer, { styles: WIDGET_CSS, children: variant === "floating" ? /* @__PURE__ */ jsx(
4187
- CopilotContainer,
4188
- {
4189
- position,
4190
- width: floatingWidth,
4191
- defaultOpen,
4192
- children: ({ close }) => renderCopilotContent(close, true)
4193
- }
4194
- ) : renderCopilotContent() });
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(