@usecrow/ui 0.1.32 → 0.1.34

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
@@ -187,6 +187,15 @@ interface WidgetConfigResponse {
187
187
  welcomeMessage?: string | null;
188
188
  /** AI model to use for this product */
189
189
  model?: string;
190
+ /** Whether page navigation is enabled for this product */
191
+ pageNavigationEnabled?: boolean;
192
+ /** Route definitions for page navigation */
193
+ pageNavigationRoutes?: Array<{
194
+ name: string;
195
+ path: string;
196
+ description?: string;
197
+ params?: Record<string, string>;
198
+ }>;
190
199
  }
191
200
 
192
201
  /** Identity data passed to the identify function */
@@ -230,10 +239,12 @@ interface CrowWidgetProps {
230
239
  onIdentify?: (identify: IdentifyFunction) => void;
231
240
  /** Client-side tools the agent can call */
232
241
  tools?: ToolsMap;
242
+ /** Custom navigation function for SPA-safe page navigation (e.g. router.push from Next.js or React Router) */
243
+ navigate?: (path: string) => void;
233
244
  /** Callback fired when a server-side tool completes, with the tool name and full result data */
234
245
  onToolResult?: (toolName: string, result: Record<string, unknown>) => void;
235
246
  }
236
- declare function CrowWidget({ productId, apiUrl, variant, styles: propStyles, previewMode, showThinking: showThinkingProp, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, onReady, onIdentify, tools, onToolResult, }: CrowWidgetProps): react_jsx_runtime.JSX.Element;
247
+ declare function CrowWidget({ productId, apiUrl, variant, styles: propStyles, previewMode, showThinking: showThinkingProp, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, onReady, onIdentify, tools, navigate, onToolResult, }: CrowWidgetProps): react_jsx_runtime.JSX.Element;
237
248
 
238
249
  interface CrowCopilotProps {
239
250
  /** Product ID for this copilot */
@@ -266,10 +277,12 @@ interface CrowCopilotProps {
266
277
  className?: string;
267
278
  /** Callback when copilot is ready */
268
279
  onReady?: () => void;
280
+ /** Custom navigation function for SPA-safe page navigation (e.g. router.push from Next.js or React Router) */
281
+ navigate?: (path: string) => void;
269
282
  /** Callback fired when a server-side tool completes, with the tool name and full result data */
270
283
  onToolResult?: (toolName: string, result: Record<string, unknown>) => void;
271
284
  }
272
- declare function CrowCopilot({ productId, apiUrl, variant, title, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, position, width, defaultOpen, showClose, onClose, styles: propStyles, previewMode, className, onReady, onToolResult, }: CrowCopilotProps): react_jsx_runtime.JSX.Element;
285
+ declare function CrowCopilot({ productId, apiUrl, variant, title, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, position, width, defaultOpen, showClose, onClose, styles: propStyles, previewMode, className, onReady, navigate, onToolResult, }: CrowCopilotProps): react_jsx_runtime.JSX.Element;
273
286
 
274
287
  interface CrowProviderProps extends CrowClientConfig {
275
288
  children: React.ReactNode;
@@ -663,6 +676,15 @@ interface UseWidgetStylesResult {
663
676
  agentName: string;
664
677
  /** Whether browser_use is enabled for this product */
665
678
  browserUseEnabled: boolean;
679
+ /** Whether page navigation is enabled for this product */
680
+ pageNavigationEnabled: boolean;
681
+ /** Route definitions for page navigation */
682
+ pageNavigationRoutes: Array<{
683
+ name: string;
684
+ path: string;
685
+ description?: string;
686
+ params?: Record<string, string>;
687
+ }>;
666
688
  /** Whether to show thinking/reasoning to users */
667
689
  showThinking: boolean;
668
690
  /** Whether to persist anonymous conversations across page refreshes (undefined while loading) */
@@ -695,10 +717,21 @@ interface UseCopilotStylesResult {
695
717
  error: Error | null;
696
718
  /** Agent name from product config */
697
719
  agentName: string;
720
+ /** Whether page navigation is enabled for this product */
721
+ pageNavigationEnabled: boolean;
722
+ /** Route definitions for page navigation */
723
+ pageNavigationRoutes: Array<{
724
+ name: string;
725
+ path: string;
726
+ description?: string;
727
+ params?: Record<string, string>;
728
+ }>;
698
729
  /** Whether to persist anonymous conversations across page refreshes (undefined while loading) */
699
730
  persistAnonymousConversations: boolean | undefined;
700
731
  /** Custom welcome message (undefined uses SDK default) */
701
732
  welcomeMessage: string | undefined;
733
+ /** AI model configured for this product */
734
+ selectedModel: string | undefined;
702
735
  /** Refetch styles from API */
703
736
  refetch: () => Promise<void>;
704
737
  }
package/dist/index.d.ts CHANGED
@@ -187,6 +187,15 @@ interface WidgetConfigResponse {
187
187
  welcomeMessage?: string | null;
188
188
  /** AI model to use for this product */
189
189
  model?: string;
190
+ /** Whether page navigation is enabled for this product */
191
+ pageNavigationEnabled?: boolean;
192
+ /** Route definitions for page navigation */
193
+ pageNavigationRoutes?: Array<{
194
+ name: string;
195
+ path: string;
196
+ description?: string;
197
+ params?: Record<string, string>;
198
+ }>;
190
199
  }
191
200
 
192
201
  /** Identity data passed to the identify function */
@@ -230,10 +239,12 @@ interface CrowWidgetProps {
230
239
  onIdentify?: (identify: IdentifyFunction) => void;
231
240
  /** Client-side tools the agent can call */
232
241
  tools?: ToolsMap;
242
+ /** Custom navigation function for SPA-safe page navigation (e.g. router.push from Next.js or React Router) */
243
+ navigate?: (path: string) => void;
233
244
  /** Callback fired when a server-side tool completes, with the tool name and full result data */
234
245
  onToolResult?: (toolName: string, result: Record<string, unknown>) => void;
235
246
  }
236
- declare function CrowWidget({ productId, apiUrl, variant, styles: propStyles, previewMode, showThinking: showThinkingProp, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, onReady, onIdentify, tools, onToolResult, }: CrowWidgetProps): react_jsx_runtime.JSX.Element;
247
+ declare function CrowWidget({ productId, apiUrl, variant, styles: propStyles, previewMode, showThinking: showThinkingProp, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, onReady, onIdentify, tools, navigate, onToolResult, }: CrowWidgetProps): react_jsx_runtime.JSX.Element;
237
248
 
238
249
  interface CrowCopilotProps {
239
250
  /** Product ID for this copilot */
@@ -266,10 +277,12 @@ interface CrowCopilotProps {
266
277
  className?: string;
267
278
  /** Callback when copilot is ready */
268
279
  onReady?: () => void;
280
+ /** Custom navigation function for SPA-safe page navigation (e.g. router.push from Next.js or React Router) */
281
+ navigate?: (path: string) => void;
269
282
  /** Callback fired when a server-side tool completes, with the tool name and full result data */
270
283
  onToolResult?: (toolName: string, result: Record<string, unknown>) => void;
271
284
  }
272
- declare function CrowCopilot({ productId, apiUrl, variant, title, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, position, width, defaultOpen, showClose, onClose, styles: propStyles, previewMode, className, onReady, onToolResult, }: CrowCopilotProps): react_jsx_runtime.JSX.Element;
285
+ declare function CrowCopilot({ productId, apiUrl, variant, title, agentName: agentNameProp, welcomeMessage: welcomeMessageProp, position, width, defaultOpen, showClose, onClose, styles: propStyles, previewMode, className, onReady, navigate, onToolResult, }: CrowCopilotProps): react_jsx_runtime.JSX.Element;
273
286
 
274
287
  interface CrowProviderProps extends CrowClientConfig {
275
288
  children: React.ReactNode;
@@ -663,6 +676,15 @@ interface UseWidgetStylesResult {
663
676
  agentName: string;
664
677
  /** Whether browser_use is enabled for this product */
665
678
  browserUseEnabled: boolean;
679
+ /** Whether page navigation is enabled for this product */
680
+ pageNavigationEnabled: boolean;
681
+ /** Route definitions for page navigation */
682
+ pageNavigationRoutes: Array<{
683
+ name: string;
684
+ path: string;
685
+ description?: string;
686
+ params?: Record<string, string>;
687
+ }>;
666
688
  /** Whether to show thinking/reasoning to users */
667
689
  showThinking: boolean;
668
690
  /** Whether to persist anonymous conversations across page refreshes (undefined while loading) */
@@ -695,10 +717,21 @@ interface UseCopilotStylesResult {
695
717
  error: Error | null;
696
718
  /** Agent name from product config */
697
719
  agentName: string;
720
+ /** Whether page navigation is enabled for this product */
721
+ pageNavigationEnabled: boolean;
722
+ /** Route definitions for page navigation */
723
+ pageNavigationRoutes: Array<{
724
+ name: string;
725
+ path: string;
726
+ description?: string;
727
+ params?: Record<string, string>;
728
+ }>;
698
729
  /** Whether to persist anonymous conversations across page refreshes (undefined while loading) */
699
730
  persistAnonymousConversations: boolean | undefined;
700
731
  /** Custom welcome message (undefined uses SDK default) */
701
732
  welcomeMessage: string | undefined;
733
+ /** AI model configured for this product */
734
+ selectedModel: string | undefined;
702
735
  /** Refetch styles from API */
703
736
  refetch: () => Promise<void>;
704
737
  }
package/dist/index.js CHANGED
@@ -1164,6 +1164,10 @@ function useWidgetStyles({
1164
1164
  const [browserUseEnabled, setBrowserUseEnabled] = useState(
1165
1165
  styleCache.get(key)?.browserUseEnabled || false
1166
1166
  );
1167
+ const [pageNavigationEnabled, setPageNavigationEnabled] = useState(
1168
+ styleCache.get(key)?.pageNavigationEnabled || false
1169
+ );
1170
+ const [pageNavigationRoutes, setPageNavigationRoutes] = useState(styleCache.get(key)?.pageNavigationRoutes || []);
1167
1171
  const [showThinking, setShowThinking] = useState(
1168
1172
  styleCache.get(key)?.showThinking ?? true
1169
1173
  );
@@ -1187,6 +1191,8 @@ function useWidgetStyles({
1187
1191
  setDbStyles(config.widgetStyles);
1188
1192
  setAgentName(config.agentName || "Assistant");
1189
1193
  setBrowserUseEnabled(config.browserUseEnabled || false);
1194
+ setPageNavigationEnabled(config.pageNavigationEnabled || false);
1195
+ setPageNavigationRoutes(config.pageNavigationRoutes || []);
1190
1196
  setShowThinking(config.showThinking ?? true);
1191
1197
  setPersistAnonymousConversations(config.persistAnonymousConversations ?? true);
1192
1198
  setWelcomeMessage(config.welcomeMessage ?? void 0);
@@ -1222,6 +1228,8 @@ function useWidgetStyles({
1222
1228
  error,
1223
1229
  agentName,
1224
1230
  browserUseEnabled,
1231
+ pageNavigationEnabled,
1232
+ pageNavigationRoutes,
1225
1233
  showThinking,
1226
1234
  persistAnonymousConversations,
1227
1235
  welcomeMessage,
@@ -1245,12 +1253,19 @@ function useCopilotStyles({
1245
1253
  const [agentName, setAgentName] = useState(
1246
1254
  styleCache.get(key)?.agentName || "Assistant"
1247
1255
  );
1256
+ const [pageNavigationEnabled, setPageNavigationEnabled] = useState(
1257
+ styleCache.get(key)?.pageNavigationEnabled || false
1258
+ );
1259
+ const [pageNavigationRoutes, setPageNavigationRoutes] = useState(styleCache.get(key)?.pageNavigationRoutes || []);
1248
1260
  const [persistAnonymousConversations, setPersistAnonymousConversations] = useState(
1249
1261
  styleCache.has(key) ? styleCache.get(key)?.persistAnonymousConversations ?? true : void 0
1250
1262
  );
1251
1263
  const [welcomeMessage, setWelcomeMessage] = useState(
1252
1264
  styleCache.get(key)?.welcomeMessage ?? void 0
1253
1265
  );
1266
+ const [selectedModel, setSelectedModel] = useState(
1267
+ styleCache.get(key)?.model ?? void 0
1268
+ );
1254
1269
  const hasFetchedRef = useRef(false);
1255
1270
  const fetchStyles = async () => {
1256
1271
  if (skip) return;
@@ -1261,8 +1276,11 @@ function useCopilotStyles({
1261
1276
  styleCache.set(key, config);
1262
1277
  setDbStyles(config.copilotStyles);
1263
1278
  setAgentName(config.agentName || "Assistant");
1279
+ setPageNavigationEnabled(config.pageNavigationEnabled || false);
1280
+ setPageNavigationRoutes(config.pageNavigationRoutes || []);
1264
1281
  setPersistAnonymousConversations(config.persistAnonymousConversations ?? true);
1265
1282
  setWelcomeMessage(config.welcomeMessage ?? void 0);
1283
+ setSelectedModel(config.model ?? void 0);
1266
1284
  } catch (err) {
1267
1285
  console.error("[CrowCopilot] Failed to fetch styles:", err);
1268
1286
  setError(err instanceof Error ? err : new Error(String(err)));
@@ -1276,8 +1294,11 @@ function useCopilotStyles({
1276
1294
  if (cached) {
1277
1295
  setDbStyles(cached.copilotStyles);
1278
1296
  setAgentName(cached.agentName || "Assistant");
1297
+ setPageNavigationEnabled(cached.pageNavigationEnabled || false);
1298
+ setPageNavigationRoutes(cached.pageNavigationRoutes || []);
1279
1299
  setPersistAnonymousConversations(cached.persistAnonymousConversations ?? true);
1280
1300
  setWelcomeMessage(cached.welcomeMessage ?? void 0);
1301
+ setSelectedModel(cached.model ?? void 0);
1281
1302
  setIsLoading(false);
1282
1303
  return;
1283
1304
  }
@@ -1290,8 +1311,11 @@ function useCopilotStyles({
1290
1311
  isLoading,
1291
1312
  error,
1292
1313
  agentName,
1314
+ pageNavigationEnabled,
1315
+ pageNavigationRoutes,
1293
1316
  persistAnonymousConversations,
1294
1317
  welcomeMessage,
1318
+ selectedModel,
1295
1319
  refetch: fetchStyles
1296
1320
  };
1297
1321
  }
@@ -2836,6 +2860,7 @@ function CrowWidget({
2836
2860
  onReady,
2837
2861
  onIdentify,
2838
2862
  tools,
2863
+ navigate,
2839
2864
  onToolResult
2840
2865
  }) {
2841
2866
  const {
@@ -2843,6 +2868,8 @@ function CrowWidget({
2843
2868
  isLoading: isLoadingStyles,
2844
2869
  agentName: agentNameFromAPI,
2845
2870
  browserUseEnabled,
2871
+ pageNavigationEnabled,
2872
+ pageNavigationRoutes,
2846
2873
  showThinking: showThinkingFromAPI,
2847
2874
  persistAnonymousConversations,
2848
2875
  welcomeMessage: welcomeMessageFromAPI,
@@ -3048,17 +3075,33 @@ function CrowWidget({
3048
3075
  };
3049
3076
  }, [handleBrowserConfirmation, handleBrowserQuestion, handleBrowserProgress]);
3050
3077
  useEffect(() => {
3051
- if (browserUseEnabled && !isLoadingStyles && Object.keys(autoTools).length === 0) {
3078
+ if (browserUseEnabled && !isLoadingStyles && !autoTools.browser_use) {
3052
3079
  import('@usecrow/client/browser').then(({ createBrowserUseTool }) => {
3053
- setAutoTools({
3080
+ setAutoTools((prev) => ({
3081
+ ...prev,
3054
3082
  browser_use: createBrowserUseTool({ productId, apiUrl })
3055
- });
3083
+ }));
3056
3084
  console.log("[Crow] browser_use tool auto-loaded");
3057
3085
  }).catch((err) => {
3058
3086
  console.warn("[Crow] Failed to load browser_use:", err);
3059
3087
  });
3060
3088
  }
3061
3089
  }, [browserUseEnabled, isLoadingStyles, productId, apiUrl, autoTools]);
3090
+ useEffect(() => {
3091
+ if (pageNavigationEnabled && pageNavigationRoutes.length > 0 && !isLoadingStyles) {
3092
+ import('@usecrow/client').then(({ createNavigateToPageTool }) => {
3093
+ setAutoTools((prev) => ({
3094
+ ...prev,
3095
+ navigateToPage: createNavigateToPageTool(pageNavigationRoutes, navigate)
3096
+ }));
3097
+ console.log(
3098
+ `[Crow] navigateToPage tool auto-loaded with ${pageNavigationRoutes.length} routes`
3099
+ );
3100
+ }).catch((err) => {
3101
+ console.warn("[Crow] Failed to load navigateToPage:", err);
3102
+ });
3103
+ }
3104
+ }, [pageNavigationEnabled, pageNavigationRoutes, isLoadingStyles, navigate]);
3062
3105
  const mergedTools = useMemo(() => ({ ...autoTools, ...tools }), [autoTools, tools]);
3063
3106
  useEffect(() => {
3064
3107
  if (Object.keys(mergedTools).length > 0) {
@@ -3355,14 +3398,18 @@ function CrowCopilot({
3355
3398
  previewMode = false,
3356
3399
  className,
3357
3400
  onReady,
3401
+ navigate,
3358
3402
  onToolResult
3359
3403
  }) {
3360
3404
  const {
3361
3405
  styles,
3362
3406
  isLoading: isLoadingStyles,
3363
3407
  agentName: agentNameFromAPI,
3408
+ pageNavigationEnabled,
3409
+ pageNavigationRoutes,
3364
3410
  persistAnonymousConversations,
3365
- welcomeMessage: welcomeMessageFromAPI
3411
+ welcomeMessage: welcomeMessageFromAPI,
3412
+ selectedModel
3366
3413
  } = useCopilotStyles({
3367
3414
  productId,
3368
3415
  apiUrl,
@@ -3371,9 +3418,31 @@ function CrowCopilot({
3371
3418
  });
3372
3419
  const agentName = agentNameProp ?? agentNameFromAPI ?? title;
3373
3420
  const welcomeMessage = welcomeMessageProp ?? welcomeMessageFromAPI;
3421
+ const [autoTools, setAutoTools] = useState({});
3422
+ useEffect(() => {
3423
+ if (pageNavigationEnabled && pageNavigationRoutes.length > 0 && !isLoadingStyles) {
3424
+ import('@usecrow/client').then(({ createNavigateToPageTool }) => {
3425
+ setAutoTools((prev) => ({
3426
+ ...prev,
3427
+ navigateToPage: createNavigateToPageTool(pageNavigationRoutes, navigate)
3428
+ }));
3429
+ console.log(
3430
+ `[Crow] navigateToPage tool auto-loaded with ${pageNavigationRoutes.length} routes`
3431
+ );
3432
+ }).catch((err) => {
3433
+ console.warn("[Crow] Failed to load navigateToPage:", err);
3434
+ });
3435
+ }
3436
+ }, [pageNavigationEnabled, pageNavigationRoutes, isLoadingStyles, navigate]);
3437
+ useEffect(() => {
3438
+ if (Object.keys(autoTools).length > 0) {
3439
+ window.crow?.("registerTools", autoTools);
3440
+ }
3441
+ }, [autoTools]);
3374
3442
  const messagesContainerRef = useRef(null);
3375
3443
  const tabsScrollRef = useRef(null);
3376
3444
  const executeClientToolRef = useRef(null);
3445
+ const submitToolResultRef = useRef(null);
3377
3446
  const [showConversationList, setShowConversationList] = useState(false);
3378
3447
  const [isVerifiedUser, setIsVerifiedUser] = useState(false);
3379
3448
  const [localTabs, setLocalTabs] = useState([
@@ -3392,24 +3461,71 @@ function CrowCopilot({
3392
3461
  apiUrl,
3393
3462
  persistAnonymousConversations,
3394
3463
  welcomeMessage,
3464
+ selectedModel,
3395
3465
  onVerificationStatus: (isVerified) => {
3396
3466
  setIsVerifiedUser(isVerified);
3397
3467
  },
3398
3468
  onConversationId: () => {
3399
3469
  },
3470
+ onWorkflowEvent: (event) => {
3471
+ switch (event.type) {
3472
+ case "started":
3473
+ if (event.name && event.todos) {
3474
+ startWorkflow(event.name, event.todos);
3475
+ }
3476
+ break;
3477
+ case "todo_updated":
3478
+ if (event.todoId && event.todoStatus) {
3479
+ updateTodo(event.todoId, event.todoStatus);
3480
+ }
3481
+ break;
3482
+ case "ended":
3483
+ endWorkflow(2e3);
3484
+ break;
3485
+ case "complete_prompt":
3486
+ markComplete();
3487
+ break;
3488
+ }
3489
+ },
3400
3490
  onToolResult,
3401
- onToolCall: (event) => {
3402
- if (event.type === "client_call" && event.toolName) {
3403
- console.log(
3404
- "[Crow Copilot] Executing client tool:",
3405
- event.toolName,
3406
- event.arguments
3407
- );
3408
- const result = executeClientToolRef.current?.(
3409
- event.toolName,
3410
- event.arguments || {}
3411
- );
3412
- result?.then((r) => console.log("[Crow Copilot] Tool result:", r)).catch((e) => console.error("[Crow Copilot] Tool error:", e));
3491
+ onToolCall: async (event) => {
3492
+ if (event.type === "client_call" && event.toolName && event.toolCallId) {
3493
+ try {
3494
+ const result = await executeClientToolRef.current?.(
3495
+ event.toolName,
3496
+ event.arguments || {}
3497
+ );
3498
+ const resultObj = result;
3499
+ const dataObj = resultObj?.data;
3500
+ const wasUserCancelled = dataObj?.declined === true || typeof resultObj?.error === "string" && resultObj.error.includes("cancelled by user") || typeof resultObj?.error === "string" && resultObj.error.includes("declined");
3501
+ if (wasUserCancelled) {
3502
+ console.log("[Crow Copilot] Tool was cancelled by user");
3503
+ if (submitToolResultRef.current) {
3504
+ await submitToolResultRef.current(
3505
+ event.toolCallId,
3506
+ event.toolName,
3507
+ { success: false, cancelled: true, error: "Action was cancelled by the user." }
3508
+ );
3509
+ }
3510
+ return;
3511
+ }
3512
+ if (result && submitToolResultRef.current) {
3513
+ await submitToolResultRef.current(
3514
+ event.toolCallId,
3515
+ event.toolName,
3516
+ result
3517
+ );
3518
+ }
3519
+ } catch (e) {
3520
+ console.error("[Crow Copilot] Tool error:", e);
3521
+ if (submitToolResultRef.current) {
3522
+ await submitToolResultRef.current(
3523
+ event.toolCallId,
3524
+ event.toolName,
3525
+ { success: false, error: String(e) }
3526
+ );
3527
+ }
3528
+ }
3413
3529
  }
3414
3530
  },
3415
3531
  onRestoredConversation: () => {
@@ -3431,6 +3547,30 @@ function CrowCopilot({
3431
3547
  injectCopilotBodyStyles();
3432
3548
  }
3433
3549
  }, [variant]);
3550
+ const {
3551
+ activeWorkflow,
3552
+ startWorkflow,
3553
+ updateTodo,
3554
+ markComplete,
3555
+ endWorkflow,
3556
+ exitWorkflow
3557
+ } = useWorkflow({
3558
+ productId,
3559
+ apiUrl,
3560
+ conversationId: chat.conversationId,
3561
+ selectedModel: chat.selectedModel,
3562
+ onMessage: (content) => {
3563
+ chat.loadMessages([
3564
+ ...chat.messages,
3565
+ {
3566
+ id: `bot-${Date.now()}`,
3567
+ content,
3568
+ isBot: true,
3569
+ timestamp: /* @__PURE__ */ new Date()
3570
+ }
3571
+ ]);
3572
+ }
3573
+ });
3434
3574
  const { executeClientTool } = useCrowAPI({
3435
3575
  onIdentified: async () => {
3436
3576
  setIsVerifiedUser(true);
@@ -3442,6 +3582,7 @@ function CrowCopilot({
3442
3582
  }
3443
3583
  });
3444
3584
  executeClientToolRef.current = executeClientTool;
3585
+ submitToolResultRef.current = chat.submitToolResult;
3445
3586
  const handleBrowserConfirmation = useCallback(
3446
3587
  (instruction) => {
3447
3588
  return new Promise((resolve) => {
@@ -3458,6 +3599,9 @@ function CrowCopilot({
3458
3599
  },
3459
3600
  []
3460
3601
  );
3602
+ const handleExitWorkflow = async () => {
3603
+ await exitWorkflow();
3604
+ };
3461
3605
  useEffect(() => {
3462
3606
  window.__crow_browser_callbacks = {
3463
3607
  onConfirmation: handleBrowserConfirmation,
@@ -3783,6 +3927,13 @@ function CrowCopilot({
3783
3927
  ),
3784
3928
  showConversationList && !isVerifiedUser && /* @__PURE__ */ jsx("div", { className: "crow-mb-3 crow-rounded-xl crow-bg-gray-50 crow-border crow-border-gray-200 crow-p-4", children: /* @__PURE__ */ jsx("div", { className: "crow-text-sm crow-text-gray-600", children: "Sign in to view conversation history." }) })
3785
3929
  ] }),
3930
+ /* @__PURE__ */ jsx(AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsx(
3931
+ WorkflowPanel,
3932
+ {
3933
+ workflow: activeWorkflow,
3934
+ onExit: handleExitWorkflow
3935
+ }
3936
+ ) }),
3786
3937
  /* @__PURE__ */ jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
3787
3938
  /* @__PURE__ */ jsx(
3788
3939
  MessageList,