@usecrow/ui 0.1.18 → 0.1.20

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
@@ -1,11 +1,11 @@
1
1
  import React3, { createContext, forwardRef, useEffect, useRef, useCallback, useContext, useState, useMemo, useLayoutEffect } from 'react';
2
2
  import { motion, AnimatePresence } from 'framer-motion';
3
+ import { DEFAULT_TOOLS, CrowClient } from '@usecrow/client';
3
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
5
  import { createPortal } from 'react-dom';
5
6
  import { Square, ArrowUp, ChevronDown, Check, MessageCircle, Plus, History, ChevronUp, Brain, ChevronRight, Loader2, X } from 'lucide-react';
6
7
  import ReactMarkdown from 'react-markdown';
7
8
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
8
- import { CrowClient } from '@usecrow/client';
9
9
 
10
10
  // src/utils.ts
11
11
  var cn = (...classes) => classes.filter(Boolean).join(" ");
@@ -45,7 +45,7 @@ var getConversationStorageKey = (productId) => `crow_conv_${productId}`;
45
45
  function useChat({
46
46
  productId,
47
47
  apiUrl = "",
48
- persistAnonymousConversations: _persistAnonymousConversations,
48
+ persistAnonymousConversations,
49
49
  welcomeMessage,
50
50
  onVerificationStatus,
51
51
  onConversationId,
@@ -64,16 +64,10 @@ function useChat({
64
64
  ]);
65
65
  const [isLoading, setIsLoading] = useState(false);
66
66
  const [activeToolCalls, setActiveToolCalls] = useState([]);
67
- const [conversationId, setConversationId] = useState(() => {
68
- try {
69
- return localStorage.getItem(getConversationStorageKey(productId));
70
- } catch {
71
- return null;
72
- }
73
- });
67
+ const [conversationId, setConversationId] = useState(null);
74
68
  const [selectedModel, setSelectedModel] = useState(DEFAULT_MODEL);
75
69
  const abortControllerRef = useRef(null);
76
- const hasRestoredRef = useRef(false);
70
+ const hasCheckedPersistRef = useRef(false);
77
71
  useEffect(() => {
78
72
  if (messages.length === 1 && messages[0].id === "welcome" && !conversationId) {
79
73
  setMessages([
@@ -87,11 +81,26 @@ function useChat({
87
81
  }
88
82
  }, [effectiveWelcomeMessage]);
89
83
  useEffect(() => {
90
- if (conversationId && onRestoredConversation && !hasRestoredRef.current) {
91
- hasRestoredRef.current = true;
92
- onRestoredConversation(conversationId);
84
+ if (persistAnonymousConversations === void 0 || hasCheckedPersistRef.current) {
85
+ return;
93
86
  }
94
- }, []);
87
+ hasCheckedPersistRef.current = true;
88
+ if (persistAnonymousConversations) {
89
+ try {
90
+ const storedId = localStorage.getItem(getConversationStorageKey(productId));
91
+ if (storedId) {
92
+ setConversationId(storedId);
93
+ onRestoredConversation?.(storedId);
94
+ }
95
+ } catch {
96
+ }
97
+ } else {
98
+ try {
99
+ localStorage.removeItem(getConversationStorageKey(productId));
100
+ } catch {
101
+ }
102
+ }
103
+ }, [persistAnonymousConversations, productId, onRestoredConversation]);
95
104
  const streamFromBackend = useCallback(
96
105
  async (message, botMsgId) => {
97
106
  let accumulatedText = "";
@@ -149,12 +158,14 @@ function useChat({
149
158
  case "conversation_id":
150
159
  if (parsed.conversation_id) {
151
160
  setConversationId(parsed.conversation_id);
152
- try {
153
- localStorage.setItem(
154
- getConversationStorageKey(productId),
155
- parsed.conversation_id
156
- );
157
- } catch {
161
+ if (persistAnonymousConversations === true) {
162
+ try {
163
+ localStorage.setItem(
164
+ getConversationStorageKey(productId),
165
+ parsed.conversation_id
166
+ );
167
+ } catch {
168
+ }
158
169
  }
159
170
  onConversationId?.(parsed.conversation_id);
160
171
  }
@@ -292,7 +303,7 @@ function useChat({
292
303
  abortControllerRef.current = null;
293
304
  }
294
305
  },
295
- [apiUrl, productId, conversationId, selectedModel, onVerificationStatus, onConversationId, onWorkflowEvent, onToolCall]
306
+ [apiUrl, productId, conversationId, selectedModel, persistAnonymousConversations, onVerificationStatus, onConversationId, onWorkflowEvent, onToolCall]
296
307
  );
297
308
  const sendMessage = useCallback(
298
309
  (content) => {
@@ -448,6 +459,37 @@ function useChat({
448
459
  },
449
460
  [apiUrl, productId, conversationId, selectedModel]
450
461
  );
462
+ const addMessage = useCallback(
463
+ async (role, content) => {
464
+ const msgId = generateMessageId(role === "user" ? "user" : "bot");
465
+ const newMessage = {
466
+ id: msgId,
467
+ content,
468
+ isBot: role === "assistant",
469
+ timestamp: /* @__PURE__ */ new Date()
470
+ };
471
+ setMessages((prev) => [...prev, newMessage]);
472
+ if (conversationId) {
473
+ try {
474
+ const identityToken = window.__crow_identity_token;
475
+ await fetch(`${apiUrl}/api/chat/conversations/${conversationId}/messages`, {
476
+ method: "POST",
477
+ headers: { "Content-Type": "application/json" },
478
+ body: JSON.stringify({
479
+ product_id: productId,
480
+ conversation_id: conversationId,
481
+ role,
482
+ content,
483
+ identity_token: identityToken
484
+ })
485
+ });
486
+ } catch (e) {
487
+ console.warn("[Crow] Failed to persist message:", e);
488
+ }
489
+ }
490
+ },
491
+ [apiUrl, productId, conversationId]
492
+ );
451
493
  return {
452
494
  messages,
453
495
  isLoading,
@@ -460,7 +502,8 @@ function useChat({
460
502
  stopGeneration,
461
503
  resetMessages,
462
504
  loadMessages,
463
- submitToolResult
505
+ submitToolResult,
506
+ addMessage
464
507
  };
465
508
  }
466
509
  function useConversations({ productId, apiUrl = "" }) {
@@ -641,16 +684,6 @@ function useWorkflow({
641
684
  exitWorkflow
642
685
  };
643
686
  }
644
- var SDK_DEFAULT_TOOLS = {
645
- refreshPage: async () => {
646
- try {
647
- window.location.reload();
648
- return { status: "success", data: { message: "Page refresh initiated" } };
649
- } catch (error) {
650
- return { status: "error", error: String(error) };
651
- }
652
- }
653
- };
654
687
  function useCrowAPI({ onIdentified, onReset } = {}) {
655
688
  const onIdentifiedRef = useRef(onIdentified);
656
689
  const onResetRef = useRef(onReset);
@@ -663,7 +696,7 @@ function useCrowAPI({ onIdentified, onReset } = {}) {
663
696
  if (!window.__crow_client_tools) {
664
697
  window.__crow_client_tools = {};
665
698
  }
666
- for (const [toolName, handler] of Object.entries(SDK_DEFAULT_TOOLS)) {
699
+ for (const [toolName, handler] of Object.entries(DEFAULT_TOOLS)) {
667
700
  if (!window.__crow_client_tools[toolName]) {
668
701
  window.__crow_client_tools[toolName] = handler;
669
702
  console.log(`[Crow] Registered default tool: ${toolName}`);
@@ -2139,7 +2172,8 @@ var PromptInput = React3.forwardRef(
2139
2172
  onValueChange,
2140
2173
  onSubmit,
2141
2174
  children,
2142
- disabled = false
2175
+ disabled = false,
2176
+ style
2143
2177
  }, ref) => {
2144
2178
  const [internalValue, setInternalValue] = React3.useState(value || "");
2145
2179
  const handleChange = (newValue) => {
@@ -2166,6 +2200,7 @@ var PromptInput = React3.forwardRef(
2166
2200
  isLoading && "crow-border-red-500",
2167
2201
  className
2168
2202
  ),
2203
+ style,
2169
2204
  children
2170
2205
  }
2171
2206
  )
@@ -2238,11 +2273,13 @@ var PromptInputBox = React3.forwardRef(
2238
2273
  },
2239
2274
  onStop,
2240
2275
  isLoading = false,
2276
+ showStopButton = false,
2241
2277
  placeholder = "Type your message here...",
2242
2278
  className,
2243
2279
  selectedModel = "gpt-4o",
2244
2280
  onModelChange,
2245
- availableModels = []
2281
+ availableModels = [],
2282
+ highlighted = false
2246
2283
  }, ref) => {
2247
2284
  const [input, setInput] = React3.useState("");
2248
2285
  const promptBoxRef = React3.useRef(null);
@@ -2262,8 +2299,13 @@ var PromptInputBox = React3.forwardRef(
2262
2299
  onSubmit: handleSubmit,
2263
2300
  className: cn(
2264
2301
  "crow-w-full crow-shadow-lg crow-transition-all crow-duration-300 crow-ease-in-out",
2302
+ highlighted && "crow-ring-4 crow-ring-offset-2 crow-animate-pulse crow-shadow-[0_0_20px_rgba(0,0,0,0.25)]",
2265
2303
  className
2266
2304
  ),
2305
+ style: highlighted ? {
2306
+ "--tw-ring-color": "var(--crow-user-bubble, #000)",
2307
+ "--tw-ring-offset-color": "var(--crow-background, #fff)"
2308
+ } : void 0,
2267
2309
  disabled: isLoading,
2268
2310
  ref: ref || promptBoxRef,
2269
2311
  children: [
@@ -2287,7 +2329,7 @@ var PromptInputBox = React3.forwardRef(
2287
2329
  /* @__PURE__ */ jsx(
2288
2330
  PromptInputAction,
2289
2331
  {
2290
- tooltip: isLoading ? "Stop generation" : hasContent ? "Send message" : "Type a message",
2332
+ tooltip: isLoading || showStopButton ? "Stop generation" : hasContent ? "Send message" : "Type a message",
2291
2333
  children: /* @__PURE__ */ jsx(
2292
2334
  Button,
2293
2335
  {
@@ -2295,18 +2337,18 @@ var PromptInputBox = React3.forwardRef(
2295
2337
  size: "icon",
2296
2338
  className: cn(
2297
2339
  "crow-h-7 crow-w-7 crow-rounded-full crow-transition-all crow-duration-200",
2298
- isLoading && "crow-bg-red-500 hover:crow-bg-red-500",
2299
- hasContent && !isLoading && "crow-bg-black hover:crow-bg-gray-800",
2300
- !hasContent && !isLoading && "crow-bg-transparent"
2340
+ (isLoading || showStopButton) && "crow-bg-red-500 hover:crow-bg-red-500",
2341
+ hasContent && !isLoading && !showStopButton && "crow-bg-black hover:crow-bg-gray-800",
2342
+ !hasContent && !isLoading && !showStopButton && "crow-bg-transparent"
2301
2343
  ),
2302
2344
  onClick: () => {
2303
- if (isLoading && onStop) {
2345
+ if ((isLoading || showStopButton) && onStop) {
2304
2346
  onStop();
2305
2347
  } else if (hasContent) {
2306
2348
  handleSubmit();
2307
2349
  }
2308
2350
  },
2309
- children: isLoading ? /* @__PURE__ */ jsx(
2351
+ children: isLoading || showStopButton ? /* @__PURE__ */ jsx(
2310
2352
  Square,
2311
2353
  {
2312
2354
  className: "crow-h-3.5 crow-w-3.5 crow-text-white",
@@ -2332,6 +2374,176 @@ var PromptInputBox = React3.forwardRef(
2332
2374
  }
2333
2375
  );
2334
2376
  PromptInputBox.displayName = "PromptInputBox";
2377
+ function BrowserUseConfirmation({
2378
+ instruction,
2379
+ onAllow,
2380
+ onDeny
2381
+ }) {
2382
+ const styles = useWidgetStyles2();
2383
+ return /* @__PURE__ */ jsx(
2384
+ "div",
2385
+ {
2386
+ className: "crow-flex crow-flex-col crow-items-start crow-w-full crow-max-w-[90%]",
2387
+ children: /* @__PURE__ */ jsxs(
2388
+ "div",
2389
+ {
2390
+ className: "crow-rounded-2xl crow-px-4 crow-py-3 crow-w-full crow-border",
2391
+ style: {
2392
+ background: styles.colors.botBubble,
2393
+ borderColor: styles.colors.primary
2394
+ },
2395
+ children: [
2396
+ /* @__PURE__ */ jsxs("div", { className: "crow-flex crow-items-center crow-gap-2 crow-mb-2", children: [
2397
+ /* @__PURE__ */ jsx("span", { className: "crow-text-lg", children: "\u{1F5B1}\uFE0F" }),
2398
+ /* @__PURE__ */ jsx(
2399
+ "span",
2400
+ {
2401
+ className: "crow-font-medium crow-text-sm",
2402
+ style: { color: styles.colors.primary },
2403
+ children: "Browser Agent"
2404
+ }
2405
+ )
2406
+ ] }),
2407
+ /* @__PURE__ */ jsx(
2408
+ "p",
2409
+ {
2410
+ className: "crow-text-sm crow-font-medium crow-mb-2",
2411
+ style: { color: styles.colors.botText },
2412
+ children: "Wants to automate your browser:"
2413
+ }
2414
+ ),
2415
+ /* @__PURE__ */ jsxs(
2416
+ "p",
2417
+ {
2418
+ className: "crow-text-sm crow-mb-4 crow-bg-black/5 crow-rounded crow-p-2 crow-italic",
2419
+ style: { color: styles.colors.botText },
2420
+ children: [
2421
+ '"',
2422
+ instruction,
2423
+ '"'
2424
+ ]
2425
+ }
2426
+ ),
2427
+ /* @__PURE__ */ jsxs("div", { className: "crow-flex crow-gap-2 crow-justify-end", children: [
2428
+ /* @__PURE__ */ jsx(
2429
+ "button",
2430
+ {
2431
+ onClick: onDeny,
2432
+ className: "crow-px-4 crow-py-1.5 crow-rounded-lg crow-text-sm crow-font-medium crow-transition-colors hover:crow-opacity-80",
2433
+ style: {
2434
+ background: "transparent",
2435
+ color: styles.colors.botText,
2436
+ border: `1px solid ${styles.colors.border}`
2437
+ },
2438
+ children: "Deny"
2439
+ }
2440
+ ),
2441
+ /* @__PURE__ */ jsx(
2442
+ "button",
2443
+ {
2444
+ onClick: onAllow,
2445
+ className: "crow-px-4 crow-py-1.5 crow-rounded-lg crow-text-sm crow-font-medium crow-transition-colors hover:crow-opacity-90",
2446
+ style: {
2447
+ background: styles.colors.primary,
2448
+ color: "#fff"
2449
+ },
2450
+ children: "Allow"
2451
+ }
2452
+ )
2453
+ ] })
2454
+ ]
2455
+ }
2456
+ )
2457
+ }
2458
+ );
2459
+ }
2460
+ function BrowserUseQuestion({
2461
+ question,
2462
+ onSubmit
2463
+ }) {
2464
+ const styles = useWidgetStyles2();
2465
+ const [answer, setAnswer] = useState("");
2466
+ const [isSubmitting, setIsSubmitting] = useState(false);
2467
+ const handleSubmit = useCallback(() => {
2468
+ if (answer.trim() && !isSubmitting) {
2469
+ setIsSubmitting(true);
2470
+ onSubmit(answer.trim());
2471
+ }
2472
+ }, [answer, isSubmitting, onSubmit]);
2473
+ const handleKeyDown = useCallback(
2474
+ (e) => {
2475
+ if (e.key === "Enter" && !e.shiftKey) {
2476
+ e.preventDefault();
2477
+ handleSubmit();
2478
+ }
2479
+ },
2480
+ [handleSubmit]
2481
+ );
2482
+ return /* @__PURE__ */ jsx("div", { className: "crow-flex crow-flex-col crow-items-start crow-w-full crow-max-w-[90%]", children: /* @__PURE__ */ jsxs(
2483
+ "div",
2484
+ {
2485
+ className: "crow-rounded-2xl crow-px-4 crow-py-3 crow-w-full crow-border",
2486
+ style: {
2487
+ background: styles.colors.botBubble,
2488
+ borderColor: styles.colors.primary
2489
+ },
2490
+ children: [
2491
+ /* @__PURE__ */ jsxs("div", { className: "crow-flex crow-items-center crow-gap-2 crow-mb-2", children: [
2492
+ /* @__PURE__ */ jsx("span", { className: "crow-text-lg", children: "\u{1F916}" }),
2493
+ /* @__PURE__ */ jsx(
2494
+ "span",
2495
+ {
2496
+ className: "crow-font-medium crow-text-sm",
2497
+ style: { color: styles.colors.primary },
2498
+ children: "Browser Agent asks:"
2499
+ }
2500
+ )
2501
+ ] }),
2502
+ /* @__PURE__ */ jsx(
2503
+ "p",
2504
+ {
2505
+ className: "crow-text-sm crow-mb-3",
2506
+ style: { color: styles.colors.botText },
2507
+ children: question
2508
+ }
2509
+ ),
2510
+ /* @__PURE__ */ jsxs("div", { className: "crow-flex crow-gap-2", children: [
2511
+ /* @__PURE__ */ jsx(
2512
+ "input",
2513
+ {
2514
+ type: "text",
2515
+ value: answer,
2516
+ onChange: (e) => setAnswer(e.target.value),
2517
+ onKeyDown: handleKeyDown,
2518
+ placeholder: "Type your response...",
2519
+ disabled: isSubmitting,
2520
+ className: "crow-flex-1 crow-px-3 crow-py-2 crow-rounded-lg crow-text-sm crow-border crow-outline-none focus:crow-ring-2 disabled:crow-opacity-50",
2521
+ style: {
2522
+ background: styles.colors.background,
2523
+ color: styles.colors.text,
2524
+ borderColor: styles.colors.border
2525
+ },
2526
+ autoFocus: true
2527
+ }
2528
+ ),
2529
+ /* @__PURE__ */ jsx(
2530
+ "button",
2531
+ {
2532
+ onClick: handleSubmit,
2533
+ disabled: !answer.trim() || isSubmitting,
2534
+ className: "crow-px-4 crow-py-2 crow-rounded-lg crow-text-sm crow-font-medium crow-transition-colors hover:crow-opacity-90 disabled:crow-opacity-50 disabled:crow-cursor-not-allowed",
2535
+ style: {
2536
+ background: styles.colors.primary,
2537
+ color: "#fff"
2538
+ },
2539
+ children: isSubmitting ? "Sending..." : "Send"
2540
+ }
2541
+ )
2542
+ ] })
2543
+ ]
2544
+ }
2545
+ ) });
2546
+ }
2335
2547
 
2336
2548
  // src/styles/cssVars.ts
2337
2549
  var CSS_VAR_NAMES = {
@@ -2435,7 +2647,7 @@ function getCssVar(varName, element = document.documentElement) {
2435
2647
  var STYLE_ID = "crow-ui-styles";
2436
2648
  var WIDGET_CSS = `*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }
2437
2649
 
2438
- /*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.crow-pointer-events-none{pointer-events:none}.crow-pointer-events-auto{pointer-events:auto}.crow-fixed{position:fixed}.crow-absolute{position:absolute}.crow-relative{position:relative}.crow-sticky{position:sticky}.crow-bottom-0{bottom:0}.crow-bottom-full{bottom:100%}.crow-left-0{left:0}.crow-right-0{right:0}.crow-top-0{top:0}.crow-z-50{z-index:50}.crow-z-\\[999999\\]{z-index:999999}.crow-m-0{margin:0}.crow-my-1{margin-top:.25rem;margin-bottom:.25rem}.crow-my-2{margin-top:.5rem;margin-bottom:.5rem}.crow-mb-1{margin-bottom:.25rem}.crow-mb-2{margin-bottom:.5rem}.crow-mb-3{margin-bottom:.75rem}.crow-ml-0{margin-left:0}.crow-ml-0\\.5{margin-left:.125rem}.crow-ml-2{margin-left:.5rem}.crow-ml-4{margin-left:1rem}.crow-mt-0{margin-top:0}.crow-mt-0\\.5{margin-top:.125rem}.crow-mt-1{margin-top:.25rem}.crow-mt-2{margin-top:.5rem}.crow-mt-auto{margin-top:auto}.crow-inline-block{display:inline-block}.crow-flex{display:flex}.crow-inline-flex{display:inline-flex}.crow-h-10{height:2.5rem}.crow-h-12{height:3rem}.crow-h-2{height:.5rem}.crow-h-3{height:.75rem}.crow-h-3\\.5{height:.875rem}.crow-h-4{height:1rem}.crow-h-7{height:1.75rem}.crow-h-8{height:2rem}.crow-h-full{height:100%}.crow-max-h-32{max-height:8rem}.crow-max-h-\\[200px\\]{max-height:200px}.crow-min-h-0{min-height:0}.crow-min-h-\\[32px\\]{min-height:32px}.crow-w-0{width:0}.crow-w-0\\.5{width:.125rem}.crow-w-2{width:.5rem}.crow-w-3{width:.75rem}.crow-w-3\\.5{width:.875rem}.crow-w-4{width:1rem}.crow-w-7{width:1.75rem}.crow-w-8{width:2rem}.crow-w-full{width:100%}.crow-min-w-0{min-width:0}.crow-min-w-\\[180px\\]{min-width:180px}.crow-max-w-\\[80\\%\\]{max-width:80%}.crow-max-w-\\[90\\%\\]{max-width:90%}.crow-max-w-full{max-width:100%}.crow-flex-1{flex:1 1 0%}.crow-flex-shrink-0{flex-shrink:0}.crow-rotate-180{--tw-rotate:180deg}.crow-rotate-180,.crow-scale-100{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.crow-scale-100{--tw-scale-x:1;--tw-scale-y:1}.crow-scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.crow-animate-fade-in{animation:crow-fadeIn .2s ease-out}.crow-animate-pulse{animation:crow-pulse 2s cubic-bezier(.4,0,.6,1) infinite}.crow-animate-slide-up{animation:crow-slideUp .3s ease-out}@keyframes crow-spin{to{transform:rotate(1turn)}}.crow-animate-spin{animation:crow-spin 1s linear infinite}.crow-cursor-default{cursor:default}.crow-cursor-not-allowed{cursor:not-allowed}.crow-cursor-pointer{cursor:pointer}.crow-select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.crow-resize-none{resize:none}.crow-list-decimal{list-style-type:decimal}.crow-list-disc{list-style-type:disc}.crow-flex-row{flex-direction:row}.crow-flex-col{flex-direction:column}.crow-items-start{align-items:flex-start}.crow-items-end{align-items:flex-end}.crow-items-center{align-items:center}.crow-justify-start{justify-content:flex-start}.crow-justify-end{justify-content:flex-end}.crow-justify-center{justify-content:center}.crow-justify-between{justify-content:space-between}.crow-gap-1{gap:.25rem}.crow-gap-1\\.5{gap:.375rem}.crow-gap-2{gap:.5rem}.crow-gap-3{gap:.75rem}.crow-gap-4{gap:1rem}.crow-gap-6{gap:1.5rem}.crow-space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.crow-space-y-1\\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.crow-space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.crow-space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.crow-space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.crow-overflow-hidden{overflow:hidden}.crow-overflow-visible{overflow:visible}.crow-overflow-x-auto{overflow-x:auto}.crow-overflow-y-auto{overflow-y:auto}.crow-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.crow-whitespace-pre-wrap{white-space:pre-wrap}.crow-break-words{overflow-wrap:break-word}.crow-rounded{border-radius:.25rem}.crow-rounded-2xl{border-radius:1rem}.crow-rounded-3xl{border-radius:1.5rem}.crow-rounded-full{border-radius:9999px}.crow-rounded-lg{border-radius:.5rem}.crow-rounded-md{border-radius:.375rem}.crow-rounded-xl{border-radius:.75rem}.crow-border{border-width:1px}.crow-border-b{border-bottom-width:1px}.crow-border-l{border-left-width:1px}.crow-border-l-2{border-left-width:2px}.crow-border-r{border-right-width:1px}.crow-border-t{border-top-width:1px}.crow-border-none{border-style:none}.crow-border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity,1))}.crow-border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1))}.crow-border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity,1))}.crow-border-red-500{--tw-border-opacity:1;border-color:rgb(239 68 68/var(--tw-border-opacity,1))}.crow-bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.crow-bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.crow-bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.crow-bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.crow-bg-gray-400{--tw-bg-opacity:1;background-color:rgb(156 163 175/var(--tw-bg-opacity,1))}.crow-bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.crow-bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.crow-bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.crow-bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1))}.crow-bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.crow-bg-transparent{background-color:transparent}.crow-bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.crow-p-0{padding:0}.crow-p-1{padding:.25rem}.crow-p-1\\.5{padding:.375rem}.crow-p-2{padding:.5rem}.crow-p-3{padding:.75rem}.crow-p-4{padding:1rem}.crow-p-6{padding:1.5rem}.crow-px-1{padding-left:.25rem;padding-right:.25rem}.crow-px-1\\.5{padding-left:.375rem;padding-right:.375rem}.crow-px-2{padding-left:.5rem;padding-right:.5rem}.crow-px-3{padding-left:.75rem;padding-right:.75rem}.crow-px-4{padding-left:1rem;padding-right:1rem}.crow-px-6{padding-left:1.5rem;padding-right:1.5rem}.crow-py-0{padding-top:0;padding-bottom:0}.crow-py-0\\.5{padding-top:.125rem;padding-bottom:.125rem}.crow-py-1{padding-top:.25rem;padding-bottom:.25rem}.crow-py-1\\.5{padding-top:.375rem;padding-bottom:.375rem}.crow-py-2{padding-top:.5rem;padding-bottom:.5rem}.crow-py-3{padding-top:.75rem;padding-bottom:.75rem}.crow-py-6{padding-top:1.5rem;padding-bottom:1.5rem}.crow-py-8{padding-top:2rem;padding-bottom:2rem}.crow-pb-2{padding-bottom:.5rem}.crow-pl-3{padding-left:.75rem}.crow-pl-4{padding-left:1rem}.crow-pl-5{padding-left:1.25rem}.crow-pr-4{padding-right:1rem}.crow-pt-1{padding-top:.25rem}.crow-text-left{text-align:left}.crow-text-center{text-align:center}.crow-text-right{text-align:right}.crow-align-text-bottom{vertical-align:text-bottom}.crow-font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.crow-text-base{font-size:1rem;line-height:1.5rem}.crow-text-lg{font-size:1.125rem;line-height:1.75rem}.crow-text-sm{font-size:.875rem;line-height:1.25rem}.crow-text-xs{font-size:.75rem;line-height:1rem}.crow-font-bold{font-weight:700}.crow-font-medium{font-weight:500}.crow-font-semibold{font-weight:600}.crow-uppercase{text-transform:uppercase}.crow-leading-relaxed{line-height:1.625}.crow-tracking-wide{letter-spacing:.025em}.crow-text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.crow-text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.crow-text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.crow-text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.crow-text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.crow-text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.crow-text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.crow-text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.crow-text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity,1))}.crow-text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.crow-text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.crow-text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.crow-text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.crow-underline{text-decoration-line:underline}.crow-opacity-0{opacity:0}.crow-opacity-100{opacity:1}.crow-opacity-50{opacity:.5}.crow-opacity-60{opacity:.6}.crow-shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.crow-shadow-2xl,.crow-shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.crow-shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.crow-shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.crow-backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.crow-backdrop-blur-md,.crow-backdrop-blur-sm{backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.crow-backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.crow-transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.crow-transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.crow-transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.crow-transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.crow-transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.crow-duration-150{transition-duration:.15s}.crow-duration-200{transition-duration:.2s}.crow-duration-300{transition-duration:.3s}.crow-duration-500{transition-duration:.5s}.crow-ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.crow-animate-fade-in{animation:crow-fadeIn .2s ease-out}.crow-animate-slide-up{animation:crow-slideUp .3s ease-out}.crow-animate-pulse{animation:crow-pulse 1.5s ease-in-out infinite}.crow-animation-delay-100{animation-delay:.1s}.crow-animation-delay-200{animation-delay:.2s}@keyframes crow-fadeIn{0%{opacity:0}to{opacity:1}}@keyframes crow-slideUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes crow-pulse{0%,to{opacity:1}50%{opacity:.4}}.crow-overflow-y-auto::-webkit-scrollbar{width:6px}.crow-overflow-y-auto::-webkit-scrollbar-track{background:transparent}.crow-overflow-y-auto::-webkit-scrollbar-thumb{background-color:#d1d5db;border-radius:3px}.crow-overflow-y-auto::-webkit-scrollbar-thumb:hover{background-color:#9ca3af}.crow-focus-visible\\:crow-outline-none:focus-visible{outline:none}.crow-focus-visible\\:crow-ring-2:focus-visible{box-shadow:0 0 0 2px var(--crow-primary,#6366f1)}:host{--crow-primary:#6366f1;--crow-primary-dark:#4f46e5;--crow-secondary:#f1f5f9;--crow-accent:#10b981}@media (prefers-color-scheme:dark){:host{--crow-primary:#818cf8;--crow-primary-dark:#6366f1}}.placeholder\\:crow-text-gray-500::-moz-placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.placeholder\\:crow-text-gray-500::placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.last\\:crow-mb-0:last-child{margin-bottom:0}.last\\:crow-border-0:last-child{border-width:0}.hover\\:crow-scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\\:crow-bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.hover\\:crow-bg-gray-200:hover{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.hover\\:crow-bg-gray-700:hover{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.hover\\:crow-bg-gray-800:hover{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.hover\\:crow-bg-red-500:hover{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.hover\\:crow-text-blue-300:hover{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.hover\\:crow-text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.hover\\:crow-text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity,1))}.hover\\:crow-opacity-100:hover{opacity:1}.focus\\:crow-outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\\:crow-ring-0:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\\:crow-ring-0:focus,.focus\\:crow-ring-2:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\\:crow-ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\\:crow-ring-offset-2:focus{--tw-ring-offset-width:2px}.focus-visible\\:crow-outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\\:crow-ring-0:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.disabled\\:crow-pointer-events-none:disabled{pointer-events:none}.disabled\\:crow-cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:crow-opacity-50:disabled{opacity:.5}`;
2650
+ /*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.crow-pointer-events-none{pointer-events:none}.crow-pointer-events-auto{pointer-events:auto}.crow-fixed{position:fixed}.crow-absolute{position:absolute}.crow-relative{position:relative}.crow-sticky{position:sticky}.crow-bottom-0{bottom:0}.crow-bottom-full{bottom:100%}.crow-left-0{left:0}.crow-right-0{right:0}.crow-top-0{top:0}.crow-z-50{z-index:50}.crow-z-\\[999999\\]{z-index:999999}.crow-m-0{margin:0}.crow-my-1{margin-top:.25rem;margin-bottom:.25rem}.crow-my-2{margin-top:.5rem;margin-bottom:.5rem}.crow-mb-1{margin-bottom:.25rem}.crow-mb-2{margin-bottom:.5rem}.crow-mb-3{margin-bottom:.75rem}.crow-mb-4{margin-bottom:1rem}.crow-ml-0{margin-left:0}.crow-ml-0\\.5{margin-left:.125rem}.crow-ml-2{margin-left:.5rem}.crow-ml-4{margin-left:1rem}.crow-mt-0{margin-top:0}.crow-mt-0\\.5{margin-top:.125rem}.crow-mt-1{margin-top:.25rem}.crow-mt-2{margin-top:.5rem}.crow-mt-auto{margin-top:auto}.crow-inline-block{display:inline-block}.crow-flex{display:flex}.crow-inline-flex{display:inline-flex}.crow-h-10{height:2.5rem}.crow-h-12{height:3rem}.crow-h-2{height:.5rem}.crow-h-3{height:.75rem}.crow-h-3\\.5{height:.875rem}.crow-h-4{height:1rem}.crow-h-7{height:1.75rem}.crow-h-8{height:2rem}.crow-h-full{height:100%}.crow-max-h-32{max-height:8rem}.crow-max-h-\\[200px\\]{max-height:200px}.crow-min-h-0{min-height:0}.crow-min-h-\\[32px\\]{min-height:32px}.crow-w-0{width:0}.crow-w-0\\.5{width:.125rem}.crow-w-2{width:.5rem}.crow-w-3{width:.75rem}.crow-w-3\\.5{width:.875rem}.crow-w-4{width:1rem}.crow-w-7{width:1.75rem}.crow-w-8{width:2rem}.crow-w-full{width:100%}.crow-min-w-0{min-width:0}.crow-min-w-\\[180px\\]{min-width:180px}.crow-max-w-\\[80\\%\\]{max-width:80%}.crow-max-w-\\[90\\%\\]{max-width:90%}.crow-max-w-full{max-width:100%}.crow-flex-1{flex:1 1 0%}.crow-flex-shrink-0{flex-shrink:0}.crow-rotate-180{--tw-rotate:180deg}.crow-rotate-180,.crow-scale-100{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.crow-scale-100{--tw-scale-x:1;--tw-scale-y:1}.crow-scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.crow-animate-fade-in{animation:crow-fadeIn .2s ease-out}.crow-animate-pulse{animation:crow-pulse 2s cubic-bezier(.4,0,.6,1) infinite}.crow-animate-slide-up{animation:crow-slideUp .3s ease-out}@keyframes crow-spin{to{transform:rotate(1turn)}}.crow-animate-spin{animation:crow-spin 1s linear infinite}.crow-cursor-default{cursor:default}.crow-cursor-not-allowed{cursor:not-allowed}.crow-cursor-pointer{cursor:pointer}.crow-select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.crow-resize-none{resize:none}.crow-list-decimal{list-style-type:decimal}.crow-list-disc{list-style-type:disc}.crow-flex-row{flex-direction:row}.crow-flex-col{flex-direction:column}.crow-items-start{align-items:flex-start}.crow-items-end{align-items:flex-end}.crow-items-center{align-items:center}.crow-justify-start{justify-content:flex-start}.crow-justify-end{justify-content:flex-end}.crow-justify-center{justify-content:center}.crow-justify-between{justify-content:space-between}.crow-gap-1{gap:.25rem}.crow-gap-1\\.5{gap:.375rem}.crow-gap-2{gap:.5rem}.crow-gap-3{gap:.75rem}.crow-gap-4{gap:1rem}.crow-gap-6{gap:1.5rem}.crow-space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.crow-space-y-1\\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.crow-space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.crow-space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.crow-space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.crow-overflow-hidden{overflow:hidden}.crow-overflow-visible{overflow:visible}.crow-overflow-x-auto{overflow-x:auto}.crow-overflow-y-auto{overflow-y:auto}.crow-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.crow-whitespace-pre-wrap{white-space:pre-wrap}.crow-break-words{overflow-wrap:break-word}.crow-rounded{border-radius:.25rem}.crow-rounded-2xl{border-radius:1rem}.crow-rounded-3xl{border-radius:1.5rem}.crow-rounded-full{border-radius:9999px}.crow-rounded-lg{border-radius:.5rem}.crow-rounded-md{border-radius:.375rem}.crow-rounded-xl{border-radius:.75rem}.crow-border{border-width:1px}.crow-border-b{border-bottom-width:1px}.crow-border-l{border-left-width:1px}.crow-border-l-2{border-left-width:2px}.crow-border-r{border-right-width:1px}.crow-border-t{border-top-width:1px}.crow-border-none{border-style:none}.crow-border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity,1))}.crow-border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1))}.crow-border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity,1))}.crow-border-red-500{--tw-border-opacity:1;border-color:rgb(239 68 68/var(--tw-border-opacity,1))}.crow-bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.crow-bg-black\\/5{background-color:rgba(0,0,0,.05)}.crow-bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.crow-bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.crow-bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.crow-bg-gray-400{--tw-bg-opacity:1;background-color:rgb(156 163 175/var(--tw-bg-opacity,1))}.crow-bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.crow-bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.crow-bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.crow-bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1))}.crow-bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.crow-bg-transparent{background-color:transparent}.crow-bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.crow-p-0{padding:0}.crow-p-1{padding:.25rem}.crow-p-1\\.5{padding:.375rem}.crow-p-2{padding:.5rem}.crow-p-3{padding:.75rem}.crow-p-4{padding:1rem}.crow-p-6{padding:1.5rem}.crow-px-1{padding-left:.25rem;padding-right:.25rem}.crow-px-1\\.5{padding-left:.375rem;padding-right:.375rem}.crow-px-2{padding-left:.5rem;padding-right:.5rem}.crow-px-3{padding-left:.75rem;padding-right:.75rem}.crow-px-4{padding-left:1rem;padding-right:1rem}.crow-px-6{padding-left:1.5rem;padding-right:1.5rem}.crow-py-0{padding-top:0;padding-bottom:0}.crow-py-0\\.5{padding-top:.125rem;padding-bottom:.125rem}.crow-py-1{padding-top:.25rem;padding-bottom:.25rem}.crow-py-1\\.5{padding-top:.375rem;padding-bottom:.375rem}.crow-py-2{padding-top:.5rem;padding-bottom:.5rem}.crow-py-3{padding-top:.75rem;padding-bottom:.75rem}.crow-py-6{padding-top:1.5rem;padding-bottom:1.5rem}.crow-py-8{padding-top:2rem;padding-bottom:2rem}.crow-pb-2{padding-bottom:.5rem}.crow-pl-3{padding-left:.75rem}.crow-pl-4{padding-left:1rem}.crow-pl-5{padding-left:1.25rem}.crow-pr-4{padding-right:1rem}.crow-pt-1{padding-top:.25rem}.crow-text-left{text-align:left}.crow-text-center{text-align:center}.crow-text-right{text-align:right}.crow-align-text-bottom{vertical-align:text-bottom}.crow-font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.crow-text-base{font-size:1rem;line-height:1.5rem}.crow-text-lg{font-size:1.125rem;line-height:1.75rem}.crow-text-sm{font-size:.875rem;line-height:1.25rem}.crow-text-xs{font-size:.75rem;line-height:1rem}.crow-font-bold{font-weight:700}.crow-font-medium{font-weight:500}.crow-font-semibold{font-weight:600}.crow-uppercase{text-transform:uppercase}.crow-italic{font-style:italic}.crow-leading-relaxed{line-height:1.625}.crow-tracking-wide{letter-spacing:.025em}.crow-text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.crow-text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.crow-text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.crow-text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.crow-text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.crow-text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.crow-text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.crow-text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.crow-text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity,1))}.crow-text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.crow-text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.crow-text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.crow-text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.crow-underline{text-decoration-line:underline}.crow-opacity-0{opacity:0}.crow-opacity-100{opacity:1}.crow-opacity-50{opacity:.5}.crow-opacity-60{opacity:.6}.crow-shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.crow-shadow-2xl,.crow-shadow-\\[0_0_20px_rgba\\(0\\,0\\,0\\,0\\.25\\)\\]{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.crow-shadow-\\[0_0_20px_rgba\\(0\\,0\\,0\\,0\\.25\\)\\]{--tw-shadow:0 0 20px rgba(0,0,0,.25);--tw-shadow-colored:0 0 20px var(--tw-shadow-color)}.crow-shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.crow-shadow-lg,.crow-shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.crow-shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.crow-outline-none{outline:2px solid transparent;outline-offset:2px}.crow-ring-4{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.crow-ring-offset-2{--tw-ring-offset-width:2px}.crow-backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.crow-backdrop-blur-md,.crow-backdrop-blur-sm{backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.crow-backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.crow-transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.crow-transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.crow-transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.crow-transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.crow-transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.crow-duration-150{transition-duration:.15s}.crow-duration-200{transition-duration:.2s}.crow-duration-300{transition-duration:.3s}.crow-duration-500{transition-duration:.5s}.crow-ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.crow-animate-fade-in{animation:crow-fadeIn .2s ease-out}.crow-animate-slide-up{animation:crow-slideUp .3s ease-out}.crow-animate-pulse{animation:crow-pulse 1.5s ease-in-out infinite}.crow-animation-delay-100{animation-delay:.1s}.crow-animation-delay-200{animation-delay:.2s}@keyframes crow-fadeIn{0%{opacity:0}to{opacity:1}}@keyframes crow-slideUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes crow-pulse{0%,to{opacity:1}50%{opacity:.4}}.crow-overflow-y-auto::-webkit-scrollbar{width:6px}.crow-overflow-y-auto::-webkit-scrollbar-track{background:transparent}.crow-overflow-y-auto::-webkit-scrollbar-thumb{background-color:#d1d5db;border-radius:3px}.crow-overflow-y-auto::-webkit-scrollbar-thumb:hover{background-color:#9ca3af}.crow-focus-visible\\:crow-outline-none:focus-visible{outline:none}.crow-focus-visible\\:crow-ring-2:focus-visible{box-shadow:0 0 0 2px var(--crow-primary,#6366f1)}:host{--crow-primary:#6366f1;--crow-primary-dark:#4f46e5;--crow-secondary:#f1f5f9;--crow-accent:#10b981}@media (prefers-color-scheme:dark){:host{--crow-primary:#818cf8;--crow-primary-dark:#6366f1}}.placeholder\\:crow-text-gray-500::-moz-placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.placeholder\\:crow-text-gray-500::placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.last\\:crow-mb-0:last-child{margin-bottom:0}.last\\:crow-border-0:last-child{border-width:0}.hover\\:crow-scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\\:crow-bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.hover\\:crow-bg-gray-200:hover{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.hover\\:crow-bg-gray-700:hover{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.hover\\:crow-bg-gray-800:hover{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.hover\\:crow-bg-red-500:hover{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.hover\\:crow-text-blue-300:hover{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.hover\\:crow-text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.hover\\:crow-text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity,1))}.hover\\:crow-opacity-100:hover{opacity:1}.hover\\:crow-opacity-80:hover{opacity:.8}.hover\\:crow-opacity-90:hover{opacity:.9}.focus\\:crow-outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\\:crow-ring-0:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\\:crow-ring-0:focus,.focus\\:crow-ring-2:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\\:crow-ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\\:crow-ring-offset-2:focus{--tw-ring-offset-width:2px}.focus-visible\\:crow-outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\\:crow-ring-0:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.disabled\\:crow-pointer-events-none:disabled{pointer-events:none}.disabled\\:crow-cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:crow-opacity-50:disabled{opacity:.5}`;
2439
2651
  var injected = false;
2440
2652
  function injectStyles(target = document) {
2441
2653
  if (target === document && injected) return;
@@ -2484,7 +2696,6 @@ function CrowWidget({
2484
2696
  });
2485
2697
  const agentName = agentNameProp ?? agentNameFromAPI;
2486
2698
  const welcomeMessage = welcomeMessageProp ?? welcomeMessageFromAPI;
2487
- console.log("[Crow Widget] persistAnonymousConversations from API:", persistAnonymousConversations, "isLoading:", isLoadingStyles);
2488
2699
  const showThinking = showThinkingProp ?? showThinkingFromAPI;
2489
2700
  const [autoTools, setAutoTools] = useState({});
2490
2701
  const cssVars = stylesToCssVars(styles);
@@ -2494,6 +2705,9 @@ function CrowWidget({
2494
2705
  const [isCollapsed, setIsCollapsed] = useState(variant === "floating");
2495
2706
  const [showConversationList, setShowConversationList] = useState(false);
2496
2707
  const [isVerifiedUser, setIsVerifiedUser] = useState(false);
2708
+ const [isBrowserUseActive, setIsBrowserUseActive] = useState(false);
2709
+ const [pendingConfirmation, setPendingConfirmation] = useState(null);
2710
+ const [askUserResolver, setAskUserResolver] = useState(null);
2497
2711
  const {
2498
2712
  activeWorkflow,
2499
2713
  startWorkflow,
@@ -2546,6 +2760,13 @@ function CrowWidget({
2546
2760
  event.toolName,
2547
2761
  event.arguments || {}
2548
2762
  );
2763
+ const resultObj = result;
2764
+ const dataObj = resultObj?.data;
2765
+ const wasUserCancelled = dataObj?.declined === true || typeof resultObj?.error === "string" && resultObj.error.includes("cancelled by user") || typeof resultObj?.error === "string" && resultObj.error.includes("declined");
2766
+ if (wasUserCancelled) {
2767
+ console.log("[Crow Widget] Tool was cancelled by user - not sending result to agent");
2768
+ return;
2769
+ }
2549
2770
  if (result && submitToolResultRef.current) {
2550
2771
  await submitToolResultRef.current(
2551
2772
  event.toolCallId,
@@ -2572,7 +2793,10 @@ function CrowWidget({
2572
2793
  useEffect(() => {
2573
2794
  if (shouldRestoreHistory && chat.conversationId && !hasRestoredHistoryRef.current) {
2574
2795
  hasRestoredHistoryRef.current = true;
2575
- console.log("[Crow Widget] Restoring conversation history:", chat.conversationId);
2796
+ console.log(
2797
+ "[Crow Widget] Restoring conversation history:",
2798
+ chat.conversationId
2799
+ );
2576
2800
  conversations.loadAnonymousConversationHistory(chat.conversationId).then((historyMessages) => {
2577
2801
  if (historyMessages.length > 0) {
2578
2802
  chat.loadMessages(historyMessages);
@@ -2626,6 +2850,41 @@ function CrowWidget({
2626
2850
  onIdentify(identify);
2627
2851
  }
2628
2852
  }, [isLoadingStyles, onIdentify]);
2853
+ const handleBrowserConfirmation = useCallback(
2854
+ (instruction) => {
2855
+ return new Promise((resolve) => {
2856
+ setPendingConfirmation({ instruction, resolve });
2857
+ });
2858
+ },
2859
+ []
2860
+ );
2861
+ const handleBrowserQuestion = useCallback(
2862
+ (question) => {
2863
+ return new Promise((resolve, reject) => {
2864
+ chat.addMessage("assistant", question);
2865
+ setAskUserResolver({ resolve, reject });
2866
+ });
2867
+ },
2868
+ [chat]
2869
+ );
2870
+ const handleBrowserProgress = useCallback(
2871
+ (step, maxSteps) => {
2872
+ if (step >= maxSteps || step === -1) {
2873
+ setIsBrowserUseActive(false);
2874
+ }
2875
+ },
2876
+ []
2877
+ );
2878
+ useEffect(() => {
2879
+ window.__crow_browser_callbacks = {
2880
+ onConfirmation: handleBrowserConfirmation,
2881
+ onQuestion: handleBrowserQuestion,
2882
+ onProgress: handleBrowserProgress
2883
+ };
2884
+ return () => {
2885
+ delete window.__crow_browser_callbacks;
2886
+ };
2887
+ }, [handleBrowserConfirmation, handleBrowserQuestion, handleBrowserProgress]);
2629
2888
  useEffect(() => {
2630
2889
  if (browserUseEnabled && !isLoadingStyles && Object.keys(autoTools).length === 0) {
2631
2890
  import('@usecrow/client/browser').then(({ createBrowserUseTool }) => {
@@ -2638,7 +2897,7 @@ function CrowWidget({
2638
2897
  });
2639
2898
  }
2640
2899
  }, [browserUseEnabled, isLoadingStyles, productId, apiUrl, autoTools]);
2641
- const mergedTools = { ...autoTools, ...tools };
2900
+ const mergedTools = useMemo(() => ({ ...autoTools, ...tools }), [autoTools, tools]);
2642
2901
  useEffect(() => {
2643
2902
  if (Object.keys(mergedTools).length > 0) {
2644
2903
  window.crow?.("registerTools", mergedTools);
@@ -2647,8 +2906,37 @@ function CrowWidget({
2647
2906
  const handleSend = (message) => {
2648
2907
  if (!message.trim()) return;
2649
2908
  setIsCollapsed(false);
2909
+ if (askUserResolver) {
2910
+ chat.addMessage("user", message);
2911
+ askUserResolver.resolve(message);
2912
+ setAskUserResolver(null);
2913
+ return;
2914
+ }
2650
2915
  chat.sendMessage(message);
2651
2916
  };
2917
+ const handleStop = () => {
2918
+ chat.stopGeneration();
2919
+ if (browserUseEnabled && isBrowserUseActive) {
2920
+ import('@usecrow/client/browser').then(({ stopActiveBrowserUse }) => {
2921
+ stopActiveBrowserUse();
2922
+ if (askUserResolver) {
2923
+ askUserResolver.reject();
2924
+ setAskUserResolver(null);
2925
+ }
2926
+ }).catch(() => {
2927
+ });
2928
+ setIsBrowserUseActive(false);
2929
+ } else {
2930
+ if (askUserResolver) {
2931
+ askUserResolver.reject();
2932
+ setAskUserResolver(null);
2933
+ }
2934
+ }
2935
+ if (pendingConfirmation) {
2936
+ pendingConfirmation.resolve(false);
2937
+ setPendingConfirmation(null);
2938
+ }
2939
+ };
2652
2940
  const handleNewChat = () => {
2653
2941
  chat.resetMessages();
2654
2942
  setShowConversationList(false);
@@ -2704,24 +2992,43 @@ function CrowWidget({
2704
2992
  onExit: handleExitWorkflow
2705
2993
  }
2706
2994
  ) }),
2707
- /* @__PURE__ */ jsx(AnimatePresence, { children: (chat.messages.length > 0 || conversations.isLoadingHistory) && /* @__PURE__ */ jsx(MessagesContainer, { ref: messagesContainerRef, children: /* @__PURE__ */ jsx(
2708
- MessageList,
2709
- {
2710
- messages: chat.messages,
2711
- activeToolCalls: chat.activeToolCalls,
2712
- isLoadingHistory: conversations.isLoadingHistory,
2713
- isGenerating: chat.isLoading
2714
- }
2715
- ) }) }),
2995
+ /* @__PURE__ */ jsx(AnimatePresence, { children: (chat.messages.length > 0 || conversations.isLoadingHistory || pendingConfirmation) && /* @__PURE__ */ jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
2996
+ /* @__PURE__ */ jsx(
2997
+ MessageList,
2998
+ {
2999
+ messages: chat.messages,
3000
+ activeToolCalls: chat.activeToolCalls,
3001
+ isLoadingHistory: conversations.isLoadingHistory,
3002
+ isGenerating: chat.isLoading
3003
+ }
3004
+ ),
3005
+ pendingConfirmation && /* @__PURE__ */ jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsx(
3006
+ BrowserUseConfirmation,
3007
+ {
3008
+ instruction: pendingConfirmation.instruction,
3009
+ onAllow: () => {
3010
+ setIsBrowserUseActive(true);
3011
+ pendingConfirmation.resolve(true);
3012
+ setPendingConfirmation(null);
3013
+ },
3014
+ onDeny: () => {
3015
+ pendingConfirmation.resolve(false);
3016
+ setPendingConfirmation(null);
3017
+ }
3018
+ }
3019
+ ) })
3020
+ ] }) }),
2716
3021
  /* @__PURE__ */ jsxs("div", { className: "crow-mt-auto crow-w-full", children: [
2717
3022
  /* @__PURE__ */ jsx(PoweredByBadge, { apiUrl }),
2718
3023
  /* @__PURE__ */ jsx(
2719
3024
  PromptInputBox,
2720
3025
  {
2721
3026
  onSend: handleSend,
2722
- onStop: chat.stopGeneration,
3027
+ onStop: handleStop,
2723
3028
  placeholder: "Type your message...",
2724
3029
  isLoading: chat.isLoading,
3030
+ showStopButton: isBrowserUseActive || !!askUserResolver || !!pendingConfirmation,
3031
+ highlighted: !!askUserResolver,
2725
3032
  className: "crow-backdrop-blur-md"
2726
3033
  }
2727
3034
  )
@@ -2737,7 +3044,13 @@ function CrowWidget({
2737
3044
  showThinking,
2738
3045
  children: [
2739
3046
  variant === "floating" && /* @__PURE__ */ jsxs(Fragment, { children: [
2740
- /* @__PURE__ */ jsx(ChatBubble, { isExpanded: !isCollapsed, onClick: handleBubbleClick }),
3047
+ /* @__PURE__ */ jsx(
3048
+ ChatBubble,
3049
+ {
3050
+ isExpanded: !isCollapsed,
3051
+ onClick: handleBubbleClick
3052
+ }
3053
+ ),
2741
3054
  !isCollapsed && /* @__PURE__ */ jsx(WidgetShell, { children: renderWidgetContent() })
2742
3055
  ] }),
2743
3056
  variant === "embedded" && /* @__PURE__ */ jsx(WidgetShell, { children: renderWidgetContent() })
@@ -2760,7 +3073,13 @@ function CrowCopilot({
2760
3073
  className,
2761
3074
  onReady
2762
3075
  }) {
2763
- const { styles, isLoading: isLoadingStyles, agentName: agentNameFromAPI, persistAnonymousConversations, welcomeMessage: welcomeMessageFromAPI } = useCopilotStyles({
3076
+ const {
3077
+ styles,
3078
+ isLoading: isLoadingStyles,
3079
+ agentName: agentNameFromAPI,
3080
+ persistAnonymousConversations,
3081
+ welcomeMessage: welcomeMessageFromAPI
3082
+ } = useCopilotStyles({
2764
3083
  productId,
2765
3084
  apiUrl,
2766
3085
  propStyles,
@@ -2772,6 +3091,8 @@ function CrowCopilot({
2772
3091
  const executeClientToolRef = useRef(null);
2773
3092
  const [showConversationList, setShowConversationList] = useState(false);
2774
3093
  const [isVerifiedUser, setIsVerifiedUser] = useState(false);
3094
+ const [pendingConfirmation, setPendingConfirmation] = useState(null);
3095
+ const [pendingQuestion, setPendingQuestion] = useState(null);
2775
3096
  const conversations = useConversations({ productId, apiUrl });
2776
3097
  const [shouldRestoreHistory, setShouldRestoreHistory] = useState(false);
2777
3098
  const hasRestoredHistoryRef = useRef(false);
@@ -2787,8 +3108,15 @@ function CrowCopilot({
2787
3108
  },
2788
3109
  onToolCall: (event) => {
2789
3110
  if (event.type === "client_call" && event.toolName) {
2790
- console.log("[Crow Copilot] Executing client tool:", event.toolName, event.arguments);
2791
- const result = executeClientToolRef.current?.(event.toolName, event.arguments || {});
3111
+ console.log(
3112
+ "[Crow Copilot] Executing client tool:",
3113
+ event.toolName,
3114
+ event.arguments
3115
+ );
3116
+ const result = executeClientToolRef.current?.(
3117
+ event.toolName,
3118
+ event.arguments || {}
3119
+ );
2792
3120
  result?.then((r) => console.log("[Crow Copilot] Tool result:", r)).catch((e) => console.error("[Crow Copilot] Tool error:", e));
2793
3121
  }
2794
3122
  },
@@ -2817,6 +3145,31 @@ function CrowCopilot({
2817
3145
  }
2818
3146
  });
2819
3147
  executeClientToolRef.current = executeClientTool;
3148
+ const handleBrowserConfirmation = useCallback(
3149
+ (instruction) => {
3150
+ return new Promise((resolve) => {
3151
+ setPendingConfirmation({ instruction, resolve });
3152
+ });
3153
+ },
3154
+ []
3155
+ );
3156
+ const handleBrowserQuestion = useCallback(
3157
+ (question) => {
3158
+ return new Promise((resolve) => {
3159
+ setPendingQuestion({ question, resolve });
3160
+ });
3161
+ },
3162
+ []
3163
+ );
3164
+ useEffect(() => {
3165
+ window.__crow_browser_callbacks = {
3166
+ onConfirmation: handleBrowserConfirmation,
3167
+ onQuestion: handleBrowserQuestion
3168
+ };
3169
+ return () => {
3170
+ delete window.__crow_browser_callbacks;
3171
+ };
3172
+ }, [handleBrowserConfirmation, handleBrowserQuestion]);
2820
3173
  useEffect(() => {
2821
3174
  if (!isLoadingStyles) {
2822
3175
  onReady?.();
@@ -2934,27 +3287,60 @@ function CrowCopilot({
2934
3287
  onClose: handleCloseConversationList
2935
3288
  }
2936
3289
  ) }),
2937
- /* @__PURE__ */ jsx(MessagesContainer, { ref: messagesContainerRef, children: /* @__PURE__ */ jsx(
2938
- MessageList,
2939
- {
2940
- messages: chat.messages,
2941
- activeToolCalls: chat.activeToolCalls,
2942
- isLoadingHistory: conversations.isLoadingHistory,
2943
- isGenerating: chat.isLoading
2944
- }
2945
- ) }),
2946
- /* @__PURE__ */ jsxs("div", { className: "crow-p-3 crow-border-t", style: { borderColor: styles.colors.border }, children: [
2947
- styles.branding.showPoweredBy && /* @__PURE__ */ jsx(PoweredByBadge, { apiUrl }),
3290
+ /* @__PURE__ */ jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
2948
3291
  /* @__PURE__ */ jsx(
2949
- PromptInputBox,
3292
+ MessageList,
2950
3293
  {
2951
- onSend: handleSend,
2952
- onStop: chat.stopGeneration,
2953
- placeholder: "Ask anything...",
2954
- isLoading: chat.isLoading
3294
+ messages: chat.messages,
3295
+ activeToolCalls: chat.activeToolCalls,
3296
+ isLoadingHistory: conversations.isLoadingHistory,
3297
+ isGenerating: chat.isLoading
2955
3298
  }
2956
- )
2957
- ] })
3299
+ ),
3300
+ pendingConfirmation && /* @__PURE__ */ jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsx(
3301
+ BrowserUseConfirmation,
3302
+ {
3303
+ instruction: pendingConfirmation.instruction,
3304
+ onAllow: () => {
3305
+ pendingConfirmation.resolve(true);
3306
+ setPendingConfirmation(null);
3307
+ },
3308
+ onDeny: () => {
3309
+ pendingConfirmation.resolve(false);
3310
+ setPendingConfirmation(null);
3311
+ }
3312
+ }
3313
+ ) }),
3314
+ pendingQuestion && /* @__PURE__ */ jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsx(
3315
+ BrowserUseQuestion,
3316
+ {
3317
+ question: pendingQuestion.question,
3318
+ onSubmit: (answer) => {
3319
+ pendingQuestion.resolve(answer);
3320
+ setPendingQuestion(null);
3321
+ }
3322
+ }
3323
+ ) })
3324
+ ] }),
3325
+ /* @__PURE__ */ jsxs(
3326
+ "div",
3327
+ {
3328
+ className: "crow-p-3 crow-border-t",
3329
+ style: { borderColor: styles.colors.border },
3330
+ children: [
3331
+ styles.branding.showPoweredBy && /* @__PURE__ */ jsx(PoweredByBadge, { apiUrl }),
3332
+ /* @__PURE__ */ jsx(
3333
+ PromptInputBox,
3334
+ {
3335
+ onSend: handleSend,
3336
+ onStop: chat.stopGeneration,
3337
+ placeholder: "Ask anything...",
3338
+ isLoading: chat.isLoading
3339
+ }
3340
+ )
3341
+ ]
3342
+ }
3343
+ )
2958
3344
  ]
2959
3345
  }
2960
3346
  )