@usecrow/ui 0.1.74 → 0.1.76

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
@@ -75,6 +75,8 @@ function useChat({
75
75
  subdomain,
76
76
  toolConsentSettings,
77
77
  language,
78
+ agentMode,
79
+ onOnboardingComplete,
78
80
  onVerificationStatus,
79
81
  onConversationId,
80
82
  onWorkflowEvent,
@@ -167,7 +169,8 @@ function useChat({
167
169
  user_local_time: (/* @__PURE__ */ new Date()).toLocaleString("en-US", { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric", hour12: true }),
168
170
  page_path: typeof window !== "undefined" ? window.location.pathname : void 0,
169
171
  context: typeof window !== "undefined" ? window.__crow_page_context : void 0,
170
- ...language && language !== "en" ? { language } : {}
172
+ ...language && language !== "en" ? { language } : {},
173
+ ...agentMode ? { agent_mode: agentMode } : {}
171
174
  }),
172
175
  signal: abortControllerRef.current.signal
173
176
  });
@@ -495,6 +498,9 @@ function useChat({
495
498
  setSuggestedActions(parsed.actions);
496
499
  }
497
500
  break;
501
+ case "onboarding_complete":
502
+ onOnboardingComplete?.(parsed.summary || "");
503
+ break;
498
504
  }
499
505
  } catch (e) {
500
506
  console.error("[Crow] Parse error:", e);
@@ -527,7 +533,7 @@ function useChat({
527
533
  abortControllerRef.current = null;
528
534
  }
529
535
  },
530
- [apiUrl, productId, conversationId, selectedModel, subdomain, persistAnonymousConversations, onVerificationStatus, onConversationId, onWorkflowEvent, onToolCall, onToolResult]
536
+ [apiUrl, productId, conversationId, selectedModel, subdomain, persistAnonymousConversations, agentMode, onOnboardingComplete, onVerificationStatus, onConversationId, onWorkflowEvent, onToolCall, onToolResult]
531
537
  );
532
538
  const sendMessage = React3.useCallback(
533
539
  (content) => {
@@ -1275,6 +1281,20 @@ function useCrowAPI({ onIdentified, onReset } = {}) {
1275
1281
  case "close":
1276
1282
  window.dispatchEvent(new CustomEvent("crow:close"));
1277
1283
  break;
1284
+ case "sendMessage": {
1285
+ const msgText = typeof options === "string" ? options : opts?.text ?? opts?.message;
1286
+ if (!msgText) {
1287
+ console.error("[Crow] sendMessage() requires a text string or { text }");
1288
+ return;
1289
+ }
1290
+ window.dispatchEvent(new CustomEvent("crow:open"));
1291
+ setTimeout(() => {
1292
+ window.dispatchEvent(
1293
+ new CustomEvent("crow:sendMessage", { detail: { text: msgText } })
1294
+ );
1295
+ }, 50);
1296
+ break;
1297
+ }
1278
1298
  case "setToolStatus":
1279
1299
  if (typeof options !== "string") {
1280
1300
  console.error("[Crow] setToolStatus() requires a string");
@@ -1683,6 +1703,18 @@ function useWidgetStyles({
1683
1703
  const [availableModels, setAvailableModels] = React3.useState(
1684
1704
  styleCache.get(key)?.availableModels || []
1685
1705
  );
1706
+ const [onboardingEnabled, setOnboardingEnabled] = React3.useState(
1707
+ styleCache.get(key)?.onboardingEnabled || false
1708
+ );
1709
+ const [onboardingAgentName, setOnboardingAgentName] = React3.useState(
1710
+ styleCache.get(key)?.onboardingAgentName ?? void 0
1711
+ );
1712
+ const [onboardingWelcomeMessage, setOnboardingWelcomeMessage] = React3.useState(
1713
+ styleCache.get(key)?.onboardingWelcomeMessage ?? void 0
1714
+ );
1715
+ const [onboardingIntroSequence, setOnboardingIntroSequence] = React3.useState(
1716
+ styleCache.get(key)?.onboardingIntroSequence ?? void 0
1717
+ );
1686
1718
  const hasFetchedRef = React3.useRef(false);
1687
1719
  const fetchStyles = async () => {
1688
1720
  if (skip) return;
@@ -1704,6 +1736,10 @@ function useWidgetStyles({
1704
1736
  setToolConsentSettings(config.toolConsentSettings || {});
1705
1737
  setModelSelectionEnabled(config.modelSelectionEnabled || false);
1706
1738
  setAvailableModels(config.availableModels || []);
1739
+ setOnboardingEnabled(config.onboardingEnabled || false);
1740
+ setOnboardingAgentName(config.onboardingAgentName ?? void 0);
1741
+ setOnboardingWelcomeMessage(config.onboardingWelcomeMessage ?? void 0);
1742
+ setOnboardingIntroSequence(config.onboardingIntroSequence ?? void 0);
1707
1743
  } catch (err) {
1708
1744
  console.error("[CrowWidget] Failed to fetch styles:", err);
1709
1745
  setError(err instanceof Error ? err : new Error(String(err)));
@@ -1747,6 +1783,10 @@ function useWidgetStyles({
1747
1783
  toolConsentSettings,
1748
1784
  modelSelectionEnabled,
1749
1785
  availableModels,
1786
+ onboardingEnabled,
1787
+ onboardingAgentName,
1788
+ onboardingWelcomeMessage,
1789
+ onboardingIntroSequence,
1750
1790
  refetch: fetchStyles
1751
1791
  };
1752
1792
  }
@@ -1795,6 +1835,18 @@ function useCopilotStyles({
1795
1835
  const [initialSuggestions, setInitialSuggestions] = React3.useState(
1796
1836
  styleCache.get(key)?.initialSuggestions || []
1797
1837
  );
1838
+ const [onboardingEnabled, setOnboardingEnabled] = React3.useState(
1839
+ styleCache.get(key)?.onboardingEnabled || false
1840
+ );
1841
+ const [onboardingAgentName, setOnboardingAgentName] = React3.useState(
1842
+ styleCache.get(key)?.onboardingAgentName ?? void 0
1843
+ );
1844
+ const [onboardingWelcomeMessage, setOnboardingWelcomeMessage] = React3.useState(
1845
+ styleCache.get(key)?.onboardingWelcomeMessage ?? void 0
1846
+ );
1847
+ const [onboardingIntroSequence, setOnboardingIntroSequence] = React3.useState(
1848
+ styleCache.get(key)?.onboardingIntroSequence ?? void 0
1849
+ );
1798
1850
  const hasFetchedRef = React3.useRef(false);
1799
1851
  const fetchStyles = async () => {
1800
1852
  if (skip) return;
@@ -1815,6 +1867,10 @@ function useCopilotStyles({
1815
1867
  setModelSelectionEnabled(config.modelSelectionEnabled || false);
1816
1868
  setAvailableModels(config.availableModels || []);
1817
1869
  setInitialSuggestions(config.initialSuggestions || []);
1870
+ setOnboardingEnabled(config.onboardingEnabled || false);
1871
+ setOnboardingAgentName(config.onboardingAgentName ?? void 0);
1872
+ setOnboardingWelcomeMessage(config.onboardingWelcomeMessage ?? void 0);
1873
+ setOnboardingIntroSequence(config.onboardingIntroSequence ?? void 0);
1818
1874
  } catch (err) {
1819
1875
  console.error("[CrowCopilot] Failed to fetch styles:", err);
1820
1876
  setError(err instanceof Error ? err : new Error(String(err)));
@@ -1837,6 +1893,10 @@ function useCopilotStyles({
1837
1893
  setModelSelectionEnabled(cached.modelSelectionEnabled || false);
1838
1894
  setAvailableModels(cached.availableModels || []);
1839
1895
  setInitialSuggestions(cached.initialSuggestions || []);
1896
+ setOnboardingEnabled(cached.onboardingEnabled || false);
1897
+ setOnboardingAgentName(cached.onboardingAgentName ?? void 0);
1898
+ setOnboardingWelcomeMessage(cached.onboardingWelcomeMessage ?? void 0);
1899
+ setOnboardingIntroSequence(cached.onboardingIntroSequence ?? void 0);
1840
1900
  setIsLoading(false);
1841
1901
  return;
1842
1902
  }
@@ -1859,6 +1919,10 @@ function useCopilotStyles({
1859
1919
  modelSelectionEnabled,
1860
1920
  availableModels,
1861
1921
  initialSuggestions,
1922
+ onboardingEnabled,
1923
+ onboardingAgentName,
1924
+ onboardingWelcomeMessage,
1925
+ onboardingIntroSequence,
1862
1926
  refetch: fetchStyles
1863
1927
  };
1864
1928
  }
@@ -4517,6 +4581,84 @@ function injectStyles(target = document) {
4517
4581
  target.prepend(style);
4518
4582
  }
4519
4583
  }
4584
+ function OnboardingIntroInline({
4585
+ lines,
4586
+ primaryColor,
4587
+ onComplete
4588
+ }) {
4589
+ const [lineIndex, setLineIndex] = React3.useState(0);
4590
+ const [charIndex, setCharIndex] = React3.useState(0);
4591
+ const [done, setDone] = React3.useState(false);
4592
+ React3.useEffect(() => {
4593
+ if (lineIndex >= lines.length) {
4594
+ setDone(true);
4595
+ return;
4596
+ }
4597
+ const currentLine = lines[lineIndex];
4598
+ if (charIndex < currentLine.length) {
4599
+ const t = setTimeout(() => setCharIndex((c) => c + 1), 35);
4600
+ return () => clearTimeout(t);
4601
+ } else {
4602
+ const t = setTimeout(() => {
4603
+ setLineIndex((l) => l + 1);
4604
+ setCharIndex(0);
4605
+ }, 500);
4606
+ return () => clearTimeout(t);
4607
+ }
4608
+ }, [lineIndex, charIndex, lines]);
4609
+ const displayedLines = lines.slice(0, lineIndex + 1).map(
4610
+ (line, i) => i < lineIndex ? line : line.slice(0, charIndex)
4611
+ );
4612
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
4613
+ display: "flex",
4614
+ flexDirection: "column",
4615
+ alignItems: "center",
4616
+ justifyContent: "center",
4617
+ flex: 1,
4618
+ padding: "24px 16px",
4619
+ textAlign: "center"
4620
+ }, children: [
4621
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minHeight: "4rem", marginBottom: "1.5rem" }, children: displayedLines.map((text, i) => /* @__PURE__ */ jsxRuntime.jsxs("p", { style: {
4622
+ fontSize: i === 0 ? 18 : 14,
4623
+ fontWeight: i === 0 ? 600 : 400,
4624
+ color: i === 0 ? "var(--crow-text, #111827)" : "var(--crow-text-secondary, #6b7280)",
4625
+ lineHeight: 1.4,
4626
+ margin: "0 0 6px 0"
4627
+ }, children: [
4628
+ text,
4629
+ i === lineIndex && !done && /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
4630
+ display: "inline-block",
4631
+ width: 2,
4632
+ height: i === 0 ? 18 : 14,
4633
+ backgroundColor: "var(--crow-text, #111827)",
4634
+ marginLeft: 2,
4635
+ verticalAlign: "middle",
4636
+ animation: "crow-blink 1s step-end infinite"
4637
+ } })
4638
+ ] }, i)) }),
4639
+ /* @__PURE__ */ jsxRuntime.jsx(
4640
+ "button",
4641
+ {
4642
+ onClick: onComplete,
4643
+ style: {
4644
+ padding: "8px 24px",
4645
+ borderRadius: 8,
4646
+ backgroundColor: primaryColor,
4647
+ color: "#fff",
4648
+ fontSize: 13,
4649
+ fontWeight: 500,
4650
+ border: "none",
4651
+ cursor: "pointer",
4652
+ opacity: done ? 1 : 0,
4653
+ pointerEvents: done ? "auto" : "none",
4654
+ transition: "opacity 0.5s ease"
4655
+ },
4656
+ children: "Get Started \u2192"
4657
+ }
4658
+ ),
4659
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `@keyframes crow-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }` })
4660
+ ] });
4661
+ }
4520
4662
  function CrowWidget({
4521
4663
  productId,
4522
4664
  apiUrl = "",
@@ -4537,7 +4679,9 @@ function CrowWidget({
4537
4679
  toolRenderers,
4538
4680
  language,
4539
4681
  customCss,
4540
- contextLabel: contextLabelProp
4682
+ contextLabel: contextLabelProp,
4683
+ forceOnboarding = false,
4684
+ fullscreenTopOffset: _fullscreenTopOffset = 0
4541
4685
  }) {
4542
4686
  const effectiveGetIdentityToken = getIdentityToken || window.__crow_identity_token_fetcher;
4543
4687
  const effectiveOnToolResult = onToolResult || window.__crow_on_tool_result;
@@ -4556,7 +4700,11 @@ function CrowWidget({
4556
4700
  initialSuggestions,
4557
4701
  toolConsentSettings,
4558
4702
  modelSelectionEnabled,
4559
- availableModels: availableModelsFromAPI
4703
+ availableModels: availableModelsFromAPI,
4704
+ onboardingEnabled,
4705
+ onboardingAgentName,
4706
+ onboardingWelcomeMessage,
4707
+ onboardingIntroSequence
4560
4708
  } = useWidgetStyles({
4561
4709
  productId,
4562
4710
  apiUrl,
@@ -4593,6 +4741,25 @@ function CrowWidget({
4593
4741
  const welcomeMessage = greetingOverride ?? welcomeMessageProp ?? welcomeMessageFromAPI;
4594
4742
  const selectedModel = selectedModelFromAPI;
4595
4743
  const showThinking = showThinkingProp ?? showThinkingFromAPI;
4744
+ const [isOnboarding, setIsOnboarding] = React3.useState(false);
4745
+ const [onboardingChecked, setOnboardingChecked] = React3.useState(false);
4746
+ const [onboardingPhase, setOnboardingPhase] = React3.useState("intro");
4747
+ React3.useEffect(() => {
4748
+ if (forceOnboarding && !isLoadingStyles && onboardingEnabled && !onboardingChecked) {
4749
+ setIsOnboarding(true);
4750
+ setOnboardingChecked(true);
4751
+ }
4752
+ }, [forceOnboarding, isLoadingStyles, onboardingEnabled, onboardingChecked]);
4753
+ React3.useEffect(() => {
4754
+ if (isOnboarding) {
4755
+ setIsCollapsed(false);
4756
+ }
4757
+ }, [isOnboarding]);
4758
+ React3.useEffect(() => {
4759
+ if (isOnboarding && !isLoadingStyles && onboardingIntroSequence !== void 0 && onboardingIntroSequence.length === 0) {
4760
+ setOnboardingPhase("chat");
4761
+ }
4762
+ }, [isOnboarding, isLoadingStyles, onboardingIntroSequence]);
4596
4763
  const [autoTools, setAutoTools] = React3.useState({});
4597
4764
  const cssVars = stylesToCssVars(styles);
4598
4765
  const transform = useWidgetTransform({
@@ -4642,11 +4809,17 @@ function CrowWidget({
4642
4809
  const conversations = useConversations({ productId, apiUrl });
4643
4810
  const [shouldRestoreHistory, setShouldRestoreHistory] = React3.useState(false);
4644
4811
  const hasRestoredHistoryRef = React3.useRef(false);
4812
+ const effectiveWelcomeMessage = isOnboarding ? onboardingWelcomeMessage || `Hi! I'm ${onboardingAgentName || agentName}. Let me help you get started.` : welcomeMessage;
4645
4813
  const chat = useChat({
4646
4814
  productId,
4647
4815
  apiUrl,
4648
4816
  persistAnonymousConversations,
4649
- welcomeMessage,
4817
+ welcomeMessage: effectiveWelcomeMessage,
4818
+ agentMode: isOnboarding ? "onboarding" : void 0,
4819
+ onOnboardingComplete: (summary) => {
4820
+ console.log("[Crow] Onboarding complete:", summary);
4821
+ setIsOnboarding(false);
4822
+ },
4650
4823
  selectedModel,
4651
4824
  subdomain,
4652
4825
  toolConsentSettings,
@@ -4734,10 +4907,10 @@ function CrowWidget({
4734
4907
  wasLoadingRef.current = chat.isLoading;
4735
4908
  }, [chat.isLoading, chat.messages]);
4736
4909
  React3.useEffect(() => {
4737
- if (initialSuggestions.length > 0 && chat.suggestedActions.length === 0) {
4910
+ if (!isOnboarding && initialSuggestions.length > 0 && chat.suggestedActions.length === 0) {
4738
4911
  chat.setSuggestedActions(initialSuggestions);
4739
4912
  }
4740
- }, [initialSuggestions]);
4913
+ }, [initialSuggestions, isOnboarding]);
4741
4914
  React3.useEffect(() => {
4742
4915
  if (shouldRestoreHistory && chat.conversationId && !hasRestoredHistoryRef.current) {
4743
4916
  hasRestoredHistoryRef.current = true;
@@ -4772,6 +4945,33 @@ function CrowWidget({
4772
4945
  const { executeClientTool } = useCrowAPI({
4773
4946
  onIdentified: async () => {
4774
4947
  setIsVerifiedUser(true);
4948
+ if (forceOnboarding) {
4949
+ setIsOnboarding(true);
4950
+ setOnboardingChecked(true);
4951
+ } else if (onboardingEnabled && !onboardingChecked) {
4952
+ try {
4953
+ const identityToken = window.__crow_identity_token;
4954
+ if (identityToken) {
4955
+ const res = await fetch(`${apiUrl}/api/chat/resolve-agent`, {
4956
+ method: "POST",
4957
+ headers: { "Content-Type": "application/json" },
4958
+ body: JSON.stringify({
4959
+ product_id: productId,
4960
+ identity_token: identityToken
4961
+ })
4962
+ });
4963
+ if (res.ok) {
4964
+ const data = await res.json();
4965
+ if (data.agent === "onboarding") {
4966
+ setIsOnboarding(true);
4967
+ }
4968
+ }
4969
+ }
4970
+ } catch (e) {
4971
+ console.error("[Crow] resolve-agent failed:", e);
4972
+ }
4973
+ setOnboardingChecked(true);
4974
+ }
4775
4975
  const convs = await conversations.loadConversations();
4776
4976
  if (convs.length > 0) {
4777
4977
  const mostRecent = convs[0];
@@ -4789,6 +4989,16 @@ function CrowWidget({
4789
4989
  });
4790
4990
  executeClientToolRef.current = executeClientTool;
4791
4991
  submitToolResultRef.current = chat.submitToolResult;
4992
+ const prevOnboardingRef = React3.useRef(isOnboarding);
4993
+ React3.useEffect(() => {
4994
+ if (isOnboarding && !prevOnboardingRef.current) {
4995
+ chat.setSuggestedActions([]);
4996
+ }
4997
+ if (prevOnboardingRef.current && !isOnboarding) {
4998
+ chat.resetMessages();
4999
+ }
5000
+ prevOnboardingRef.current = isOnboarding;
5001
+ }, [isOnboarding]);
4792
5002
  React3.useEffect(() => {
4793
5003
  if (!isLoadingStyles) {
4794
5004
  onReady?.();
@@ -5042,6 +5252,10 @@ function CrowWidget({
5042
5252
  React3.useEffect(() => {
5043
5253
  const handleOpen = () => setIsCollapsed(false);
5044
5254
  const handleClose = () => setIsCollapsed(true);
5255
+ const handleSendMessage = (e) => {
5256
+ const text = e.detail?.text;
5257
+ if (text) handleSend(text);
5258
+ };
5045
5259
  const handleSetSuggestions = (e) => {
5046
5260
  const actions = e.detail;
5047
5261
  if (Array.isArray(actions)) {
@@ -5051,6 +5265,7 @@ function CrowWidget({
5051
5265
  };
5052
5266
  window.addEventListener("crow:open", handleOpen);
5053
5267
  window.addEventListener("crow:close", handleClose);
5268
+ window.addEventListener("crow:sendMessage", handleSendMessage);
5054
5269
  window.addEventListener("crow:setSuggestedActions", handleSetSuggestions);
5055
5270
  const pending = window.__crow_suggested_actions;
5056
5271
  if (Array.isArray(pending) && pending.length > 0) {
@@ -5060,6 +5275,7 @@ function CrowWidget({
5060
5275
  return () => {
5061
5276
  window.removeEventListener("crow:open", handleOpen);
5062
5277
  window.removeEventListener("crow:close", handleClose);
5278
+ window.removeEventListener("crow:sendMessage", handleSendMessage);
5063
5279
  window.removeEventListener("crow:setSuggestedActions", handleSetSuggestions);
5064
5280
  };
5065
5281
  }, []);
@@ -5067,7 +5283,59 @@ function CrowWidget({
5067
5283
  setIsCollapsed(!isCollapsed);
5068
5284
  };
5069
5285
  const renderWidgetContent = () => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5070
- /* @__PURE__ */ jsxRuntime.jsx(
5286
+ isOnboarding ? /* @__PURE__ */ jsxRuntime.jsxs(
5287
+ "div",
5288
+ {
5289
+ style: {
5290
+ display: "flex",
5291
+ alignItems: "center",
5292
+ justifyContent: "space-between",
5293
+ padding: "10px 16px",
5294
+ borderBottom: "1px solid var(--crow-border, #e5e7eb)",
5295
+ flexShrink: 0,
5296
+ cursor: variant === "floating" ? "grab" : void 0
5297
+ },
5298
+ onPointerDown: variant === "floating" ? transform.onDragPointerDown : void 0,
5299
+ children: [
5300
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 13, fontWeight: 600, color: "var(--crow-text, #111827)" }, children: onboardingAgentName || agentName }),
5301
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
5302
+ /* @__PURE__ */ jsxRuntime.jsx(
5303
+ "button",
5304
+ {
5305
+ onClick: () => {
5306
+ setIsOnboarding(false);
5307
+ chat.resetMessages();
5308
+ },
5309
+ style: {
5310
+ fontSize: 12,
5311
+ color: "#9ca3af",
5312
+ background: "none",
5313
+ border: "none",
5314
+ cursor: "pointer",
5315
+ padding: "4px 8px"
5316
+ },
5317
+ children: "Skip"
5318
+ }
5319
+ ),
5320
+ variant === "floating" && /* @__PURE__ */ jsxRuntime.jsx(
5321
+ "button",
5322
+ {
5323
+ onClick: () => setIsCollapsed(true),
5324
+ style: {
5325
+ background: "none",
5326
+ border: "none",
5327
+ cursor: "pointer",
5328
+ padding: "4px",
5329
+ color: "#9ca3af",
5330
+ display: "flex"
5331
+ },
5332
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 18L18 6M6 6l12 12" }) })
5333
+ }
5334
+ )
5335
+ ] })
5336
+ ]
5337
+ }
5338
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
5071
5339
  WidgetHeader,
5072
5340
  {
5073
5341
  isVerifiedUser,
@@ -5083,82 +5351,92 @@ function CrowWidget({
5083
5351
  contextLabel
5084
5352
  }
5085
5353
  ),
5086
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: showConversationList && isVerifiedUser && /* @__PURE__ */ jsxRuntime.jsx(
5087
- ConversationList,
5354
+ isOnboarding && onboardingPhase === "intro" && /* @__PURE__ */ jsxRuntime.jsx(
5355
+ OnboardingIntroInline,
5088
5356
  {
5089
- conversations: conversations.conversations,
5090
- currentConversationId: chat.conversationId,
5091
- onSelect: handleSelectConversation,
5092
- onClose: handleCloseConversationList
5357
+ lines: onboardingIntroSequence || [],
5358
+ primaryColor: styles.colors.primary,
5359
+ onComplete: () => setOnboardingPhase("chat")
5093
5360
  }
5094
- ) }),
5095
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsxRuntime.jsx(
5096
- WorkflowPanel,
5097
- {
5098
- workflow: activeWorkflow,
5099
- onExit: handleExitWorkflow
5100
- }
5101
- ) }),
5102
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: (chat.messages.length > 0 || conversations.isLoadingHistory || pendingConfirmation) && /* @__PURE__ */ jsxRuntime.jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
5103
- /* @__PURE__ */ jsxRuntime.jsx(
5104
- MessageList,
5361
+ ),
5362
+ !(isOnboarding && onboardingPhase === "intro") && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5363
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: showConversationList && isVerifiedUser && /* @__PURE__ */ jsxRuntime.jsx(
5364
+ ConversationList,
5105
5365
  {
5106
- messages: chat.messages,
5107
- activeToolCalls: chat.activeToolCalls,
5108
- isLoadingHistory: conversations.isLoadingHistory,
5109
- isGenerating: chat.isLoading,
5110
- toolRenderers: effectiveToolRenderers,
5111
- onToolConsent: handleToolConsent
5366
+ conversations: conversations.conversations,
5367
+ currentConversationId: chat.conversationId,
5368
+ onSelect: handleSelectConversation,
5369
+ onClose: handleCloseConversationList
5112
5370
  }
5113
- ),
5114
- pendingConfirmation && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsxRuntime.jsx(
5115
- BrowserUseConfirmation,
5371
+ ) }),
5372
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsxRuntime.jsx(
5373
+ WorkflowPanel,
5116
5374
  {
5117
- instruction: pendingConfirmation.instruction,
5118
- onAllow: () => {
5119
- setIsBrowserUseActive(true);
5120
- pendingConfirmation.resolve(true);
5121
- setPendingConfirmation(null);
5122
- },
5123
- onDeny: () => {
5124
- pendingConfirmation.resolve(false);
5125
- setPendingConfirmation(null);
5126
- }
5375
+ workflow: activeWorkflow,
5376
+ onExit: handleExitWorkflow
5127
5377
  }
5128
- ) })
5129
- ] }) }),
5130
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "crow-mt-auto crow-w-full", children: [
5131
- toolStatus && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "crow-mx-3 crow-mb-1 crow-flex crow-items-center crow-gap-2 crow-rounded-lg crow-border crow-border-[var(--crow-border,#e5e7eb)] crow-bg-[var(--crow-bg-secondary,#f3f4f6)] crow-px-3 crow-py-2 crow-text-sm", children: [
5132
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "crow-animate-spin crow-h-4 crow-w-4 crow-shrink-0 crow-text-[var(--crow-primary,#7c3aed)]", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
5133
- /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "crow-opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
5134
- /* @__PURE__ */ jsxRuntime.jsx("path", { className: "crow-opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
5378
+ ) }),
5379
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: (chat.messages.length > 0 || conversations.isLoadingHistory || pendingConfirmation) && /* @__PURE__ */ jsxRuntime.jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
5380
+ /* @__PURE__ */ jsxRuntime.jsx(
5381
+ MessageList,
5382
+ {
5383
+ messages: chat.messages,
5384
+ activeToolCalls: chat.activeToolCalls,
5385
+ isLoadingHistory: conversations.isLoadingHistory,
5386
+ isGenerating: chat.isLoading,
5387
+ toolRenderers: effectiveToolRenderers,
5388
+ onToolConsent: handleToolConsent
5389
+ }
5390
+ ),
5391
+ pendingConfirmation && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsxRuntime.jsx(
5392
+ BrowserUseConfirmation,
5393
+ {
5394
+ instruction: pendingConfirmation.instruction,
5395
+ onAllow: () => {
5396
+ setIsBrowserUseActive(true);
5397
+ pendingConfirmation.resolve(true);
5398
+ setPendingConfirmation(null);
5399
+ },
5400
+ onDeny: () => {
5401
+ pendingConfirmation.resolve(false);
5402
+ setPendingConfirmation(null);
5403
+ }
5404
+ }
5405
+ ) })
5406
+ ] }) }),
5407
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "crow-mt-auto crow-w-full", children: [
5408
+ toolStatus && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "crow-mx-3 crow-mb-1 crow-flex crow-items-center crow-gap-2 crow-rounded-lg crow-border crow-border-[var(--crow-border,#e5e7eb)] crow-bg-[var(--crow-bg-secondary,#f3f4f6)] crow-px-3 crow-py-2 crow-text-sm", children: [
5409
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "crow-animate-spin crow-h-4 crow-w-4 crow-shrink-0 crow-text-[var(--crow-primary,#7c3aed)]", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
5410
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "crow-opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
5411
+ /* @__PURE__ */ jsxRuntime.jsx("path", { className: "crow-opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
5412
+ ] }),
5413
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "crow-font-medium crow-text-[var(--crow-text,#111827)]", children: toolStatus })
5135
5414
  ] }),
5136
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "crow-font-medium crow-text-[var(--crow-text,#111827)]", children: toolStatus })
5137
- ] }),
5138
- (chat.suggestedActions.length > 0 || !chat.isLoading && defaultSuggestedActionsRef.current.length > 0) && /* @__PURE__ */ jsxRuntime.jsx(
5139
- SuggestedActions,
5140
- {
5141
- actions: chat.suggestedActions.length > 0 ? chat.suggestedActions : defaultSuggestedActionsRef.current,
5142
- onActionClick: (action) => handleSend(action.message)
5143
- }
5144
- ),
5145
- /* @__PURE__ */ jsxRuntime.jsx(PoweredByBadge, { apiUrl }),
5146
- /* @__PURE__ */ jsxRuntime.jsx(
5147
- PromptInputBox,
5148
- {
5149
- onSend: handleSend,
5150
- onStop: handleStop,
5151
- placeholder: "Type your message...",
5152
- isLoading: chat.isLoading,
5153
- showStopButton: isBrowserUseActive || !!askUserResolver || !!pendingConfirmation,
5154
- highlighted: !!askUserResolver,
5155
- className: "crow-backdrop-blur-md",
5156
- backendUrl: apiUrl,
5157
- selectedModel: chat.selectedModel || selectedModelFromAPI,
5158
- onModelChange: chat.setSelectedModel,
5159
- availableModels: modelSelectionEnabled ? availableModelsFromAPI : []
5160
- }
5161
- )
5415
+ (chat.suggestedActions.length > 0 || !isOnboarding && !chat.isLoading && defaultSuggestedActionsRef.current.length > 0) && /* @__PURE__ */ jsxRuntime.jsx(
5416
+ SuggestedActions,
5417
+ {
5418
+ actions: chat.suggestedActions.length > 0 ? chat.suggestedActions : defaultSuggestedActionsRef.current,
5419
+ onActionClick: (action) => handleSend(action.message)
5420
+ }
5421
+ ),
5422
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByBadge, { apiUrl }),
5423
+ /* @__PURE__ */ jsxRuntime.jsx(
5424
+ PromptInputBox,
5425
+ {
5426
+ onSend: handleSend,
5427
+ onStop: handleStop,
5428
+ placeholder: "Type your message...",
5429
+ isLoading: chat.isLoading,
5430
+ showStopButton: isBrowserUseActive || !!askUserResolver || !!pendingConfirmation,
5431
+ highlighted: !!askUserResolver,
5432
+ className: "crow-backdrop-blur-md",
5433
+ backendUrl: apiUrl,
5434
+ selectedModel: chat.selectedModel || selectedModelFromAPI,
5435
+ onModelChange: chat.setSelectedModel,
5436
+ availableModels: modelSelectionEnabled ? availableModelsFromAPI : []
5437
+ }
5438
+ )
5439
+ ] })
5162
5440
  ] })
5163
5441
  ] });
5164
5442
  const combinedStyles = React3.useMemo(
@@ -5172,7 +5450,7 @@ ${customCss}` : WIDGET_CSS,
5172
5450
  WidgetStyleProvider,
5173
5451
  {
5174
5452
  styles,
5175
- agentName,
5453
+ agentName: isOnboarding ? onboardingAgentName || agentName : agentName,
5176
5454
  isLoading: isLoadingStyles,
5177
5455
  variant,
5178
5456
  showThinking,
@@ -5469,6 +5747,78 @@ function CopilotContainer({
5469
5747
  )
5470
5748
  ] });
5471
5749
  }
5750
+ function OnboardingIntroInline2({
5751
+ lines,
5752
+ primaryColor,
5753
+ textColor,
5754
+ textMutedColor,
5755
+ onComplete
5756
+ }) {
5757
+ const [lineIndex, setLineIndex] = React3.useState(0);
5758
+ const [charIndex, setCharIndex] = React3.useState(0);
5759
+ const [done, setDone] = React3.useState(false);
5760
+ React3.useEffect(() => {
5761
+ if (lineIndex >= lines.length) {
5762
+ setDone(true);
5763
+ return;
5764
+ }
5765
+ const currentLine = lines[lineIndex];
5766
+ if (charIndex < currentLine.length) {
5767
+ const t = setTimeout(() => setCharIndex((c) => c + 1), 35);
5768
+ return () => clearTimeout(t);
5769
+ } else {
5770
+ const t = setTimeout(() => {
5771
+ setLineIndex((l) => l + 1);
5772
+ setCharIndex(0);
5773
+ }, 500);
5774
+ return () => clearTimeout(t);
5775
+ }
5776
+ }, [lineIndex, charIndex, lines]);
5777
+ const displayedLines = lines.slice(0, lineIndex + 1).map(
5778
+ (line, i) => i < lineIndex ? line : line.slice(0, charIndex)
5779
+ );
5780
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5781
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minHeight: "4rem", marginBottom: "1.5rem" }, children: displayedLines.map((text, i) => /* @__PURE__ */ jsxRuntime.jsxs("p", { style: {
5782
+ fontSize: i === 0 ? 18 : 14,
5783
+ fontWeight: i === 0 ? 600 : 400,
5784
+ color: i === 0 ? textColor : textMutedColor,
5785
+ lineHeight: 1.4,
5786
+ margin: "0 0 6px 0"
5787
+ }, children: [
5788
+ text,
5789
+ i === lineIndex && !done && /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
5790
+ display: "inline-block",
5791
+ width: 2,
5792
+ height: i === 0 ? 18 : 14,
5793
+ backgroundColor: textColor,
5794
+ marginLeft: 2,
5795
+ verticalAlign: "middle",
5796
+ animation: "crow-blink 1s step-end infinite"
5797
+ } })
5798
+ ] }, i)) }),
5799
+ /* @__PURE__ */ jsxRuntime.jsx(
5800
+ "button",
5801
+ {
5802
+ onClick: onComplete,
5803
+ style: {
5804
+ padding: "8px 24px",
5805
+ borderRadius: 8,
5806
+ backgroundColor: primaryColor,
5807
+ color: "#fff",
5808
+ fontSize: 13,
5809
+ fontWeight: 500,
5810
+ border: "none",
5811
+ cursor: "pointer",
5812
+ opacity: done ? 1 : 0,
5813
+ pointerEvents: done ? "auto" : "none",
5814
+ transition: "opacity 0.5s ease"
5815
+ },
5816
+ children: "Get Started \u2192"
5817
+ }
5818
+ ),
5819
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `@keyframes crow-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }` })
5820
+ ] });
5821
+ }
5472
5822
  function CrowCopilot({
5473
5823
  productId,
5474
5824
  apiUrl = "",
@@ -5492,7 +5842,10 @@ function CrowCopilot({
5492
5842
  getIdentityToken,
5493
5843
  context,
5494
5844
  language,
5495
- contextLabel: contextLabelProp
5845
+ contextLabel: contextLabelProp,
5846
+ forceOnboarding = false,
5847
+ fullscreenTopOffset: _fullscreenTopOffset = 0,
5848
+ mode: _mode
5496
5849
  }) {
5497
5850
  const effectiveGetIdentityToken = getIdentityToken || window.__crow_identity_token_fetcher;
5498
5851
  const effectiveOnToolResult = onToolResult || window.__crow_on_tool_result;
@@ -5510,7 +5863,11 @@ function CrowCopilot({
5510
5863
  toolConsentSettings,
5511
5864
  modelSelectionEnabled,
5512
5865
  availableModels: availableModelsFromAPI,
5513
- initialSuggestions
5866
+ initialSuggestions,
5867
+ onboardingEnabled,
5868
+ onboardingAgentName,
5869
+ onboardingWelcomeMessage,
5870
+ onboardingIntroSequence
5514
5871
  } = useCopilotStyles({
5515
5872
  productId,
5516
5873
  apiUrl,
@@ -5519,6 +5876,20 @@ function CrowCopilot({
5519
5876
  language
5520
5877
  });
5521
5878
  const agentName = agentNameProp ?? agentNameFromAPI ?? title;
5879
+ const [isOnboarding, setIsOnboarding] = React3.useState(false);
5880
+ const [onboardingChecked, setOnboardingChecked] = React3.useState(false);
5881
+ const [onboardingPhase, setOnboardingPhase] = React3.useState("intro");
5882
+ React3.useEffect(() => {
5883
+ if (forceOnboarding && !isLoadingStyles && onboardingEnabled && !onboardingChecked) {
5884
+ setIsOnboarding(true);
5885
+ setOnboardingChecked(true);
5886
+ }
5887
+ }, [forceOnboarding, isLoadingStyles, onboardingEnabled, onboardingChecked]);
5888
+ React3.useEffect(() => {
5889
+ if (isOnboarding && !isLoadingStyles && onboardingIntroSequence !== void 0 && onboardingIntroSequence.length === 0) {
5890
+ setOnboardingPhase("chat");
5891
+ }
5892
+ }, [isOnboarding, isLoadingStyles, onboardingIntroSequence]);
5522
5893
  const [toolStatus, setToolStatus] = React3.useState(
5523
5894
  () => window.__crow_tool_status ?? ""
5524
5895
  );
@@ -5671,6 +6042,10 @@ function CrowCopilot({
5671
6042
  React3.useEffect(() => {
5672
6043
  const handleOpen = () => setIsCollapsed(false);
5673
6044
  const handleClose = () => setIsCollapsed(true);
6045
+ const handleSendMessage = (e) => {
6046
+ const text = e.detail?.text;
6047
+ if (text) handleSend(text);
6048
+ };
5674
6049
  const handleSetSuggestions = (e) => {
5675
6050
  const actions = e.detail;
5676
6051
  if (Array.isArray(actions)) {
@@ -5680,6 +6055,7 @@ function CrowCopilot({
5680
6055
  };
5681
6056
  window.addEventListener("crow:open", handleOpen);
5682
6057
  window.addEventListener("crow:close", handleClose);
6058
+ window.addEventListener("crow:sendMessage", handleSendMessage);
5683
6059
  window.addEventListener("crow:setSuggestedActions", handleSetSuggestions);
5684
6060
  const pending = window.__crow_suggested_actions;
5685
6061
  if (Array.isArray(pending) && pending.length > 0) {
@@ -5689,14 +6065,15 @@ function CrowCopilot({
5689
6065
  return () => {
5690
6066
  window.removeEventListener("crow:open", handleOpen);
5691
6067
  window.removeEventListener("crow:close", handleClose);
6068
+ window.removeEventListener("crow:sendMessage", handleSendMessage);
5692
6069
  window.removeEventListener("crow:setSuggestedActions", handleSetSuggestions);
5693
6070
  };
5694
6071
  }, []);
5695
6072
  React3.useEffect(() => {
5696
- if (initialSuggestions.length > 0 && chat.suggestedActions.length === 0) {
6073
+ if (!isOnboarding && initialSuggestions.length > 0 && chat.suggestedActions.length === 0) {
5697
6074
  chat.setSuggestedActions(initialSuggestions);
5698
6075
  }
5699
- }, [initialSuggestions]);
6076
+ }, [initialSuggestions, isOnboarding]);
5700
6077
  const messagesContainerRef = React3.useRef(null);
5701
6078
  const tabsScrollRef = React3.useRef(null);
5702
6079
  const executeClientToolRef = React3.useRef(null);
@@ -5726,11 +6103,17 @@ function CrowCopilot({
5726
6103
  pendingRestoreConvId.current = "";
5727
6104
  }
5728
6105
  }
6106
+ const effectiveWelcomeMessage = isOnboarding ? onboardingWelcomeMessage || `Hi! I'm ${onboardingAgentName || agentName}. Let me help you get started.` : welcomeMessage;
5729
6107
  const chat = useChat({
5730
6108
  productId,
5731
6109
  apiUrl,
5732
6110
  persistAnonymousConversations,
5733
- welcomeMessage,
6111
+ welcomeMessage: effectiveWelcomeMessage,
6112
+ agentMode: isOnboarding ? "onboarding" : void 0,
6113
+ onOnboardingComplete: (summary) => {
6114
+ console.log("[Crow] Onboarding complete:", summary);
6115
+ setIsOnboarding(false);
6116
+ },
5734
6117
  selectedModel,
5735
6118
  subdomain,
5736
6119
  toolConsentSettings,
@@ -5874,6 +6257,33 @@ function CrowCopilot({
5874
6257
  const { executeClientTool } = useCrowAPI({
5875
6258
  onIdentified: async () => {
5876
6259
  setIsVerifiedUser(true);
6260
+ if (forceOnboarding) {
6261
+ setIsOnboarding(true);
6262
+ setOnboardingChecked(true);
6263
+ } else if (onboardingEnabled && !onboardingChecked) {
6264
+ try {
6265
+ const identityToken = window.__crow_identity_token;
6266
+ if (identityToken) {
6267
+ const res = await fetch(`${apiUrl}/api/chat/resolve-agent`, {
6268
+ method: "POST",
6269
+ headers: { "Content-Type": "application/json" },
6270
+ body: JSON.stringify({
6271
+ product_id: productId,
6272
+ identity_token: identityToken
6273
+ })
6274
+ });
6275
+ if (res.ok) {
6276
+ const data = await res.json();
6277
+ if (data.agent === "onboarding") {
6278
+ setIsOnboarding(true);
6279
+ }
6280
+ }
6281
+ }
6282
+ } catch (e) {
6283
+ console.error("[Crow] resolve-agent failed:", e);
6284
+ }
6285
+ setOnboardingChecked(true);
6286
+ }
5877
6287
  await conversations.loadConversations();
5878
6288
  const savedId = pendingRestoreConvId.current;
5879
6289
  if (savedId && !hasRestoredActiveConvRef.current) {
@@ -5896,6 +6306,16 @@ function CrowCopilot({
5896
6306
  });
5897
6307
  executeClientToolRef.current = executeClientTool;
5898
6308
  submitToolResultRef.current = chat.submitToolResult;
6309
+ const prevOnboardingRef = React3.useRef(isOnboarding);
6310
+ React3.useEffect(() => {
6311
+ if (isOnboarding && !prevOnboardingRef.current) {
6312
+ chat.setSuggestedActions([]);
6313
+ }
6314
+ if (prevOnboardingRef.current && !isOnboarding) {
6315
+ chat.resetMessages();
6316
+ }
6317
+ prevOnboardingRef.current = isOnboarding;
6318
+ }, [isOnboarding]);
5899
6319
  const handleBrowserConfirmation = React3.useCallback(
5900
6320
  (instruction) => {
5901
6321
  return new Promise((resolve) => {
@@ -6236,312 +6656,347 @@ function CrowCopilot({
6236
6656
  "--crow-bg-active": styles.colors.text + "18"
6237
6657
  },
6238
6658
  children: [
6239
- /* @__PURE__ */ jsxRuntime.jsxs(
6240
- "div",
6241
- {
6242
- className: "crow-flex crow-items-stretch crow-border-b crow-min-h-[40px]",
6243
- style: { borderColor: styles.colors.border },
6244
- children: [
6245
- /* @__PURE__ */ jsxRuntime.jsx(
6246
- "div",
6247
- {
6248
- ref: tabsScrollRef,
6249
- className: "crow-flex crow-items-stretch crow-flex-1 crow-min-w-0 crow-overflow-x-auto",
6250
- style: {
6251
- scrollbarWidth: "none",
6252
- msOverflowStyle: "none"
6253
- },
6254
- onScroll: handleTabsScroll,
6255
- children: tabs.map((tab, idx) => {
6256
- const isActive = activeTabId === tab.id;
6257
- const isHovered = hoveredTabId === tab.id;
6258
- const isCloseable = tab.type !== "new" && (tab.type !== "local" || localTabs.length > 1);
6259
- return /* @__PURE__ */ jsxRuntime.jsxs(
6260
- "div",
6261
- {
6262
- className: "crow-relative crow-flex-shrink-0 crow-flex crow-items-center crow-text-[13px] crow-leading-tight crow-py-2.5 crow-transition-colors crow-select-none crow-cursor-pointer",
6263
- style: {
6264
- color: isActive ? styles.colors.text : styles.colors.text + "80",
6265
- fontWeight: isActive ? 500 : void 0,
6266
- maxWidth: "180px",
6267
- borderRight: idx < tabs.length - 1 ? `1px solid ${styles.colors.border}` : "none",
6268
- paddingLeft: "16px",
6269
- paddingRight: isCloseable ? "8px" : "16px"
6270
- },
6271
- title: tab.name,
6272
- onMouseEnter: () => setHoveredTabId(tab.id),
6273
- onMouseLeave: () => setHoveredTabId(null),
6274
- onClick: () => {
6275
- if (tab.type === "new") {
6276
- handleNewChat();
6277
- return;
6278
- }
6279
- if (tab.type === "server") {
6280
- handleSelectConversation(tab.id);
6281
- return;
6282
- }
6283
- handleSelectLocalTab(tab.id);
6284
- },
6285
- children: [
6286
- /* @__PURE__ */ jsxRuntime.jsx(
6287
- "span",
6288
- {
6289
- className: "crow-block crow-truncate",
6290
- style: { maxWidth: isCloseable ? "112px" : "128px" },
6291
- children: tab.name
6292
- }
6293
- ),
6294
- isCloseable && /* @__PURE__ */ jsxRuntime.jsx(
6295
- "span",
6296
- {
6297
- className: "crow-rounded crow-p-0.5 crow-flex-shrink-0 crow-inline-flex crow-items-center crow-justify-center crow-transition-opacity",
6298
- style: {
6299
- marginLeft: "6px",
6300
- opacity: isHovered ? 1 : 0,
6301
- pointerEvents: isHovered ? "auto" : "none"
6302
- },
6303
- onClick: (e) => {
6304
- e.stopPropagation();
6305
- handleCloseTab(tab.id, tab.type);
6306
- },
6307
- role: "button",
6308
- "aria-label": `Close ${tab.name}`,
6309
- children: /* @__PURE__ */ jsxRuntime.jsx(TabCloseIcon, { className: "crow-w-3 crow-h-3", style: { color: styles.colors.text + "80" } })
6310
- }
6311
- ),
6312
- isActive && /* @__PURE__ */ jsxRuntime.jsx(
6313
- "span",
6314
- {
6315
- className: "crow-absolute crow-bottom-0 crow-left-0 crow-right-0",
6316
- style: {
6317
- height: "2px",
6318
- background: styles.colors.primary || "#2563eb"
6319
- }
6320
- }
6321
- )
6322
- ]
6323
- },
6324
- `${tab.id}-${idx}`
6325
- );
6326
- })
6327
- }
6328
- ),
6329
- /* @__PURE__ */ jsxRuntime.jsxs(
6330
- "div",
6331
- {
6332
- className: "crow-flex crow-items-center crow-flex-shrink-0 crow-border-l",
6333
- style: { borderColor: styles.colors.border },
6334
- children: [
6335
- /* @__PURE__ */ jsxRuntime.jsx(
6336
- "button",
6337
- {
6338
- onClick: handleNewChat,
6339
- className: "crow-p-2 crow-transition-colors crow-rounded",
6340
- style: { color: styles.colors.text + "80" },
6341
- onMouseEnter: (e) => {
6342
- e.currentTarget.style.background = styles.colors.text + "10";
6343
- },
6344
- onMouseLeave: (e) => {
6345
- e.currentTarget.style.background = "transparent";
6346
- },
6347
- "aria-label": "New Chat",
6348
- title: "New Chat",
6349
- children: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { className: "crow-w-4 crow-h-4" })
6350
- }
6351
- ),
6352
- /* @__PURE__ */ jsxRuntime.jsx(
6353
- "button",
6354
- {
6355
- onClick: handleToggleHistory,
6356
- disabled: !isVerifiedUser,
6357
- "aria-disabled": !isVerifiedUser,
6358
- className: `crow-p-2 crow-transition-colors crow-rounded ${!isVerifiedUser ? "crow-opacity-40 crow-cursor-not-allowed" : ""}`,
6359
- style: {
6360
- color: styles.colors.text + "80",
6361
- background: showConversationList ? styles.colors.text + "10" : "transparent"
6362
- },
6363
- onMouseEnter: (e) => {
6364
- if (isVerifiedUser) e.currentTarget.style.background = styles.colors.text + "10";
6365
- },
6366
- onMouseLeave: (e) => {
6367
- if (!showConversationList) e.currentTarget.style.background = "transparent";
6368
- },
6369
- "aria-label": "Conversation History",
6370
- title: isVerifiedUser ? "Conversation History" : "Sign in to view history",
6371
- children: /* @__PURE__ */ jsxRuntime.jsx(HistoryIcon, { className: "crow-w-4 crow-h-4" })
6372
- }
6373
- ),
6374
- canScrollRight && /* @__PURE__ */ jsxRuntime.jsx(
6375
- "button",
6376
- {
6377
- onClick: handleScrollRight,
6378
- className: "crow-p-2 crow-transition-colors crow-rounded",
6379
- style: { color: styles.colors.text + "80" },
6380
- onMouseEnter: (e) => {
6381
- e.currentTarget.style.background = styles.colors.text + "10";
6382
- },
6383
- onMouseLeave: (e) => {
6384
- e.currentTarget.style.background = "transparent";
6385
- },
6386
- "aria-label": "Scroll tabs",
6387
- title: "Scroll tabs",
6388
- children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { className: "crow-w-4 crow-h-4" })
6389
- }
6390
- ),
6391
- (forceShowClose ?? showClose) && (overrideOnClose ?? onClose) && /* @__PURE__ */ jsxRuntime.jsx(
6392
- "button",
6393
- {
6394
- onClick: overrideOnClose ?? onClose,
6395
- className: "crow-p-2 crow-transition-colors crow-rounded",
6396
- style: { color: styles.colors.text + "80" },
6397
- onMouseEnter: (e) => {
6398
- e.currentTarget.style.background = styles.colors.text + "10";
6399
- },
6400
- onMouseLeave: (e) => {
6401
- e.currentTarget.style.background = "transparent";
6402
- },
6403
- "aria-label": "Close",
6404
- children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { className: "crow-w-4 crow-h-4" })
6405
- }
6406
- )
6407
- ]
6408
- }
6409
- )
6410
- ]
6411
- }
6412
- ),
6413
- contextLabel && /* @__PURE__ */ jsxRuntime.jsxs(
6414
- "div",
6415
- {
6416
- className: "crow-flex crow-items-center crow-gap-1.5 crow-px-3 crow-py-1.5 crow-border-b crow-text-xs",
6417
- style: {
6418
- color: styles.colors.text + "80",
6419
- borderColor: styles.colors.border
6420
- },
6421
- children: [
6422
- /* @__PURE__ */ jsxRuntime.jsxs(
6423
- "svg",
6424
- {
6425
- xmlns: "http://www.w3.org/2000/svg",
6426
- width: "12",
6427
- height: "12",
6428
- viewBox: "0 0 24 24",
6429
- fill: "none",
6430
- stroke: "currentColor",
6431
- strokeWidth: "2",
6432
- strokeLinecap: "round",
6433
- strokeLinejoin: "round",
6434
- className: "crow-shrink-0",
6435
- children: [
6436
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }),
6437
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "10", r: "3" })
6438
- ]
6439
- }
6440
- ),
6441
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "crow-truncate", children: contextLabel })
6442
- ]
6443
- }
6444
- ),
6445
- /* @__PURE__ */ jsxRuntime.jsxs(framerMotion.AnimatePresence, { children: [
6446
- showConversationList && isVerifiedUser && /* @__PURE__ */ jsxRuntime.jsx(
6447
- ConversationList,
6659
+ isOnboarding && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6660
+ /* @__PURE__ */ jsxRuntime.jsxs(
6661
+ "div",
6448
6662
  {
6449
- conversations: conversations.conversations,
6450
- currentConversationId: chat.conversationId,
6451
- onSelect: handleSelectConversation,
6452
- onClose: handleCloseConversationList
6663
+ className: "crow-flex crow-items-center crow-justify-between crow-border-b crow-px-4 crow-py-2.5",
6664
+ style: { borderColor: styles.colors.border },
6665
+ children: [
6666
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "crow-text-[13px] crow-font-semibold", style: { color: styles.colors.text }, children: onboardingAgentName || agentName }),
6667
+ /* @__PURE__ */ jsxRuntime.jsx(
6668
+ "button",
6669
+ {
6670
+ onClick: () => {
6671
+ setIsOnboarding(false);
6672
+ },
6673
+ className: "crow-text-xs crow-border-none crow-bg-transparent crow-cursor-pointer crow-px-2 crow-py-1",
6674
+ style: { color: styles.colors.text + "60" },
6675
+ children: "Skip"
6676
+ }
6677
+ )
6678
+ ]
6453
6679
  }
6454
6680
  ),
6455
- showConversationList && !isVerifiedUser && /* @__PURE__ */ jsxRuntime.jsx(
6456
- "div",
6681
+ onboardingPhase === "intro" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-flex crow-flex-col crow-items-center crow-justify-center crow-flex-1 crow-px-4 crow-py-6 crow-text-center", children: /* @__PURE__ */ jsxRuntime.jsx(
6682
+ OnboardingIntroInline2,
6457
6683
  {
6458
- className: "crow-mb-3 crow-rounded-xl crow-border crow-p-4",
6459
- style: { background: styles.colors.text + "08", borderColor: styles.colors.border },
6460
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-text-sm", style: { color: styles.colors.text + "99" }, children: "Sign in to view conversation history." })
6684
+ lines: onboardingIntroSequence || [],
6685
+ primaryColor: styles.colors.primary,
6686
+ textColor: styles.colors.text,
6687
+ textMutedColor: styles.colors.text + "80",
6688
+ onComplete: () => setOnboardingPhase("chat")
6461
6689
  }
6462
- )
6690
+ ) })
6463
6691
  ] }),
6464
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsxRuntime.jsx(
6465
- WorkflowPanel,
6466
- {
6467
- workflow: activeWorkflow,
6468
- onExit: handleExitWorkflow
6469
- }
6470
- ) }),
6471
- /* @__PURE__ */ jsxRuntime.jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
6472
- /* @__PURE__ */ jsxRuntime.jsx(
6473
- MessageList,
6692
+ !(isOnboarding && onboardingPhase === "intro") && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6693
+ !isOnboarding && /* @__PURE__ */ jsxRuntime.jsxs(
6694
+ "div",
6474
6695
  {
6475
- messages: chat.messages,
6476
- activeToolCalls: chat.activeToolCalls,
6477
- isLoadingHistory: conversations.isLoadingHistory,
6478
- isGenerating: chat.isLoading,
6479
- toolRenderers: effectiveToolRenderers,
6480
- onToolConsent: handleToolConsent
6696
+ className: "crow-flex crow-items-stretch crow-border-b crow-min-h-[40px]",
6697
+ style: { borderColor: styles.colors.border },
6698
+ children: [
6699
+ /* @__PURE__ */ jsxRuntime.jsx(
6700
+ "div",
6701
+ {
6702
+ ref: tabsScrollRef,
6703
+ className: "crow-flex crow-items-stretch crow-flex-1 crow-min-w-0 crow-overflow-x-auto",
6704
+ style: {
6705
+ scrollbarWidth: "none",
6706
+ msOverflowStyle: "none"
6707
+ },
6708
+ onScroll: handleTabsScroll,
6709
+ children: tabs.map((tab, idx) => {
6710
+ const isActive = activeTabId === tab.id;
6711
+ const isHovered = hoveredTabId === tab.id;
6712
+ const isCloseable = tab.type !== "new" && (tab.type !== "local" || localTabs.length > 1);
6713
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6714
+ "div",
6715
+ {
6716
+ className: "crow-relative crow-flex-shrink-0 crow-flex crow-items-center crow-text-[13px] crow-leading-tight crow-py-2.5 crow-transition-colors crow-select-none crow-cursor-pointer",
6717
+ style: {
6718
+ color: isActive ? styles.colors.text : styles.colors.text + "80",
6719
+ fontWeight: isActive ? 500 : void 0,
6720
+ maxWidth: "180px",
6721
+ borderRight: idx < tabs.length - 1 ? `1px solid ${styles.colors.border}` : "none",
6722
+ paddingLeft: "16px",
6723
+ paddingRight: isCloseable ? "8px" : "16px"
6724
+ },
6725
+ title: tab.name,
6726
+ onMouseEnter: () => setHoveredTabId(tab.id),
6727
+ onMouseLeave: () => setHoveredTabId(null),
6728
+ onClick: () => {
6729
+ if (tab.type === "new") {
6730
+ handleNewChat();
6731
+ return;
6732
+ }
6733
+ if (tab.type === "server") {
6734
+ handleSelectConversation(tab.id);
6735
+ return;
6736
+ }
6737
+ handleSelectLocalTab(tab.id);
6738
+ },
6739
+ children: [
6740
+ /* @__PURE__ */ jsxRuntime.jsx(
6741
+ "span",
6742
+ {
6743
+ className: "crow-block crow-truncate",
6744
+ style: { maxWidth: isCloseable ? "112px" : "128px" },
6745
+ children: tab.name
6746
+ }
6747
+ ),
6748
+ isCloseable && /* @__PURE__ */ jsxRuntime.jsx(
6749
+ "span",
6750
+ {
6751
+ className: "crow-rounded crow-p-0.5 crow-flex-shrink-0 crow-inline-flex crow-items-center crow-justify-center crow-transition-opacity",
6752
+ style: {
6753
+ marginLeft: "6px",
6754
+ opacity: isHovered ? 1 : 0,
6755
+ pointerEvents: isHovered ? "auto" : "none"
6756
+ },
6757
+ onClick: (e) => {
6758
+ e.stopPropagation();
6759
+ handleCloseTab(tab.id, tab.type);
6760
+ },
6761
+ role: "button",
6762
+ "aria-label": `Close ${tab.name}`,
6763
+ children: /* @__PURE__ */ jsxRuntime.jsx(TabCloseIcon, { className: "crow-w-3 crow-h-3", style: { color: styles.colors.text + "80" } })
6764
+ }
6765
+ ),
6766
+ isActive && /* @__PURE__ */ jsxRuntime.jsx(
6767
+ "span",
6768
+ {
6769
+ className: "crow-absolute crow-bottom-0 crow-left-0 crow-right-0",
6770
+ style: {
6771
+ height: "2px",
6772
+ background: styles.colors.primary || "#2563eb"
6773
+ }
6774
+ }
6775
+ )
6776
+ ]
6777
+ },
6778
+ `${tab.id}-${idx}`
6779
+ );
6780
+ })
6781
+ }
6782
+ ),
6783
+ /* @__PURE__ */ jsxRuntime.jsxs(
6784
+ "div",
6785
+ {
6786
+ className: "crow-flex crow-items-center crow-flex-shrink-0 crow-border-l",
6787
+ style: { borderColor: styles.colors.border },
6788
+ children: [
6789
+ /* @__PURE__ */ jsxRuntime.jsx(
6790
+ "button",
6791
+ {
6792
+ onClick: handleNewChat,
6793
+ className: "crow-p-2 crow-transition-colors crow-rounded",
6794
+ style: { color: styles.colors.text + "80" },
6795
+ onMouseEnter: (e) => {
6796
+ e.currentTarget.style.background = styles.colors.text + "10";
6797
+ },
6798
+ onMouseLeave: (e) => {
6799
+ e.currentTarget.style.background = "transparent";
6800
+ },
6801
+ "aria-label": "New Chat",
6802
+ title: "New Chat",
6803
+ children: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { className: "crow-w-4 crow-h-4" })
6804
+ }
6805
+ ),
6806
+ /* @__PURE__ */ jsxRuntime.jsx(
6807
+ "button",
6808
+ {
6809
+ onClick: handleToggleHistory,
6810
+ disabled: !isVerifiedUser,
6811
+ "aria-disabled": !isVerifiedUser,
6812
+ className: `crow-p-2 crow-transition-colors crow-rounded ${!isVerifiedUser ? "crow-opacity-40 crow-cursor-not-allowed" : ""}`,
6813
+ style: {
6814
+ color: styles.colors.text + "80",
6815
+ background: showConversationList ? styles.colors.text + "10" : "transparent"
6816
+ },
6817
+ onMouseEnter: (e) => {
6818
+ if (isVerifiedUser) e.currentTarget.style.background = styles.colors.text + "10";
6819
+ },
6820
+ onMouseLeave: (e) => {
6821
+ if (!showConversationList) e.currentTarget.style.background = "transparent";
6822
+ },
6823
+ "aria-label": "Conversation History",
6824
+ title: isVerifiedUser ? "Conversation History" : "Sign in to view history",
6825
+ children: /* @__PURE__ */ jsxRuntime.jsx(HistoryIcon, { className: "crow-w-4 crow-h-4" })
6826
+ }
6827
+ ),
6828
+ canScrollRight && /* @__PURE__ */ jsxRuntime.jsx(
6829
+ "button",
6830
+ {
6831
+ onClick: handleScrollRight,
6832
+ className: "crow-p-2 crow-transition-colors crow-rounded",
6833
+ style: { color: styles.colors.text + "80" },
6834
+ onMouseEnter: (e) => {
6835
+ e.currentTarget.style.background = styles.colors.text + "10";
6836
+ },
6837
+ onMouseLeave: (e) => {
6838
+ e.currentTarget.style.background = "transparent";
6839
+ },
6840
+ "aria-label": "Scroll tabs",
6841
+ title: "Scroll tabs",
6842
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { className: "crow-w-4 crow-h-4" })
6843
+ }
6844
+ ),
6845
+ (forceShowClose ?? showClose) && (overrideOnClose ?? onClose) && /* @__PURE__ */ jsxRuntime.jsx(
6846
+ "button",
6847
+ {
6848
+ onClick: overrideOnClose ?? onClose,
6849
+ className: "crow-p-2 crow-transition-colors crow-rounded",
6850
+ style: { color: styles.colors.text + "80" },
6851
+ onMouseEnter: (e) => {
6852
+ e.currentTarget.style.background = styles.colors.text + "10";
6853
+ },
6854
+ onMouseLeave: (e) => {
6855
+ e.currentTarget.style.background = "transparent";
6856
+ },
6857
+ "aria-label": "Close",
6858
+ children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { className: "crow-w-4 crow-h-4" })
6859
+ }
6860
+ )
6861
+ ]
6862
+ }
6863
+ )
6864
+ ]
6481
6865
  }
6482
6866
  ),
6483
- pendingConfirmation && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsxRuntime.jsx(
6484
- BrowserUseConfirmation,
6867
+ contextLabel && /* @__PURE__ */ jsxRuntime.jsxs(
6868
+ "div",
6485
6869
  {
6486
- instruction: pendingConfirmation.instruction,
6487
- onAllow: () => {
6488
- pendingConfirmation.resolve(true);
6489
- setPendingConfirmation(null);
6870
+ className: "crow-flex crow-items-center crow-gap-1.5 crow-px-3 crow-py-1.5 crow-border-b crow-text-xs",
6871
+ style: {
6872
+ color: styles.colors.text + "80",
6873
+ borderColor: styles.colors.border
6490
6874
  },
6491
- onDeny: () => {
6492
- pendingConfirmation.resolve(false);
6493
- setPendingConfirmation(null);
6875
+ children: [
6876
+ /* @__PURE__ */ jsxRuntime.jsxs(
6877
+ "svg",
6878
+ {
6879
+ xmlns: "http://www.w3.org/2000/svg",
6880
+ width: "12",
6881
+ height: "12",
6882
+ viewBox: "0 0 24 24",
6883
+ fill: "none",
6884
+ stroke: "currentColor",
6885
+ strokeWidth: "2",
6886
+ strokeLinecap: "round",
6887
+ strokeLinejoin: "round",
6888
+ className: "crow-shrink-0",
6889
+ children: [
6890
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }),
6891
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "10", r: "3" })
6892
+ ]
6893
+ }
6894
+ ),
6895
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "crow-truncate", children: contextLabel })
6896
+ ]
6897
+ }
6898
+ ),
6899
+ /* @__PURE__ */ jsxRuntime.jsxs(framerMotion.AnimatePresence, { children: [
6900
+ showConversationList && isVerifiedUser && /* @__PURE__ */ jsxRuntime.jsx(
6901
+ ConversationList,
6902
+ {
6903
+ conversations: conversations.conversations,
6904
+ currentConversationId: chat.conversationId,
6905
+ onSelect: handleSelectConversation,
6906
+ onClose: handleCloseConversationList
6494
6907
  }
6908
+ ),
6909
+ showConversationList && !isVerifiedUser && /* @__PURE__ */ jsxRuntime.jsx(
6910
+ "div",
6911
+ {
6912
+ className: "crow-mb-3 crow-rounded-xl crow-border crow-p-4",
6913
+ style: { background: styles.colors.text + "08", borderColor: styles.colors.border },
6914
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-text-sm", style: { color: styles.colors.text + "99" }, children: "Sign in to view conversation history." })
6915
+ }
6916
+ )
6917
+ ] }),
6918
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsxRuntime.jsx(
6919
+ WorkflowPanel,
6920
+ {
6921
+ workflow: activeWorkflow,
6922
+ onExit: handleExitWorkflow
6495
6923
  }
6496
6924
  ) }),
6497
- askUserResolver && browserQuestion && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsxRuntime.jsx(
6498
- BrowserUseQuestion,
6499
- {
6500
- question: browserQuestion,
6501
- onSubmit: (answer) => {
6502
- askUserResolver.resolve(answer);
6503
- setAskUserResolver(null);
6504
- setBrowserQuestion(null);
6925
+ /* @__PURE__ */ jsxRuntime.jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
6926
+ /* @__PURE__ */ jsxRuntime.jsx(
6927
+ MessageList,
6928
+ {
6929
+ messages: chat.messages,
6930
+ activeToolCalls: chat.activeToolCalls,
6931
+ isLoadingHistory: conversations.isLoadingHistory,
6932
+ isGenerating: chat.isLoading,
6933
+ toolRenderers: effectiveToolRenderers,
6934
+ onToolConsent: handleToolConsent
6505
6935
  }
6506
- }
6507
- ) })
6508
- ] }),
6509
- /* @__PURE__ */ jsxRuntime.jsxs(
6510
- "div",
6511
- {
6512
- className: "crow-p-3 crow-border-t",
6513
- style: { borderColor: styles.colors.border },
6514
- children: [
6515
- toolStatus && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "crow-mb-1 crow-flex crow-items-center crow-gap-2 crow-rounded-lg crow-border crow-px-3 crow-py-2 crow-text-sm", style: { borderColor: styles.colors.border, background: styles.colors.border + "30" }, children: [
6516
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "crow-animate-spin crow-h-4 crow-w-4 crow-shrink-0 crow-text-[var(--crow-primary,#7c3aed)]", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
6517
- /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "crow-opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
6518
- /* @__PURE__ */ jsxRuntime.jsx("path", { className: "crow-opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
6519
- ] }),
6520
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "crow-font-medium crow-text-[var(--crow-text,#111827)]", children: toolStatus })
6521
- ] }),
6522
- (chat.suggestedActions.length > 0 || !chat.isLoading && defaultSuggestedActionsRef.current.length > 0) && /* @__PURE__ */ jsxRuntime.jsx(
6523
- SuggestedActions,
6524
- {
6525
- actions: chat.suggestedActions.length > 0 ? chat.suggestedActions : defaultSuggestedActionsRef.current,
6526
- onActionClick: (action) => handleSend(action.message)
6936
+ ),
6937
+ pendingConfirmation && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsxRuntime.jsx(
6938
+ BrowserUseConfirmation,
6939
+ {
6940
+ instruction: pendingConfirmation.instruction,
6941
+ onAllow: () => {
6942
+ pendingConfirmation.resolve(true);
6943
+ setPendingConfirmation(null);
6944
+ },
6945
+ onDeny: () => {
6946
+ pendingConfirmation.resolve(false);
6947
+ setPendingConfirmation(null);
6527
6948
  }
6528
- ),
6529
- styles.branding.showPoweredBy && /* @__PURE__ */ jsxRuntime.jsx(PoweredByBadge, { apiUrl }),
6530
- /* @__PURE__ */ jsxRuntime.jsx(
6531
- PromptInputBox,
6532
- {
6533
- onSend: handleSend,
6534
- onStop: handleStop,
6535
- placeholder: "Ask anything...",
6536
- isLoading: chat.isLoading,
6537
- selectedModel: chat.selectedModel || selectedModel,
6538
- onModelChange: chat.setSelectedModel,
6539
- availableModels: modelSelectionEnabled ? availableModelsFromAPI : []
6949
+ }
6950
+ ) }),
6951
+ askUserResolver && browserQuestion && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsxRuntime.jsx(
6952
+ BrowserUseQuestion,
6953
+ {
6954
+ question: browserQuestion,
6955
+ onSubmit: (answer) => {
6956
+ askUserResolver.resolve(answer);
6957
+ setAskUserResolver(null);
6958
+ setBrowserQuestion(null);
6540
6959
  }
6541
- )
6542
- ]
6543
- }
6544
- )
6960
+ }
6961
+ ) })
6962
+ ] }),
6963
+ /* @__PURE__ */ jsxRuntime.jsxs(
6964
+ "div",
6965
+ {
6966
+ className: "crow-p-3 crow-border-t",
6967
+ style: { borderColor: styles.colors.border },
6968
+ children: [
6969
+ toolStatus && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "crow-mb-1 crow-flex crow-items-center crow-gap-2 crow-rounded-lg crow-border crow-px-3 crow-py-2 crow-text-sm", style: { borderColor: styles.colors.border, background: styles.colors.border + "30" }, children: [
6970
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "crow-animate-spin crow-h-4 crow-w-4 crow-shrink-0 crow-text-[var(--crow-primary,#7c3aed)]", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
6971
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "crow-opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
6972
+ /* @__PURE__ */ jsxRuntime.jsx("path", { className: "crow-opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
6973
+ ] }),
6974
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "crow-font-medium crow-text-[var(--crow-text,#111827)]", children: toolStatus })
6975
+ ] }),
6976
+ (chat.suggestedActions.length > 0 || !isOnboarding && !chat.isLoading && defaultSuggestedActionsRef.current.length > 0) && /* @__PURE__ */ jsxRuntime.jsx(
6977
+ SuggestedActions,
6978
+ {
6979
+ actions: chat.suggestedActions.length > 0 ? chat.suggestedActions : defaultSuggestedActionsRef.current,
6980
+ onActionClick: (action) => handleSend(action.message)
6981
+ }
6982
+ ),
6983
+ styles.branding.showPoweredBy && /* @__PURE__ */ jsxRuntime.jsx(PoweredByBadge, { apiUrl }),
6984
+ /* @__PURE__ */ jsxRuntime.jsx(
6985
+ PromptInputBox,
6986
+ {
6987
+ onSend: handleSend,
6988
+ onStop: handleStop,
6989
+ placeholder: "Ask anything...",
6990
+ isLoading: chat.isLoading,
6991
+ selectedModel: chat.selectedModel || selectedModel,
6992
+ onModelChange: chat.setSelectedModel,
6993
+ availableModels: modelSelectionEnabled ? availableModelsFromAPI : []
6994
+ }
6995
+ )
6996
+ ]
6997
+ }
6998
+ )
6999
+ ] })
6545
7000
  ]
6546
7001
  }
6547
7002
  )
@@ -6563,7 +7018,7 @@ function CrowCopilot({
6563
7018
  const edgeSide = isRight ? "left" : "right";
6564
7019
  const toggleIconColor = styles.colors.text + "80";
6565
7020
  const toggleIcon = isCollapsed ? /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: toggleIconColor, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z" }) }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: toggleIconColor, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: isRight ? /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) : /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) });
6566
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", flexShrink: 0, height: "100%" }, children: [
7021
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", flexShrink: 0, height: "100%" }, children: [
6567
7022
  /* @__PURE__ */ jsxRuntime.jsx(
6568
7023
  "button",
6569
7024
  {
@@ -6607,7 +7062,7 @@ function CrowCopilot({
6607
7062
  children: /* @__PURE__ */ jsxRuntime.jsx(ShadowContainer, { styles: WIDGET_CSS, children: renderCopilotContent(void 0, false, "100%") })
6608
7063
  }
6609
7064
  )
6610
- ] });
7065
+ ] }) });
6611
7066
  }
6612
7067
  function PlusIcon({ className }) {
6613
7068
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -6713,6 +7168,320 @@ function CloseIcon({ className }) {
6713
7168
  }
6714
7169
  );
6715
7170
  }
7171
+ function IntroSequence({ lines, onComplete, onSkip, primaryColor }) {
7172
+ const [lineIndex, setLineIndex] = React3.useState(0);
7173
+ const [charIndex, setCharIndex] = React3.useState(0);
7174
+ const [done, setDone] = React3.useState(false);
7175
+ React3.useEffect(() => {
7176
+ if (lineIndex >= lines.length) {
7177
+ setDone(true);
7178
+ return;
7179
+ }
7180
+ const currentLine = lines[lineIndex];
7181
+ if (charIndex < currentLine.length) {
7182
+ const t = setTimeout(() => setCharIndex((c) => c + 1), 35);
7183
+ return () => clearTimeout(t);
7184
+ } else {
7185
+ const t = setTimeout(() => {
7186
+ setLineIndex((l) => l + 1);
7187
+ setCharIndex(0);
7188
+ }, 500);
7189
+ return () => clearTimeout(t);
7190
+ }
7191
+ }, [lineIndex, charIndex, lines]);
7192
+ const displayedLines = lines.slice(0, lineIndex + 1).map((line, i) => {
7193
+ if (i < lineIndex) return line;
7194
+ return line.slice(0, charIndex);
7195
+ });
7196
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "100%", padding: "2rem" }, children: [
7197
+ /* @__PURE__ */ jsxRuntime.jsx(
7198
+ "button",
7199
+ {
7200
+ onClick: onSkip,
7201
+ style: {
7202
+ position: "absolute",
7203
+ top: 20,
7204
+ right: 24,
7205
+ fontSize: 14,
7206
+ color: "#9ca3af",
7207
+ background: "none",
7208
+ border: "none",
7209
+ cursor: "pointer",
7210
+ padding: "4px 8px"
7211
+ },
7212
+ children: "Skip"
7213
+ }
7214
+ ),
7215
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", minHeight: "5rem", marginBottom: "2.5rem" }, children: displayedLines.map((text, i) => /* @__PURE__ */ jsxRuntime.jsxs(
7216
+ "p",
7217
+ {
7218
+ style: {
7219
+ fontSize: i === 0 ? 30 : 18,
7220
+ fontWeight: i === 0 ? 600 : 400,
7221
+ color: i === 0 ? "#111827" : "#6b7280",
7222
+ lineHeight: 1.4,
7223
+ margin: "0 0 8px 0"
7224
+ },
7225
+ children: [
7226
+ text,
7227
+ i === lineIndex && !done && /* @__PURE__ */ jsxRuntime.jsx(
7228
+ "span",
7229
+ {
7230
+ style: {
7231
+ display: "inline-block",
7232
+ width: 2,
7233
+ height: i === 0 ? 28 : 18,
7234
+ backgroundColor: "#111827",
7235
+ marginLeft: 2,
7236
+ verticalAlign: "middle",
7237
+ animation: "crow-blink 1s step-end infinite"
7238
+ }
7239
+ }
7240
+ )
7241
+ ]
7242
+ },
7243
+ i
7244
+ )) }),
7245
+ /* @__PURE__ */ jsxRuntime.jsx(
7246
+ "button",
7247
+ {
7248
+ onClick: onComplete,
7249
+ style: {
7250
+ padding: "10px 32px",
7251
+ borderRadius: 12,
7252
+ backgroundColor: primaryColor,
7253
+ color: "#fff",
7254
+ fontSize: 15,
7255
+ fontWeight: 500,
7256
+ border: "none",
7257
+ cursor: "pointer",
7258
+ opacity: done ? 1 : 0,
7259
+ pointerEvents: done ? "auto" : "none",
7260
+ transition: "opacity 0.5s ease"
7261
+ },
7262
+ children: "Get Started \u2192"
7263
+ }
7264
+ ),
7265
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
7266
+ @keyframes crow-blink {
7267
+ 0%, 100% { opacity: 1; }
7268
+ 50% { opacity: 0; }
7269
+ }
7270
+ ` })
7271
+ ] });
7272
+ }
7273
+ function CrowOnboarding({
7274
+ productId,
7275
+ apiUrl,
7276
+ subdomain,
7277
+ agentName,
7278
+ welcomeMessage,
7279
+ introSequence,
7280
+ topOffset = 0,
7281
+ onComplete,
7282
+ language,
7283
+ styles: preResolvedStyles,
7284
+ getIdentityToken
7285
+ }) {
7286
+ const [phase, setPhase] = React3.useState(
7287
+ introSequence && introSequence.length > 0 ? "intro" : "chat"
7288
+ );
7289
+ const [isDismissing, setIsDismissing] = React3.useState(false);
7290
+ const bottomRef = React3.useRef(null);
7291
+ const styles = React3.useMemo(
7292
+ () => preResolvedStyles || mergeWidgetStyles(void 0, void 0),
7293
+ [preResolvedStyles]
7294
+ );
7295
+ const cssVars = React3.useMemo(
7296
+ () => stylesToCssVars(styles),
7297
+ [styles]
7298
+ );
7299
+ const dismiss = React3.useCallback(() => {
7300
+ setIsDismissing(true);
7301
+ setTimeout(() => onComplete(), 400);
7302
+ }, [onComplete]);
7303
+ const handleOnboardingComplete = React3.useCallback(
7304
+ (summary) => {
7305
+ console.log("[Crow] Onboarding complete:", summary);
7306
+ dismiss();
7307
+ },
7308
+ [dismiss]
7309
+ );
7310
+ const chat = useChat({
7311
+ productId,
7312
+ apiUrl,
7313
+ subdomain,
7314
+ welcomeMessage: welcomeMessage || `Hi! I'm ${agentName}. Let me help you get started.`,
7315
+ agentMode: "onboarding",
7316
+ onOnboardingComplete: handleOnboardingComplete,
7317
+ language
7318
+ });
7319
+ React3.useEffect(() => {
7320
+ bottomRef.current?.scrollIntoView({ behavior: "smooth" });
7321
+ }, [chat.messages, chat.isLoading]);
7322
+ const handleSend = React3.useCallback(
7323
+ (content) => {
7324
+ chat.sendMessage(content);
7325
+ },
7326
+ [chat]
7327
+ );
7328
+ const handleStop = React3.useCallback(() => {
7329
+ chat.stopGeneration();
7330
+ }, [chat]);
7331
+ const handleSuggestedActionClick = React3.useCallback(
7332
+ (action) => {
7333
+ chat.sendMessage(action.message);
7334
+ },
7335
+ [chat]
7336
+ );
7337
+ React3.useEffect(() => {
7338
+ const effectiveGetIdentityToken = getIdentityToken || window.__crow_identity_token_fetcher;
7339
+ if (!effectiveGetIdentityToken) return;
7340
+ let cancelled = false;
7341
+ const identify = async () => {
7342
+ try {
7343
+ const token = await effectiveGetIdentityToken();
7344
+ if (!cancelled && token) {
7345
+ window.__crow_identity_token = token;
7346
+ }
7347
+ } catch (e) {
7348
+ console.error("[Crow] Onboarding getIdentityToken failed:", e);
7349
+ }
7350
+ };
7351
+ identify();
7352
+ return () => {
7353
+ cancelled = true;
7354
+ };
7355
+ }, [getIdentityToken]);
7356
+ const renderChat = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", height: "100%", background: "#ffffff" }, children: [
7357
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
7358
+ display: "flex",
7359
+ alignItems: "center",
7360
+ justifyContent: "space-between",
7361
+ padding: "12px 24px",
7362
+ borderBottom: "1px solid #f3f4f6",
7363
+ flexShrink: 0
7364
+ }, children: [
7365
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10 }, children: [
7366
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
7367
+ width: 28,
7368
+ height: 28,
7369
+ borderRadius: "50%",
7370
+ backgroundColor: styles.colors.primary,
7371
+ display: "flex",
7372
+ alignItems: "center",
7373
+ justifyContent: "center",
7374
+ color: "#fff",
7375
+ fontSize: 13,
7376
+ fontWeight: 600,
7377
+ flexShrink: 0
7378
+ }, children: agentName.charAt(0).toUpperCase() }),
7379
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 14, fontWeight: 600, color: "#111827" }, children: agentName })
7380
+ ] }),
7381
+ /* @__PURE__ */ jsxRuntime.jsx(
7382
+ "button",
7383
+ {
7384
+ onClick: dismiss,
7385
+ style: {
7386
+ fontSize: 13,
7387
+ color: "#9ca3af",
7388
+ background: "none",
7389
+ border: "none",
7390
+ cursor: "pointer",
7391
+ padding: "4px 8px"
7392
+ },
7393
+ children: "Skip"
7394
+ }
7395
+ )
7396
+ ] }),
7397
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, overflowY: "auto", minHeight: 0 }, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "crow-widget-root", style: { ...cssVars, maxWidth: 560, margin: "0 auto", padding: "24px 16px" }, children: [
7398
+ /* @__PURE__ */ jsxRuntime.jsx(
7399
+ WidgetStyleProvider,
7400
+ {
7401
+ styles,
7402
+ agentName,
7403
+ isLoading: false,
7404
+ variant: "embedded",
7405
+ children: /* @__PURE__ */ jsxRuntime.jsx(
7406
+ MessageList,
7407
+ {
7408
+ messages: chat.messages,
7409
+ activeToolCalls: chat.activeToolCalls,
7410
+ isLoadingHistory: false,
7411
+ isGenerating: chat.isLoading
7412
+ }
7413
+ )
7414
+ }
7415
+ ),
7416
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: bottomRef })
7417
+ ] }) }),
7418
+ chat.suggestedActions.length > 0 && !chat.isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-widget-root", style: { ...cssVars, maxWidth: 560, margin: "0 auto", width: "100%", padding: "0 16px 8px" }, children: /* @__PURE__ */ jsxRuntime.jsx(
7419
+ WidgetStyleProvider,
7420
+ {
7421
+ styles,
7422
+ agentName,
7423
+ isLoading: false,
7424
+ variant: "embedded",
7425
+ children: /* @__PURE__ */ jsxRuntime.jsx(
7426
+ SuggestedActions,
7427
+ {
7428
+ actions: chat.suggestedActions,
7429
+ onActionClick: handleSuggestedActionClick
7430
+ }
7431
+ )
7432
+ }
7433
+ ) }),
7434
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { borderTop: "1px solid #f3f4f6", flexShrink: 0 }, children: [
7435
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-widget-root", style: { ...cssVars, maxWidth: 560, margin: "0 auto", padding: "12px 16px" }, children: /* @__PURE__ */ jsxRuntime.jsx(
7436
+ WidgetStyleProvider,
7437
+ {
7438
+ styles,
7439
+ agentName,
7440
+ isLoading: false,
7441
+ variant: "embedded",
7442
+ children: /* @__PURE__ */ jsxRuntime.jsx(
7443
+ PromptInputBox,
7444
+ {
7445
+ onSend: handleSend,
7446
+ onStop: handleStop,
7447
+ placeholder: "Type your message...",
7448
+ isLoading: chat.isLoading
7449
+ }
7450
+ )
7451
+ }
7452
+ ) }),
7453
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", padding: "0 0 10px" }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 11, color: "#d1d5db" }, children: "Powered by Crow" }) })
7454
+ ] })
7455
+ ] });
7456
+ return /* @__PURE__ */ jsxRuntime.jsx(ShadowContainer, { styles: WIDGET_CSS, hostId: "crow-onboarding-host", children: /* @__PURE__ */ jsxRuntime.jsx(
7457
+ framerMotion.motion.div,
7458
+ {
7459
+ style: {
7460
+ position: "fixed",
7461
+ top: topOffset,
7462
+ left: 0,
7463
+ right: 0,
7464
+ bottom: 0,
7465
+ zIndex: 999999,
7466
+ background: "#ffffff",
7467
+ fontFamily: styles.typography.fontFamily || '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
7468
+ fontSize: 14
7469
+ },
7470
+ initial: { opacity: 0 },
7471
+ animate: { opacity: isDismissing ? 0 : 1 },
7472
+ transition: { duration: 0.35 },
7473
+ children: phase === "intro" ? /* @__PURE__ */ jsxRuntime.jsx(
7474
+ IntroSequence,
7475
+ {
7476
+ lines: introSequence || [],
7477
+ onComplete: () => setPhase("chat"),
7478
+ onSkip: dismiss,
7479
+ primaryColor: styles.colors.primary
7480
+ }
7481
+ ) : renderChat()
7482
+ }
7483
+ ) });
7484
+ }
6716
7485
  var CrowContext = React3.createContext(null);
6717
7486
  function CrowProvider({
6718
7487
  children,
@@ -6743,6 +7512,7 @@ exports.CopilotContainer = CopilotContainer;
6743
7512
  exports.CopilotStyleProvider = CopilotStyleProvider;
6744
7513
  exports.CopilotToggleButton = CopilotToggleButton;
6745
7514
  exports.CrowCopilot = CrowCopilot;
7515
+ exports.CrowOnboarding = CrowOnboarding;
6746
7516
  exports.CrowProvider = CrowProvider;
6747
7517
  exports.CrowWidget = CrowWidget;
6748
7518
  exports.DEFAULT_COPILOT_STYLES = DEFAULT_COPILOT_STYLES;