@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.cjs CHANGED
@@ -1190,6 +1190,10 @@ function useWidgetStyles({
1190
1190
  const [browserUseEnabled, setBrowserUseEnabled] = React3.useState(
1191
1191
  styleCache.get(key)?.browserUseEnabled || false
1192
1192
  );
1193
+ const [pageNavigationEnabled, setPageNavigationEnabled] = React3.useState(
1194
+ styleCache.get(key)?.pageNavigationEnabled || false
1195
+ );
1196
+ const [pageNavigationRoutes, setPageNavigationRoutes] = React3.useState(styleCache.get(key)?.pageNavigationRoutes || []);
1193
1197
  const [showThinking, setShowThinking] = React3.useState(
1194
1198
  styleCache.get(key)?.showThinking ?? true
1195
1199
  );
@@ -1213,6 +1217,8 @@ function useWidgetStyles({
1213
1217
  setDbStyles(config.widgetStyles);
1214
1218
  setAgentName(config.agentName || "Assistant");
1215
1219
  setBrowserUseEnabled(config.browserUseEnabled || false);
1220
+ setPageNavigationEnabled(config.pageNavigationEnabled || false);
1221
+ setPageNavigationRoutes(config.pageNavigationRoutes || []);
1216
1222
  setShowThinking(config.showThinking ?? true);
1217
1223
  setPersistAnonymousConversations(config.persistAnonymousConversations ?? true);
1218
1224
  setWelcomeMessage(config.welcomeMessage ?? void 0);
@@ -1248,6 +1254,8 @@ function useWidgetStyles({
1248
1254
  error,
1249
1255
  agentName,
1250
1256
  browserUseEnabled,
1257
+ pageNavigationEnabled,
1258
+ pageNavigationRoutes,
1251
1259
  showThinking,
1252
1260
  persistAnonymousConversations,
1253
1261
  welcomeMessage,
@@ -1271,12 +1279,19 @@ function useCopilotStyles({
1271
1279
  const [agentName, setAgentName] = React3.useState(
1272
1280
  styleCache.get(key)?.agentName || "Assistant"
1273
1281
  );
1282
+ const [pageNavigationEnabled, setPageNavigationEnabled] = React3.useState(
1283
+ styleCache.get(key)?.pageNavigationEnabled || false
1284
+ );
1285
+ const [pageNavigationRoutes, setPageNavigationRoutes] = React3.useState(styleCache.get(key)?.pageNavigationRoutes || []);
1274
1286
  const [persistAnonymousConversations, setPersistAnonymousConversations] = React3.useState(
1275
1287
  styleCache.has(key) ? styleCache.get(key)?.persistAnonymousConversations ?? true : void 0
1276
1288
  );
1277
1289
  const [welcomeMessage, setWelcomeMessage] = React3.useState(
1278
1290
  styleCache.get(key)?.welcomeMessage ?? void 0
1279
1291
  );
1292
+ const [selectedModel, setSelectedModel] = React3.useState(
1293
+ styleCache.get(key)?.model ?? void 0
1294
+ );
1280
1295
  const hasFetchedRef = React3.useRef(false);
1281
1296
  const fetchStyles = async () => {
1282
1297
  if (skip) return;
@@ -1287,8 +1302,11 @@ function useCopilotStyles({
1287
1302
  styleCache.set(key, config);
1288
1303
  setDbStyles(config.copilotStyles);
1289
1304
  setAgentName(config.agentName || "Assistant");
1305
+ setPageNavigationEnabled(config.pageNavigationEnabled || false);
1306
+ setPageNavigationRoutes(config.pageNavigationRoutes || []);
1290
1307
  setPersistAnonymousConversations(config.persistAnonymousConversations ?? true);
1291
1308
  setWelcomeMessage(config.welcomeMessage ?? void 0);
1309
+ setSelectedModel(config.model ?? void 0);
1292
1310
  } catch (err) {
1293
1311
  console.error("[CrowCopilot] Failed to fetch styles:", err);
1294
1312
  setError(err instanceof Error ? err : new Error(String(err)));
@@ -1302,8 +1320,11 @@ function useCopilotStyles({
1302
1320
  if (cached) {
1303
1321
  setDbStyles(cached.copilotStyles);
1304
1322
  setAgentName(cached.agentName || "Assistant");
1323
+ setPageNavigationEnabled(cached.pageNavigationEnabled || false);
1324
+ setPageNavigationRoutes(cached.pageNavigationRoutes || []);
1305
1325
  setPersistAnonymousConversations(cached.persistAnonymousConversations ?? true);
1306
1326
  setWelcomeMessage(cached.welcomeMessage ?? void 0);
1327
+ setSelectedModel(cached.model ?? void 0);
1307
1328
  setIsLoading(false);
1308
1329
  return;
1309
1330
  }
@@ -1316,8 +1337,11 @@ function useCopilotStyles({
1316
1337
  isLoading,
1317
1338
  error,
1318
1339
  agentName,
1340
+ pageNavigationEnabled,
1341
+ pageNavigationRoutes,
1319
1342
  persistAnonymousConversations,
1320
1343
  welcomeMessage,
1344
+ selectedModel,
1321
1345
  refetch: fetchStyles
1322
1346
  };
1323
1347
  }
@@ -2862,6 +2886,7 @@ function CrowWidget({
2862
2886
  onReady,
2863
2887
  onIdentify,
2864
2888
  tools,
2889
+ navigate,
2865
2890
  onToolResult
2866
2891
  }) {
2867
2892
  const {
@@ -2869,6 +2894,8 @@ function CrowWidget({
2869
2894
  isLoading: isLoadingStyles,
2870
2895
  agentName: agentNameFromAPI,
2871
2896
  browserUseEnabled,
2897
+ pageNavigationEnabled,
2898
+ pageNavigationRoutes,
2872
2899
  showThinking: showThinkingFromAPI,
2873
2900
  persistAnonymousConversations,
2874
2901
  welcomeMessage: welcomeMessageFromAPI,
@@ -3074,17 +3101,33 @@ function CrowWidget({
3074
3101
  };
3075
3102
  }, [handleBrowserConfirmation, handleBrowserQuestion, handleBrowserProgress]);
3076
3103
  React3.useEffect(() => {
3077
- if (browserUseEnabled && !isLoadingStyles && Object.keys(autoTools).length === 0) {
3104
+ if (browserUseEnabled && !isLoadingStyles && !autoTools.browser_use) {
3078
3105
  import('@usecrow/client/browser').then(({ createBrowserUseTool }) => {
3079
- setAutoTools({
3106
+ setAutoTools((prev) => ({
3107
+ ...prev,
3080
3108
  browser_use: createBrowserUseTool({ productId, apiUrl })
3081
- });
3109
+ }));
3082
3110
  console.log("[Crow] browser_use tool auto-loaded");
3083
3111
  }).catch((err) => {
3084
3112
  console.warn("[Crow] Failed to load browser_use:", err);
3085
3113
  });
3086
3114
  }
3087
3115
  }, [browserUseEnabled, isLoadingStyles, productId, apiUrl, autoTools]);
3116
+ React3.useEffect(() => {
3117
+ if (pageNavigationEnabled && pageNavigationRoutes.length > 0 && !isLoadingStyles) {
3118
+ import('@usecrow/client').then(({ createNavigateToPageTool }) => {
3119
+ setAutoTools((prev) => ({
3120
+ ...prev,
3121
+ navigateToPage: createNavigateToPageTool(pageNavigationRoutes, navigate)
3122
+ }));
3123
+ console.log(
3124
+ `[Crow] navigateToPage tool auto-loaded with ${pageNavigationRoutes.length} routes`
3125
+ );
3126
+ }).catch((err) => {
3127
+ console.warn("[Crow] Failed to load navigateToPage:", err);
3128
+ });
3129
+ }
3130
+ }, [pageNavigationEnabled, pageNavigationRoutes, isLoadingStyles, navigate]);
3088
3131
  const mergedTools = React3.useMemo(() => ({ ...autoTools, ...tools }), [autoTools, tools]);
3089
3132
  React3.useEffect(() => {
3090
3133
  if (Object.keys(mergedTools).length > 0) {
@@ -3381,14 +3424,18 @@ function CrowCopilot({
3381
3424
  previewMode = false,
3382
3425
  className,
3383
3426
  onReady,
3427
+ navigate,
3384
3428
  onToolResult
3385
3429
  }) {
3386
3430
  const {
3387
3431
  styles,
3388
3432
  isLoading: isLoadingStyles,
3389
3433
  agentName: agentNameFromAPI,
3434
+ pageNavigationEnabled,
3435
+ pageNavigationRoutes,
3390
3436
  persistAnonymousConversations,
3391
- welcomeMessage: welcomeMessageFromAPI
3437
+ welcomeMessage: welcomeMessageFromAPI,
3438
+ selectedModel
3392
3439
  } = useCopilotStyles({
3393
3440
  productId,
3394
3441
  apiUrl,
@@ -3397,9 +3444,31 @@ function CrowCopilot({
3397
3444
  });
3398
3445
  const agentName = agentNameProp ?? agentNameFromAPI ?? title;
3399
3446
  const welcomeMessage = welcomeMessageProp ?? welcomeMessageFromAPI;
3447
+ const [autoTools, setAutoTools] = React3.useState({});
3448
+ React3.useEffect(() => {
3449
+ if (pageNavigationEnabled && pageNavigationRoutes.length > 0 && !isLoadingStyles) {
3450
+ import('@usecrow/client').then(({ createNavigateToPageTool }) => {
3451
+ setAutoTools((prev) => ({
3452
+ ...prev,
3453
+ navigateToPage: createNavigateToPageTool(pageNavigationRoutes, navigate)
3454
+ }));
3455
+ console.log(
3456
+ `[Crow] navigateToPage tool auto-loaded with ${pageNavigationRoutes.length} routes`
3457
+ );
3458
+ }).catch((err) => {
3459
+ console.warn("[Crow] Failed to load navigateToPage:", err);
3460
+ });
3461
+ }
3462
+ }, [pageNavigationEnabled, pageNavigationRoutes, isLoadingStyles, navigate]);
3463
+ React3.useEffect(() => {
3464
+ if (Object.keys(autoTools).length > 0) {
3465
+ window.crow?.("registerTools", autoTools);
3466
+ }
3467
+ }, [autoTools]);
3400
3468
  const messagesContainerRef = React3.useRef(null);
3401
3469
  const tabsScrollRef = React3.useRef(null);
3402
3470
  const executeClientToolRef = React3.useRef(null);
3471
+ const submitToolResultRef = React3.useRef(null);
3403
3472
  const [showConversationList, setShowConversationList] = React3.useState(false);
3404
3473
  const [isVerifiedUser, setIsVerifiedUser] = React3.useState(false);
3405
3474
  const [localTabs, setLocalTabs] = React3.useState([
@@ -3418,24 +3487,71 @@ function CrowCopilot({
3418
3487
  apiUrl,
3419
3488
  persistAnonymousConversations,
3420
3489
  welcomeMessage,
3490
+ selectedModel,
3421
3491
  onVerificationStatus: (isVerified) => {
3422
3492
  setIsVerifiedUser(isVerified);
3423
3493
  },
3424
3494
  onConversationId: () => {
3425
3495
  },
3496
+ onWorkflowEvent: (event) => {
3497
+ switch (event.type) {
3498
+ case "started":
3499
+ if (event.name && event.todos) {
3500
+ startWorkflow(event.name, event.todos);
3501
+ }
3502
+ break;
3503
+ case "todo_updated":
3504
+ if (event.todoId && event.todoStatus) {
3505
+ updateTodo(event.todoId, event.todoStatus);
3506
+ }
3507
+ break;
3508
+ case "ended":
3509
+ endWorkflow(2e3);
3510
+ break;
3511
+ case "complete_prompt":
3512
+ markComplete();
3513
+ break;
3514
+ }
3515
+ },
3426
3516
  onToolResult,
3427
- onToolCall: (event) => {
3428
- if (event.type === "client_call" && event.toolName) {
3429
- console.log(
3430
- "[Crow Copilot] Executing client tool:",
3431
- event.toolName,
3432
- event.arguments
3433
- );
3434
- const result = executeClientToolRef.current?.(
3435
- event.toolName,
3436
- event.arguments || {}
3437
- );
3438
- result?.then((r) => console.log("[Crow Copilot] Tool result:", r)).catch((e) => console.error("[Crow Copilot] Tool error:", e));
3517
+ onToolCall: async (event) => {
3518
+ if (event.type === "client_call" && event.toolName && event.toolCallId) {
3519
+ try {
3520
+ const result = await executeClientToolRef.current?.(
3521
+ event.toolName,
3522
+ event.arguments || {}
3523
+ );
3524
+ const resultObj = result;
3525
+ const dataObj = resultObj?.data;
3526
+ const wasUserCancelled = dataObj?.declined === true || typeof resultObj?.error === "string" && resultObj.error.includes("cancelled by user") || typeof resultObj?.error === "string" && resultObj.error.includes("declined");
3527
+ if (wasUserCancelled) {
3528
+ console.log("[Crow Copilot] Tool was cancelled by user");
3529
+ if (submitToolResultRef.current) {
3530
+ await submitToolResultRef.current(
3531
+ event.toolCallId,
3532
+ event.toolName,
3533
+ { success: false, cancelled: true, error: "Action was cancelled by the user." }
3534
+ );
3535
+ }
3536
+ return;
3537
+ }
3538
+ if (result && submitToolResultRef.current) {
3539
+ await submitToolResultRef.current(
3540
+ event.toolCallId,
3541
+ event.toolName,
3542
+ result
3543
+ );
3544
+ }
3545
+ } catch (e) {
3546
+ console.error("[Crow Copilot] Tool error:", e);
3547
+ if (submitToolResultRef.current) {
3548
+ await submitToolResultRef.current(
3549
+ event.toolCallId,
3550
+ event.toolName,
3551
+ { success: false, error: String(e) }
3552
+ );
3553
+ }
3554
+ }
3439
3555
  }
3440
3556
  },
3441
3557
  onRestoredConversation: () => {
@@ -3457,6 +3573,30 @@ function CrowCopilot({
3457
3573
  injectCopilotBodyStyles();
3458
3574
  }
3459
3575
  }, [variant]);
3576
+ const {
3577
+ activeWorkflow,
3578
+ startWorkflow,
3579
+ updateTodo,
3580
+ markComplete,
3581
+ endWorkflow,
3582
+ exitWorkflow
3583
+ } = useWorkflow({
3584
+ productId,
3585
+ apiUrl,
3586
+ conversationId: chat.conversationId,
3587
+ selectedModel: chat.selectedModel,
3588
+ onMessage: (content) => {
3589
+ chat.loadMessages([
3590
+ ...chat.messages,
3591
+ {
3592
+ id: `bot-${Date.now()}`,
3593
+ content,
3594
+ isBot: true,
3595
+ timestamp: /* @__PURE__ */ new Date()
3596
+ }
3597
+ ]);
3598
+ }
3599
+ });
3460
3600
  const { executeClientTool } = useCrowAPI({
3461
3601
  onIdentified: async () => {
3462
3602
  setIsVerifiedUser(true);
@@ -3468,6 +3608,7 @@ function CrowCopilot({
3468
3608
  }
3469
3609
  });
3470
3610
  executeClientToolRef.current = executeClientTool;
3611
+ submitToolResultRef.current = chat.submitToolResult;
3471
3612
  const handleBrowserConfirmation = React3.useCallback(
3472
3613
  (instruction) => {
3473
3614
  return new Promise((resolve) => {
@@ -3484,6 +3625,9 @@ function CrowCopilot({
3484
3625
  },
3485
3626
  []
3486
3627
  );
3628
+ const handleExitWorkflow = async () => {
3629
+ await exitWorkflow();
3630
+ };
3487
3631
  React3.useEffect(() => {
3488
3632
  window.__crow_browser_callbacks = {
3489
3633
  onConfirmation: handleBrowserConfirmation,
@@ -3809,6 +3953,13 @@ function CrowCopilot({
3809
3953
  ),
3810
3954
  showConversationList && !isVerifiedUser && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-mb-3 crow-rounded-xl crow-bg-gray-50 crow-border crow-border-gray-200 crow-p-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-text-sm crow-text-gray-600", children: "Sign in to view conversation history." }) })
3811
3955
  ] }),
3956
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsxRuntime.jsx(
3957
+ WorkflowPanel,
3958
+ {
3959
+ workflow: activeWorkflow,
3960
+ onExit: handleExitWorkflow
3961
+ }
3962
+ ) }),
3812
3963
  /* @__PURE__ */ jsxRuntime.jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
3813
3964
  /* @__PURE__ */ jsxRuntime.jsx(
3814
3965
  MessageList,