@usecrow/ui 0.1.15 → 0.1.16

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
@@ -68,41 +68,68 @@ var MESSAGES_CONTAINER_ID = "crow-messages-container";
68
68
 
69
69
  // src/hooks/useChat.ts
70
70
  var getConversationStorageKey = (productId) => `crow_conv_${productId}`;
71
+ var inMemoryConversations = {};
71
72
  function useChat({
72
73
  productId,
73
74
  apiUrl = "",
75
+ persistAnonymousConversations,
76
+ welcomeMessage,
74
77
  onVerificationStatus,
75
78
  onConversationId,
76
79
  onWorkflowEvent,
77
80
  onToolCall,
78
81
  onRestoredConversation
79
82
  }) {
83
+ const effectiveWelcomeMessage = welcomeMessage || DEFAULT_WELCOME_MESSAGE;
80
84
  const [messages, setMessages] = React3.useState([
81
85
  {
82
86
  id: "welcome",
83
- content: DEFAULT_WELCOME_MESSAGE,
87
+ content: effectiveWelcomeMessage,
84
88
  isBot: true,
85
89
  timestamp: /* @__PURE__ */ new Date()
86
90
  }
87
91
  ]);
88
92
  const [isLoading, setIsLoading] = React3.useState(false);
89
93
  const [activeToolCalls, setActiveToolCalls] = React3.useState([]);
90
- const [conversationId, setConversationId] = React3.useState(() => {
91
- try {
92
- return localStorage.getItem(getConversationStorageKey(productId));
93
- } catch {
94
- return null;
95
- }
96
- });
94
+ const [conversationId, setConversationId] = React3.useState(null);
97
95
  const [selectedModel, setSelectedModel] = React3.useState(DEFAULT_MODEL);
98
96
  const abortControllerRef = React3.useRef(null);
99
- const hasRestoredRef = React3.useRef(false);
97
+ const hasInitializedConversationRef = React3.useRef(false);
100
98
  React3.useEffect(() => {
101
- if (conversationId && onRestoredConversation && !hasRestoredRef.current) {
102
- hasRestoredRef.current = true;
103
- onRestoredConversation(conversationId);
99
+ if (messages.length === 1 && messages[0].id === "welcome" && !conversationId) {
100
+ setMessages([
101
+ {
102
+ id: "welcome",
103
+ content: effectiveWelcomeMessage,
104
+ isBot: true,
105
+ timestamp: /* @__PURE__ */ new Date()
106
+ }
107
+ ]);
104
108
  }
105
- }, []);
109
+ }, [effectiveWelcomeMessage]);
110
+ React3.useEffect(() => {
111
+ if (hasInitializedConversationRef.current || persistAnonymousConversations === void 0) {
112
+ return;
113
+ }
114
+ hasInitializedConversationRef.current = true;
115
+ try {
116
+ if (persistAnonymousConversations) {
117
+ const convId = localStorage.getItem(getConversationStorageKey(productId));
118
+ if (convId) {
119
+ setConversationId(convId);
120
+ onRestoredConversation?.(convId);
121
+ }
122
+ } else {
123
+ const convId = inMemoryConversations[productId];
124
+ if (convId) {
125
+ setConversationId(convId);
126
+ onRestoredConversation?.(convId);
127
+ }
128
+ }
129
+ } catch (e) {
130
+ console.error("[Crow] Error initializing conversation:", e);
131
+ }
132
+ }, [persistAnonymousConversations, productId, onRestoredConversation]);
106
133
  const streamFromBackend = React3.useCallback(
107
134
  async (message, botMsgId) => {
108
135
  let accumulatedText = "";
@@ -160,12 +187,16 @@ function useChat({
160
187
  case "conversation_id":
161
188
  if (parsed.conversation_id) {
162
189
  setConversationId(parsed.conversation_id);
163
- try {
164
- localStorage.setItem(
165
- getConversationStorageKey(productId),
166
- parsed.conversation_id
167
- );
168
- } catch {
190
+ if (persistAnonymousConversations) {
191
+ try {
192
+ localStorage.setItem(
193
+ getConversationStorageKey(productId),
194
+ parsed.conversation_id
195
+ );
196
+ } catch {
197
+ }
198
+ } else {
199
+ inMemoryConversations[productId] = parsed.conversation_id;
169
200
  }
170
201
  onConversationId?.(parsed.conversation_id);
171
202
  }
@@ -303,7 +334,7 @@ function useChat({
303
334
  abortControllerRef.current = null;
304
335
  }
305
336
  },
306
- [apiUrl, productId, conversationId, selectedModel, onVerificationStatus, onConversationId, onWorkflowEvent, onToolCall]
337
+ [apiUrl, productId, conversationId, selectedModel, persistAnonymousConversations, onVerificationStatus, onConversationId, onWorkflowEvent, onToolCall]
307
338
  );
308
339
  const sendMessage = React3.useCallback(
309
340
  (content) => {
@@ -347,17 +378,18 @@ function useChat({
347
378
  setMessages([
348
379
  {
349
380
  id: "welcome",
350
- content: DEFAULT_WELCOME_MESSAGE,
381
+ content: effectiveWelcomeMessage,
351
382
  isBot: true,
352
383
  timestamp: /* @__PURE__ */ new Date()
353
384
  }
354
385
  ]);
355
386
  setConversationId(null);
387
+ delete inMemoryConversations[productId];
356
388
  try {
357
389
  localStorage.removeItem(getConversationStorageKey(productId));
358
390
  } catch {
359
391
  }
360
- }, [productId]);
392
+ }, [productId, effectiveWelcomeMessage]);
361
393
  const loadMessages = React3.useCallback((historyMessages) => {
362
394
  setMessages(historyMessages);
363
395
  }, []);
@@ -1042,6 +1074,12 @@ function useWidgetStyles({
1042
1074
  const [showThinking, setShowThinking] = React3.useState(
1043
1075
  styleCache.get(key)?.showThinking ?? true
1044
1076
  );
1077
+ const [persistAnonymousConversations, setPersistAnonymousConversations] = React3.useState(
1078
+ styleCache.has(key) ? styleCache.get(key)?.persistAnonymousConversations ?? true : void 0
1079
+ );
1080
+ const [welcomeMessage, setWelcomeMessage] = React3.useState(
1081
+ styleCache.get(key)?.welcomeMessage ?? void 0
1082
+ );
1045
1083
  const hasFetchedRef = React3.useRef(false);
1046
1084
  const fetchStyles = async () => {
1047
1085
  if (skip) return;
@@ -1054,6 +1092,8 @@ function useWidgetStyles({
1054
1092
  setAgentName(config.agentName || "Assistant");
1055
1093
  setBrowserUseEnabled(config.browserUseEnabled || false);
1056
1094
  setShowThinking(config.showThinking ?? true);
1095
+ setPersistAnonymousConversations(config.persistAnonymousConversations ?? true);
1096
+ setWelcomeMessage(config.welcomeMessage ?? void 0);
1057
1097
  } catch (err) {
1058
1098
  console.error("[CrowWidget] Failed to fetch styles:", err);
1059
1099
  setError(err instanceof Error ? err : new Error(String(err)));
@@ -1069,6 +1109,8 @@ function useWidgetStyles({
1069
1109
  setAgentName(cached.agentName || "Assistant");
1070
1110
  setBrowserUseEnabled(cached.browserUseEnabled || false);
1071
1111
  setShowThinking(cached.showThinking ?? true);
1112
+ setPersistAnonymousConversations(cached.persistAnonymousConversations ?? true);
1113
+ setWelcomeMessage(cached.welcomeMessage ?? void 0);
1072
1114
  setIsLoading(false);
1073
1115
  return;
1074
1116
  }
@@ -1083,6 +1125,8 @@ function useWidgetStyles({
1083
1125
  agentName,
1084
1126
  browserUseEnabled,
1085
1127
  showThinking,
1128
+ persistAnonymousConversations,
1129
+ welcomeMessage,
1086
1130
  refetch: fetchStyles
1087
1131
  };
1088
1132
  }
@@ -1102,6 +1146,12 @@ function useCopilotStyles({
1102
1146
  const [agentName, setAgentName] = React3.useState(
1103
1147
  styleCache.get(key)?.agentName || "Assistant"
1104
1148
  );
1149
+ const [persistAnonymousConversations, setPersistAnonymousConversations] = React3.useState(
1150
+ styleCache.has(key) ? styleCache.get(key)?.persistAnonymousConversations ?? true : void 0
1151
+ );
1152
+ const [welcomeMessage, setWelcomeMessage] = React3.useState(
1153
+ styleCache.get(key)?.welcomeMessage ?? void 0
1154
+ );
1105
1155
  const hasFetchedRef = React3.useRef(false);
1106
1156
  const fetchStyles = async () => {
1107
1157
  if (skip) return;
@@ -1112,6 +1162,8 @@ function useCopilotStyles({
1112
1162
  styleCache.set(key, config);
1113
1163
  setDbStyles(config.copilotStyles);
1114
1164
  setAgentName(config.agentName || "Assistant");
1165
+ setPersistAnonymousConversations(config.persistAnonymousConversations ?? true);
1166
+ setWelcomeMessage(config.welcomeMessage ?? void 0);
1115
1167
  } catch (err) {
1116
1168
  console.error("[CrowCopilot] Failed to fetch styles:", err);
1117
1169
  setError(err instanceof Error ? err : new Error(String(err)));
@@ -1125,6 +1177,8 @@ function useCopilotStyles({
1125
1177
  if (cached) {
1126
1178
  setDbStyles(cached.copilotStyles);
1127
1179
  setAgentName(cached.agentName || "Assistant");
1180
+ setPersistAnonymousConversations(cached.persistAnonymousConversations ?? true);
1181
+ setWelcomeMessage(cached.welcomeMessage ?? void 0);
1128
1182
  setIsLoading(false);
1129
1183
  return;
1130
1184
  }
@@ -1137,6 +1191,8 @@ function useCopilotStyles({
1137
1191
  isLoading,
1138
1192
  error,
1139
1193
  agentName,
1194
+ persistAnonymousConversations,
1195
+ welcomeMessage,
1140
1196
  refetch: fetchStyles
1141
1197
  };
1142
1198
  }
@@ -2449,16 +2505,27 @@ function CrowWidget({
2449
2505
  styles: propStyles,
2450
2506
  previewMode = false,
2451
2507
  showThinking: showThinkingProp,
2508
+ welcomeMessage: welcomeMessageProp,
2452
2509
  onReady,
2453
2510
  onIdentify,
2454
2511
  tools
2455
2512
  }) {
2456
- const { styles, isLoading: isLoadingStyles, agentName, browserUseEnabled, showThinking: showThinkingFromAPI } = useWidgetStyles({
2513
+ const {
2514
+ styles,
2515
+ isLoading: isLoadingStyles,
2516
+ agentName,
2517
+ browserUseEnabled,
2518
+ showThinking: showThinkingFromAPI,
2519
+ persistAnonymousConversations,
2520
+ welcomeMessage: welcomeMessageFromAPI
2521
+ } = useWidgetStyles({
2457
2522
  productId,
2458
2523
  apiUrl,
2459
2524
  propStyles,
2460
2525
  skip: previewMode
2461
2526
  });
2527
+ const welcomeMessage = welcomeMessageProp ?? welcomeMessageFromAPI;
2528
+ console.log("[Crow Widget] persistAnonymousConversations from API:", persistAnonymousConversations, "isLoading:", isLoadingStyles);
2462
2529
  const showThinking = showThinkingProp ?? showThinkingFromAPI;
2463
2530
  const [autoTools, setAutoTools] = React3.useState({});
2464
2531
  const cssVars = stylesToCssVars(styles);
@@ -2486,6 +2553,8 @@ function CrowWidget({
2486
2553
  const chat = useChat({
2487
2554
  productId,
2488
2555
  apiUrl,
2556
+ persistAnonymousConversations,
2557
+ welcomeMessage,
2489
2558
  onVerificationStatus: (isVerified) => {
2490
2559
  setIsVerifiedUser(isVerified);
2491
2560
  },
@@ -2730,7 +2799,7 @@ function CrowCopilot({
2730
2799
  className,
2731
2800
  onReady
2732
2801
  }) {
2733
- const { styles, isLoading: isLoadingStyles, agentName } = useCopilotStyles({
2802
+ const { styles, isLoading: isLoadingStyles, agentName, persistAnonymousConversations, welcomeMessage } = useCopilotStyles({
2734
2803
  productId,
2735
2804
  apiUrl,
2736
2805
  propStyles,
@@ -2746,6 +2815,8 @@ function CrowCopilot({
2746
2815
  const chat = useChat({
2747
2816
  productId,
2748
2817
  apiUrl,
2818
+ persistAnonymousConversations,
2819
+ welcomeMessage,
2749
2820
  onVerificationStatus: (isVerified) => {
2750
2821
  setIsVerifiedUser(isVerified);
2751
2822
  },