@usecrow/ui 0.1.75 → 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) => {
@@ -1697,6 +1703,18 @@ function useWidgetStyles({
1697
1703
  const [availableModels, setAvailableModels] = React3.useState(
1698
1704
  styleCache.get(key)?.availableModels || []
1699
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
+ );
1700
1718
  const hasFetchedRef = React3.useRef(false);
1701
1719
  const fetchStyles = async () => {
1702
1720
  if (skip) return;
@@ -1718,6 +1736,10 @@ function useWidgetStyles({
1718
1736
  setToolConsentSettings(config.toolConsentSettings || {});
1719
1737
  setModelSelectionEnabled(config.modelSelectionEnabled || false);
1720
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);
1721
1743
  } catch (err) {
1722
1744
  console.error("[CrowWidget] Failed to fetch styles:", err);
1723
1745
  setError(err instanceof Error ? err : new Error(String(err)));
@@ -1761,6 +1783,10 @@ function useWidgetStyles({
1761
1783
  toolConsentSettings,
1762
1784
  modelSelectionEnabled,
1763
1785
  availableModels,
1786
+ onboardingEnabled,
1787
+ onboardingAgentName,
1788
+ onboardingWelcomeMessage,
1789
+ onboardingIntroSequence,
1764
1790
  refetch: fetchStyles
1765
1791
  };
1766
1792
  }
@@ -1809,6 +1835,18 @@ function useCopilotStyles({
1809
1835
  const [initialSuggestions, setInitialSuggestions] = React3.useState(
1810
1836
  styleCache.get(key)?.initialSuggestions || []
1811
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
+ );
1812
1850
  const hasFetchedRef = React3.useRef(false);
1813
1851
  const fetchStyles = async () => {
1814
1852
  if (skip) return;
@@ -1829,6 +1867,10 @@ function useCopilotStyles({
1829
1867
  setModelSelectionEnabled(config.modelSelectionEnabled || false);
1830
1868
  setAvailableModels(config.availableModels || []);
1831
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);
1832
1874
  } catch (err) {
1833
1875
  console.error("[CrowCopilot] Failed to fetch styles:", err);
1834
1876
  setError(err instanceof Error ? err : new Error(String(err)));
@@ -1851,6 +1893,10 @@ function useCopilotStyles({
1851
1893
  setModelSelectionEnabled(cached.modelSelectionEnabled || false);
1852
1894
  setAvailableModels(cached.availableModels || []);
1853
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);
1854
1900
  setIsLoading(false);
1855
1901
  return;
1856
1902
  }
@@ -1873,6 +1919,10 @@ function useCopilotStyles({
1873
1919
  modelSelectionEnabled,
1874
1920
  availableModels,
1875
1921
  initialSuggestions,
1922
+ onboardingEnabled,
1923
+ onboardingAgentName,
1924
+ onboardingWelcomeMessage,
1925
+ onboardingIntroSequence,
1876
1926
  refetch: fetchStyles
1877
1927
  };
1878
1928
  }
@@ -4531,6 +4581,84 @@ function injectStyles(target = document) {
4531
4581
  target.prepend(style);
4532
4582
  }
4533
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
+ }
4534
4662
  function CrowWidget({
4535
4663
  productId,
4536
4664
  apiUrl = "",
@@ -4551,7 +4679,9 @@ function CrowWidget({
4551
4679
  toolRenderers,
4552
4680
  language,
4553
4681
  customCss,
4554
- contextLabel: contextLabelProp
4682
+ contextLabel: contextLabelProp,
4683
+ forceOnboarding = false,
4684
+ fullscreenTopOffset: _fullscreenTopOffset = 0
4555
4685
  }) {
4556
4686
  const effectiveGetIdentityToken = getIdentityToken || window.__crow_identity_token_fetcher;
4557
4687
  const effectiveOnToolResult = onToolResult || window.__crow_on_tool_result;
@@ -4570,7 +4700,11 @@ function CrowWidget({
4570
4700
  initialSuggestions,
4571
4701
  toolConsentSettings,
4572
4702
  modelSelectionEnabled,
4573
- availableModels: availableModelsFromAPI
4703
+ availableModels: availableModelsFromAPI,
4704
+ onboardingEnabled,
4705
+ onboardingAgentName,
4706
+ onboardingWelcomeMessage,
4707
+ onboardingIntroSequence
4574
4708
  } = useWidgetStyles({
4575
4709
  productId,
4576
4710
  apiUrl,
@@ -4607,6 +4741,25 @@ function CrowWidget({
4607
4741
  const welcomeMessage = greetingOverride ?? welcomeMessageProp ?? welcomeMessageFromAPI;
4608
4742
  const selectedModel = selectedModelFromAPI;
4609
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]);
4610
4763
  const [autoTools, setAutoTools] = React3.useState({});
4611
4764
  const cssVars = stylesToCssVars(styles);
4612
4765
  const transform = useWidgetTransform({
@@ -4656,11 +4809,17 @@ function CrowWidget({
4656
4809
  const conversations = useConversations({ productId, apiUrl });
4657
4810
  const [shouldRestoreHistory, setShouldRestoreHistory] = React3.useState(false);
4658
4811
  const hasRestoredHistoryRef = React3.useRef(false);
4812
+ const effectiveWelcomeMessage = isOnboarding ? onboardingWelcomeMessage || `Hi! I'm ${onboardingAgentName || agentName}. Let me help you get started.` : welcomeMessage;
4659
4813
  const chat = useChat({
4660
4814
  productId,
4661
4815
  apiUrl,
4662
4816
  persistAnonymousConversations,
4663
- welcomeMessage,
4817
+ welcomeMessage: effectiveWelcomeMessage,
4818
+ agentMode: isOnboarding ? "onboarding" : void 0,
4819
+ onOnboardingComplete: (summary) => {
4820
+ console.log("[Crow] Onboarding complete:", summary);
4821
+ setIsOnboarding(false);
4822
+ },
4664
4823
  selectedModel,
4665
4824
  subdomain,
4666
4825
  toolConsentSettings,
@@ -4748,10 +4907,10 @@ function CrowWidget({
4748
4907
  wasLoadingRef.current = chat.isLoading;
4749
4908
  }, [chat.isLoading, chat.messages]);
4750
4909
  React3.useEffect(() => {
4751
- if (initialSuggestions.length > 0 && chat.suggestedActions.length === 0) {
4910
+ if (!isOnboarding && initialSuggestions.length > 0 && chat.suggestedActions.length === 0) {
4752
4911
  chat.setSuggestedActions(initialSuggestions);
4753
4912
  }
4754
- }, [initialSuggestions]);
4913
+ }, [initialSuggestions, isOnboarding]);
4755
4914
  React3.useEffect(() => {
4756
4915
  if (shouldRestoreHistory && chat.conversationId && !hasRestoredHistoryRef.current) {
4757
4916
  hasRestoredHistoryRef.current = true;
@@ -4786,6 +4945,33 @@ function CrowWidget({
4786
4945
  const { executeClientTool } = useCrowAPI({
4787
4946
  onIdentified: async () => {
4788
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
+ }
4789
4975
  const convs = await conversations.loadConversations();
4790
4976
  if (convs.length > 0) {
4791
4977
  const mostRecent = convs[0];
@@ -4803,6 +4989,16 @@ function CrowWidget({
4803
4989
  });
4804
4990
  executeClientToolRef.current = executeClientTool;
4805
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]);
4806
5002
  React3.useEffect(() => {
4807
5003
  if (!isLoadingStyles) {
4808
5004
  onReady?.();
@@ -5087,7 +5283,59 @@ function CrowWidget({
5087
5283
  setIsCollapsed(!isCollapsed);
5088
5284
  };
5089
5285
  const renderWidgetContent = () => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5090
- /* @__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(
5091
5339
  WidgetHeader,
5092
5340
  {
5093
5341
  isVerifiedUser,
@@ -5103,82 +5351,92 @@ function CrowWidget({
5103
5351
  contextLabel
5104
5352
  }
5105
5353
  ),
5106
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: showConversationList && isVerifiedUser && /* @__PURE__ */ jsxRuntime.jsx(
5107
- ConversationList,
5108
- {
5109
- conversations: conversations.conversations,
5110
- currentConversationId: chat.conversationId,
5111
- onSelect: handleSelectConversation,
5112
- onClose: handleCloseConversationList
5113
- }
5114
- ) }),
5115
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsxRuntime.jsx(
5116
- WorkflowPanel,
5354
+ isOnboarding && onboardingPhase === "intro" && /* @__PURE__ */ jsxRuntime.jsx(
5355
+ OnboardingIntroInline,
5117
5356
  {
5118
- workflow: activeWorkflow,
5119
- onExit: handleExitWorkflow
5357
+ lines: onboardingIntroSequence || [],
5358
+ primaryColor: styles.colors.primary,
5359
+ onComplete: () => setOnboardingPhase("chat")
5120
5360
  }
5121
- ) }),
5122
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: (chat.messages.length > 0 || conversations.isLoadingHistory || pendingConfirmation) && /* @__PURE__ */ jsxRuntime.jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
5123
- /* @__PURE__ */ jsxRuntime.jsx(
5124
- 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,
5125
5365
  {
5126
- messages: chat.messages,
5127
- activeToolCalls: chat.activeToolCalls,
5128
- isLoadingHistory: conversations.isLoadingHistory,
5129
- isGenerating: chat.isLoading,
5130
- toolRenderers: effectiveToolRenderers,
5131
- onToolConsent: handleToolConsent
5366
+ conversations: conversations.conversations,
5367
+ currentConversationId: chat.conversationId,
5368
+ onSelect: handleSelectConversation,
5369
+ onClose: handleCloseConversationList
5132
5370
  }
5133
- ),
5134
- pendingConfirmation && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsxRuntime.jsx(
5135
- BrowserUseConfirmation,
5371
+ ) }),
5372
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsxRuntime.jsx(
5373
+ WorkflowPanel,
5136
5374
  {
5137
- instruction: pendingConfirmation.instruction,
5138
- onAllow: () => {
5139
- setIsBrowserUseActive(true);
5140
- pendingConfirmation.resolve(true);
5141
- setPendingConfirmation(null);
5142
- },
5143
- onDeny: () => {
5144
- pendingConfirmation.resolve(false);
5145
- setPendingConfirmation(null);
5146
- }
5375
+ workflow: activeWorkflow,
5376
+ onExit: handleExitWorkflow
5147
5377
  }
5148
- ) })
5149
- ] }) }),
5150
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "crow-mt-auto crow-w-full", children: [
5151
- 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: [
5152
- /* @__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: [
5153
- /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "crow-opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
5154
- /* @__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 })
5155
5414
  ] }),
5156
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "crow-font-medium crow-text-[var(--crow-text,#111827)]", children: toolStatus })
5157
- ] }),
5158
- (chat.suggestedActions.length > 0 || !chat.isLoading && defaultSuggestedActionsRef.current.length > 0) && /* @__PURE__ */ jsxRuntime.jsx(
5159
- SuggestedActions,
5160
- {
5161
- actions: chat.suggestedActions.length > 0 ? chat.suggestedActions : defaultSuggestedActionsRef.current,
5162
- onActionClick: (action) => handleSend(action.message)
5163
- }
5164
- ),
5165
- /* @__PURE__ */ jsxRuntime.jsx(PoweredByBadge, { apiUrl }),
5166
- /* @__PURE__ */ jsxRuntime.jsx(
5167
- PromptInputBox,
5168
- {
5169
- onSend: handleSend,
5170
- onStop: handleStop,
5171
- placeholder: "Type your message...",
5172
- isLoading: chat.isLoading,
5173
- showStopButton: isBrowserUseActive || !!askUserResolver || !!pendingConfirmation,
5174
- highlighted: !!askUserResolver,
5175
- className: "crow-backdrop-blur-md",
5176
- backendUrl: apiUrl,
5177
- selectedModel: chat.selectedModel || selectedModelFromAPI,
5178
- onModelChange: chat.setSelectedModel,
5179
- availableModels: modelSelectionEnabled ? availableModelsFromAPI : []
5180
- }
5181
- )
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
+ ] })
5182
5440
  ] })
5183
5441
  ] });
5184
5442
  const combinedStyles = React3.useMemo(
@@ -5192,7 +5450,7 @@ ${customCss}` : WIDGET_CSS,
5192
5450
  WidgetStyleProvider,
5193
5451
  {
5194
5452
  styles,
5195
- agentName,
5453
+ agentName: isOnboarding ? onboardingAgentName || agentName : agentName,
5196
5454
  isLoading: isLoadingStyles,
5197
5455
  variant,
5198
5456
  showThinking,
@@ -5489,6 +5747,78 @@ function CopilotContainer({
5489
5747
  )
5490
5748
  ] });
5491
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
+ }
5492
5822
  function CrowCopilot({
5493
5823
  productId,
5494
5824
  apiUrl = "",
@@ -5512,7 +5842,10 @@ function CrowCopilot({
5512
5842
  getIdentityToken,
5513
5843
  context,
5514
5844
  language,
5515
- contextLabel: contextLabelProp
5845
+ contextLabel: contextLabelProp,
5846
+ forceOnboarding = false,
5847
+ fullscreenTopOffset: _fullscreenTopOffset = 0,
5848
+ mode: _mode
5516
5849
  }) {
5517
5850
  const effectiveGetIdentityToken = getIdentityToken || window.__crow_identity_token_fetcher;
5518
5851
  const effectiveOnToolResult = onToolResult || window.__crow_on_tool_result;
@@ -5530,7 +5863,11 @@ function CrowCopilot({
5530
5863
  toolConsentSettings,
5531
5864
  modelSelectionEnabled,
5532
5865
  availableModels: availableModelsFromAPI,
5533
- initialSuggestions
5866
+ initialSuggestions,
5867
+ onboardingEnabled,
5868
+ onboardingAgentName,
5869
+ onboardingWelcomeMessage,
5870
+ onboardingIntroSequence
5534
5871
  } = useCopilotStyles({
5535
5872
  productId,
5536
5873
  apiUrl,
@@ -5539,6 +5876,20 @@ function CrowCopilot({
5539
5876
  language
5540
5877
  });
5541
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]);
5542
5893
  const [toolStatus, setToolStatus] = React3.useState(
5543
5894
  () => window.__crow_tool_status ?? ""
5544
5895
  );
@@ -5719,10 +6070,10 @@ function CrowCopilot({
5719
6070
  };
5720
6071
  }, []);
5721
6072
  React3.useEffect(() => {
5722
- if (initialSuggestions.length > 0 && chat.suggestedActions.length === 0) {
6073
+ if (!isOnboarding && initialSuggestions.length > 0 && chat.suggestedActions.length === 0) {
5723
6074
  chat.setSuggestedActions(initialSuggestions);
5724
6075
  }
5725
- }, [initialSuggestions]);
6076
+ }, [initialSuggestions, isOnboarding]);
5726
6077
  const messagesContainerRef = React3.useRef(null);
5727
6078
  const tabsScrollRef = React3.useRef(null);
5728
6079
  const executeClientToolRef = React3.useRef(null);
@@ -5752,11 +6103,17 @@ function CrowCopilot({
5752
6103
  pendingRestoreConvId.current = "";
5753
6104
  }
5754
6105
  }
6106
+ const effectiveWelcomeMessage = isOnboarding ? onboardingWelcomeMessage || `Hi! I'm ${onboardingAgentName || agentName}. Let me help you get started.` : welcomeMessage;
5755
6107
  const chat = useChat({
5756
6108
  productId,
5757
6109
  apiUrl,
5758
6110
  persistAnonymousConversations,
5759
- welcomeMessage,
6111
+ welcomeMessage: effectiveWelcomeMessage,
6112
+ agentMode: isOnboarding ? "onboarding" : void 0,
6113
+ onOnboardingComplete: (summary) => {
6114
+ console.log("[Crow] Onboarding complete:", summary);
6115
+ setIsOnboarding(false);
6116
+ },
5760
6117
  selectedModel,
5761
6118
  subdomain,
5762
6119
  toolConsentSettings,
@@ -5900,6 +6257,33 @@ function CrowCopilot({
5900
6257
  const { executeClientTool } = useCrowAPI({
5901
6258
  onIdentified: async () => {
5902
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
+ }
5903
6287
  await conversations.loadConversations();
5904
6288
  const savedId = pendingRestoreConvId.current;
5905
6289
  if (savedId && !hasRestoredActiveConvRef.current) {
@@ -5922,6 +6306,16 @@ function CrowCopilot({
5922
6306
  });
5923
6307
  executeClientToolRef.current = executeClientTool;
5924
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]);
5925
6319
  const handleBrowserConfirmation = React3.useCallback(
5926
6320
  (instruction) => {
5927
6321
  return new Promise((resolve) => {
@@ -6262,312 +6656,347 @@ function CrowCopilot({
6262
6656
  "--crow-bg-active": styles.colors.text + "18"
6263
6657
  },
6264
6658
  children: [
6265
- /* @__PURE__ */ jsxRuntime.jsxs(
6266
- "div",
6267
- {
6268
- className: "crow-flex crow-items-stretch crow-border-b crow-min-h-[40px]",
6269
- style: { borderColor: styles.colors.border },
6270
- children: [
6271
- /* @__PURE__ */ jsxRuntime.jsx(
6272
- "div",
6273
- {
6274
- ref: tabsScrollRef,
6275
- className: "crow-flex crow-items-stretch crow-flex-1 crow-min-w-0 crow-overflow-x-auto",
6276
- style: {
6277
- scrollbarWidth: "none",
6278
- msOverflowStyle: "none"
6279
- },
6280
- onScroll: handleTabsScroll,
6281
- children: tabs.map((tab, idx) => {
6282
- const isActive = activeTabId === tab.id;
6283
- const isHovered = hoveredTabId === tab.id;
6284
- const isCloseable = tab.type !== "new" && (tab.type !== "local" || localTabs.length > 1);
6285
- return /* @__PURE__ */ jsxRuntime.jsxs(
6286
- "div",
6287
- {
6288
- 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",
6289
- style: {
6290
- color: isActive ? styles.colors.text : styles.colors.text + "80",
6291
- fontWeight: isActive ? 500 : void 0,
6292
- maxWidth: "180px",
6293
- borderRight: idx < tabs.length - 1 ? `1px solid ${styles.colors.border}` : "none",
6294
- paddingLeft: "16px",
6295
- paddingRight: isCloseable ? "8px" : "16px"
6296
- },
6297
- title: tab.name,
6298
- onMouseEnter: () => setHoveredTabId(tab.id),
6299
- onMouseLeave: () => setHoveredTabId(null),
6300
- onClick: () => {
6301
- if (tab.type === "new") {
6302
- handleNewChat();
6303
- return;
6304
- }
6305
- if (tab.type === "server") {
6306
- handleSelectConversation(tab.id);
6307
- return;
6308
- }
6309
- handleSelectLocalTab(tab.id);
6310
- },
6311
- children: [
6312
- /* @__PURE__ */ jsxRuntime.jsx(
6313
- "span",
6314
- {
6315
- className: "crow-block crow-truncate",
6316
- style: { maxWidth: isCloseable ? "112px" : "128px" },
6317
- children: tab.name
6318
- }
6319
- ),
6320
- isCloseable && /* @__PURE__ */ jsxRuntime.jsx(
6321
- "span",
6322
- {
6323
- className: "crow-rounded crow-p-0.5 crow-flex-shrink-0 crow-inline-flex crow-items-center crow-justify-center crow-transition-opacity",
6324
- style: {
6325
- marginLeft: "6px",
6326
- opacity: isHovered ? 1 : 0,
6327
- pointerEvents: isHovered ? "auto" : "none"
6328
- },
6329
- onClick: (e) => {
6330
- e.stopPropagation();
6331
- handleCloseTab(tab.id, tab.type);
6332
- },
6333
- role: "button",
6334
- "aria-label": `Close ${tab.name}`,
6335
- children: /* @__PURE__ */ jsxRuntime.jsx(TabCloseIcon, { className: "crow-w-3 crow-h-3", style: { color: styles.colors.text + "80" } })
6336
- }
6337
- ),
6338
- isActive && /* @__PURE__ */ jsxRuntime.jsx(
6339
- "span",
6340
- {
6341
- className: "crow-absolute crow-bottom-0 crow-left-0 crow-right-0",
6342
- style: {
6343
- height: "2px",
6344
- background: styles.colors.primary || "#2563eb"
6345
- }
6346
- }
6347
- )
6348
- ]
6349
- },
6350
- `${tab.id}-${idx}`
6351
- );
6352
- })
6353
- }
6354
- ),
6355
- /* @__PURE__ */ jsxRuntime.jsxs(
6356
- "div",
6357
- {
6358
- className: "crow-flex crow-items-center crow-flex-shrink-0 crow-border-l",
6359
- style: { borderColor: styles.colors.border },
6360
- children: [
6361
- /* @__PURE__ */ jsxRuntime.jsx(
6362
- "button",
6363
- {
6364
- onClick: handleNewChat,
6365
- className: "crow-p-2 crow-transition-colors crow-rounded",
6366
- style: { color: styles.colors.text + "80" },
6367
- onMouseEnter: (e) => {
6368
- e.currentTarget.style.background = styles.colors.text + "10";
6369
- },
6370
- onMouseLeave: (e) => {
6371
- e.currentTarget.style.background = "transparent";
6372
- },
6373
- "aria-label": "New Chat",
6374
- title: "New Chat",
6375
- children: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { className: "crow-w-4 crow-h-4" })
6376
- }
6377
- ),
6378
- /* @__PURE__ */ jsxRuntime.jsx(
6379
- "button",
6380
- {
6381
- onClick: handleToggleHistory,
6382
- disabled: !isVerifiedUser,
6383
- "aria-disabled": !isVerifiedUser,
6384
- className: `crow-p-2 crow-transition-colors crow-rounded ${!isVerifiedUser ? "crow-opacity-40 crow-cursor-not-allowed" : ""}`,
6385
- style: {
6386
- color: styles.colors.text + "80",
6387
- background: showConversationList ? styles.colors.text + "10" : "transparent"
6388
- },
6389
- onMouseEnter: (e) => {
6390
- if (isVerifiedUser) e.currentTarget.style.background = styles.colors.text + "10";
6391
- },
6392
- onMouseLeave: (e) => {
6393
- if (!showConversationList) e.currentTarget.style.background = "transparent";
6394
- },
6395
- "aria-label": "Conversation History",
6396
- title: isVerifiedUser ? "Conversation History" : "Sign in to view history",
6397
- children: /* @__PURE__ */ jsxRuntime.jsx(HistoryIcon, { className: "crow-w-4 crow-h-4" })
6398
- }
6399
- ),
6400
- canScrollRight && /* @__PURE__ */ jsxRuntime.jsx(
6401
- "button",
6402
- {
6403
- onClick: handleScrollRight,
6404
- className: "crow-p-2 crow-transition-colors crow-rounded",
6405
- style: { color: styles.colors.text + "80" },
6406
- onMouseEnter: (e) => {
6407
- e.currentTarget.style.background = styles.colors.text + "10";
6408
- },
6409
- onMouseLeave: (e) => {
6410
- e.currentTarget.style.background = "transparent";
6411
- },
6412
- "aria-label": "Scroll tabs",
6413
- title: "Scroll tabs",
6414
- children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { className: "crow-w-4 crow-h-4" })
6415
- }
6416
- ),
6417
- (forceShowClose ?? showClose) && (overrideOnClose ?? onClose) && /* @__PURE__ */ jsxRuntime.jsx(
6418
- "button",
6419
- {
6420
- onClick: overrideOnClose ?? onClose,
6421
- className: "crow-p-2 crow-transition-colors crow-rounded",
6422
- style: { color: styles.colors.text + "80" },
6423
- onMouseEnter: (e) => {
6424
- e.currentTarget.style.background = styles.colors.text + "10";
6425
- },
6426
- onMouseLeave: (e) => {
6427
- e.currentTarget.style.background = "transparent";
6428
- },
6429
- "aria-label": "Close",
6430
- children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { className: "crow-w-4 crow-h-4" })
6431
- }
6432
- )
6433
- ]
6434
- }
6435
- )
6436
- ]
6437
- }
6438
- ),
6439
- contextLabel && /* @__PURE__ */ jsxRuntime.jsxs(
6440
- "div",
6441
- {
6442
- className: "crow-flex crow-items-center crow-gap-1.5 crow-px-3 crow-py-1.5 crow-border-b crow-text-xs",
6443
- style: {
6444
- color: styles.colors.text + "80",
6445
- borderColor: styles.colors.border
6446
- },
6447
- children: [
6448
- /* @__PURE__ */ jsxRuntime.jsxs(
6449
- "svg",
6450
- {
6451
- xmlns: "http://www.w3.org/2000/svg",
6452
- width: "12",
6453
- height: "12",
6454
- viewBox: "0 0 24 24",
6455
- fill: "none",
6456
- stroke: "currentColor",
6457
- strokeWidth: "2",
6458
- strokeLinecap: "round",
6459
- strokeLinejoin: "round",
6460
- className: "crow-shrink-0",
6461
- children: [
6462
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }),
6463
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "10", r: "3" })
6464
- ]
6465
- }
6466
- ),
6467
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "crow-truncate", children: contextLabel })
6468
- ]
6469
- }
6470
- ),
6471
- /* @__PURE__ */ jsxRuntime.jsxs(framerMotion.AnimatePresence, { children: [
6472
- showConversationList && isVerifiedUser && /* @__PURE__ */ jsxRuntime.jsx(
6473
- ConversationList,
6659
+ isOnboarding && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6660
+ /* @__PURE__ */ jsxRuntime.jsxs(
6661
+ "div",
6474
6662
  {
6475
- conversations: conversations.conversations,
6476
- currentConversationId: chat.conversationId,
6477
- onSelect: handleSelectConversation,
6478
- 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
+ ]
6479
6679
  }
6480
6680
  ),
6481
- showConversationList && !isVerifiedUser && /* @__PURE__ */ jsxRuntime.jsx(
6482
- "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,
6483
6683
  {
6484
- className: "crow-mb-3 crow-rounded-xl crow-border crow-p-4",
6485
- style: { background: styles.colors.text + "08", borderColor: styles.colors.border },
6486
- 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")
6487
6689
  }
6488
- )
6690
+ ) })
6489
6691
  ] }),
6490
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsxRuntime.jsx(
6491
- WorkflowPanel,
6492
- {
6493
- workflow: activeWorkflow,
6494
- onExit: handleExitWorkflow
6495
- }
6496
- ) }),
6497
- /* @__PURE__ */ jsxRuntime.jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
6498
- /* @__PURE__ */ jsxRuntime.jsx(
6499
- MessageList,
6692
+ !(isOnboarding && onboardingPhase === "intro") && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6693
+ !isOnboarding && /* @__PURE__ */ jsxRuntime.jsxs(
6694
+ "div",
6500
6695
  {
6501
- messages: chat.messages,
6502
- activeToolCalls: chat.activeToolCalls,
6503
- isLoadingHistory: conversations.isLoadingHistory,
6504
- isGenerating: chat.isLoading,
6505
- toolRenderers: effectiveToolRenderers,
6506
- 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
+ ]
6507
6865
  }
6508
6866
  ),
6509
- pendingConfirmation && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsxRuntime.jsx(
6510
- BrowserUseConfirmation,
6867
+ contextLabel && /* @__PURE__ */ jsxRuntime.jsxs(
6868
+ "div",
6511
6869
  {
6512
- instruction: pendingConfirmation.instruction,
6513
- onAllow: () => {
6514
- pendingConfirmation.resolve(true);
6515
- 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
6516
6874
  },
6517
- onDeny: () => {
6518
- pendingConfirmation.resolve(false);
6519
- 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
6520
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
6521
6923
  }
6522
6924
  ) }),
6523
- askUserResolver && browserQuestion && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsxRuntime.jsx(
6524
- BrowserUseQuestion,
6525
- {
6526
- question: browserQuestion,
6527
- onSubmit: (answer) => {
6528
- askUserResolver.resolve(answer);
6529
- setAskUserResolver(null);
6530
- 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
6531
6935
  }
6532
- }
6533
- ) })
6534
- ] }),
6535
- /* @__PURE__ */ jsxRuntime.jsxs(
6536
- "div",
6537
- {
6538
- className: "crow-p-3 crow-border-t",
6539
- style: { borderColor: styles.colors.border },
6540
- children: [
6541
- 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: [
6542
- /* @__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: [
6543
- /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "crow-opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
6544
- /* @__PURE__ */ jsxRuntime.jsx("path", { className: "crow-opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
6545
- ] }),
6546
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "crow-font-medium crow-text-[var(--crow-text,#111827)]", children: toolStatus })
6547
- ] }),
6548
- (chat.suggestedActions.length > 0 || !chat.isLoading && defaultSuggestedActionsRef.current.length > 0) && /* @__PURE__ */ jsxRuntime.jsx(
6549
- SuggestedActions,
6550
- {
6551
- actions: chat.suggestedActions.length > 0 ? chat.suggestedActions : defaultSuggestedActionsRef.current,
6552
- 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);
6553
6948
  }
6554
- ),
6555
- styles.branding.showPoweredBy && /* @__PURE__ */ jsxRuntime.jsx(PoweredByBadge, { apiUrl }),
6556
- /* @__PURE__ */ jsxRuntime.jsx(
6557
- PromptInputBox,
6558
- {
6559
- onSend: handleSend,
6560
- onStop: handleStop,
6561
- placeholder: "Ask anything...",
6562
- isLoading: chat.isLoading,
6563
- selectedModel: chat.selectedModel || selectedModel,
6564
- onModelChange: chat.setSelectedModel,
6565
- 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);
6566
6959
  }
6567
- )
6568
- ]
6569
- }
6570
- )
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
+ ] })
6571
7000
  ]
6572
7001
  }
6573
7002
  )
@@ -6589,7 +7018,7 @@ function CrowCopilot({
6589
7018
  const edgeSide = isRight ? "left" : "right";
6590
7019
  const toggleIconColor = styles.colors.text + "80";
6591
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" }) });
6592
- 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: [
6593
7022
  /* @__PURE__ */ jsxRuntime.jsx(
6594
7023
  "button",
6595
7024
  {
@@ -6633,7 +7062,7 @@ function CrowCopilot({
6633
7062
  children: /* @__PURE__ */ jsxRuntime.jsx(ShadowContainer, { styles: WIDGET_CSS, children: renderCopilotContent(void 0, false, "100%") })
6634
7063
  }
6635
7064
  )
6636
- ] });
7065
+ ] }) });
6637
7066
  }
6638
7067
  function PlusIcon({ className }) {
6639
7068
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -6739,6 +7168,320 @@ function CloseIcon({ className }) {
6739
7168
  }
6740
7169
  );
6741
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
+ }
6742
7485
  var CrowContext = React3.createContext(null);
6743
7486
  function CrowProvider({
6744
7487
  children,
@@ -6769,6 +7512,7 @@ exports.CopilotContainer = CopilotContainer;
6769
7512
  exports.CopilotStyleProvider = CopilotStyleProvider;
6770
7513
  exports.CopilotToggleButton = CopilotToggleButton;
6771
7514
  exports.CrowCopilot = CrowCopilot;
7515
+ exports.CrowOnboarding = CrowOnboarding;
6772
7516
  exports.CrowProvider = CrowProvider;
6773
7517
  exports.CrowWidget = CrowWidget;
6774
7518
  exports.DEFAULT_COPILOT_STYLES = DEFAULT_COPILOT_STYLES;