@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.js CHANGED
@@ -48,6 +48,8 @@ function useChat({
48
48
  subdomain,
49
49
  toolConsentSettings,
50
50
  language,
51
+ agentMode,
52
+ onOnboardingComplete,
51
53
  onVerificationStatus,
52
54
  onConversationId,
53
55
  onWorkflowEvent,
@@ -140,7 +142,8 @@ function useChat({
140
142
  user_local_time: (/* @__PURE__ */ new Date()).toLocaleString("en-US", { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric", hour12: true }),
141
143
  page_path: typeof window !== "undefined" ? window.location.pathname : void 0,
142
144
  context: typeof window !== "undefined" ? window.__crow_page_context : void 0,
143
- ...language && language !== "en" ? { language } : {}
145
+ ...language && language !== "en" ? { language } : {},
146
+ ...agentMode ? { agent_mode: agentMode } : {}
144
147
  }),
145
148
  signal: abortControllerRef.current.signal
146
149
  });
@@ -468,6 +471,9 @@ function useChat({
468
471
  setSuggestedActions(parsed.actions);
469
472
  }
470
473
  break;
474
+ case "onboarding_complete":
475
+ onOnboardingComplete?.(parsed.summary || "");
476
+ break;
471
477
  }
472
478
  } catch (e) {
473
479
  console.error("[Crow] Parse error:", e);
@@ -500,7 +506,7 @@ function useChat({
500
506
  abortControllerRef.current = null;
501
507
  }
502
508
  },
503
- [apiUrl, productId, conversationId, selectedModel, subdomain, persistAnonymousConversations, onVerificationStatus, onConversationId, onWorkflowEvent, onToolCall, onToolResult]
509
+ [apiUrl, productId, conversationId, selectedModel, subdomain, persistAnonymousConversations, agentMode, onOnboardingComplete, onVerificationStatus, onConversationId, onWorkflowEvent, onToolCall, onToolResult]
504
510
  );
505
511
  const sendMessage = useCallback(
506
512
  (content) => {
@@ -1248,6 +1254,20 @@ function useCrowAPI({ onIdentified, onReset } = {}) {
1248
1254
  case "close":
1249
1255
  window.dispatchEvent(new CustomEvent("crow:close"));
1250
1256
  break;
1257
+ case "sendMessage": {
1258
+ const msgText = typeof options === "string" ? options : opts?.text ?? opts?.message;
1259
+ if (!msgText) {
1260
+ console.error("[Crow] sendMessage() requires a text string or { text }");
1261
+ return;
1262
+ }
1263
+ window.dispatchEvent(new CustomEvent("crow:open"));
1264
+ setTimeout(() => {
1265
+ window.dispatchEvent(
1266
+ new CustomEvent("crow:sendMessage", { detail: { text: msgText } })
1267
+ );
1268
+ }, 50);
1269
+ break;
1270
+ }
1251
1271
  case "setToolStatus":
1252
1272
  if (typeof options !== "string") {
1253
1273
  console.error("[Crow] setToolStatus() requires a string");
@@ -1656,6 +1676,18 @@ function useWidgetStyles({
1656
1676
  const [availableModels, setAvailableModels] = useState(
1657
1677
  styleCache.get(key)?.availableModels || []
1658
1678
  );
1679
+ const [onboardingEnabled, setOnboardingEnabled] = useState(
1680
+ styleCache.get(key)?.onboardingEnabled || false
1681
+ );
1682
+ const [onboardingAgentName, setOnboardingAgentName] = useState(
1683
+ styleCache.get(key)?.onboardingAgentName ?? void 0
1684
+ );
1685
+ const [onboardingWelcomeMessage, setOnboardingWelcomeMessage] = useState(
1686
+ styleCache.get(key)?.onboardingWelcomeMessage ?? void 0
1687
+ );
1688
+ const [onboardingIntroSequence, setOnboardingIntroSequence] = useState(
1689
+ styleCache.get(key)?.onboardingIntroSequence ?? void 0
1690
+ );
1659
1691
  const hasFetchedRef = useRef(false);
1660
1692
  const fetchStyles = async () => {
1661
1693
  if (skip) return;
@@ -1677,6 +1709,10 @@ function useWidgetStyles({
1677
1709
  setToolConsentSettings(config.toolConsentSettings || {});
1678
1710
  setModelSelectionEnabled(config.modelSelectionEnabled || false);
1679
1711
  setAvailableModels(config.availableModels || []);
1712
+ setOnboardingEnabled(config.onboardingEnabled || false);
1713
+ setOnboardingAgentName(config.onboardingAgentName ?? void 0);
1714
+ setOnboardingWelcomeMessage(config.onboardingWelcomeMessage ?? void 0);
1715
+ setOnboardingIntroSequence(config.onboardingIntroSequence ?? void 0);
1680
1716
  } catch (err) {
1681
1717
  console.error("[CrowWidget] Failed to fetch styles:", err);
1682
1718
  setError(err instanceof Error ? err : new Error(String(err)));
@@ -1720,6 +1756,10 @@ function useWidgetStyles({
1720
1756
  toolConsentSettings,
1721
1757
  modelSelectionEnabled,
1722
1758
  availableModels,
1759
+ onboardingEnabled,
1760
+ onboardingAgentName,
1761
+ onboardingWelcomeMessage,
1762
+ onboardingIntroSequence,
1723
1763
  refetch: fetchStyles
1724
1764
  };
1725
1765
  }
@@ -1768,6 +1808,18 @@ function useCopilotStyles({
1768
1808
  const [initialSuggestions, setInitialSuggestions] = useState(
1769
1809
  styleCache.get(key)?.initialSuggestions || []
1770
1810
  );
1811
+ const [onboardingEnabled, setOnboardingEnabled] = useState(
1812
+ styleCache.get(key)?.onboardingEnabled || false
1813
+ );
1814
+ const [onboardingAgentName, setOnboardingAgentName] = useState(
1815
+ styleCache.get(key)?.onboardingAgentName ?? void 0
1816
+ );
1817
+ const [onboardingWelcomeMessage, setOnboardingWelcomeMessage] = useState(
1818
+ styleCache.get(key)?.onboardingWelcomeMessage ?? void 0
1819
+ );
1820
+ const [onboardingIntroSequence, setOnboardingIntroSequence] = useState(
1821
+ styleCache.get(key)?.onboardingIntroSequence ?? void 0
1822
+ );
1771
1823
  const hasFetchedRef = useRef(false);
1772
1824
  const fetchStyles = async () => {
1773
1825
  if (skip) return;
@@ -1788,6 +1840,10 @@ function useCopilotStyles({
1788
1840
  setModelSelectionEnabled(config.modelSelectionEnabled || false);
1789
1841
  setAvailableModels(config.availableModels || []);
1790
1842
  setInitialSuggestions(config.initialSuggestions || []);
1843
+ setOnboardingEnabled(config.onboardingEnabled || false);
1844
+ setOnboardingAgentName(config.onboardingAgentName ?? void 0);
1845
+ setOnboardingWelcomeMessage(config.onboardingWelcomeMessage ?? void 0);
1846
+ setOnboardingIntroSequence(config.onboardingIntroSequence ?? void 0);
1791
1847
  } catch (err) {
1792
1848
  console.error("[CrowCopilot] Failed to fetch styles:", err);
1793
1849
  setError(err instanceof Error ? err : new Error(String(err)));
@@ -1810,6 +1866,10 @@ function useCopilotStyles({
1810
1866
  setModelSelectionEnabled(cached.modelSelectionEnabled || false);
1811
1867
  setAvailableModels(cached.availableModels || []);
1812
1868
  setInitialSuggestions(cached.initialSuggestions || []);
1869
+ setOnboardingEnabled(cached.onboardingEnabled || false);
1870
+ setOnboardingAgentName(cached.onboardingAgentName ?? void 0);
1871
+ setOnboardingWelcomeMessage(cached.onboardingWelcomeMessage ?? void 0);
1872
+ setOnboardingIntroSequence(cached.onboardingIntroSequence ?? void 0);
1813
1873
  setIsLoading(false);
1814
1874
  return;
1815
1875
  }
@@ -1832,6 +1892,10 @@ function useCopilotStyles({
1832
1892
  modelSelectionEnabled,
1833
1893
  availableModels,
1834
1894
  initialSuggestions,
1895
+ onboardingEnabled,
1896
+ onboardingAgentName,
1897
+ onboardingWelcomeMessage,
1898
+ onboardingIntroSequence,
1835
1899
  refetch: fetchStyles
1836
1900
  };
1837
1901
  }
@@ -4490,6 +4554,84 @@ function injectStyles(target = document) {
4490
4554
  target.prepend(style);
4491
4555
  }
4492
4556
  }
4557
+ function OnboardingIntroInline({
4558
+ lines,
4559
+ primaryColor,
4560
+ onComplete
4561
+ }) {
4562
+ const [lineIndex, setLineIndex] = useState(0);
4563
+ const [charIndex, setCharIndex] = useState(0);
4564
+ const [done, setDone] = useState(false);
4565
+ useEffect(() => {
4566
+ if (lineIndex >= lines.length) {
4567
+ setDone(true);
4568
+ return;
4569
+ }
4570
+ const currentLine = lines[lineIndex];
4571
+ if (charIndex < currentLine.length) {
4572
+ const t = setTimeout(() => setCharIndex((c) => c + 1), 35);
4573
+ return () => clearTimeout(t);
4574
+ } else {
4575
+ const t = setTimeout(() => {
4576
+ setLineIndex((l) => l + 1);
4577
+ setCharIndex(0);
4578
+ }, 500);
4579
+ return () => clearTimeout(t);
4580
+ }
4581
+ }, [lineIndex, charIndex, lines]);
4582
+ const displayedLines = lines.slice(0, lineIndex + 1).map(
4583
+ (line, i) => i < lineIndex ? line : line.slice(0, charIndex)
4584
+ );
4585
+ return /* @__PURE__ */ jsxs("div", { style: {
4586
+ display: "flex",
4587
+ flexDirection: "column",
4588
+ alignItems: "center",
4589
+ justifyContent: "center",
4590
+ flex: 1,
4591
+ padding: "24px 16px",
4592
+ textAlign: "center"
4593
+ }, children: [
4594
+ /* @__PURE__ */ jsx("div", { style: { minHeight: "4rem", marginBottom: "1.5rem" }, children: displayedLines.map((text, i) => /* @__PURE__ */ jsxs("p", { style: {
4595
+ fontSize: i === 0 ? 18 : 14,
4596
+ fontWeight: i === 0 ? 600 : 400,
4597
+ color: i === 0 ? "var(--crow-text, #111827)" : "var(--crow-text-secondary, #6b7280)",
4598
+ lineHeight: 1.4,
4599
+ margin: "0 0 6px 0"
4600
+ }, children: [
4601
+ text,
4602
+ i === lineIndex && !done && /* @__PURE__ */ jsx("span", { style: {
4603
+ display: "inline-block",
4604
+ width: 2,
4605
+ height: i === 0 ? 18 : 14,
4606
+ backgroundColor: "var(--crow-text, #111827)",
4607
+ marginLeft: 2,
4608
+ verticalAlign: "middle",
4609
+ animation: "crow-blink 1s step-end infinite"
4610
+ } })
4611
+ ] }, i)) }),
4612
+ /* @__PURE__ */ jsx(
4613
+ "button",
4614
+ {
4615
+ onClick: onComplete,
4616
+ style: {
4617
+ padding: "8px 24px",
4618
+ borderRadius: 8,
4619
+ backgroundColor: primaryColor,
4620
+ color: "#fff",
4621
+ fontSize: 13,
4622
+ fontWeight: 500,
4623
+ border: "none",
4624
+ cursor: "pointer",
4625
+ opacity: done ? 1 : 0,
4626
+ pointerEvents: done ? "auto" : "none",
4627
+ transition: "opacity 0.5s ease"
4628
+ },
4629
+ children: "Get Started \u2192"
4630
+ }
4631
+ ),
4632
+ /* @__PURE__ */ jsx("style", { children: `@keyframes crow-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }` })
4633
+ ] });
4634
+ }
4493
4635
  function CrowWidget({
4494
4636
  productId,
4495
4637
  apiUrl = "",
@@ -4510,7 +4652,9 @@ function CrowWidget({
4510
4652
  toolRenderers,
4511
4653
  language,
4512
4654
  customCss,
4513
- contextLabel: contextLabelProp
4655
+ contextLabel: contextLabelProp,
4656
+ forceOnboarding = false,
4657
+ fullscreenTopOffset: _fullscreenTopOffset = 0
4514
4658
  }) {
4515
4659
  const effectiveGetIdentityToken = getIdentityToken || window.__crow_identity_token_fetcher;
4516
4660
  const effectiveOnToolResult = onToolResult || window.__crow_on_tool_result;
@@ -4529,7 +4673,11 @@ function CrowWidget({
4529
4673
  initialSuggestions,
4530
4674
  toolConsentSettings,
4531
4675
  modelSelectionEnabled,
4532
- availableModels: availableModelsFromAPI
4676
+ availableModels: availableModelsFromAPI,
4677
+ onboardingEnabled,
4678
+ onboardingAgentName,
4679
+ onboardingWelcomeMessage,
4680
+ onboardingIntroSequence
4533
4681
  } = useWidgetStyles({
4534
4682
  productId,
4535
4683
  apiUrl,
@@ -4566,6 +4714,25 @@ function CrowWidget({
4566
4714
  const welcomeMessage = greetingOverride ?? welcomeMessageProp ?? welcomeMessageFromAPI;
4567
4715
  const selectedModel = selectedModelFromAPI;
4568
4716
  const showThinking = showThinkingProp ?? showThinkingFromAPI;
4717
+ const [isOnboarding, setIsOnboarding] = useState(false);
4718
+ const [onboardingChecked, setOnboardingChecked] = useState(false);
4719
+ const [onboardingPhase, setOnboardingPhase] = useState("intro");
4720
+ useEffect(() => {
4721
+ if (forceOnboarding && !isLoadingStyles && onboardingEnabled && !onboardingChecked) {
4722
+ setIsOnboarding(true);
4723
+ setOnboardingChecked(true);
4724
+ }
4725
+ }, [forceOnboarding, isLoadingStyles, onboardingEnabled, onboardingChecked]);
4726
+ useEffect(() => {
4727
+ if (isOnboarding) {
4728
+ setIsCollapsed(false);
4729
+ }
4730
+ }, [isOnboarding]);
4731
+ useEffect(() => {
4732
+ if (isOnboarding && !isLoadingStyles && onboardingIntroSequence !== void 0 && onboardingIntroSequence.length === 0) {
4733
+ setOnboardingPhase("chat");
4734
+ }
4735
+ }, [isOnboarding, isLoadingStyles, onboardingIntroSequence]);
4569
4736
  const [autoTools, setAutoTools] = useState({});
4570
4737
  const cssVars = stylesToCssVars(styles);
4571
4738
  const transform = useWidgetTransform({
@@ -4615,11 +4782,17 @@ function CrowWidget({
4615
4782
  const conversations = useConversations({ productId, apiUrl });
4616
4783
  const [shouldRestoreHistory, setShouldRestoreHistory] = useState(false);
4617
4784
  const hasRestoredHistoryRef = useRef(false);
4785
+ const effectiveWelcomeMessage = isOnboarding ? onboardingWelcomeMessage || `Hi! I'm ${onboardingAgentName || agentName}. Let me help you get started.` : welcomeMessage;
4618
4786
  const chat = useChat({
4619
4787
  productId,
4620
4788
  apiUrl,
4621
4789
  persistAnonymousConversations,
4622
- welcomeMessage,
4790
+ welcomeMessage: effectiveWelcomeMessage,
4791
+ agentMode: isOnboarding ? "onboarding" : void 0,
4792
+ onOnboardingComplete: (summary) => {
4793
+ console.log("[Crow] Onboarding complete:", summary);
4794
+ setIsOnboarding(false);
4795
+ },
4623
4796
  selectedModel,
4624
4797
  subdomain,
4625
4798
  toolConsentSettings,
@@ -4707,10 +4880,10 @@ function CrowWidget({
4707
4880
  wasLoadingRef.current = chat.isLoading;
4708
4881
  }, [chat.isLoading, chat.messages]);
4709
4882
  useEffect(() => {
4710
- if (initialSuggestions.length > 0 && chat.suggestedActions.length === 0) {
4883
+ if (!isOnboarding && initialSuggestions.length > 0 && chat.suggestedActions.length === 0) {
4711
4884
  chat.setSuggestedActions(initialSuggestions);
4712
4885
  }
4713
- }, [initialSuggestions]);
4886
+ }, [initialSuggestions, isOnboarding]);
4714
4887
  useEffect(() => {
4715
4888
  if (shouldRestoreHistory && chat.conversationId && !hasRestoredHistoryRef.current) {
4716
4889
  hasRestoredHistoryRef.current = true;
@@ -4745,6 +4918,33 @@ function CrowWidget({
4745
4918
  const { executeClientTool } = useCrowAPI({
4746
4919
  onIdentified: async () => {
4747
4920
  setIsVerifiedUser(true);
4921
+ if (forceOnboarding) {
4922
+ setIsOnboarding(true);
4923
+ setOnboardingChecked(true);
4924
+ } else if (onboardingEnabled && !onboardingChecked) {
4925
+ try {
4926
+ const identityToken = window.__crow_identity_token;
4927
+ if (identityToken) {
4928
+ const res = await fetch(`${apiUrl}/api/chat/resolve-agent`, {
4929
+ method: "POST",
4930
+ headers: { "Content-Type": "application/json" },
4931
+ body: JSON.stringify({
4932
+ product_id: productId,
4933
+ identity_token: identityToken
4934
+ })
4935
+ });
4936
+ if (res.ok) {
4937
+ const data = await res.json();
4938
+ if (data.agent === "onboarding") {
4939
+ setIsOnboarding(true);
4940
+ }
4941
+ }
4942
+ }
4943
+ } catch (e) {
4944
+ console.error("[Crow] resolve-agent failed:", e);
4945
+ }
4946
+ setOnboardingChecked(true);
4947
+ }
4748
4948
  const convs = await conversations.loadConversations();
4749
4949
  if (convs.length > 0) {
4750
4950
  const mostRecent = convs[0];
@@ -4762,6 +4962,16 @@ function CrowWidget({
4762
4962
  });
4763
4963
  executeClientToolRef.current = executeClientTool;
4764
4964
  submitToolResultRef.current = chat.submitToolResult;
4965
+ const prevOnboardingRef = useRef(isOnboarding);
4966
+ useEffect(() => {
4967
+ if (isOnboarding && !prevOnboardingRef.current) {
4968
+ chat.setSuggestedActions([]);
4969
+ }
4970
+ if (prevOnboardingRef.current && !isOnboarding) {
4971
+ chat.resetMessages();
4972
+ }
4973
+ prevOnboardingRef.current = isOnboarding;
4974
+ }, [isOnboarding]);
4765
4975
  useEffect(() => {
4766
4976
  if (!isLoadingStyles) {
4767
4977
  onReady?.();
@@ -5015,6 +5225,10 @@ function CrowWidget({
5015
5225
  useEffect(() => {
5016
5226
  const handleOpen = () => setIsCollapsed(false);
5017
5227
  const handleClose = () => setIsCollapsed(true);
5228
+ const handleSendMessage = (e) => {
5229
+ const text = e.detail?.text;
5230
+ if (text) handleSend(text);
5231
+ };
5018
5232
  const handleSetSuggestions = (e) => {
5019
5233
  const actions = e.detail;
5020
5234
  if (Array.isArray(actions)) {
@@ -5024,6 +5238,7 @@ function CrowWidget({
5024
5238
  };
5025
5239
  window.addEventListener("crow:open", handleOpen);
5026
5240
  window.addEventListener("crow:close", handleClose);
5241
+ window.addEventListener("crow:sendMessage", handleSendMessage);
5027
5242
  window.addEventListener("crow:setSuggestedActions", handleSetSuggestions);
5028
5243
  const pending = window.__crow_suggested_actions;
5029
5244
  if (Array.isArray(pending) && pending.length > 0) {
@@ -5033,6 +5248,7 @@ function CrowWidget({
5033
5248
  return () => {
5034
5249
  window.removeEventListener("crow:open", handleOpen);
5035
5250
  window.removeEventListener("crow:close", handleClose);
5251
+ window.removeEventListener("crow:sendMessage", handleSendMessage);
5036
5252
  window.removeEventListener("crow:setSuggestedActions", handleSetSuggestions);
5037
5253
  };
5038
5254
  }, []);
@@ -5040,7 +5256,59 @@ function CrowWidget({
5040
5256
  setIsCollapsed(!isCollapsed);
5041
5257
  };
5042
5258
  const renderWidgetContent = () => /* @__PURE__ */ jsxs(Fragment, { children: [
5043
- /* @__PURE__ */ jsx(
5259
+ isOnboarding ? /* @__PURE__ */ jsxs(
5260
+ "div",
5261
+ {
5262
+ style: {
5263
+ display: "flex",
5264
+ alignItems: "center",
5265
+ justifyContent: "space-between",
5266
+ padding: "10px 16px",
5267
+ borderBottom: "1px solid var(--crow-border, #e5e7eb)",
5268
+ flexShrink: 0,
5269
+ cursor: variant === "floating" ? "grab" : void 0
5270
+ },
5271
+ onPointerDown: variant === "floating" ? transform.onDragPointerDown : void 0,
5272
+ children: [
5273
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 13, fontWeight: 600, color: "var(--crow-text, #111827)" }, children: onboardingAgentName || agentName }),
5274
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
5275
+ /* @__PURE__ */ jsx(
5276
+ "button",
5277
+ {
5278
+ onClick: () => {
5279
+ setIsOnboarding(false);
5280
+ chat.resetMessages();
5281
+ },
5282
+ style: {
5283
+ fontSize: 12,
5284
+ color: "#9ca3af",
5285
+ background: "none",
5286
+ border: "none",
5287
+ cursor: "pointer",
5288
+ padding: "4px 8px"
5289
+ },
5290
+ children: "Skip"
5291
+ }
5292
+ ),
5293
+ variant === "floating" && /* @__PURE__ */ jsx(
5294
+ "button",
5295
+ {
5296
+ onClick: () => setIsCollapsed(true),
5297
+ style: {
5298
+ background: "none",
5299
+ border: "none",
5300
+ cursor: "pointer",
5301
+ padding: "4px",
5302
+ color: "#9ca3af",
5303
+ display: "flex"
5304
+ },
5305
+ children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M6 18L18 6M6 6l12 12" }) })
5306
+ }
5307
+ )
5308
+ ] })
5309
+ ]
5310
+ }
5311
+ ) : /* @__PURE__ */ jsx(
5044
5312
  WidgetHeader,
5045
5313
  {
5046
5314
  isVerifiedUser,
@@ -5056,82 +5324,92 @@ function CrowWidget({
5056
5324
  contextLabel
5057
5325
  }
5058
5326
  ),
5059
- /* @__PURE__ */ jsx(AnimatePresence, { children: showConversationList && isVerifiedUser && /* @__PURE__ */ jsx(
5060
- ConversationList,
5327
+ isOnboarding && onboardingPhase === "intro" && /* @__PURE__ */ jsx(
5328
+ OnboardingIntroInline,
5061
5329
  {
5062
- conversations: conversations.conversations,
5063
- currentConversationId: chat.conversationId,
5064
- onSelect: handleSelectConversation,
5065
- onClose: handleCloseConversationList
5330
+ lines: onboardingIntroSequence || [],
5331
+ primaryColor: styles.colors.primary,
5332
+ onComplete: () => setOnboardingPhase("chat")
5066
5333
  }
5067
- ) }),
5068
- /* @__PURE__ */ jsx(AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsx(
5069
- WorkflowPanel,
5070
- {
5071
- workflow: activeWorkflow,
5072
- onExit: handleExitWorkflow
5073
- }
5074
- ) }),
5075
- /* @__PURE__ */ jsx(AnimatePresence, { children: (chat.messages.length > 0 || conversations.isLoadingHistory || pendingConfirmation) && /* @__PURE__ */ jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
5076
- /* @__PURE__ */ jsx(
5077
- MessageList,
5334
+ ),
5335
+ !(isOnboarding && onboardingPhase === "intro") && /* @__PURE__ */ jsxs(Fragment, { children: [
5336
+ /* @__PURE__ */ jsx(AnimatePresence, { children: showConversationList && isVerifiedUser && /* @__PURE__ */ jsx(
5337
+ ConversationList,
5078
5338
  {
5079
- messages: chat.messages,
5080
- activeToolCalls: chat.activeToolCalls,
5081
- isLoadingHistory: conversations.isLoadingHistory,
5082
- isGenerating: chat.isLoading,
5083
- toolRenderers: effectiveToolRenderers,
5084
- onToolConsent: handleToolConsent
5339
+ conversations: conversations.conversations,
5340
+ currentConversationId: chat.conversationId,
5341
+ onSelect: handleSelectConversation,
5342
+ onClose: handleCloseConversationList
5085
5343
  }
5086
- ),
5087
- pendingConfirmation && /* @__PURE__ */ jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsx(
5088
- BrowserUseConfirmation,
5344
+ ) }),
5345
+ /* @__PURE__ */ jsx(AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsx(
5346
+ WorkflowPanel,
5089
5347
  {
5090
- instruction: pendingConfirmation.instruction,
5091
- onAllow: () => {
5092
- setIsBrowserUseActive(true);
5093
- pendingConfirmation.resolve(true);
5094
- setPendingConfirmation(null);
5095
- },
5096
- onDeny: () => {
5097
- pendingConfirmation.resolve(false);
5098
- setPendingConfirmation(null);
5099
- }
5348
+ workflow: activeWorkflow,
5349
+ onExit: handleExitWorkflow
5100
5350
  }
5101
- ) })
5102
- ] }) }),
5103
- /* @__PURE__ */ jsxs("div", { className: "crow-mt-auto crow-w-full", children: [
5104
- toolStatus && /* @__PURE__ */ 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: [
5105
- /* @__PURE__ */ 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: [
5106
- /* @__PURE__ */ jsx("circle", { className: "crow-opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
5107
- /* @__PURE__ */ jsx("path", { className: "crow-opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
5351
+ ) }),
5352
+ /* @__PURE__ */ jsx(AnimatePresence, { children: (chat.messages.length > 0 || conversations.isLoadingHistory || pendingConfirmation) && /* @__PURE__ */ jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
5353
+ /* @__PURE__ */ jsx(
5354
+ MessageList,
5355
+ {
5356
+ messages: chat.messages,
5357
+ activeToolCalls: chat.activeToolCalls,
5358
+ isLoadingHistory: conversations.isLoadingHistory,
5359
+ isGenerating: chat.isLoading,
5360
+ toolRenderers: effectiveToolRenderers,
5361
+ onToolConsent: handleToolConsent
5362
+ }
5363
+ ),
5364
+ pendingConfirmation && /* @__PURE__ */ jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsx(
5365
+ BrowserUseConfirmation,
5366
+ {
5367
+ instruction: pendingConfirmation.instruction,
5368
+ onAllow: () => {
5369
+ setIsBrowserUseActive(true);
5370
+ pendingConfirmation.resolve(true);
5371
+ setPendingConfirmation(null);
5372
+ },
5373
+ onDeny: () => {
5374
+ pendingConfirmation.resolve(false);
5375
+ setPendingConfirmation(null);
5376
+ }
5377
+ }
5378
+ ) })
5379
+ ] }) }),
5380
+ /* @__PURE__ */ jsxs("div", { className: "crow-mt-auto crow-w-full", children: [
5381
+ toolStatus && /* @__PURE__ */ 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: [
5382
+ /* @__PURE__ */ 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: [
5383
+ /* @__PURE__ */ jsx("circle", { className: "crow-opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
5384
+ /* @__PURE__ */ jsx("path", { className: "crow-opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
5385
+ ] }),
5386
+ /* @__PURE__ */ jsx("span", { className: "crow-font-medium crow-text-[var(--crow-text,#111827)]", children: toolStatus })
5108
5387
  ] }),
5109
- /* @__PURE__ */ jsx("span", { className: "crow-font-medium crow-text-[var(--crow-text,#111827)]", children: toolStatus })
5110
- ] }),
5111
- (chat.suggestedActions.length > 0 || !chat.isLoading && defaultSuggestedActionsRef.current.length > 0) && /* @__PURE__ */ jsx(
5112
- SuggestedActions,
5113
- {
5114
- actions: chat.suggestedActions.length > 0 ? chat.suggestedActions : defaultSuggestedActionsRef.current,
5115
- onActionClick: (action) => handleSend(action.message)
5116
- }
5117
- ),
5118
- /* @__PURE__ */ jsx(PoweredByBadge, { apiUrl }),
5119
- /* @__PURE__ */ jsx(
5120
- PromptInputBox,
5121
- {
5122
- onSend: handleSend,
5123
- onStop: handleStop,
5124
- placeholder: "Type your message...",
5125
- isLoading: chat.isLoading,
5126
- showStopButton: isBrowserUseActive || !!askUserResolver || !!pendingConfirmation,
5127
- highlighted: !!askUserResolver,
5128
- className: "crow-backdrop-blur-md",
5129
- backendUrl: apiUrl,
5130
- selectedModel: chat.selectedModel || selectedModelFromAPI,
5131
- onModelChange: chat.setSelectedModel,
5132
- availableModels: modelSelectionEnabled ? availableModelsFromAPI : []
5133
- }
5134
- )
5388
+ (chat.suggestedActions.length > 0 || !isOnboarding && !chat.isLoading && defaultSuggestedActionsRef.current.length > 0) && /* @__PURE__ */ jsx(
5389
+ SuggestedActions,
5390
+ {
5391
+ actions: chat.suggestedActions.length > 0 ? chat.suggestedActions : defaultSuggestedActionsRef.current,
5392
+ onActionClick: (action) => handleSend(action.message)
5393
+ }
5394
+ ),
5395
+ /* @__PURE__ */ jsx(PoweredByBadge, { apiUrl }),
5396
+ /* @__PURE__ */ jsx(
5397
+ PromptInputBox,
5398
+ {
5399
+ onSend: handleSend,
5400
+ onStop: handleStop,
5401
+ placeholder: "Type your message...",
5402
+ isLoading: chat.isLoading,
5403
+ showStopButton: isBrowserUseActive || !!askUserResolver || !!pendingConfirmation,
5404
+ highlighted: !!askUserResolver,
5405
+ className: "crow-backdrop-blur-md",
5406
+ backendUrl: apiUrl,
5407
+ selectedModel: chat.selectedModel || selectedModelFromAPI,
5408
+ onModelChange: chat.setSelectedModel,
5409
+ availableModels: modelSelectionEnabled ? availableModelsFromAPI : []
5410
+ }
5411
+ )
5412
+ ] })
5135
5413
  ] })
5136
5414
  ] });
5137
5415
  const combinedStyles = useMemo(
@@ -5145,7 +5423,7 @@ ${customCss}` : WIDGET_CSS,
5145
5423
  WidgetStyleProvider,
5146
5424
  {
5147
5425
  styles,
5148
- agentName,
5426
+ agentName: isOnboarding ? onboardingAgentName || agentName : agentName,
5149
5427
  isLoading: isLoadingStyles,
5150
5428
  variant,
5151
5429
  showThinking,
@@ -5442,6 +5720,78 @@ function CopilotContainer({
5442
5720
  )
5443
5721
  ] });
5444
5722
  }
5723
+ function OnboardingIntroInline2({
5724
+ lines,
5725
+ primaryColor,
5726
+ textColor,
5727
+ textMutedColor,
5728
+ onComplete
5729
+ }) {
5730
+ const [lineIndex, setLineIndex] = useState(0);
5731
+ const [charIndex, setCharIndex] = useState(0);
5732
+ const [done, setDone] = useState(false);
5733
+ useEffect(() => {
5734
+ if (lineIndex >= lines.length) {
5735
+ setDone(true);
5736
+ return;
5737
+ }
5738
+ const currentLine = lines[lineIndex];
5739
+ if (charIndex < currentLine.length) {
5740
+ const t = setTimeout(() => setCharIndex((c) => c + 1), 35);
5741
+ return () => clearTimeout(t);
5742
+ } else {
5743
+ const t = setTimeout(() => {
5744
+ setLineIndex((l) => l + 1);
5745
+ setCharIndex(0);
5746
+ }, 500);
5747
+ return () => clearTimeout(t);
5748
+ }
5749
+ }, [lineIndex, charIndex, lines]);
5750
+ const displayedLines = lines.slice(0, lineIndex + 1).map(
5751
+ (line, i) => i < lineIndex ? line : line.slice(0, charIndex)
5752
+ );
5753
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
5754
+ /* @__PURE__ */ jsx("div", { style: { minHeight: "4rem", marginBottom: "1.5rem" }, children: displayedLines.map((text, i) => /* @__PURE__ */ jsxs("p", { style: {
5755
+ fontSize: i === 0 ? 18 : 14,
5756
+ fontWeight: i === 0 ? 600 : 400,
5757
+ color: i === 0 ? textColor : textMutedColor,
5758
+ lineHeight: 1.4,
5759
+ margin: "0 0 6px 0"
5760
+ }, children: [
5761
+ text,
5762
+ i === lineIndex && !done && /* @__PURE__ */ jsx("span", { style: {
5763
+ display: "inline-block",
5764
+ width: 2,
5765
+ height: i === 0 ? 18 : 14,
5766
+ backgroundColor: textColor,
5767
+ marginLeft: 2,
5768
+ verticalAlign: "middle",
5769
+ animation: "crow-blink 1s step-end infinite"
5770
+ } })
5771
+ ] }, i)) }),
5772
+ /* @__PURE__ */ jsx(
5773
+ "button",
5774
+ {
5775
+ onClick: onComplete,
5776
+ style: {
5777
+ padding: "8px 24px",
5778
+ borderRadius: 8,
5779
+ backgroundColor: primaryColor,
5780
+ color: "#fff",
5781
+ fontSize: 13,
5782
+ fontWeight: 500,
5783
+ border: "none",
5784
+ cursor: "pointer",
5785
+ opacity: done ? 1 : 0,
5786
+ pointerEvents: done ? "auto" : "none",
5787
+ transition: "opacity 0.5s ease"
5788
+ },
5789
+ children: "Get Started \u2192"
5790
+ }
5791
+ ),
5792
+ /* @__PURE__ */ jsx("style", { children: `@keyframes crow-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }` })
5793
+ ] });
5794
+ }
5445
5795
  function CrowCopilot({
5446
5796
  productId,
5447
5797
  apiUrl = "",
@@ -5465,7 +5815,10 @@ function CrowCopilot({
5465
5815
  getIdentityToken,
5466
5816
  context,
5467
5817
  language,
5468
- contextLabel: contextLabelProp
5818
+ contextLabel: contextLabelProp,
5819
+ forceOnboarding = false,
5820
+ fullscreenTopOffset: _fullscreenTopOffset = 0,
5821
+ mode: _mode
5469
5822
  }) {
5470
5823
  const effectiveGetIdentityToken = getIdentityToken || window.__crow_identity_token_fetcher;
5471
5824
  const effectiveOnToolResult = onToolResult || window.__crow_on_tool_result;
@@ -5483,7 +5836,11 @@ function CrowCopilot({
5483
5836
  toolConsentSettings,
5484
5837
  modelSelectionEnabled,
5485
5838
  availableModels: availableModelsFromAPI,
5486
- initialSuggestions
5839
+ initialSuggestions,
5840
+ onboardingEnabled,
5841
+ onboardingAgentName,
5842
+ onboardingWelcomeMessage,
5843
+ onboardingIntroSequence
5487
5844
  } = useCopilotStyles({
5488
5845
  productId,
5489
5846
  apiUrl,
@@ -5492,6 +5849,20 @@ function CrowCopilot({
5492
5849
  language
5493
5850
  });
5494
5851
  const agentName = agentNameProp ?? agentNameFromAPI ?? title;
5852
+ const [isOnboarding, setIsOnboarding] = useState(false);
5853
+ const [onboardingChecked, setOnboardingChecked] = useState(false);
5854
+ const [onboardingPhase, setOnboardingPhase] = useState("intro");
5855
+ useEffect(() => {
5856
+ if (forceOnboarding && !isLoadingStyles && onboardingEnabled && !onboardingChecked) {
5857
+ setIsOnboarding(true);
5858
+ setOnboardingChecked(true);
5859
+ }
5860
+ }, [forceOnboarding, isLoadingStyles, onboardingEnabled, onboardingChecked]);
5861
+ useEffect(() => {
5862
+ if (isOnboarding && !isLoadingStyles && onboardingIntroSequence !== void 0 && onboardingIntroSequence.length === 0) {
5863
+ setOnboardingPhase("chat");
5864
+ }
5865
+ }, [isOnboarding, isLoadingStyles, onboardingIntroSequence]);
5495
5866
  const [toolStatus, setToolStatus] = useState(
5496
5867
  () => window.__crow_tool_status ?? ""
5497
5868
  );
@@ -5644,6 +6015,10 @@ function CrowCopilot({
5644
6015
  useEffect(() => {
5645
6016
  const handleOpen = () => setIsCollapsed(false);
5646
6017
  const handleClose = () => setIsCollapsed(true);
6018
+ const handleSendMessage = (e) => {
6019
+ const text = e.detail?.text;
6020
+ if (text) handleSend(text);
6021
+ };
5647
6022
  const handleSetSuggestions = (e) => {
5648
6023
  const actions = e.detail;
5649
6024
  if (Array.isArray(actions)) {
@@ -5653,6 +6028,7 @@ function CrowCopilot({
5653
6028
  };
5654
6029
  window.addEventListener("crow:open", handleOpen);
5655
6030
  window.addEventListener("crow:close", handleClose);
6031
+ window.addEventListener("crow:sendMessage", handleSendMessage);
5656
6032
  window.addEventListener("crow:setSuggestedActions", handleSetSuggestions);
5657
6033
  const pending = window.__crow_suggested_actions;
5658
6034
  if (Array.isArray(pending) && pending.length > 0) {
@@ -5662,14 +6038,15 @@ function CrowCopilot({
5662
6038
  return () => {
5663
6039
  window.removeEventListener("crow:open", handleOpen);
5664
6040
  window.removeEventListener("crow:close", handleClose);
6041
+ window.removeEventListener("crow:sendMessage", handleSendMessage);
5665
6042
  window.removeEventListener("crow:setSuggestedActions", handleSetSuggestions);
5666
6043
  };
5667
6044
  }, []);
5668
6045
  useEffect(() => {
5669
- if (initialSuggestions.length > 0 && chat.suggestedActions.length === 0) {
6046
+ if (!isOnboarding && initialSuggestions.length > 0 && chat.suggestedActions.length === 0) {
5670
6047
  chat.setSuggestedActions(initialSuggestions);
5671
6048
  }
5672
- }, [initialSuggestions]);
6049
+ }, [initialSuggestions, isOnboarding]);
5673
6050
  const messagesContainerRef = useRef(null);
5674
6051
  const tabsScrollRef = useRef(null);
5675
6052
  const executeClientToolRef = useRef(null);
@@ -5699,11 +6076,17 @@ function CrowCopilot({
5699
6076
  pendingRestoreConvId.current = "";
5700
6077
  }
5701
6078
  }
6079
+ const effectiveWelcomeMessage = isOnboarding ? onboardingWelcomeMessage || `Hi! I'm ${onboardingAgentName || agentName}. Let me help you get started.` : welcomeMessage;
5702
6080
  const chat = useChat({
5703
6081
  productId,
5704
6082
  apiUrl,
5705
6083
  persistAnonymousConversations,
5706
- welcomeMessage,
6084
+ welcomeMessage: effectiveWelcomeMessage,
6085
+ agentMode: isOnboarding ? "onboarding" : void 0,
6086
+ onOnboardingComplete: (summary) => {
6087
+ console.log("[Crow] Onboarding complete:", summary);
6088
+ setIsOnboarding(false);
6089
+ },
5707
6090
  selectedModel,
5708
6091
  subdomain,
5709
6092
  toolConsentSettings,
@@ -5847,6 +6230,33 @@ function CrowCopilot({
5847
6230
  const { executeClientTool } = useCrowAPI({
5848
6231
  onIdentified: async () => {
5849
6232
  setIsVerifiedUser(true);
6233
+ if (forceOnboarding) {
6234
+ setIsOnboarding(true);
6235
+ setOnboardingChecked(true);
6236
+ } else if (onboardingEnabled && !onboardingChecked) {
6237
+ try {
6238
+ const identityToken = window.__crow_identity_token;
6239
+ if (identityToken) {
6240
+ const res = await fetch(`${apiUrl}/api/chat/resolve-agent`, {
6241
+ method: "POST",
6242
+ headers: { "Content-Type": "application/json" },
6243
+ body: JSON.stringify({
6244
+ product_id: productId,
6245
+ identity_token: identityToken
6246
+ })
6247
+ });
6248
+ if (res.ok) {
6249
+ const data = await res.json();
6250
+ if (data.agent === "onboarding") {
6251
+ setIsOnboarding(true);
6252
+ }
6253
+ }
6254
+ }
6255
+ } catch (e) {
6256
+ console.error("[Crow] resolve-agent failed:", e);
6257
+ }
6258
+ setOnboardingChecked(true);
6259
+ }
5850
6260
  await conversations.loadConversations();
5851
6261
  const savedId = pendingRestoreConvId.current;
5852
6262
  if (savedId && !hasRestoredActiveConvRef.current) {
@@ -5869,6 +6279,16 @@ function CrowCopilot({
5869
6279
  });
5870
6280
  executeClientToolRef.current = executeClientTool;
5871
6281
  submitToolResultRef.current = chat.submitToolResult;
6282
+ const prevOnboardingRef = useRef(isOnboarding);
6283
+ useEffect(() => {
6284
+ if (isOnboarding && !prevOnboardingRef.current) {
6285
+ chat.setSuggestedActions([]);
6286
+ }
6287
+ if (prevOnboardingRef.current && !isOnboarding) {
6288
+ chat.resetMessages();
6289
+ }
6290
+ prevOnboardingRef.current = isOnboarding;
6291
+ }, [isOnboarding]);
5872
6292
  const handleBrowserConfirmation = useCallback(
5873
6293
  (instruction) => {
5874
6294
  return new Promise((resolve) => {
@@ -6209,312 +6629,347 @@ function CrowCopilot({
6209
6629
  "--crow-bg-active": styles.colors.text + "18"
6210
6630
  },
6211
6631
  children: [
6212
- /* @__PURE__ */ jsxs(
6213
- "div",
6214
- {
6215
- className: "crow-flex crow-items-stretch crow-border-b crow-min-h-[40px]",
6216
- style: { borderColor: styles.colors.border },
6217
- children: [
6218
- /* @__PURE__ */ jsx(
6219
- "div",
6220
- {
6221
- ref: tabsScrollRef,
6222
- className: "crow-flex crow-items-stretch crow-flex-1 crow-min-w-0 crow-overflow-x-auto",
6223
- style: {
6224
- scrollbarWidth: "none",
6225
- msOverflowStyle: "none"
6226
- },
6227
- onScroll: handleTabsScroll,
6228
- children: tabs.map((tab, idx) => {
6229
- const isActive = activeTabId === tab.id;
6230
- const isHovered = hoveredTabId === tab.id;
6231
- const isCloseable = tab.type !== "new" && (tab.type !== "local" || localTabs.length > 1);
6232
- return /* @__PURE__ */ jsxs(
6233
- "div",
6234
- {
6235
- 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",
6236
- style: {
6237
- color: isActive ? styles.colors.text : styles.colors.text + "80",
6238
- fontWeight: isActive ? 500 : void 0,
6239
- maxWidth: "180px",
6240
- borderRight: idx < tabs.length - 1 ? `1px solid ${styles.colors.border}` : "none",
6241
- paddingLeft: "16px",
6242
- paddingRight: isCloseable ? "8px" : "16px"
6243
- },
6244
- title: tab.name,
6245
- onMouseEnter: () => setHoveredTabId(tab.id),
6246
- onMouseLeave: () => setHoveredTabId(null),
6247
- onClick: () => {
6248
- if (tab.type === "new") {
6249
- handleNewChat();
6250
- return;
6251
- }
6252
- if (tab.type === "server") {
6253
- handleSelectConversation(tab.id);
6254
- return;
6255
- }
6256
- handleSelectLocalTab(tab.id);
6257
- },
6258
- children: [
6259
- /* @__PURE__ */ jsx(
6260
- "span",
6261
- {
6262
- className: "crow-block crow-truncate",
6263
- style: { maxWidth: isCloseable ? "112px" : "128px" },
6264
- children: tab.name
6265
- }
6266
- ),
6267
- isCloseable && /* @__PURE__ */ jsx(
6268
- "span",
6269
- {
6270
- className: "crow-rounded crow-p-0.5 crow-flex-shrink-0 crow-inline-flex crow-items-center crow-justify-center crow-transition-opacity",
6271
- style: {
6272
- marginLeft: "6px",
6273
- opacity: isHovered ? 1 : 0,
6274
- pointerEvents: isHovered ? "auto" : "none"
6275
- },
6276
- onClick: (e) => {
6277
- e.stopPropagation();
6278
- handleCloseTab(tab.id, tab.type);
6279
- },
6280
- role: "button",
6281
- "aria-label": `Close ${tab.name}`,
6282
- children: /* @__PURE__ */ jsx(TabCloseIcon, { className: "crow-w-3 crow-h-3", style: { color: styles.colors.text + "80" } })
6283
- }
6284
- ),
6285
- isActive && /* @__PURE__ */ jsx(
6286
- "span",
6287
- {
6288
- className: "crow-absolute crow-bottom-0 crow-left-0 crow-right-0",
6289
- style: {
6290
- height: "2px",
6291
- background: styles.colors.primary || "#2563eb"
6292
- }
6293
- }
6294
- )
6295
- ]
6296
- },
6297
- `${tab.id}-${idx}`
6298
- );
6299
- })
6300
- }
6301
- ),
6302
- /* @__PURE__ */ jsxs(
6303
- "div",
6304
- {
6305
- className: "crow-flex crow-items-center crow-flex-shrink-0 crow-border-l",
6306
- style: { borderColor: styles.colors.border },
6307
- children: [
6308
- /* @__PURE__ */ jsx(
6309
- "button",
6310
- {
6311
- onClick: handleNewChat,
6312
- className: "crow-p-2 crow-transition-colors crow-rounded",
6313
- style: { color: styles.colors.text + "80" },
6314
- onMouseEnter: (e) => {
6315
- e.currentTarget.style.background = styles.colors.text + "10";
6316
- },
6317
- onMouseLeave: (e) => {
6318
- e.currentTarget.style.background = "transparent";
6319
- },
6320
- "aria-label": "New Chat",
6321
- title: "New Chat",
6322
- children: /* @__PURE__ */ jsx(PlusIcon, { className: "crow-w-4 crow-h-4" })
6323
- }
6324
- ),
6325
- /* @__PURE__ */ jsx(
6326
- "button",
6327
- {
6328
- onClick: handleToggleHistory,
6329
- disabled: !isVerifiedUser,
6330
- "aria-disabled": !isVerifiedUser,
6331
- className: `crow-p-2 crow-transition-colors crow-rounded ${!isVerifiedUser ? "crow-opacity-40 crow-cursor-not-allowed" : ""}`,
6332
- style: {
6333
- color: styles.colors.text + "80",
6334
- background: showConversationList ? styles.colors.text + "10" : "transparent"
6335
- },
6336
- onMouseEnter: (e) => {
6337
- if (isVerifiedUser) e.currentTarget.style.background = styles.colors.text + "10";
6338
- },
6339
- onMouseLeave: (e) => {
6340
- if (!showConversationList) e.currentTarget.style.background = "transparent";
6341
- },
6342
- "aria-label": "Conversation History",
6343
- title: isVerifiedUser ? "Conversation History" : "Sign in to view history",
6344
- children: /* @__PURE__ */ jsx(HistoryIcon, { className: "crow-w-4 crow-h-4" })
6345
- }
6346
- ),
6347
- canScrollRight && /* @__PURE__ */ jsx(
6348
- "button",
6349
- {
6350
- onClick: handleScrollRight,
6351
- className: "crow-p-2 crow-transition-colors crow-rounded",
6352
- style: { color: styles.colors.text + "80" },
6353
- onMouseEnter: (e) => {
6354
- e.currentTarget.style.background = styles.colors.text + "10";
6355
- },
6356
- onMouseLeave: (e) => {
6357
- e.currentTarget.style.background = "transparent";
6358
- },
6359
- "aria-label": "Scroll tabs",
6360
- title: "Scroll tabs",
6361
- children: /* @__PURE__ */ jsx(ChevronRightIcon, { className: "crow-w-4 crow-h-4" })
6362
- }
6363
- ),
6364
- (forceShowClose ?? showClose) && (overrideOnClose ?? onClose) && /* @__PURE__ */ jsx(
6365
- "button",
6366
- {
6367
- onClick: overrideOnClose ?? onClose,
6368
- className: "crow-p-2 crow-transition-colors crow-rounded",
6369
- style: { color: styles.colors.text + "80" },
6370
- onMouseEnter: (e) => {
6371
- e.currentTarget.style.background = styles.colors.text + "10";
6372
- },
6373
- onMouseLeave: (e) => {
6374
- e.currentTarget.style.background = "transparent";
6375
- },
6376
- "aria-label": "Close",
6377
- children: /* @__PURE__ */ jsx(CloseIcon, { className: "crow-w-4 crow-h-4" })
6378
- }
6379
- )
6380
- ]
6381
- }
6382
- )
6383
- ]
6384
- }
6385
- ),
6386
- contextLabel && /* @__PURE__ */ jsxs(
6387
- "div",
6388
- {
6389
- className: "crow-flex crow-items-center crow-gap-1.5 crow-px-3 crow-py-1.5 crow-border-b crow-text-xs",
6390
- style: {
6391
- color: styles.colors.text + "80",
6392
- borderColor: styles.colors.border
6393
- },
6394
- children: [
6395
- /* @__PURE__ */ jsxs(
6396
- "svg",
6397
- {
6398
- xmlns: "http://www.w3.org/2000/svg",
6399
- width: "12",
6400
- height: "12",
6401
- viewBox: "0 0 24 24",
6402
- fill: "none",
6403
- stroke: "currentColor",
6404
- strokeWidth: "2",
6405
- strokeLinecap: "round",
6406
- strokeLinejoin: "round",
6407
- className: "crow-shrink-0",
6408
- children: [
6409
- /* @__PURE__ */ jsx("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }),
6410
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "10", r: "3" })
6411
- ]
6412
- }
6413
- ),
6414
- /* @__PURE__ */ jsx("span", { className: "crow-truncate", children: contextLabel })
6415
- ]
6416
- }
6417
- ),
6418
- /* @__PURE__ */ jsxs(AnimatePresence, { children: [
6419
- showConversationList && isVerifiedUser && /* @__PURE__ */ jsx(
6420
- ConversationList,
6632
+ isOnboarding && /* @__PURE__ */ jsxs(Fragment, { children: [
6633
+ /* @__PURE__ */ jsxs(
6634
+ "div",
6421
6635
  {
6422
- conversations: conversations.conversations,
6423
- currentConversationId: chat.conversationId,
6424
- onSelect: handleSelectConversation,
6425
- onClose: handleCloseConversationList
6636
+ className: "crow-flex crow-items-center crow-justify-between crow-border-b crow-px-4 crow-py-2.5",
6637
+ style: { borderColor: styles.colors.border },
6638
+ children: [
6639
+ /* @__PURE__ */ jsx("span", { className: "crow-text-[13px] crow-font-semibold", style: { color: styles.colors.text }, children: onboardingAgentName || agentName }),
6640
+ /* @__PURE__ */ jsx(
6641
+ "button",
6642
+ {
6643
+ onClick: () => {
6644
+ setIsOnboarding(false);
6645
+ },
6646
+ className: "crow-text-xs crow-border-none crow-bg-transparent crow-cursor-pointer crow-px-2 crow-py-1",
6647
+ style: { color: styles.colors.text + "60" },
6648
+ children: "Skip"
6649
+ }
6650
+ )
6651
+ ]
6426
6652
  }
6427
6653
  ),
6428
- showConversationList && !isVerifiedUser && /* @__PURE__ */ jsx(
6429
- "div",
6654
+ onboardingPhase === "intro" && /* @__PURE__ */ 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__ */ jsx(
6655
+ OnboardingIntroInline2,
6430
6656
  {
6431
- className: "crow-mb-3 crow-rounded-xl crow-border crow-p-4",
6432
- style: { background: styles.colors.text + "08", borderColor: styles.colors.border },
6433
- children: /* @__PURE__ */ jsx("div", { className: "crow-text-sm", style: { color: styles.colors.text + "99" }, children: "Sign in to view conversation history." })
6657
+ lines: onboardingIntroSequence || [],
6658
+ primaryColor: styles.colors.primary,
6659
+ textColor: styles.colors.text,
6660
+ textMutedColor: styles.colors.text + "80",
6661
+ onComplete: () => setOnboardingPhase("chat")
6434
6662
  }
6435
- )
6663
+ ) })
6436
6664
  ] }),
6437
- /* @__PURE__ */ jsx(AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsx(
6438
- WorkflowPanel,
6439
- {
6440
- workflow: activeWorkflow,
6441
- onExit: handleExitWorkflow
6442
- }
6443
- ) }),
6444
- /* @__PURE__ */ jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
6445
- /* @__PURE__ */ jsx(
6446
- MessageList,
6665
+ !(isOnboarding && onboardingPhase === "intro") && /* @__PURE__ */ jsxs(Fragment, { children: [
6666
+ !isOnboarding && /* @__PURE__ */ jsxs(
6667
+ "div",
6447
6668
  {
6448
- messages: chat.messages,
6449
- activeToolCalls: chat.activeToolCalls,
6450
- isLoadingHistory: conversations.isLoadingHistory,
6451
- isGenerating: chat.isLoading,
6452
- toolRenderers: effectiveToolRenderers,
6453
- onToolConsent: handleToolConsent
6669
+ className: "crow-flex crow-items-stretch crow-border-b crow-min-h-[40px]",
6670
+ style: { borderColor: styles.colors.border },
6671
+ children: [
6672
+ /* @__PURE__ */ jsx(
6673
+ "div",
6674
+ {
6675
+ ref: tabsScrollRef,
6676
+ className: "crow-flex crow-items-stretch crow-flex-1 crow-min-w-0 crow-overflow-x-auto",
6677
+ style: {
6678
+ scrollbarWidth: "none",
6679
+ msOverflowStyle: "none"
6680
+ },
6681
+ onScroll: handleTabsScroll,
6682
+ children: tabs.map((tab, idx) => {
6683
+ const isActive = activeTabId === tab.id;
6684
+ const isHovered = hoveredTabId === tab.id;
6685
+ const isCloseable = tab.type !== "new" && (tab.type !== "local" || localTabs.length > 1);
6686
+ return /* @__PURE__ */ jsxs(
6687
+ "div",
6688
+ {
6689
+ 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",
6690
+ style: {
6691
+ color: isActive ? styles.colors.text : styles.colors.text + "80",
6692
+ fontWeight: isActive ? 500 : void 0,
6693
+ maxWidth: "180px",
6694
+ borderRight: idx < tabs.length - 1 ? `1px solid ${styles.colors.border}` : "none",
6695
+ paddingLeft: "16px",
6696
+ paddingRight: isCloseable ? "8px" : "16px"
6697
+ },
6698
+ title: tab.name,
6699
+ onMouseEnter: () => setHoveredTabId(tab.id),
6700
+ onMouseLeave: () => setHoveredTabId(null),
6701
+ onClick: () => {
6702
+ if (tab.type === "new") {
6703
+ handleNewChat();
6704
+ return;
6705
+ }
6706
+ if (tab.type === "server") {
6707
+ handleSelectConversation(tab.id);
6708
+ return;
6709
+ }
6710
+ handleSelectLocalTab(tab.id);
6711
+ },
6712
+ children: [
6713
+ /* @__PURE__ */ jsx(
6714
+ "span",
6715
+ {
6716
+ className: "crow-block crow-truncate",
6717
+ style: { maxWidth: isCloseable ? "112px" : "128px" },
6718
+ children: tab.name
6719
+ }
6720
+ ),
6721
+ isCloseable && /* @__PURE__ */ jsx(
6722
+ "span",
6723
+ {
6724
+ className: "crow-rounded crow-p-0.5 crow-flex-shrink-0 crow-inline-flex crow-items-center crow-justify-center crow-transition-opacity",
6725
+ style: {
6726
+ marginLeft: "6px",
6727
+ opacity: isHovered ? 1 : 0,
6728
+ pointerEvents: isHovered ? "auto" : "none"
6729
+ },
6730
+ onClick: (e) => {
6731
+ e.stopPropagation();
6732
+ handleCloseTab(tab.id, tab.type);
6733
+ },
6734
+ role: "button",
6735
+ "aria-label": `Close ${tab.name}`,
6736
+ children: /* @__PURE__ */ jsx(TabCloseIcon, { className: "crow-w-3 crow-h-3", style: { color: styles.colors.text + "80" } })
6737
+ }
6738
+ ),
6739
+ isActive && /* @__PURE__ */ jsx(
6740
+ "span",
6741
+ {
6742
+ className: "crow-absolute crow-bottom-0 crow-left-0 crow-right-0",
6743
+ style: {
6744
+ height: "2px",
6745
+ background: styles.colors.primary || "#2563eb"
6746
+ }
6747
+ }
6748
+ )
6749
+ ]
6750
+ },
6751
+ `${tab.id}-${idx}`
6752
+ );
6753
+ })
6754
+ }
6755
+ ),
6756
+ /* @__PURE__ */ jsxs(
6757
+ "div",
6758
+ {
6759
+ className: "crow-flex crow-items-center crow-flex-shrink-0 crow-border-l",
6760
+ style: { borderColor: styles.colors.border },
6761
+ children: [
6762
+ /* @__PURE__ */ jsx(
6763
+ "button",
6764
+ {
6765
+ onClick: handleNewChat,
6766
+ className: "crow-p-2 crow-transition-colors crow-rounded",
6767
+ style: { color: styles.colors.text + "80" },
6768
+ onMouseEnter: (e) => {
6769
+ e.currentTarget.style.background = styles.colors.text + "10";
6770
+ },
6771
+ onMouseLeave: (e) => {
6772
+ e.currentTarget.style.background = "transparent";
6773
+ },
6774
+ "aria-label": "New Chat",
6775
+ title: "New Chat",
6776
+ children: /* @__PURE__ */ jsx(PlusIcon, { className: "crow-w-4 crow-h-4" })
6777
+ }
6778
+ ),
6779
+ /* @__PURE__ */ jsx(
6780
+ "button",
6781
+ {
6782
+ onClick: handleToggleHistory,
6783
+ disabled: !isVerifiedUser,
6784
+ "aria-disabled": !isVerifiedUser,
6785
+ className: `crow-p-2 crow-transition-colors crow-rounded ${!isVerifiedUser ? "crow-opacity-40 crow-cursor-not-allowed" : ""}`,
6786
+ style: {
6787
+ color: styles.colors.text + "80",
6788
+ background: showConversationList ? styles.colors.text + "10" : "transparent"
6789
+ },
6790
+ onMouseEnter: (e) => {
6791
+ if (isVerifiedUser) e.currentTarget.style.background = styles.colors.text + "10";
6792
+ },
6793
+ onMouseLeave: (e) => {
6794
+ if (!showConversationList) e.currentTarget.style.background = "transparent";
6795
+ },
6796
+ "aria-label": "Conversation History",
6797
+ title: isVerifiedUser ? "Conversation History" : "Sign in to view history",
6798
+ children: /* @__PURE__ */ jsx(HistoryIcon, { className: "crow-w-4 crow-h-4" })
6799
+ }
6800
+ ),
6801
+ canScrollRight && /* @__PURE__ */ jsx(
6802
+ "button",
6803
+ {
6804
+ onClick: handleScrollRight,
6805
+ className: "crow-p-2 crow-transition-colors crow-rounded",
6806
+ style: { color: styles.colors.text + "80" },
6807
+ onMouseEnter: (e) => {
6808
+ e.currentTarget.style.background = styles.colors.text + "10";
6809
+ },
6810
+ onMouseLeave: (e) => {
6811
+ e.currentTarget.style.background = "transparent";
6812
+ },
6813
+ "aria-label": "Scroll tabs",
6814
+ title: "Scroll tabs",
6815
+ children: /* @__PURE__ */ jsx(ChevronRightIcon, { className: "crow-w-4 crow-h-4" })
6816
+ }
6817
+ ),
6818
+ (forceShowClose ?? showClose) && (overrideOnClose ?? onClose) && /* @__PURE__ */ jsx(
6819
+ "button",
6820
+ {
6821
+ onClick: overrideOnClose ?? onClose,
6822
+ className: "crow-p-2 crow-transition-colors crow-rounded",
6823
+ style: { color: styles.colors.text + "80" },
6824
+ onMouseEnter: (e) => {
6825
+ e.currentTarget.style.background = styles.colors.text + "10";
6826
+ },
6827
+ onMouseLeave: (e) => {
6828
+ e.currentTarget.style.background = "transparent";
6829
+ },
6830
+ "aria-label": "Close",
6831
+ children: /* @__PURE__ */ jsx(CloseIcon, { className: "crow-w-4 crow-h-4" })
6832
+ }
6833
+ )
6834
+ ]
6835
+ }
6836
+ )
6837
+ ]
6454
6838
  }
6455
6839
  ),
6456
- pendingConfirmation && /* @__PURE__ */ jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsx(
6457
- BrowserUseConfirmation,
6840
+ contextLabel && /* @__PURE__ */ jsxs(
6841
+ "div",
6458
6842
  {
6459
- instruction: pendingConfirmation.instruction,
6460
- onAllow: () => {
6461
- pendingConfirmation.resolve(true);
6462
- setPendingConfirmation(null);
6843
+ className: "crow-flex crow-items-center crow-gap-1.5 crow-px-3 crow-py-1.5 crow-border-b crow-text-xs",
6844
+ style: {
6845
+ color: styles.colors.text + "80",
6846
+ borderColor: styles.colors.border
6463
6847
  },
6464
- onDeny: () => {
6465
- pendingConfirmation.resolve(false);
6466
- setPendingConfirmation(null);
6848
+ children: [
6849
+ /* @__PURE__ */ jsxs(
6850
+ "svg",
6851
+ {
6852
+ xmlns: "http://www.w3.org/2000/svg",
6853
+ width: "12",
6854
+ height: "12",
6855
+ viewBox: "0 0 24 24",
6856
+ fill: "none",
6857
+ stroke: "currentColor",
6858
+ strokeWidth: "2",
6859
+ strokeLinecap: "round",
6860
+ strokeLinejoin: "round",
6861
+ className: "crow-shrink-0",
6862
+ children: [
6863
+ /* @__PURE__ */ jsx("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }),
6864
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "10", r: "3" })
6865
+ ]
6866
+ }
6867
+ ),
6868
+ /* @__PURE__ */ jsx("span", { className: "crow-truncate", children: contextLabel })
6869
+ ]
6870
+ }
6871
+ ),
6872
+ /* @__PURE__ */ jsxs(AnimatePresence, { children: [
6873
+ showConversationList && isVerifiedUser && /* @__PURE__ */ jsx(
6874
+ ConversationList,
6875
+ {
6876
+ conversations: conversations.conversations,
6877
+ currentConversationId: chat.conversationId,
6878
+ onSelect: handleSelectConversation,
6879
+ onClose: handleCloseConversationList
6467
6880
  }
6881
+ ),
6882
+ showConversationList && !isVerifiedUser && /* @__PURE__ */ jsx(
6883
+ "div",
6884
+ {
6885
+ className: "crow-mb-3 crow-rounded-xl crow-border crow-p-4",
6886
+ style: { background: styles.colors.text + "08", borderColor: styles.colors.border },
6887
+ children: /* @__PURE__ */ jsx("div", { className: "crow-text-sm", style: { color: styles.colors.text + "99" }, children: "Sign in to view conversation history." })
6888
+ }
6889
+ )
6890
+ ] }),
6891
+ /* @__PURE__ */ jsx(AnimatePresence, { children: activeWorkflow && /* @__PURE__ */ jsx(
6892
+ WorkflowPanel,
6893
+ {
6894
+ workflow: activeWorkflow,
6895
+ onExit: handleExitWorkflow
6468
6896
  }
6469
6897
  ) }),
6470
- askUserResolver && browserQuestion && /* @__PURE__ */ jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsx(
6471
- BrowserUseQuestion,
6472
- {
6473
- question: browserQuestion,
6474
- onSubmit: (answer) => {
6475
- askUserResolver.resolve(answer);
6476
- setAskUserResolver(null);
6477
- setBrowserQuestion(null);
6898
+ /* @__PURE__ */ jsxs(MessagesContainer, { ref: messagesContainerRef, children: [
6899
+ /* @__PURE__ */ jsx(
6900
+ MessageList,
6901
+ {
6902
+ messages: chat.messages,
6903
+ activeToolCalls: chat.activeToolCalls,
6904
+ isLoadingHistory: conversations.isLoadingHistory,
6905
+ isGenerating: chat.isLoading,
6906
+ toolRenderers: effectiveToolRenderers,
6907
+ onToolConsent: handleToolConsent
6478
6908
  }
6479
- }
6480
- ) })
6481
- ] }),
6482
- /* @__PURE__ */ jsxs(
6483
- "div",
6484
- {
6485
- className: "crow-p-3 crow-border-t",
6486
- style: { borderColor: styles.colors.border },
6487
- children: [
6488
- toolStatus && /* @__PURE__ */ 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: [
6489
- /* @__PURE__ */ 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: [
6490
- /* @__PURE__ */ jsx("circle", { className: "crow-opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
6491
- /* @__PURE__ */ jsx("path", { className: "crow-opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
6492
- ] }),
6493
- /* @__PURE__ */ jsx("span", { className: "crow-font-medium crow-text-[var(--crow-text,#111827)]", children: toolStatus })
6494
- ] }),
6495
- (chat.suggestedActions.length > 0 || !chat.isLoading && defaultSuggestedActionsRef.current.length > 0) && /* @__PURE__ */ jsx(
6496
- SuggestedActions,
6497
- {
6498
- actions: chat.suggestedActions.length > 0 ? chat.suggestedActions : defaultSuggestedActionsRef.current,
6499
- onActionClick: (action) => handleSend(action.message)
6909
+ ),
6910
+ pendingConfirmation && /* @__PURE__ */ jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsx(
6911
+ BrowserUseConfirmation,
6912
+ {
6913
+ instruction: pendingConfirmation.instruction,
6914
+ onAllow: () => {
6915
+ pendingConfirmation.resolve(true);
6916
+ setPendingConfirmation(null);
6917
+ },
6918
+ onDeny: () => {
6919
+ pendingConfirmation.resolve(false);
6920
+ setPendingConfirmation(null);
6500
6921
  }
6501
- ),
6502
- styles.branding.showPoweredBy && /* @__PURE__ */ jsx(PoweredByBadge, { apiUrl }),
6503
- /* @__PURE__ */ jsx(
6504
- PromptInputBox,
6505
- {
6506
- onSend: handleSend,
6507
- onStop: handleStop,
6508
- placeholder: "Ask anything...",
6509
- isLoading: chat.isLoading,
6510
- selectedModel: chat.selectedModel || selectedModel,
6511
- onModelChange: chat.setSelectedModel,
6512
- availableModels: modelSelectionEnabled ? availableModelsFromAPI : []
6922
+ }
6923
+ ) }),
6924
+ askUserResolver && browserQuestion && /* @__PURE__ */ jsx("div", { className: "crow-px-4 crow-py-2", children: /* @__PURE__ */ jsx(
6925
+ BrowserUseQuestion,
6926
+ {
6927
+ question: browserQuestion,
6928
+ onSubmit: (answer) => {
6929
+ askUserResolver.resolve(answer);
6930
+ setAskUserResolver(null);
6931
+ setBrowserQuestion(null);
6513
6932
  }
6514
- )
6515
- ]
6516
- }
6517
- )
6933
+ }
6934
+ ) })
6935
+ ] }),
6936
+ /* @__PURE__ */ jsxs(
6937
+ "div",
6938
+ {
6939
+ className: "crow-p-3 crow-border-t",
6940
+ style: { borderColor: styles.colors.border },
6941
+ children: [
6942
+ toolStatus && /* @__PURE__ */ 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: [
6943
+ /* @__PURE__ */ 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: [
6944
+ /* @__PURE__ */ jsx("circle", { className: "crow-opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
6945
+ /* @__PURE__ */ jsx("path", { className: "crow-opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
6946
+ ] }),
6947
+ /* @__PURE__ */ jsx("span", { className: "crow-font-medium crow-text-[var(--crow-text,#111827)]", children: toolStatus })
6948
+ ] }),
6949
+ (chat.suggestedActions.length > 0 || !isOnboarding && !chat.isLoading && defaultSuggestedActionsRef.current.length > 0) && /* @__PURE__ */ jsx(
6950
+ SuggestedActions,
6951
+ {
6952
+ actions: chat.suggestedActions.length > 0 ? chat.suggestedActions : defaultSuggestedActionsRef.current,
6953
+ onActionClick: (action) => handleSend(action.message)
6954
+ }
6955
+ ),
6956
+ styles.branding.showPoweredBy && /* @__PURE__ */ jsx(PoweredByBadge, { apiUrl }),
6957
+ /* @__PURE__ */ jsx(
6958
+ PromptInputBox,
6959
+ {
6960
+ onSend: handleSend,
6961
+ onStop: handleStop,
6962
+ placeholder: "Ask anything...",
6963
+ isLoading: chat.isLoading,
6964
+ selectedModel: chat.selectedModel || selectedModel,
6965
+ onModelChange: chat.setSelectedModel,
6966
+ availableModels: modelSelectionEnabled ? availableModelsFromAPI : []
6967
+ }
6968
+ )
6969
+ ]
6970
+ }
6971
+ )
6972
+ ] })
6518
6973
  ]
6519
6974
  }
6520
6975
  )
@@ -6536,7 +6991,7 @@ function CrowCopilot({
6536
6991
  const edgeSide = isRight ? "left" : "right";
6537
6992
  const toggleIconColor = styles.colors.text + "80";
6538
6993
  const toggleIcon = isCollapsed ? /* @__PURE__ */ 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__ */ jsx("path", { d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z" }) }) : /* @__PURE__ */ 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__ */ jsx("path", { d: "m9 18 6-6-6-6" }) : /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" }) });
6539
- return /* @__PURE__ */ jsxs("div", { style: { position: "relative", flexShrink: 0, height: "100%" }, children: [
6994
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("div", { style: { position: "relative", flexShrink: 0, height: "100%" }, children: [
6540
6995
  /* @__PURE__ */ jsx(
6541
6996
  "button",
6542
6997
  {
@@ -6580,7 +7035,7 @@ function CrowCopilot({
6580
7035
  children: /* @__PURE__ */ jsx(ShadowContainer, { styles: WIDGET_CSS, children: renderCopilotContent(void 0, false, "100%") })
6581
7036
  }
6582
7037
  )
6583
- ] });
7038
+ ] }) });
6584
7039
  }
6585
7040
  function PlusIcon({ className }) {
6586
7041
  return /* @__PURE__ */ jsxs(
@@ -6686,6 +7141,320 @@ function CloseIcon({ className }) {
6686
7141
  }
6687
7142
  );
6688
7143
  }
7144
+ function IntroSequence({ lines, onComplete, onSkip, primaryColor }) {
7145
+ const [lineIndex, setLineIndex] = useState(0);
7146
+ const [charIndex, setCharIndex] = useState(0);
7147
+ const [done, setDone] = useState(false);
7148
+ useEffect(() => {
7149
+ if (lineIndex >= lines.length) {
7150
+ setDone(true);
7151
+ return;
7152
+ }
7153
+ const currentLine = lines[lineIndex];
7154
+ if (charIndex < currentLine.length) {
7155
+ const t = setTimeout(() => setCharIndex((c) => c + 1), 35);
7156
+ return () => clearTimeout(t);
7157
+ } else {
7158
+ const t = setTimeout(() => {
7159
+ setLineIndex((l) => l + 1);
7160
+ setCharIndex(0);
7161
+ }, 500);
7162
+ return () => clearTimeout(t);
7163
+ }
7164
+ }, [lineIndex, charIndex, lines]);
7165
+ const displayedLines = lines.slice(0, lineIndex + 1).map((line, i) => {
7166
+ if (i < lineIndex) return line;
7167
+ return line.slice(0, charIndex);
7168
+ });
7169
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "100%", padding: "2rem" }, children: [
7170
+ /* @__PURE__ */ jsx(
7171
+ "button",
7172
+ {
7173
+ onClick: onSkip,
7174
+ style: {
7175
+ position: "absolute",
7176
+ top: 20,
7177
+ right: 24,
7178
+ fontSize: 14,
7179
+ color: "#9ca3af",
7180
+ background: "none",
7181
+ border: "none",
7182
+ cursor: "pointer",
7183
+ padding: "4px 8px"
7184
+ },
7185
+ children: "Skip"
7186
+ }
7187
+ ),
7188
+ /* @__PURE__ */ jsx("div", { style: { textAlign: "center", minHeight: "5rem", marginBottom: "2.5rem" }, children: displayedLines.map((text, i) => /* @__PURE__ */ jsxs(
7189
+ "p",
7190
+ {
7191
+ style: {
7192
+ fontSize: i === 0 ? 30 : 18,
7193
+ fontWeight: i === 0 ? 600 : 400,
7194
+ color: i === 0 ? "#111827" : "#6b7280",
7195
+ lineHeight: 1.4,
7196
+ margin: "0 0 8px 0"
7197
+ },
7198
+ children: [
7199
+ text,
7200
+ i === lineIndex && !done && /* @__PURE__ */ jsx(
7201
+ "span",
7202
+ {
7203
+ style: {
7204
+ display: "inline-block",
7205
+ width: 2,
7206
+ height: i === 0 ? 28 : 18,
7207
+ backgroundColor: "#111827",
7208
+ marginLeft: 2,
7209
+ verticalAlign: "middle",
7210
+ animation: "crow-blink 1s step-end infinite"
7211
+ }
7212
+ }
7213
+ )
7214
+ ]
7215
+ },
7216
+ i
7217
+ )) }),
7218
+ /* @__PURE__ */ jsx(
7219
+ "button",
7220
+ {
7221
+ onClick: onComplete,
7222
+ style: {
7223
+ padding: "10px 32px",
7224
+ borderRadius: 12,
7225
+ backgroundColor: primaryColor,
7226
+ color: "#fff",
7227
+ fontSize: 15,
7228
+ fontWeight: 500,
7229
+ border: "none",
7230
+ cursor: "pointer",
7231
+ opacity: done ? 1 : 0,
7232
+ pointerEvents: done ? "auto" : "none",
7233
+ transition: "opacity 0.5s ease"
7234
+ },
7235
+ children: "Get Started \u2192"
7236
+ }
7237
+ ),
7238
+ /* @__PURE__ */ jsx("style", { children: `
7239
+ @keyframes crow-blink {
7240
+ 0%, 100% { opacity: 1; }
7241
+ 50% { opacity: 0; }
7242
+ }
7243
+ ` })
7244
+ ] });
7245
+ }
7246
+ function CrowOnboarding({
7247
+ productId,
7248
+ apiUrl,
7249
+ subdomain,
7250
+ agentName,
7251
+ welcomeMessage,
7252
+ introSequence,
7253
+ topOffset = 0,
7254
+ onComplete,
7255
+ language,
7256
+ styles: preResolvedStyles,
7257
+ getIdentityToken
7258
+ }) {
7259
+ const [phase, setPhase] = useState(
7260
+ introSequence && introSequence.length > 0 ? "intro" : "chat"
7261
+ );
7262
+ const [isDismissing, setIsDismissing] = useState(false);
7263
+ const bottomRef = useRef(null);
7264
+ const styles = useMemo(
7265
+ () => preResolvedStyles || mergeWidgetStyles(void 0, void 0),
7266
+ [preResolvedStyles]
7267
+ );
7268
+ const cssVars = useMemo(
7269
+ () => stylesToCssVars(styles),
7270
+ [styles]
7271
+ );
7272
+ const dismiss = useCallback(() => {
7273
+ setIsDismissing(true);
7274
+ setTimeout(() => onComplete(), 400);
7275
+ }, [onComplete]);
7276
+ const handleOnboardingComplete = useCallback(
7277
+ (summary) => {
7278
+ console.log("[Crow] Onboarding complete:", summary);
7279
+ dismiss();
7280
+ },
7281
+ [dismiss]
7282
+ );
7283
+ const chat = useChat({
7284
+ productId,
7285
+ apiUrl,
7286
+ subdomain,
7287
+ welcomeMessage: welcomeMessage || `Hi! I'm ${agentName}. Let me help you get started.`,
7288
+ agentMode: "onboarding",
7289
+ onOnboardingComplete: handleOnboardingComplete,
7290
+ language
7291
+ });
7292
+ useEffect(() => {
7293
+ bottomRef.current?.scrollIntoView({ behavior: "smooth" });
7294
+ }, [chat.messages, chat.isLoading]);
7295
+ const handleSend = useCallback(
7296
+ (content) => {
7297
+ chat.sendMessage(content);
7298
+ },
7299
+ [chat]
7300
+ );
7301
+ const handleStop = useCallback(() => {
7302
+ chat.stopGeneration();
7303
+ }, [chat]);
7304
+ const handleSuggestedActionClick = useCallback(
7305
+ (action) => {
7306
+ chat.sendMessage(action.message);
7307
+ },
7308
+ [chat]
7309
+ );
7310
+ useEffect(() => {
7311
+ const effectiveGetIdentityToken = getIdentityToken || window.__crow_identity_token_fetcher;
7312
+ if (!effectiveGetIdentityToken) return;
7313
+ let cancelled = false;
7314
+ const identify = async () => {
7315
+ try {
7316
+ const token = await effectiveGetIdentityToken();
7317
+ if (!cancelled && token) {
7318
+ window.__crow_identity_token = token;
7319
+ }
7320
+ } catch (e) {
7321
+ console.error("[Crow] Onboarding getIdentityToken failed:", e);
7322
+ }
7323
+ };
7324
+ identify();
7325
+ return () => {
7326
+ cancelled = true;
7327
+ };
7328
+ }, [getIdentityToken]);
7329
+ const renderChat = () => /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", height: "100%", background: "#ffffff" }, children: [
7330
+ /* @__PURE__ */ jsxs("div", { style: {
7331
+ display: "flex",
7332
+ alignItems: "center",
7333
+ justifyContent: "space-between",
7334
+ padding: "12px 24px",
7335
+ borderBottom: "1px solid #f3f4f6",
7336
+ flexShrink: 0
7337
+ }, children: [
7338
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10 }, children: [
7339
+ /* @__PURE__ */ jsx("div", { style: {
7340
+ width: 28,
7341
+ height: 28,
7342
+ borderRadius: "50%",
7343
+ backgroundColor: styles.colors.primary,
7344
+ display: "flex",
7345
+ alignItems: "center",
7346
+ justifyContent: "center",
7347
+ color: "#fff",
7348
+ fontSize: 13,
7349
+ fontWeight: 600,
7350
+ flexShrink: 0
7351
+ }, children: agentName.charAt(0).toUpperCase() }),
7352
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 14, fontWeight: 600, color: "#111827" }, children: agentName })
7353
+ ] }),
7354
+ /* @__PURE__ */ jsx(
7355
+ "button",
7356
+ {
7357
+ onClick: dismiss,
7358
+ style: {
7359
+ fontSize: 13,
7360
+ color: "#9ca3af",
7361
+ background: "none",
7362
+ border: "none",
7363
+ cursor: "pointer",
7364
+ padding: "4px 8px"
7365
+ },
7366
+ children: "Skip"
7367
+ }
7368
+ )
7369
+ ] }),
7370
+ /* @__PURE__ */ jsx("div", { style: { flex: 1, overflowY: "auto", minHeight: 0 }, children: /* @__PURE__ */ jsxs("div", { className: "crow-widget-root", style: { ...cssVars, maxWidth: 560, margin: "0 auto", padding: "24px 16px" }, children: [
7371
+ /* @__PURE__ */ jsx(
7372
+ WidgetStyleProvider,
7373
+ {
7374
+ styles,
7375
+ agentName,
7376
+ isLoading: false,
7377
+ variant: "embedded",
7378
+ children: /* @__PURE__ */ jsx(
7379
+ MessageList,
7380
+ {
7381
+ messages: chat.messages,
7382
+ activeToolCalls: chat.activeToolCalls,
7383
+ isLoadingHistory: false,
7384
+ isGenerating: chat.isLoading
7385
+ }
7386
+ )
7387
+ }
7388
+ ),
7389
+ /* @__PURE__ */ jsx("div", { ref: bottomRef })
7390
+ ] }) }),
7391
+ chat.suggestedActions.length > 0 && !chat.isLoading && /* @__PURE__ */ jsx("div", { className: "crow-widget-root", style: { ...cssVars, maxWidth: 560, margin: "0 auto", width: "100%", padding: "0 16px 8px" }, children: /* @__PURE__ */ jsx(
7392
+ WidgetStyleProvider,
7393
+ {
7394
+ styles,
7395
+ agentName,
7396
+ isLoading: false,
7397
+ variant: "embedded",
7398
+ children: /* @__PURE__ */ jsx(
7399
+ SuggestedActions,
7400
+ {
7401
+ actions: chat.suggestedActions,
7402
+ onActionClick: handleSuggestedActionClick
7403
+ }
7404
+ )
7405
+ }
7406
+ ) }),
7407
+ /* @__PURE__ */ jsxs("div", { style: { borderTop: "1px solid #f3f4f6", flexShrink: 0 }, children: [
7408
+ /* @__PURE__ */ jsx("div", { className: "crow-widget-root", style: { ...cssVars, maxWidth: 560, margin: "0 auto", padding: "12px 16px" }, children: /* @__PURE__ */ jsx(
7409
+ WidgetStyleProvider,
7410
+ {
7411
+ styles,
7412
+ agentName,
7413
+ isLoading: false,
7414
+ variant: "embedded",
7415
+ children: /* @__PURE__ */ jsx(
7416
+ PromptInputBox,
7417
+ {
7418
+ onSend: handleSend,
7419
+ onStop: handleStop,
7420
+ placeholder: "Type your message...",
7421
+ isLoading: chat.isLoading
7422
+ }
7423
+ )
7424
+ }
7425
+ ) }),
7426
+ /* @__PURE__ */ jsx("div", { style: { textAlign: "center", padding: "0 0 10px" }, children: /* @__PURE__ */ jsx("span", { style: { fontSize: 11, color: "#d1d5db" }, children: "Powered by Crow" }) })
7427
+ ] })
7428
+ ] });
7429
+ return /* @__PURE__ */ jsx(ShadowContainer, { styles: WIDGET_CSS, hostId: "crow-onboarding-host", children: /* @__PURE__ */ jsx(
7430
+ motion.div,
7431
+ {
7432
+ style: {
7433
+ position: "fixed",
7434
+ top: topOffset,
7435
+ left: 0,
7436
+ right: 0,
7437
+ bottom: 0,
7438
+ zIndex: 999999,
7439
+ background: "#ffffff",
7440
+ fontFamily: styles.typography.fontFamily || '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
7441
+ fontSize: 14
7442
+ },
7443
+ initial: { opacity: 0 },
7444
+ animate: { opacity: isDismissing ? 0 : 1 },
7445
+ transition: { duration: 0.35 },
7446
+ children: phase === "intro" ? /* @__PURE__ */ jsx(
7447
+ IntroSequence,
7448
+ {
7449
+ lines: introSequence || [],
7450
+ onComplete: () => setPhase("chat"),
7451
+ onSkip: dismiss,
7452
+ primaryColor: styles.colors.primary
7453
+ }
7454
+ ) : renderChat()
7455
+ }
7456
+ ) });
7457
+ }
6689
7458
  var CrowContext = createContext(null);
6690
7459
  function CrowProvider({
6691
7460
  children,
@@ -6708,6 +7477,6 @@ function CrowProvider({
6708
7477
  return /* @__PURE__ */ jsx(CrowContext.Provider, { value, children });
6709
7478
  }
6710
7479
 
6711
- export { AVAILABLE_MODELS, CSS_VAR_NAMES, ChatBubble, ConversationList, CopilotContainer, CopilotStyleProvider, CopilotToggleButton, CrowCopilot, CrowProvider, CrowWidget, DEFAULT_COPILOT_STYLES, DEFAULT_MODEL, DEFAULT_WELCOME_MESSAGE, DEFAULT_WIDGET_STYLES, LoadingHistory, MESSAGES_CONTAINER_ID, MessageBubble, MessageList, MessagesContainer, ModelSelector, PoweredByBadge, PromptInputBox, ReasoningTrace, ShadowContainer, StreamingText, ThinkingIndicator, WIDGET_CSS, WidgetHeader, WidgetShell, WidgetStyleProvider, WorkflowPanel, clearStyleCache, getCssVar, injectStyles, mergeCopilotStyles, mergeWidgetStyles, stylesToCSSVariables, stylesToCssVars, useChat, useConversations, useCopilotStyleContext, useCopilotStyles, useCopilotStyles2 as useCopilotStylesContext, useCrowAPI, usePreviewCopilotStyles, usePreviewWidgetStyles, useVoiceInput, useWidgetStyleContext, useWidgetStyles, useWidgetStyles2 as useWidgetStylesContext, useWorkflow };
7480
+ export { AVAILABLE_MODELS, CSS_VAR_NAMES, ChatBubble, ConversationList, CopilotContainer, CopilotStyleProvider, CopilotToggleButton, CrowCopilot, CrowOnboarding, CrowProvider, CrowWidget, DEFAULT_COPILOT_STYLES, DEFAULT_MODEL, DEFAULT_WELCOME_MESSAGE, DEFAULT_WIDGET_STYLES, LoadingHistory, MESSAGES_CONTAINER_ID, MessageBubble, MessageList, MessagesContainer, ModelSelector, PoweredByBadge, PromptInputBox, ReasoningTrace, ShadowContainer, StreamingText, ThinkingIndicator, WIDGET_CSS, WidgetHeader, WidgetShell, WidgetStyleProvider, WorkflowPanel, clearStyleCache, getCssVar, injectStyles, mergeCopilotStyles, mergeWidgetStyles, stylesToCSSVariables, stylesToCssVars, useChat, useConversations, useCopilotStyleContext, useCopilotStyles, useCopilotStyles2 as useCopilotStylesContext, useCrowAPI, usePreviewCopilotStyles, usePreviewWidgetStyles, useVoiceInput, useWidgetStyleContext, useWidgetStyles, useWidgetStyles2 as useWidgetStylesContext, useWorkflow };
6712
7481
  //# sourceMappingURL=index.js.map
6713
7482
  //# sourceMappingURL=index.js.map