@usecrow/ui 0.1.12 → 0.1.14

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.d.cts CHANGED
@@ -180,6 +180,8 @@ interface WidgetConfigResponse {
180
180
  agentName: string;
181
181
  widgetStyles: WidgetStyleConfig;
182
182
  copilotStyles: CopilotStyleConfig;
183
+ browserUseEnabled?: boolean;
184
+ showThinking?: boolean;
183
185
  }
184
186
 
185
187
  /** Identity data passed to the identify function */
@@ -208,6 +210,8 @@ interface CrowWidgetProps {
208
210
  styles?: Partial<WidgetStyleConfig>;
209
211
  /** Skip fetching styles from API (use for preview mode with local state) */
210
212
  previewMode?: boolean;
213
+ /** Whether to show AI thinking/reasoning to users (overrides API setting if provided) */
214
+ showThinking?: boolean;
211
215
  /** Callback when widget is ready */
212
216
  onReady?: () => void;
213
217
  /**
@@ -218,7 +222,7 @@ interface CrowWidgetProps {
218
222
  /** Client-side tools the agent can call */
219
223
  tools?: ToolsMap;
220
224
  }
221
- declare function CrowWidget({ productId, apiUrl, variant, styles: propStyles, previewMode, onReady, onIdentify, tools, }: CrowWidgetProps): react_jsx_runtime.JSX.Element;
225
+ declare function CrowWidget({ productId, apiUrl, variant, styles: propStyles, previewMode, showThinking: showThinkingProp, onReady, onIdentify, tools, }: CrowWidgetProps): react_jsx_runtime.JSX.Element;
222
226
 
223
227
  interface CrowCopilotProps {
224
228
  /** Product ID for this copilot */
@@ -628,6 +632,10 @@ interface UseWidgetStylesResult {
628
632
  error: Error | null;
629
633
  /** Agent name from product config */
630
634
  agentName: string;
635
+ /** Whether browser_use is enabled for this product */
636
+ browserUseEnabled: boolean;
637
+ /** Whether to show thinking/reasoning to users */
638
+ showThinking: boolean;
631
639
  /** Refetch styles from API */
632
640
  refetch: () => Promise<void>;
633
641
  }
@@ -706,6 +714,7 @@ interface WidgetStyleContextValue {
706
714
  agentName: string;
707
715
  isLoading: boolean;
708
716
  variant: "floating" | "embedded";
717
+ showThinking: boolean;
709
718
  }
710
719
  interface WidgetStyleProviderProps {
711
720
  children: react__default.ReactNode;
@@ -713,11 +722,12 @@ interface WidgetStyleProviderProps {
713
722
  agentName?: string;
714
723
  isLoading?: boolean;
715
724
  variant?: "floating" | "embedded";
725
+ showThinking?: boolean;
716
726
  }
717
727
  /**
718
728
  * Provider for widget styles
719
729
  */
720
- declare function WidgetStyleProvider({ children, styles, agentName, isLoading, variant, }: WidgetStyleProviderProps): react_jsx_runtime.JSX.Element;
730
+ declare function WidgetStyleProvider({ children, styles, agentName, isLoading, variant, showThinking, }: WidgetStyleProviderProps): react_jsx_runtime.JSX.Element;
721
731
  /**
722
732
  * Hook to access widget styles from context
723
733
  *
@@ -789,8 +799,10 @@ interface ReasoningTraceProps {
789
799
  isComplete?: boolean;
790
800
  toolCalls?: ToolCall[];
791
801
  isWaiting?: boolean;
802
+ /** Whether to show detailed reasoning (text + tool calls). If false, only shows "Thinking..." indicator */
803
+ showDetails?: boolean;
792
804
  }
793
- declare function ReasoningTrace({ thinking, isComplete, toolCalls, isWaiting, }: ReasoningTraceProps): react_jsx_runtime.JSX.Element | null;
805
+ declare function ReasoningTrace({ thinking, isComplete, toolCalls, isWaiting, showDetails, }: ReasoningTraceProps): react_jsx_runtime.JSX.Element | null;
794
806
 
795
807
  interface MessageBubbleProps {
796
808
  message: Message;
package/dist/index.d.ts CHANGED
@@ -180,6 +180,8 @@ interface WidgetConfigResponse {
180
180
  agentName: string;
181
181
  widgetStyles: WidgetStyleConfig;
182
182
  copilotStyles: CopilotStyleConfig;
183
+ browserUseEnabled?: boolean;
184
+ showThinking?: boolean;
183
185
  }
184
186
 
185
187
  /** Identity data passed to the identify function */
@@ -208,6 +210,8 @@ interface CrowWidgetProps {
208
210
  styles?: Partial<WidgetStyleConfig>;
209
211
  /** Skip fetching styles from API (use for preview mode with local state) */
210
212
  previewMode?: boolean;
213
+ /** Whether to show AI thinking/reasoning to users (overrides API setting if provided) */
214
+ showThinking?: boolean;
211
215
  /** Callback when widget is ready */
212
216
  onReady?: () => void;
213
217
  /**
@@ -218,7 +222,7 @@ interface CrowWidgetProps {
218
222
  /** Client-side tools the agent can call */
219
223
  tools?: ToolsMap;
220
224
  }
221
- declare function CrowWidget({ productId, apiUrl, variant, styles: propStyles, previewMode, onReady, onIdentify, tools, }: CrowWidgetProps): react_jsx_runtime.JSX.Element;
225
+ declare function CrowWidget({ productId, apiUrl, variant, styles: propStyles, previewMode, showThinking: showThinkingProp, onReady, onIdentify, tools, }: CrowWidgetProps): react_jsx_runtime.JSX.Element;
222
226
 
223
227
  interface CrowCopilotProps {
224
228
  /** Product ID for this copilot */
@@ -628,6 +632,10 @@ interface UseWidgetStylesResult {
628
632
  error: Error | null;
629
633
  /** Agent name from product config */
630
634
  agentName: string;
635
+ /** Whether browser_use is enabled for this product */
636
+ browserUseEnabled: boolean;
637
+ /** Whether to show thinking/reasoning to users */
638
+ showThinking: boolean;
631
639
  /** Refetch styles from API */
632
640
  refetch: () => Promise<void>;
633
641
  }
@@ -706,6 +714,7 @@ interface WidgetStyleContextValue {
706
714
  agentName: string;
707
715
  isLoading: boolean;
708
716
  variant: "floating" | "embedded";
717
+ showThinking: boolean;
709
718
  }
710
719
  interface WidgetStyleProviderProps {
711
720
  children: react__default.ReactNode;
@@ -713,11 +722,12 @@ interface WidgetStyleProviderProps {
713
722
  agentName?: string;
714
723
  isLoading?: boolean;
715
724
  variant?: "floating" | "embedded";
725
+ showThinking?: boolean;
716
726
  }
717
727
  /**
718
728
  * Provider for widget styles
719
729
  */
720
- declare function WidgetStyleProvider({ children, styles, agentName, isLoading, variant, }: WidgetStyleProviderProps): react_jsx_runtime.JSX.Element;
730
+ declare function WidgetStyleProvider({ children, styles, agentName, isLoading, variant, showThinking, }: WidgetStyleProviderProps): react_jsx_runtime.JSX.Element;
721
731
  /**
722
732
  * Hook to access widget styles from context
723
733
  *
@@ -789,8 +799,10 @@ interface ReasoningTraceProps {
789
799
  isComplete?: boolean;
790
800
  toolCalls?: ToolCall[];
791
801
  isWaiting?: boolean;
802
+ /** Whether to show detailed reasoning (text + tool calls). If false, only shows "Thinking..." indicator */
803
+ showDetails?: boolean;
792
804
  }
793
- declare function ReasoningTrace({ thinking, isComplete, toolCalls, isWaiting, }: ReasoningTraceProps): react_jsx_runtime.JSX.Element | null;
805
+ declare function ReasoningTrace({ thinking, isComplete, toolCalls, isWaiting, showDetails, }: ReasoningTraceProps): react_jsx_runtime.JSX.Element | null;
794
806
 
795
807
  interface MessageBubbleProps {
796
808
  message: Message;
package/dist/index.js CHANGED
@@ -1010,6 +1010,12 @@ function useWidgetStyles({
1010
1010
  const [agentName, setAgentName] = useState(
1011
1011
  styleCache.get(key)?.agentName || "Assistant"
1012
1012
  );
1013
+ const [browserUseEnabled, setBrowserUseEnabled] = useState(
1014
+ styleCache.get(key)?.browserUseEnabled || false
1015
+ );
1016
+ const [showThinking, setShowThinking] = useState(
1017
+ styleCache.get(key)?.showThinking ?? true
1018
+ );
1013
1019
  const hasFetchedRef = useRef(false);
1014
1020
  const fetchStyles = async () => {
1015
1021
  if (skip) return;
@@ -1020,6 +1026,8 @@ function useWidgetStyles({
1020
1026
  styleCache.set(key, config);
1021
1027
  setDbStyles(config.widgetStyles);
1022
1028
  setAgentName(config.agentName || "Assistant");
1029
+ setBrowserUseEnabled(config.browserUseEnabled || false);
1030
+ setShowThinking(config.showThinking ?? true);
1023
1031
  } catch (err) {
1024
1032
  console.error("[CrowWidget] Failed to fetch styles:", err);
1025
1033
  setError(err instanceof Error ? err : new Error(String(err)));
@@ -1033,6 +1041,8 @@ function useWidgetStyles({
1033
1041
  if (cached) {
1034
1042
  setDbStyles(cached.widgetStyles);
1035
1043
  setAgentName(cached.agentName || "Assistant");
1044
+ setBrowserUseEnabled(cached.browserUseEnabled || false);
1045
+ setShowThinking(cached.showThinking ?? true);
1036
1046
  setIsLoading(false);
1037
1047
  return;
1038
1048
  }
@@ -1045,6 +1055,8 @@ function useWidgetStyles({
1045
1055
  isLoading,
1046
1056
  error,
1047
1057
  agentName,
1058
+ browserUseEnabled,
1059
+ showThinking,
1048
1060
  refetch: fetchStyles
1049
1061
  };
1050
1062
  }
@@ -1125,11 +1137,12 @@ function WidgetStyleProvider({
1125
1137
  styles,
1126
1138
  agentName = "Assistant",
1127
1139
  isLoading = false,
1128
- variant = "floating"
1140
+ variant = "floating",
1141
+ showThinking = true
1129
1142
  }) {
1130
1143
  const value = useMemo(
1131
- () => ({ styles, agentName, isLoading, variant }),
1132
- [styles, agentName, isLoading, variant]
1144
+ () => ({ styles, agentName, isLoading, variant, showThinking }),
1145
+ [styles, agentName, isLoading, variant, showThinking]
1133
1146
  );
1134
1147
  return /* @__PURE__ */ jsx(WidgetStyleContext.Provider, { value, children });
1135
1148
  }
@@ -1146,6 +1159,10 @@ function useWidgetStyles2() {
1146
1159
  const context = useContext(WidgetStyleContext);
1147
1160
  return context?.styles ?? DEFAULT_WIDGET_STYLES;
1148
1161
  }
1162
+ function useShowThinking() {
1163
+ const context = useContext(WidgetStyleContext);
1164
+ return context?.showThinking ?? true;
1165
+ }
1149
1166
  var CopilotStyleContext = createContext(
1150
1167
  null
1151
1168
  );
@@ -1519,10 +1536,6 @@ var THINKING_MESSAGES = [
1519
1536
  "Connecting",
1520
1537
  "Synthesizing"
1521
1538
  ];
1522
- function getRandomThinkingMessage() {
1523
- const idx = Math.floor(Math.random() * THINKING_MESSAGES.length);
1524
- return THINKING_MESSAGES[idx] + "...";
1525
- }
1526
1539
  function ShimmeringContent({ children }) {
1527
1540
  return /* @__PURE__ */ jsxs(
1528
1541
  "span",
@@ -1552,11 +1565,17 @@ function ReasoningTrace({
1552
1565
  thinking,
1553
1566
  isComplete,
1554
1567
  toolCalls = [],
1555
- isWaiting = false
1568
+ isWaiting = false,
1569
+ showDetails = true
1556
1570
  }) {
1557
1571
  const hasThinking = !!thinking && thinking.trim().length > 0;
1558
1572
  const hasToolCalls = toolCalls.length > 0;
1573
+ const isActive = isWaiting || hasThinking && !isComplete || toolCalls.some((t) => t.status === "executing");
1559
1574
  if (!isWaiting && !hasThinking && !hasToolCalls) return null;
1575
+ if (!showDetails) {
1576
+ if (!isActive) return null;
1577
+ return /* @__PURE__ */ jsx("div", { className: "crow-flex crow-justify-start crow-mb-2", children: /* @__PURE__ */ jsx("div", { className: "crow-max-w-[90%]", children: /* @__PURE__ */ jsx(WaitingIndicator, {}) }) });
1578
+ }
1560
1579
  return /* @__PURE__ */ jsx("div", { className: "crow-flex crow-justify-start crow-mb-2", children: /* @__PURE__ */ jsxs("div", { className: "crow-max-w-[90%] crow-space-y-1.5", children: [
1561
1580
  isWaiting && !hasThinking && /* @__PURE__ */ jsx(WaitingIndicator, {}),
1562
1581
  hasThinking && /* @__PURE__ */ jsx(ThinkingBlock, { thinking, isComplete }),
@@ -1564,9 +1583,19 @@ function ReasoningTrace({
1564
1583
  ] }) });
1565
1584
  }
1566
1585
  function WaitingIndicator() {
1586
+ const [messageIndex, setMessageIndex] = useState(
1587
+ () => Math.floor(Math.random() * THINKING_MESSAGES.length)
1588
+ );
1589
+ useEffect(() => {
1590
+ const interval = setInterval(() => {
1591
+ setMessageIndex((i) => (i + 1) % THINKING_MESSAGES.length);
1592
+ }, 3e3);
1593
+ return () => clearInterval(interval);
1594
+ }, []);
1595
+ const message = THINKING_MESSAGES[messageIndex] + "...";
1567
1596
  return /* @__PURE__ */ jsxs("div", { className: "crow-flex crow-items-center crow-gap-1.5 crow-text-xs crow-text-gray-500", children: [
1568
1597
  /* @__PURE__ */ jsx("div", { className: "crow-flex crow-items-center crow-justify-center crow-w-4 crow-h-4", children: /* @__PURE__ */ jsx(ShimmeringContent, { children: /* @__PURE__ */ jsx(Brain, { className: "crow-w-3.5 crow-h-3.5" }) }) }),
1569
- /* @__PURE__ */ jsx("span", { className: "crow-font-medium", children: /* @__PURE__ */ jsx(ShimmeringContent, { children: getRandomThinkingMessage() }) })
1598
+ /* @__PURE__ */ jsx("span", { className: "crow-font-medium", children: /* @__PURE__ */ jsx(ShimmeringContent, { children: message }) })
1570
1599
  ] });
1571
1600
  }
1572
1601
  function ThinkingBlock({
@@ -1574,10 +1603,21 @@ function ThinkingBlock({
1574
1603
  isComplete
1575
1604
  }) {
1576
1605
  const [isExpanded, setIsExpanded] = useState(!isComplete);
1606
+ const [messageIndex, setMessageIndex] = useState(
1607
+ () => Math.floor(Math.random() * THINKING_MESSAGES.length)
1608
+ );
1577
1609
  useLayoutEffect(() => {
1578
1610
  setIsExpanded(!isComplete);
1579
1611
  }, [isComplete]);
1612
+ useEffect(() => {
1613
+ if (isComplete) return;
1614
+ const interval = setInterval(() => {
1615
+ setMessageIndex((i) => (i + 1) % THINKING_MESSAGES.length);
1616
+ }, 3e3);
1617
+ return () => clearInterval(interval);
1618
+ }, [isComplete]);
1580
1619
  const isInProgress = !isComplete;
1620
+ const message = THINKING_MESSAGES[messageIndex] + "...";
1581
1621
  return /* @__PURE__ */ jsxs("div", { className: "crow-flex crow-flex-col crow-gap-1 crow-text-xs", children: [
1582
1622
  /* @__PURE__ */ jsxs(
1583
1623
  "button",
@@ -1586,7 +1626,7 @@ function ThinkingBlock({
1586
1626
  className: `crow-flex crow-items-center crow-gap-1.5 crow-select-none crow-transition-colors ${isInProgress ? "crow-text-gray-500" : "crow-text-gray-600 hover:crow-text-gray-800"} crow-cursor-pointer`,
1587
1627
  children: [
1588
1628
  /* @__PURE__ */ jsx("div", { className: "crow-flex crow-items-center crow-justify-center crow-w-4 crow-h-4", children: isInProgress ? /* @__PURE__ */ jsx(ShimmeringContent, { children: /* @__PURE__ */ jsx(Brain, { className: "crow-w-3.5 crow-h-3.5" }) }) : /* @__PURE__ */ jsx(Brain, { className: "crow-w-3.5 crow-h-3.5" }) }),
1589
- /* @__PURE__ */ jsx("span", { className: "crow-font-medium", children: isInProgress ? /* @__PURE__ */ jsx(ShimmeringContent, { children: getRandomThinkingMessage() }) : "Thought" }),
1629
+ /* @__PURE__ */ jsx("span", { className: "crow-font-medium", children: isInProgress ? /* @__PURE__ */ jsx(ShimmeringContent, { children: message }) : "Thought" }),
1590
1630
  /* @__PURE__ */ jsx(
1591
1631
  motion.div,
1592
1632
  {
@@ -1672,6 +1712,7 @@ function MessageBubble({
1672
1712
  isLoading = false
1673
1713
  }) {
1674
1714
  const styles = useWidgetStyles2();
1715
+ const showThinkingSetting = useShowThinking();
1675
1716
  const isWaiting = message.content === "Thinking..." || message.isBot && isLoading && !message.content;
1676
1717
  const hasThinking = message.isBot && message.thinking;
1677
1718
  const hasContent = message.content && message.content !== "Thinking...";
@@ -1690,7 +1731,8 @@ function MessageBubble({
1690
1731
  thinking: message.thinking,
1691
1732
  isComplete: message.thinkingComplete,
1692
1733
  toolCalls,
1693
- isWaiting: isWaiting && !hasThinking
1734
+ isWaiting: isWaiting && !hasThinking,
1735
+ showDetails: showThinkingSetting
1694
1736
  }
1695
1737
  ),
1696
1738
  hasContent && /* @__PURE__ */ jsxs(
@@ -2380,16 +2422,19 @@ function CrowWidget({
2380
2422
  variant = "floating",
2381
2423
  styles: propStyles,
2382
2424
  previewMode = false,
2425
+ showThinking: showThinkingProp,
2383
2426
  onReady,
2384
2427
  onIdentify,
2385
2428
  tools
2386
2429
  }) {
2387
- const { styles, isLoading: isLoadingStyles, agentName } = useWidgetStyles({
2430
+ const { styles, isLoading: isLoadingStyles, agentName, browserUseEnabled, showThinking: showThinkingFromAPI } = useWidgetStyles({
2388
2431
  productId,
2389
2432
  apiUrl,
2390
2433
  propStyles,
2391
2434
  skip: previewMode
2392
2435
  });
2436
+ const showThinking = showThinkingProp ?? showThinkingFromAPI;
2437
+ const [autoTools, setAutoTools] = useState({});
2393
2438
  const cssVars = stylesToCssVars(styles);
2394
2439
  const messagesContainerRef = useRef(null);
2395
2440
  const executeClientToolRef = useRef(null);
@@ -2528,10 +2573,23 @@ function CrowWidget({
2528
2573
  }
2529
2574
  }, [isLoadingStyles, onIdentify]);
2530
2575
  useEffect(() => {
2531
- if (tools && Object.keys(tools).length > 0) {
2532
- window.crow?.("registerTools", tools);
2576
+ if (browserUseEnabled && !isLoadingStyles && Object.keys(autoTools).length === 0) {
2577
+ import('@usecrow/client/browser').then(({ createBrowserUseTool }) => {
2578
+ setAutoTools({
2579
+ browser_use: createBrowserUseTool({ productId, apiUrl })
2580
+ });
2581
+ console.log("[Crow] browser_use tool auto-loaded");
2582
+ }).catch((err) => {
2583
+ console.warn("[Crow] Failed to load browser_use:", err);
2584
+ });
2585
+ }
2586
+ }, [browserUseEnabled, isLoadingStyles, productId, apiUrl, autoTools]);
2587
+ const mergedTools = { ...autoTools, ...tools };
2588
+ useEffect(() => {
2589
+ if (Object.keys(mergedTools).length > 0) {
2590
+ window.crow?.("registerTools", mergedTools);
2533
2591
  }
2534
- }, [tools]);
2592
+ }, [mergedTools]);
2535
2593
  const handleSend = (message) => {
2536
2594
  if (!message.trim()) return;
2537
2595
  setIsCollapsed(false);
@@ -2622,6 +2680,7 @@ function CrowWidget({
2622
2680
  agentName,
2623
2681
  isLoading: isLoadingStyles,
2624
2682
  variant,
2683
+ showThinking,
2625
2684
  children: [
2626
2685
  variant === "floating" && /* @__PURE__ */ jsxs(Fragment, { children: [
2627
2686
  /* @__PURE__ */ jsx(ChatBubble, { isExpanded: !isCollapsed, onClick: handleBubbleClick }),