@chatwidgetai/chat-widget 0.1.7 → 0.1.9

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.
@@ -17533,6 +17533,124 @@
17533
17533
  throw error;
17534
17534
  }
17535
17535
  }
17536
+ /**
17537
+ * Stream chat message responses
17538
+ */
17539
+ async *sendMessageStream(conversationId, message, fileIds) {
17540
+ const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/chat`, {
17541
+ method: 'POST',
17542
+ headers: {
17543
+ 'Content-Type': 'application/json',
17544
+ },
17545
+ body: JSON.stringify({
17546
+ conversationId: conversationId,
17547
+ message,
17548
+ fileIds,
17549
+ timeZone: this.getTimeZone(),
17550
+ }),
17551
+ });
17552
+ if (!response.ok) {
17553
+ throw await buildApiError(response, 'Failed to send message');
17554
+ }
17555
+ if (!response.body) {
17556
+ throw new Error('Response body is null');
17557
+ }
17558
+ const reader = response.body.getReader();
17559
+ const decoder = new TextDecoder();
17560
+ let buffer = '';
17561
+ try {
17562
+ while (true) {
17563
+ const { done, value } = await reader.read();
17564
+ if (done)
17565
+ break;
17566
+ buffer += decoder.decode(value, { stream: true });
17567
+ const lines = buffer.split('\n');
17568
+ buffer = lines.pop() || '';
17569
+ for (const line of lines) {
17570
+ if (line.startsWith('data: ')) {
17571
+ try {
17572
+ const data = JSON.parse(line.slice(6));
17573
+ // Handle error events
17574
+ if (data.type === 'error') {
17575
+ throw new Error(data.error || 'Stream error');
17576
+ }
17577
+ // Yield ConversationMessage objects
17578
+ if (data.id) {
17579
+ yield data;
17580
+ }
17581
+ }
17582
+ catch (e) {
17583
+ console.error('[Widget API Client] Failed to parse SSE data:', line, e);
17584
+ throw e;
17585
+ }
17586
+ }
17587
+ }
17588
+ }
17589
+ }
17590
+ finally {
17591
+ reader.releaseLock();
17592
+ }
17593
+ }
17594
+ /**
17595
+ * Stream agent message responses with tool execution
17596
+ * Handles streaming events from backend and yields ConversationMessage updates
17597
+ */
17598
+ async *sendAgentMessageStream(conversationId, message, fileIds) {
17599
+ const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/agent`, {
17600
+ method: 'POST',
17601
+ headers: {
17602
+ 'Content-Type': 'application/json',
17603
+ },
17604
+ body: JSON.stringify({
17605
+ conversationId: conversationId,
17606
+ message,
17607
+ fileIds,
17608
+ timeZone: this.getTimeZone(),
17609
+ }),
17610
+ });
17611
+ if (!response.ok) {
17612
+ throw await buildApiError(response, 'Failed to send agent message');
17613
+ }
17614
+ if (!response.body) {
17615
+ throw new Error('Response body is null');
17616
+ }
17617
+ const reader = response.body.getReader();
17618
+ const decoder = new TextDecoder();
17619
+ let buffer = '';
17620
+ try {
17621
+ while (true) {
17622
+ const { done, value } = await reader.read();
17623
+ if (done)
17624
+ break;
17625
+ buffer += decoder.decode(value, { stream: true });
17626
+ const lines = buffer.split('\n');
17627
+ buffer = lines.pop() || '';
17628
+ for (const line of lines) {
17629
+ if (line.startsWith('data: ')) {
17630
+ try {
17631
+ const data = JSON.parse(line.slice(6));
17632
+ // Handle error events
17633
+ if (data.type === 'error') {
17634
+ throw new Error(data.error || 'Stream error');
17635
+ }
17636
+ // Yield ConversationMessage objects that come from the backend
17637
+ // The backend yields full ConversationMessage objects during streaming
17638
+ if (data.id) {
17639
+ yield data;
17640
+ }
17641
+ }
17642
+ catch (e) {
17643
+ console.error('[Widget API Client] Failed to parse SSE data:', line, e);
17644
+ throw e;
17645
+ }
17646
+ }
17647
+ }
17648
+ }
17649
+ }
17650
+ finally {
17651
+ reader.releaseLock();
17652
+ }
17653
+ }
17536
17654
  /**
17537
17655
  * Submit feedback for a message
17538
17656
  */
@@ -17599,8 +17717,10 @@
17599
17717
  /**
17600
17718
  * Local Storage Utilities
17601
17719
  * Handles conversation persistence in browser localStorage
17720
+ * Supports multiple conversations per widget with history
17602
17721
  */
17603
17722
  const STORAGE_PREFIX = 'ai-chat-widget';
17723
+ const MAX_STORED_CONVERSATIONS = 20;
17604
17724
  /**
17605
17725
  * Generate a storage key for a widget
17606
17726
  */
@@ -17608,33 +17728,113 @@
17608
17728
  return `${STORAGE_PREFIX}:${widgetId}`;
17609
17729
  }
17610
17730
  /**
17611
- * Save conversation to localStorage
17731
+ * Get widget storage data
17612
17732
  */
17613
- function saveConversation(widgetId, conversationId, messages) {
17733
+ function getWidgetStorage(widgetId) {
17734
+ try {
17735
+ const key = getStorageKey(widgetId);
17736
+ const data = localStorage.getItem(key);
17737
+ if (!data) {
17738
+ return { activeConversationId: null, conversations: {}, history: [] };
17739
+ }
17740
+ const parsed = JSON.parse(data);
17741
+ // Handle legacy format (single conversation)
17742
+ if (parsed.conversationId && parsed.messages) {
17743
+ const legacy = parsed;
17744
+ return {
17745
+ activeConversationId: legacy.conversationId,
17746
+ conversations: { [legacy.conversationId]: legacy },
17747
+ history: [{
17748
+ id: legacy.conversationId,
17749
+ preview: getConversationPreview(legacy.messages),
17750
+ lastUpdated: legacy.lastUpdated,
17751
+ messageCount: legacy.messages.length,
17752
+ }],
17753
+ };
17754
+ }
17755
+ return parsed;
17756
+ }
17757
+ catch (error) {
17758
+ console.error('Failed to get widget storage:', error);
17759
+ return { activeConversationId: null, conversations: {}, history: [] };
17760
+ }
17761
+ }
17762
+ /**
17763
+ * Save widget storage data
17764
+ */
17765
+ function setWidgetStorage(widgetId, storage) {
17614
17766
  try {
17615
17767
  const key = getStorageKey(widgetId);
17616
- const data = {
17768
+ localStorage.setItem(key, JSON.stringify(storage));
17769
+ }
17770
+ catch (error) {
17771
+ console.error('Failed to save widget storage:', error);
17772
+ }
17773
+ }
17774
+ /**
17775
+ * Get preview text from messages
17776
+ */
17777
+ function getConversationPreview(messages) {
17778
+ const firstUserMessage = messages.find(m => m.message.type === 'human');
17779
+ if (firstUserMessage) {
17780
+ return firstUserMessage.message.content.slice(0, 100);
17781
+ }
17782
+ return 'New conversation';
17783
+ }
17784
+ /**
17785
+ * Save conversation to localStorage (updates both conversation and history)
17786
+ */
17787
+ function saveConversation(widgetId, conversationId, messages) {
17788
+ try {
17789
+ const storage = getWidgetStorage(widgetId);
17790
+ const now = new Date().toISOString();
17791
+ // Update conversation data
17792
+ storage.conversations[conversationId] = {
17617
17793
  conversationId,
17618
17794
  messages,
17619
- lastUpdated: new Date().toISOString(),
17795
+ lastUpdated: now,
17796
+ };
17797
+ // Update active conversation
17798
+ storage.activeConversationId = conversationId;
17799
+ // Update history entry
17800
+ const existingIndex = storage.history.findIndex(h => h.id === conversationId);
17801
+ const historyEntry = {
17802
+ id: conversationId,
17803
+ preview: getConversationPreview(messages),
17804
+ lastUpdated: now,
17805
+ messageCount: messages.length,
17620
17806
  };
17621
- localStorage.setItem(key, JSON.stringify(data));
17807
+ if (existingIndex >= 0) {
17808
+ storage.history[existingIndex] = historyEntry;
17809
+ }
17810
+ else {
17811
+ storage.history.unshift(historyEntry);
17812
+ }
17813
+ // Sort by lastUpdated (most recent first)
17814
+ storage.history.sort((a, b) => new Date(b.lastUpdated).getTime() - new Date(a.lastUpdated).getTime());
17815
+ // Limit stored conversations
17816
+ if (storage.history.length > MAX_STORED_CONVERSATIONS) {
17817
+ const toRemove = storage.history.slice(MAX_STORED_CONVERSATIONS);
17818
+ storage.history = storage.history.slice(0, MAX_STORED_CONVERSATIONS);
17819
+ toRemove.forEach(entry => {
17820
+ delete storage.conversations[entry.id];
17821
+ });
17822
+ }
17823
+ setWidgetStorage(widgetId, storage);
17622
17824
  }
17623
17825
  catch (error) {
17624
17826
  console.error('Failed to save conversation:', error);
17625
17827
  }
17626
17828
  }
17627
17829
  /**
17628
- * Load conversation from localStorage
17830
+ * Load active conversation from localStorage (legacy compatibility)
17629
17831
  */
17630
17832
  function loadConversation(widgetId) {
17631
17833
  try {
17632
- const key = getStorageKey(widgetId);
17633
- const data = localStorage.getItem(key);
17634
- if (!data)
17834
+ const storage = getWidgetStorage(widgetId);
17835
+ if (!storage.activeConversationId)
17635
17836
  return null;
17636
- const parsed = JSON.parse(data);
17637
- return parsed;
17837
+ return storage.conversations[storage.activeConversationId] || null;
17638
17838
  }
17639
17839
  catch (error) {
17640
17840
  console.error('Failed to load conversation:', error);
@@ -17642,12 +17842,52 @@
17642
17842
  }
17643
17843
  }
17644
17844
  /**
17645
- * Clear conversation from localStorage
17845
+ * Load a specific conversation by ID
17846
+ */
17847
+ function loadConversationById(widgetId, conversationId) {
17848
+ try {
17849
+ const storage = getWidgetStorage(widgetId);
17850
+ return storage.conversations[conversationId] || null;
17851
+ }
17852
+ catch (error) {
17853
+ console.error('Failed to load conversation by ID:', error);
17854
+ return null;
17855
+ }
17856
+ }
17857
+ /**
17858
+ * Get conversation history list
17859
+ */
17860
+ function getConversationHistory(widgetId) {
17861
+ try {
17862
+ const storage = getWidgetStorage(widgetId);
17863
+ return storage.history;
17864
+ }
17865
+ catch (error) {
17866
+ console.error('Failed to get conversation history:', error);
17867
+ return [];
17868
+ }
17869
+ }
17870
+ /**
17871
+ * Set active conversation
17872
+ */
17873
+ function setActiveConversation(widgetId, conversationId) {
17874
+ try {
17875
+ const storage = getWidgetStorage(widgetId);
17876
+ storage.activeConversationId = conversationId;
17877
+ setWidgetStorage(widgetId, storage);
17878
+ }
17879
+ catch (error) {
17880
+ console.error('Failed to set active conversation:', error);
17881
+ }
17882
+ }
17883
+ /**
17884
+ * Clear current conversation (start fresh, but keep history)
17646
17885
  */
17647
17886
  function clearConversation(widgetId) {
17648
17887
  try {
17649
- const key = getStorageKey(widgetId);
17650
- localStorage.removeItem(key);
17888
+ const storage = getWidgetStorage(widgetId);
17889
+ storage.activeConversationId = null;
17890
+ setWidgetStorage(widgetId, storage);
17651
17891
  }
17652
17892
  catch (error) {
17653
17893
  console.error('Failed to clear conversation:', error);
@@ -17744,6 +17984,8 @@
17744
17984
  conversationId: '', // Will be set after loading conversation
17745
17985
  config: null,
17746
17986
  });
17987
+ // Chat history state
17988
+ const [conversations, setConversations] = reactExports.useState([]);
17747
17989
  const apiClient = reactExports.useRef(new WidgetApiClient({ widgetId, apiUrl }));
17748
17990
  // Load configuration on mount and hydrate with existing conversation if available
17749
17991
  reactExports.useEffect(() => {
@@ -17756,7 +17998,7 @@
17756
17998
  console.log('[useChat] Config fetched successfully:', {
17757
17999
  hasAppearance: !!config.appearance,
17758
18000
  });
17759
- const persistConversation = config.behavior.persistConversation ?? true;
18001
+ const persistConversation = config.settings.persistConversation ?? true;
17760
18002
  let conversationId = '';
17761
18003
  let messages = [];
17762
18004
  if (persistConversation && isStorageAvailable()) {
@@ -17804,14 +18046,14 @@
17804
18046
  }, [widgetId, apiUrl, onError]);
17805
18047
  // Save conversation when messages change
17806
18048
  reactExports.useEffect(() => {
17807
- const persistConversation = state.config?.behavior.persistConversation ?? true;
18049
+ const persistConversation = state.config?.settings.persistConversation ?? true;
17808
18050
  if (persistConversation &&
17809
18051
  isStorageAvailable() &&
17810
18052
  state.messages.length > 0 &&
17811
18053
  state.conversationId) {
17812
18054
  saveConversation(widgetId, state.conversationId, state.messages);
17813
18055
  }
17814
- }, [widgetId, state.messages, state.conversationId, state.config?.behavior.persistConversation]);
18056
+ }, [widgetId, state.messages, state.conversationId, state.config?.settings.persistConversation]);
17815
18057
  /**
17816
18058
  * Send a message
17817
18059
  */
@@ -17833,8 +18075,8 @@
17833
18075
  setState(prev => ({
17834
18076
  ...prev,
17835
18077
  messages: [...prev.messages, userMessage],
17836
- isLoading: true,
17837
- isTyping: true,
18078
+ isLoading: false, // Don't show loading, will show typing when stream starts
18079
+ isTyping: true, // Show typing indicator immediately
17838
18080
  error: null,
17839
18081
  }));
17840
18082
  onMessage?.(userMessage);
@@ -17880,71 +18122,56 @@
17880
18122
  }
17881
18123
  // Determine if widget has actions (use agent endpoint)
17882
18124
  const useAgent = state.config?.behavior.agentic || (state.config?.actions && state.config.actions.length > 0);
17883
- let response;
17884
- if (useAgent) {
17885
- // Use agent endpoint - returns ConversationMessage[]
17886
- response = await apiClient.current.sendAgentMessage(conversationId, trimmedContent, fileIds);
17887
- }
17888
- else {
17889
- // Use standard chat endpoint
17890
- response = await apiClient.current.sendMessage(conversationId, trimmedContent, fileIds);
17891
- }
17892
- // Both endpoints now return ConversationMessage[] array (FULL conversation)
17893
- if (Array.isArray(response)) {
17894
- // Response is already ConversationMessage[]
17895
- const allMessages = response;
17896
- // Find new messages (those not in current state)
17897
- const existingIds = new Set(state.messages.map(m => m.id));
17898
- const newMessages = allMessages.filter(msg => !existingIds.has(msg.id));
17899
- setState(prev => ({
17900
- ...prev,
17901
- messages: allMessages, // Replace with full conversation
17902
- isLoading: false,
17903
- isTyping: false,
17904
- }));
17905
- // Only notify about new messages
17906
- newMessages.forEach(msg => onMessage?.(msg));
17907
- }
17908
- else if (response.type === 'error') {
17909
- // Error response from agent
17910
- const errorContent = response.message || response.error || 'An error occurred';
17911
- const errorMessage = {
17912
- id: response.message_id || generateMessageId(),
17913
- message: {
17914
- type: 'ai',
17915
- content: `⚠️ ${errorContent}`,
17916
- },
17917
- timestamp: response.timestamp || new Date().toISOString(),
17918
- sources: [],
17919
- };
17920
- setState(prev => ({
17921
- ...prev,
17922
- messages: [...prev.messages, errorMessage],
17923
- isLoading: false,
17924
- isTyping: false,
17925
- error: errorContent,
17926
- }));
17927
- onMessage?.(errorMessage);
18125
+ // Stream the response
18126
+ let lastStreamedMessage = null;
18127
+ const stream = useAgent
18128
+ ? apiClient.current.sendAgentMessageStream(conversationId, trimmedContent, fileIds)
18129
+ : apiClient.current.sendMessageStream(conversationId, trimmedContent, fileIds);
18130
+ for await (const message of stream) {
18131
+ lastStreamedMessage = message;
18132
+ // Update state with streamed message
18133
+ setState(prev => {
18134
+ const existingIndex = prev.messages.findIndex(m => m.id === message.id);
18135
+ if (existingIndex >= 0) {
18136
+ // Update existing streaming message
18137
+ const newMessages = [...prev.messages];
18138
+ newMessages[existingIndex] = message;
18139
+ // Show typing indicator if:
18140
+ // 1. Message is streaming AND has no content (waiting for first token or after tool call)
18141
+ // 2. Message is a tool execution (shows loading spinner on the tool)
18142
+ const isAIMessage = message.message.type === 'ai';
18143
+ const hasContent = isAIMessage && message.message.content.trim().length > 0;
18144
+ const isToolExecuting = message.toolExecuting !== undefined;
18145
+ return {
18146
+ ...prev,
18147
+ messages: newMessages,
18148
+ isTyping: (message.isStreaming && !hasContent && isAIMessage) || isToolExecuting,
18149
+ isLoading: false,
18150
+ };
18151
+ }
18152
+ else {
18153
+ // Add new streaming message
18154
+ const isAIMessage = message.message.type === 'ai';
18155
+ const hasContent = isAIMessage && message.message.content.trim().length > 0;
18156
+ const isToolExecuting = message.toolExecuting !== undefined;
18157
+ return {
18158
+ ...prev,
18159
+ messages: [...prev.messages, message],
18160
+ isTyping: (message.isStreaming && !hasContent && isAIMessage) || isToolExecuting,
18161
+ isLoading: false,
18162
+ };
18163
+ }
18164
+ });
17928
18165
  }
17929
- else {
17930
- // Standard message response (type: 'message' or undefined)
17931
- const messageContent = response.content || response.message || '';
17932
- const assistantMessage = {
17933
- id: response.message_id || response.messageId || generateMessageId(),
17934
- message: {
17935
- type: 'ai',
17936
- content: messageContent,
17937
- },
17938
- timestamp: response.timestamp || new Date().toISOString(),
17939
- sources: response.sources || [],
17940
- };
17941
- setState(prev => ({
17942
- ...prev,
17943
- messages: [...prev.messages, assistantMessage],
17944
- isLoading: false,
17945
- isTyping: false,
17946
- }));
17947
- onMessage?.(assistantMessage);
18166
+ // Stream completed - finalize state
18167
+ setState(prev => ({
18168
+ ...prev,
18169
+ isLoading: false,
18170
+ isTyping: false,
18171
+ }));
18172
+ // Notify about final message
18173
+ if (lastStreamedMessage) {
18174
+ onMessage?.(lastStreamedMessage);
17948
18175
  }
17949
18176
  }
17950
18177
  catch (error) {
@@ -18002,11 +18229,11 @@
18002
18229
  conversationId: '',
18003
18230
  error: null,
18004
18231
  }));
18005
- const persistConversation = state.config?.behavior.persistConversation ?? true;
18232
+ const persistConversation = state.config?.settings.persistConversation ?? true;
18006
18233
  if (persistConversation && isStorageAvailable()) {
18007
18234
  clearConversation(widgetId);
18008
18235
  }
18009
- }, [widgetId, state.config?.behavior.persistConversation]);
18236
+ }, [widgetId, state.config?.settings.persistConversation]);
18010
18237
  /**
18011
18238
  * Submit feedback for a message
18012
18239
  */
@@ -18029,6 +18256,78 @@
18029
18256
  onError?.(err);
18030
18257
  }
18031
18258
  }, [state.conversationId, onError]);
18259
+ /**
18260
+ * Load conversation history list from localStorage
18261
+ */
18262
+ const loadConversations = reactExports.useCallback(() => {
18263
+ const persistConversation = state.config?.settings.persistConversation ?? true;
18264
+ if (!persistConversation || !isStorageAvailable()) {
18265
+ setConversations([]);
18266
+ return;
18267
+ }
18268
+ const history = getConversationHistory(widgetId);
18269
+ setConversations(history.map(entry => ({
18270
+ id: entry.id,
18271
+ preview: entry.preview,
18272
+ lastMessageAt: entry.lastUpdated,
18273
+ messageCount: entry.messageCount,
18274
+ startedAt: entry.lastUpdated,
18275
+ })));
18276
+ }, [widgetId, state.config?.settings.persistConversation]);
18277
+ /**
18278
+ * Switch to a different conversation (from localStorage first, then fetch from server if needed)
18279
+ */
18280
+ const switchConversation = reactExports.useCallback(async (conversationId) => {
18281
+ const persistConversation = state.config?.settings.persistConversation ?? true;
18282
+ // First try to load from localStorage
18283
+ if (persistConversation && isStorageAvailable()) {
18284
+ const stored = loadConversationById(widgetId, conversationId);
18285
+ if (stored) {
18286
+ setState(prev => ({
18287
+ ...prev,
18288
+ conversationId: stored.conversationId,
18289
+ messages: stored.messages,
18290
+ }));
18291
+ setActiveConversation(widgetId, conversationId);
18292
+ return;
18293
+ }
18294
+ }
18295
+ // If not in localStorage, fetch from server
18296
+ setState(prev => ({ ...prev, isLoading: true, error: null }));
18297
+ try {
18298
+ const conversation = await apiClient.current.getOrCreateConversation(conversationId);
18299
+ setState(prev => ({
18300
+ ...prev,
18301
+ conversationId: conversation.id,
18302
+ messages: conversation.messages,
18303
+ isLoading: false,
18304
+ }));
18305
+ // Save to local storage
18306
+ if (persistConversation && isStorageAvailable()) {
18307
+ saveConversation(widgetId, conversation.id, conversation.messages);
18308
+ }
18309
+ }
18310
+ catch (error) {
18311
+ const errorInfo = deriveErrorInfo(error);
18312
+ setState(prev => ({ ...prev, isLoading: false, error: errorInfo.message }));
18313
+ }
18314
+ }, [widgetId, state.config?.settings.persistConversation]);
18315
+ /**
18316
+ * Start a new conversation (keeps history)
18317
+ */
18318
+ const startNewConversation = reactExports.useCallback(() => {
18319
+ setState(prev => ({
18320
+ ...prev,
18321
+ messages: [],
18322
+ conversationId: '',
18323
+ error: null,
18324
+ }));
18325
+ // Clear active conversation but keep history
18326
+ const persistConversation = state.config?.settings.persistConversation ?? true;
18327
+ if (persistConversation && isStorageAvailable()) {
18328
+ clearConversation(widgetId);
18329
+ }
18330
+ }, [widgetId, state.config?.settings.persistConversation]);
18032
18331
  return {
18033
18332
  messages: state.messages,
18034
18333
  isLoading: state.isLoading,
@@ -18039,6 +18338,11 @@
18039
18338
  sendMessage,
18040
18339
  clearMessages,
18041
18340
  submitFeedback,
18341
+ // Chat history features
18342
+ conversations,
18343
+ loadConversations,
18344
+ switchConversation,
18345
+ startNewConversation,
18042
18346
  };
18043
18347
  }
18044
18348
 
@@ -38727,7 +39031,7 @@
38727
39031
  return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-sources", children: [jsxRuntimeExports.jsxs("button", { className: "ai-chat-sources-toggle", onClick: () => setIsExpanded(!isExpanded), "aria-expanded": isExpanded, children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-sources-icon", children: isExpanded ? '▼' : '▶' }), jsxRuntimeExports.jsxs("span", { className: "ai-chat-sources-title", children: [sources.length, " source", sources.length > 1 ? 's' : ''] })] }), isExpanded && displayMode !== 'minimal' && (jsxRuntimeExports.jsx("div", { className: "ai-chat-sources-list", children: sources.map((source, index) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-source-item", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-source-number", children: [index + 1, "."] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-source-details", children: [displayMode === 'with-score' && source.score && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-source-score", children: ["Score: ", (source.score * 100).toFixed(0), "%"] })), (displayMode === 'with-content' || displayMode === 'full') && source.doc.pageContent && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-source-content", children: [source.doc.pageContent.substring(0, 100), source.doc.pageContent.length > 100 ? '...' : ''] })), displayMode === 'full' && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [source.score && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-source-score", children: ["Score: ", (source.score * 100).toFixed(0), "%"] })), source.doc.metadata && Object.keys(source.doc.metadata).length > 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-source-metadata", children: Object.entries(source.doc.metadata).map(([key, value]) => (jsxRuntimeExports.jsxs("span", { className: "ai-chat-source-meta-item", children: [key, ": ", String(value)] }, key))) }))] }))] })] }, `${source.kbId}-${source.doc.id}-${index}`))) }))] }));
38728
39032
  };
38729
39033
 
38730
- const Message = ({ message, showTimestamp = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', onFeedback, toolCallNameById, }) => {
39034
+ const Message = ({ message, showTimestamp = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', onFeedback, }) => {
38731
39035
  const formatTime = (timestamp) => {
38732
39036
  const date = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;
38733
39037
  return date.toLocaleTimeString('en-US', {
@@ -38736,72 +39040,84 @@
38736
39040
  hour12: true,
38737
39041
  });
38738
39042
  };
38739
- // Map message type to CSS class
38740
- const messageClass = message.message.type === 'human' ? 'user' :
38741
- message.message.type === 'ai' ? 'assistant' :
38742
- message.message.type === 'system' ? 'system' : 'tool';
38743
- const isAssistant = message.message.type === 'ai';
38744
- const isSystem = message.message.type === 'system';
38745
- const isTool = message.message.type === 'tool';
38746
- const isHuman = message.message.type === 'human';
38747
- const userMessage = isHuman ? message.message.content.split('--- File Content ---')[0] : '';
38748
- const aiContent = isAssistant ? (message.message.content || '') : '';
38749
- const aiHasContent = isAssistant ? aiContent.trim().length > 0 : false;
38750
- const renderAssistant = () => {
38751
- // Only render assistant bubble if there's textual content
38752
- return jsxRuntimeExports.jsx(Markdown, { children: aiContent });
38753
- };
38754
39043
  const formatToolName = (name) => {
38755
- // Remove common prefixes like "action_" or "tool_"
38756
- let formatted = name.replace(/^(action_|tool_)/, '');
38757
- // Convert snake_case to Title Case
38758
- formatted = formatted
39044
+ return name
39045
+ .replace(/^(action_|tool_)/, '')
38759
39046
  .split('_')
38760
39047
  .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
38761
39048
  .join(' ');
38762
- return formatted;
38763
39049
  };
38764
- const renderTool = () => {
38765
- const tool = message.message;
38766
- const rawToolName = (toolCallNameById && toolCallNameById[tool.tool_call_id]) || 'Tool';
38767
- const displayName = formatToolName(rawToolName);
38768
- return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-tool-message", title: rawToolName, children: [jsxRuntimeExports.jsx("span", { className: "tool-finished", children: jsxRuntimeExports.jsx("span", { className: "tool-check", children: "\u2713" }) }), jsxRuntimeExports.jsx("span", { className: "tool-name", children: displayName })] }));
38769
- };
38770
- // If assistant message has no content (e.g., only started a tool), render nothing at all
38771
- if (isAssistant && !aiHasContent) {
38772
- return null;
39050
+ const SpinnerIcon = () => (jsxRuntimeExports.jsx("svg", { className: "ai-chat-tool-spinner", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) }));
39051
+ const CheckIcon = () => (jsxRuntimeExports.jsx("svg", { className: "ai-chat-tool-check", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "20 6 9 17 4 12" }) }));
39052
+ const ErrorIcon = () => (jsxRuntimeExports.jsx("svg", { className: "ai-chat-tool-error", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }));
39053
+ const msgType = message.message.type;
39054
+ const isError = message.isError || false;
39055
+ const isTool = msgType === 'tool';
39056
+ const isAssistant = msgType === 'ai';
39057
+ const isSystem = msgType === 'system';
39058
+ const isHuman = msgType === 'human';
39059
+ // Tool message rendering - show as a minimal pill
39060
+ if (isTool) {
39061
+ // Get tool name from toolExecuting (during execution) or message.name (persisted)
39062
+ const toolName = message.toolExecuting || message.message.name || 'Tool';
39063
+ const hasError = isError;
39064
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-message tool", children: jsxRuntimeExports.jsxs("div", { className: `ai-chat-tool-message ${hasError ? 'error' : ''}`, title: toolName, children: [message.isStreaming ? (jsxRuntimeExports.jsx(SpinnerIcon, {})) : hasError ? (jsxRuntimeExports.jsx(ErrorIcon, {})) : (jsxRuntimeExports.jsx(CheckIcon, {})), jsxRuntimeExports.jsx("span", { className: "tool-name", children: formatToolName(toolName) })] }) }));
39065
+ }
39066
+ // AI message rendering
39067
+ if (isAssistant) {
39068
+ const aiContent = message.message.content || '';
39069
+ const hasContent = aiContent.trim().length > 0;
39070
+ if (!hasContent)
39071
+ return null;
39072
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-message assistant ${isError ? 'error' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-message-content", children: [isError && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-error-indicator", children: [jsxRuntimeExports.jsx("span", { className: "error-icon", children: "\u26A0\uFE0F" }), jsxRuntimeExports.jsx("span", { className: "error-text", children: "Error" })] })), jsxRuntimeExports.jsx(Markdown, { children: aiContent })] }), showTimestamp && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-message-meta", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }), enableFeedback && onFeedback && (jsxRuntimeExports.jsx(FeedbackButtons, { messageId: message.id, currentFeedback: message.feedback, onFeedback: onFeedback }))] })), showSources && message.sources?.length > 0 && (jsxRuntimeExports.jsx(Sources, { sources: message.sources, displayMode: sourceDisplayMode }))] }));
39073
+ }
39074
+ // System message rendering
39075
+ if (isSystem) {
39076
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-message system", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-message-content", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-system-message", children: [jsxRuntimeExports.jsx("span", { className: "system-icon", children: "\u2139\uFE0F" }), message.message.content] }) }), showTimestamp && (jsxRuntimeExports.jsx("div", { className: "ai-chat-message-meta", children: jsxRuntimeExports.jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }) }))] }));
38773
39077
  }
38774
- const showTimestampForThis = showTimestamp && !isTool && !(isAssistant && !aiHasContent);
38775
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-message ${messageClass}`, children: [isTool ? (
38776
- // Render tool call completion as a standalone, non-bubble event
38777
- renderTool()) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-message-content", children: isAssistant ? (renderAssistant()) : isSystem ? (jsxRuntimeExports.jsxs("div", { className: "ai-chat-system-message", children: [jsxRuntimeExports.jsx("span", { className: "system-icon", children: "\u2139\uFE0F" }), message.message.content] })) : (userMessage) })), showTimestampForThis && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-message-meta", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }), isAssistant && aiHasContent && enableFeedback && onFeedback && (jsxRuntimeExports.jsx(FeedbackButtons, { messageId: message.id, currentFeedback: message.feedback, onFeedback: onFeedback }))] })), isAssistant && aiHasContent && showSources && message.sources && message.sources.length > 0 && (jsxRuntimeExports.jsx(Sources, { sources: message.sources, displayMode: sourceDisplayMode }))] }));
39078
+ // Human message rendering
39079
+ if (isHuman) {
39080
+ const userContent = message.message.content.split('--- File Content ---')[0];
39081
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-message user", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-message-content", children: userContent }), showTimestamp && (jsxRuntimeExports.jsx("div", { className: "ai-chat-message-meta", children: jsxRuntimeExports.jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }) }))] }));
39082
+ }
39083
+ return null;
38778
39084
  };
38779
39085
 
38780
39086
  const TypingIndicator = () => {
38781
39087
  return (jsxRuntimeExports.jsx("div", { className: "ai-chat-message assistant", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-typing", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-typing-dot" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-typing-dot" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-typing-dot" })] }) }));
38782
39088
  };
38783
39089
 
38784
- const MessageList = ({ messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', welcomeTitle, welcomeMessage, onFeedback, }) => {
39090
+ const SuggestedQuestions = ({ questions, onQuestionClick, }) => {
39091
+ if (!questions || questions.length === 0) {
39092
+ return null;
39093
+ }
39094
+ // Filter out empty questions
39095
+ const validQuestions = questions.filter(q => q && q.trim());
39096
+ if (validQuestions.length === 0) {
39097
+ return null;
39098
+ }
39099
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-suggested-questions", children: jsxRuntimeExports.jsx("div", { className: "ai-chat-suggested-questions-list", children: validQuestions.slice(0, 5).map((question, index) => (jsxRuntimeExports.jsx("button", { className: "ai-chat-suggested-question", onClick: () => onQuestionClick(question), type: "button", children: jsxRuntimeExports.jsx("span", { className: "ai-chat-suggested-question-text", children: question }) }, index))) }) }));
39100
+ };
39101
+
39102
+ const MessageList = ({ messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', welcomeTitle, welcomeMessage, suggestedQuestions, onSuggestedQuestionClick, onFeedback, }) => {
39103
+ const containerRef = reactExports.useRef(null);
38785
39104
  const messagesEndRef = reactExports.useRef(null);
38786
- // Auto-scroll to bottom when new messages arrive
39105
+ // Auto-scroll to bottom only on initial mount/load
38787
39106
  reactExports.useEffect(() => {
38788
- messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
38789
- }, [messages, isTyping]);
38790
- // Build a map from tool_call_id -> tool name from AI messages
38791
- const toolCallNameById = reactExports.useMemo(() => {
38792
- const map = {};
38793
- for (const m of messages) {
38794
- if (m.message.type === 'ai' && Array.isArray(m.message.tool_calls)) {
38795
- for (const tc of m.message.tool_calls) {
38796
- if (tc?.id && tc?.name) {
38797
- map[tc.id] = tc.name;
38798
- }
38799
- }
38800
- }
39107
+ const container = containerRef.current;
39108
+ if (!container)
39109
+ return;
39110
+ // Only scroll if content actually overflows AND the user is near the bottom.
39111
+ // This prevents the "first message" case from being pushed to the very bottom
39112
+ // (which looks like a huge empty gap above the first user message).
39113
+ const overflow = container.scrollHeight - container.clientHeight;
39114
+ const isOverflowing = overflow > 20;
39115
+ const nearBottom = container.scrollTop + container.clientHeight >= container.scrollHeight - 80;
39116
+ if (isOverflowing && nearBottom) {
39117
+ messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
38801
39118
  }
38802
- return map;
38803
- }, [messages]);
38804
- return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-messages", role: "log", "aria-live": "polite", "aria-atomic": "false", children: [messages.length === 0 && (welcomeTitle || welcomeMessage) && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-welcome", children: [welcomeTitle && (jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-title", children: welcomeTitle })), welcomeMessage && (jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-text", children: welcomeMessage }))] })), messages.map((message) => (jsxRuntimeExports.jsx(Message, { message: message, showTimestamp: showTimestamps, enableFeedback: enableFeedback, showSources: showSources, sourceDisplayMode: sourceDisplayMode, toolCallNameById: toolCallNameById, onFeedback: onFeedback }, message.id))), isTyping && showTypingIndicator && jsxRuntimeExports.jsx(TypingIndicator, {}), jsxRuntimeExports.jsx("div", { ref: messagesEndRef })] }));
39119
+ }, [messages, isTyping]);
39120
+ return (jsxRuntimeExports.jsxs("div", { ref: containerRef, className: "ai-chat-messages", role: "log", "aria-live": "polite", "aria-atomic": "false", children: [(welcomeTitle || welcomeMessage) && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-welcome", children: [welcomeTitle && (jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-title", children: welcomeTitle })), welcomeMessage && (jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-text", children: welcomeMessage })), messages.length === 0 && onSuggestedQuestionClick && suggestedQuestions && suggestedQuestions.length > 0 && (jsxRuntimeExports.jsx(SuggestedQuestions, { questions: suggestedQuestions, onQuestionClick: onSuggestedQuestionClick }))] })), messages.map((message) => (jsxRuntimeExports.jsx(Message, { message: message, showTimestamp: showTimestamps, enableFeedback: enableFeedback, showSources: showSources, sourceDisplayMode: sourceDisplayMode, onFeedback: onFeedback }, message.id))), isTyping && showTypingIndicator && jsxRuntimeExports.jsx(TypingIndicator, {}), jsxRuntimeExports.jsx("div", { ref: messagesEndRef })] }));
38805
39121
  };
38806
39122
 
38807
39123
  // Allowed file types
@@ -38889,58 +39205,98 @@
38889
39205
  return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-input-container ${separateFromChat ? 'separate' : 'integrated'}`, children: [selectedFiles.length > 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-file-list", children: selectedFiles.map((file, index) => {
38890
39206
  const ext = getFileExtension(file.name);
38891
39207
  return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-item", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-extension", children: ext }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-info", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-name", children: file.name }), jsxRuntimeExports.jsx("span", { className: "ai-chat-file-size", children: formatFileSize(file.size) })] }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-remove", onClick: () => handleRemoveFile(index), "aria-label": "Remove file", children: jsxRuntimeExports.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) })] }, index));
38892
- }) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(','), "aria-label": "File input" }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsxRuntimeExports.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) })] })), jsxRuntimeExports.jsx("textarea", { ref: textareaRef, className: "ai-chat-input", value: value, onChange: handleChange, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, rows: 1, "aria-label": "Message input" }), jsxRuntimeExports.jsx("button", { className: `ai-chat-send-button ${canSend ? 'active' : ''}`, onClick: handleSend, disabled: disabled || !canSend, "aria-label": "Send message", children: jsxRuntimeExports.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M22 2L11 13" }), jsxRuntimeExports.jsx("path", { d: "M22 2L15 22L11 13L2 9L22 2Z" })] }) })] })] }));
39208
+ }) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(','), "aria-label": "File input" }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsxRuntimeExports.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) })] })), jsxRuntimeExports.jsx("textarea", { ref: textareaRef, className: "ai-chat-input", value: value, onChange: handleChange, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, rows: 1, "aria-label": "Message input" }), jsxRuntimeExports.jsx("button", { className: `ai-chat-send-button ${canSend ? 'active' : ''}`, onClick: handleSend, disabled: disabled || !canSend, "aria-label": "Send message", children: jsxRuntimeExports.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M12 19V5" }), jsxRuntimeExports.jsx("path", { d: "M5 12l7-7 7 7" })] }) })] })] }));
38893
39209
  };
38894
39210
 
38895
- const ArrowIcon = () => (jsxRuntimeExports.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M5 12h14M12 5l7 7-7 7" }) }));
38896
- const SuggestedQuestions = ({ questions, onQuestionClick, }) => {
38897
- if (!questions || questions.length === 0) {
38898
- return null;
38899
- }
38900
- // Filter out empty questions
38901
- const validQuestions = questions.filter(q => q && q.trim());
38902
- if (validQuestions.length === 0) {
38903
- return null;
38904
- }
38905
- return (jsxRuntimeExports.jsx("div", { className: "ai-chat-suggested-questions", children: jsxRuntimeExports.jsx("div", { className: "ai-chat-suggested-questions-list", children: validQuestions.slice(0, 3).map((question, index) => (jsxRuntimeExports.jsxs("button", { className: "ai-chat-suggested-question", onClick: () => onQuestionClick(question), type: "button", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-suggested-question-text", children: question }), jsxRuntimeExports.jsx("span", { className: "ai-chat-suggested-question-icon", children: jsxRuntimeExports.jsx(ArrowIcon, {}) })] }, index))) }) }));
38906
- };
38907
-
38908
- const MinimizeIcon = () => (jsxRuntimeExports.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M5 12h14" }) }));
38909
- const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessage, onClose, onFeedback, }) => {
39211
+ const MenuIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "26", height: "26", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M4 10h16" }), jsxRuntimeExports.jsx("path", { d: "M10 14h10" })] }));
39212
+ const PlusIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "26", height: "26", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M12 5v14" }), jsxRuntimeExports.jsx("path", { d: "M5 12h14" })] }));
39213
+ const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessage, onClose: _onClose, onFeedback,
39214
+ // Chat history props (only active when persistConversation is true)
39215
+ conversations = [], onLoadConversations, onSwitchConversation, onStartNewConversation, currentConversationId,
39216
+ // Override props for live preview
39217
+ headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOverride, suggestedQuestionsOverride, }) => {
38910
39218
  console.log('[ChatWindow] Rendering ChatWindow component');
38911
39219
  const appearance = config?.appearance;
38912
- const behavior = config?.behavior;
38913
- // Use simplified appearance fields
39220
+ const settings = config?.settings;
39221
+ // Check if chat history should be shown (requires both persistConversation AND showChatHistory)
39222
+ const canShowHistory = (settings?.persistConversation ?? true) && (settings?.showChatHistory ?? true);
39223
+ // Apply overrides for live preview (overrides take priority over saved config)
38914
39224
  const size = appearance?.size || 'medium';
38915
- const headerTitle = appearance?.headerTitle || 'AI Assistant';
38916
- const welcomeMessage = appearance?.welcomeMessage || '👋 Hi there! How can I assist you today?';
38917
- const inputPlaceholder = appearance?.placeholder || 'Ask me anything...';
39225
+ const headerTitle = headerTitleOverride ?? appearance?.headerTitle ?? 'AI Assistant';
39226
+ const welcomeTitle = welcomeTitleOverride ?? appearance?.welcomeTitle ?? '';
39227
+ const welcomeMessage = welcomeMessageOverride ?? appearance?.welcomeMessage ?? '';
39228
+ const inputPlaceholder = placeholderOverride ?? appearance?.placeholder ?? 'Ask me anything...';
38918
39229
  console.log('[ChatWindow] Appearance values:', {
38919
39230
  size,
38920
39231
  headerTitle,
39232
+ welcomeTitle,
38921
39233
  welcomeMessage,
38922
39234
  inputPlaceholder,
38923
39235
  });
38924
- // Track if suggested questions should be shown
38925
- const [showSuggestedQuestions, setShowSuggestedQuestions] = reactExports.useState(true);
38926
- // Hide suggested questions after first user message
38927
- reactExports.useEffect(() => {
38928
- const userMessages = messages.filter(m => m.message.type === 'human');
38929
- if (userMessages.length > 0) {
38930
- setShowSuggestedQuestions(false);
39236
+ // Track if history panel is open
39237
+ const [showHistory, setShowHistory] = reactExports.useState(false);
39238
+ // History exit animation when starting a new chat from overview
39239
+ const [isHistoryExiting, setIsHistoryExiting] = reactExports.useState(false);
39240
+ // Load conversations when history panel opens
39241
+ const handleOpenHistory = () => {
39242
+ setShowHistory(true);
39243
+ if (onLoadConversations) {
39244
+ onLoadConversations();
39245
+ }
39246
+ };
39247
+ // Handle conversation selection
39248
+ const handleSelectConversation = async (conversationId) => {
39249
+ if (onSwitchConversation) {
39250
+ await onSwitchConversation(conversationId);
39251
+ setShowHistory(false);
38931
39252
  }
38932
- }, [messages]);
39253
+ };
39254
+ const handleNewConversation = () => {
39255
+ if (!onStartNewConversation)
39256
+ return;
39257
+ onStartNewConversation();
39258
+ setShowHistory(false);
39259
+ };
39260
+ const handleSendFromOverview = (content) => {
39261
+ const trimmed = content.trim();
39262
+ if (!trimmed)
39263
+ return;
39264
+ if (!onStartNewConversation) {
39265
+ // Fallback: just go back to chat and send
39266
+ setShowHistory(false);
39267
+ onSendMessage(trimmed);
39268
+ return;
39269
+ }
39270
+ setIsHistoryExiting(true);
39271
+ window.setTimeout(() => {
39272
+ onStartNewConversation();
39273
+ setShowHistory(false);
39274
+ setIsHistoryExiting(false);
39275
+ onSendMessage(trimmed);
39276
+ }, 240);
39277
+ };
38933
39278
  // Check if message limit is reached
38934
- const maxMessages = behavior?.maxMessagesPerSession;
39279
+ const maxMessages = settings?.maxMessagesPerSession;
38935
39280
  const userMessageCount = messages.filter(m => m.message.type === 'human').length;
38936
39281
  const isLimitReached = maxMessages ? userMessageCount >= maxMessages : false;
38937
- // Handle suggested question click
38938
39282
  const handleQuestionClick = (question) => {
38939
- setShowSuggestedQuestions(false);
38940
39283
  onSendMessage(question);
38941
39284
  };
38942
- const hasMessages = messages.length > 0;
38943
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-header", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsxRuntimeExports.jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsxRuntimeExports.jsx("button", { className: "ai-chat-close-button", onClick: onClose, "aria-label": "Minimize chat", children: jsxRuntimeExports.jsx(MinimizeIcon, {}) })] }), error && (jsxRuntimeExports.jsx("div", { className: "ai-chat-error", role: "alert", children: error })), maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining"] })), isLimitReached && (jsxRuntimeExports.jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. Please start a new conversation." })), jsxRuntimeExports.jsx(MessageList, { messages: messages, isTyping: isTyping, showTypingIndicator: behavior?.showTypingIndicator, showTimestamps: behavior?.showTimestamps, enableFeedback: behavior?.enableFeedback, showSources: behavior?.showSources, sourceDisplayMode: behavior?.sourceDisplayMode, welcomeMessage: welcomeMessage, onFeedback: onFeedback }), showSuggestedQuestions && !hasMessages && behavior?.suggestedQuestions && behavior.suggestedQuestions.length > 0 && (jsxRuntimeExports.jsx(SuggestedQuestions, { questions: behavior.suggestedQuestions, onQuestionClick: handleQuestionClick })), jsxRuntimeExports.jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : inputPlaceholder, disabled: isLoading || isLimitReached, enableFileUpload: behavior?.enableFileUpload })] }));
39285
+ // Format date for conversation list
39286
+ const formatDate = (dateString) => {
39287
+ const date = new Date(dateString);
39288
+ const now = new Date();
39289
+ const diffMs = now.getTime() - date.getTime();
39290
+ const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
39291
+ if (diffDays === 0)
39292
+ return 'Today';
39293
+ if (diffDays === 1)
39294
+ return 'Yesterday';
39295
+ if (diffDays < 7)
39296
+ return `${diffDays} days ago`;
39297
+ return date.toLocaleDateString();
39298
+ };
39299
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxRuntimeExports.jsx("div", { className: `ai-chat-header ${showHistory ? 'is-history' : ''}`, children: showHistory ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle }), jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleNewConversation, "aria-label": "New chat", children: jsxRuntimeExports.jsx(PlusIcon, {}) })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsxRuntimeExports.jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle })] }), canShowHistory && (jsxRuntimeExports.jsx("div", { className: "ai-chat-header-actions", children: jsxRuntimeExports.jsx("button", { className: "ai-chat-close-button", onClick: handleOpenHistory, "aria-label": "Chat overview", children: jsxRuntimeExports.jsx(MenuIcon, {}) }) }))] })) }), showHistory ? (jsxRuntimeExports.jsxs("div", { className: "ai-chat-history-panel", children: [conversations.length === 0 ? (jsxRuntimeExports.jsx("div", { className: "ai-chat-history-empty", children: "No previous conversations" })) : (jsxRuntimeExports.jsx("div", { className: `ai-chat-history-list ${isHistoryExiting ? 'exiting' : ''}`, children: conversations.map((conv) => (jsxRuntimeExports.jsxs("button", { className: `ai-chat-history-item ${conv.id === currentConversationId ? 'active' : ''}`, onClick: () => handleSelectConversation(conv.id), children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-history-item-preview", children: conv.preview }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-history-item-meta", children: [jsxRuntimeExports.jsx("span", { children: formatDate(conv.lastMessageAt) }), jsxRuntimeExports.jsxs("span", { children: [conv.messageCount, " messages"] })] })] }, conv.id))) })), jsxRuntimeExports.jsx(MessageInput, { onSend: (text) => handleSendFromOverview(text), placeholder: inputPlaceholder, disabled: isLoading, enableFileUpload: settings?.enableFileUpload })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [error && (jsxRuntimeExports.jsx("div", { className: "ai-chat-error", role: "alert", children: error })), maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining"] })), isLimitReached && (jsxRuntimeExports.jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. Please start a new conversation." })), jsxRuntimeExports.jsx(MessageList, { messages: messages, isTyping: isTyping, showTypingIndicator: settings?.showTypingIndicator, showTimestamps: settings?.showTimestamps, enableFeedback: settings?.enableFeedback, showSources: settings?.showSources, sourceDisplayMode: settings?.sourceDisplayMode, welcomeTitle: welcomeTitle || 'Welcome Message', welcomeMessage: welcomeMessage, suggestedQuestions: suggestedQuestionsOverride ?? settings?.suggestedQuestions, onSuggestedQuestionClick: handleQuestionClick, onFeedback: onFeedback }), jsxRuntimeExports.jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : inputPlaceholder, disabled: isLoading || isLimitReached, enableFileUpload: settings?.enableFileUpload })] }))] }));
38944
39300
  };
38945
39301
 
38946
39302
  /**
@@ -39123,22 +39479,18 @@
39123
39479
  * Generate all CSS custom properties for the widget
39124
39480
  */
39125
39481
  function generateThemeStyles(appearance, theme) {
39126
- const palette = theme === 'dark'
39127
- ? generateDarkPalette(appearance.accentColor)
39128
- : generateLightPalette(appearance.accentColor);
39482
+ const hasAccentColor = appearance.accentColor && appearance.accentColor.trim() !== '';
39129
39483
  // Liquid glass design - frosted glass with transparency
39130
39484
  const isLight = theme === 'light';
39131
- return {
39485
+ // Base styles that don't depend on accent color
39486
+ const styles = {
39132
39487
  // ========================================================================
39133
- // BUTTON (FAB) - Liquid Glass Style
39488
+ // BUTTON (FAB) - Base styles
39134
39489
  // ========================================================================
39135
- '--button-color': palette.accent,
39136
39490
  '--button-opacity': '1',
39137
39491
  '--button-size': '56px',
39138
- '--button-icon-color': palette.userBubbleText,
39139
39492
  '--button-border-radius': '50%',
39140
39493
  '--button-border-width': '0px',
39141
- '--button-border-color': palette.accent,
39142
39494
  '--button-border-opacity': '1',
39143
39495
  '--button-backdrop-blur': '20px',
39144
39496
  '--button-shadow': `0 4px 24px rgba(0, 0, 0, 0.15), 0 2px 8px rgba(0, 0, 0, 0.1)`,
@@ -39161,7 +39513,6 @@
39161
39513
  // ========================================================================
39162
39514
  '--header-background': 'transparent',
39163
39515
  '--header-opacity': '1',
39164
- '--header-text-color': palette.accent,
39165
39516
  '--header-border-bottom-width': '0px',
39166
39517
  '--header-border-bottom-color': 'transparent',
39167
39518
  '--header-border-bottom-opacity': '0',
@@ -39171,17 +39522,13 @@
39171
39522
  // ========================================================================
39172
39523
  '--chat-background': 'transparent',
39173
39524
  '--chat-opacity': '1',
39174
- '--welcome-color': palette.text,
39175
- '--message-text-color': palette.text,
39176
39525
  // ========================================================================
39177
39526
  // MESSAGE BUBBLES - Glass style
39178
39527
  // ========================================================================
39179
- '--bubble-user-color': palette.userBubble,
39180
39528
  '--bubble-user-opacity': '1',
39181
- '--user-message-text': palette.userBubbleText,
39182
39529
  '--bubble-assistant-color': isLight ? 'rgba(255, 255, 255, 0.8)' : 'rgba(255, 255, 255, 0.1)',
39183
39530
  '--bubble-assistant-opacity': '1',
39184
- '--assistant-message-text': isLight ? palette.text : '#f0f0f0',
39531
+ '--assistant-message-text': isLight ? '#000000' : '#f0f0f0',
39185
39532
  '--bubble-border-radius': '20px',
39186
39533
  '--bubble-border-width': isLight ? '1px' : '1px',
39187
39534
  '--bubble-border-color': isLight ? 'rgba(0, 0, 0, 0.05)' : 'rgba(255, 255, 255, 0.08)',
@@ -39203,38 +39550,48 @@
39203
39550
  '--input-border-color': isLight ? 'rgba(0, 0, 0, 0.08)' : 'rgba(255, 255, 255, 0.1)',
39204
39551
  '--input-border-opacity': '1',
39205
39552
  '--input-shadow': `inset 0 1px 3px rgba(0, 0, 0, 0.04), 0 2px 8px rgba(0, 0, 0, 0.04)`,
39206
- '--send-button-background': palette.accent,
39207
39553
  '--send-button-opacity': '1',
39208
39554
  '--send-button-border-radius': '50%',
39209
39555
  '--send-button-border-width': '0px',
39210
- '--send-button-border-color': palette.accent,
39211
39556
  '--send-button-border-opacity': '1',
39212
39557
  // ========================================================================
39213
39558
  // HOVER STATES
39214
39559
  // ========================================================================
39215
39560
  '--hover-button-scale': '1.08',
39216
39561
  '--hover-button-opacity': '1',
39217
- '--hover-input-border-color': palette.accent,
39218
39562
  '--hover-send-button-opacity': '1',
39219
39563
  '--hover-close-button-opacity': '1',
39220
39564
  // ========================================================================
39221
- // ACTIVE STATES
39222
- // ========================================================================
39223
- '--active-input-border-color': palette.accent,
39224
- '--active-input-shadow': `0 0 0 4px ${withAlpha(palette.accent, 0.15)}`,
39225
- // ========================================================================
39226
- // GENERAL
39227
- // ========================================================================
39228
- '--primary-color': palette.accent,
39229
- '--background-color': palette.background,
39230
- '--text-color': palette.text,
39231
- '--border-color': palette.border,
39232
- // ========================================================================
39233
39565
  // GLASS EFFECTS
39234
39566
  // ========================================================================
39235
39567
  '--glass-blur': '20px',
39236
39568
  '--glass-saturation': '180%',
39237
39569
  };
39570
+ // Only add accent-color-based styles if an accent color is provided
39571
+ if (hasAccentColor) {
39572
+ const palette = theme === 'dark'
39573
+ ? generateDarkPalette(appearance.accentColor)
39574
+ : generateLightPalette(appearance.accentColor);
39575
+ // Add accent color styles
39576
+ styles['--button-color'] = palette.accent;
39577
+ styles['--button-icon-color'] = palette.userBubbleText;
39578
+ styles['--button-border-color'] = palette.accent;
39579
+ styles['--header-text-color'] = palette.accent;
39580
+ styles['--welcome-color'] = palette.text;
39581
+ styles['--message-text-color'] = palette.text;
39582
+ styles['--bubble-user-color'] = palette.userBubble;
39583
+ styles['--user-message-text'] = palette.userBubbleText;
39584
+ styles['--send-button-background'] = palette.accent;
39585
+ styles['--send-button-border-color'] = palette.accent;
39586
+ styles['--hover-input-border-color'] = palette.accent;
39587
+ styles['--active-input-border-color'] = palette.accent;
39588
+ styles['--active-input-shadow'] = `0 0 0 4px ${withAlpha(palette.accent, 0.15)}`;
39589
+ styles['--primary-color'] = palette.accent;
39590
+ styles['--background-color'] = palette.background;
39591
+ styles['--text-color'] = palette.text;
39592
+ styles['--border-color'] = palette.border;
39593
+ }
39594
+ return styles;
39238
39595
  }
39239
39596
 
39240
39597
  /**
@@ -39345,7 +39702,7 @@
39345
39702
  if ( ref === void 0 ) ref = {};
39346
39703
  var insertAt = ref.insertAt;
39347
39704
 
39348
- if (!css || typeof document === 'undefined') { return; }
39705
+ if (typeof document === 'undefined') { return; }
39349
39706
 
39350
39707
  var head = document.head || document.getElementsByTagName('head')[0];
39351
39708
  var style = document.createElement('style');
@@ -39368,10 +39725,7 @@
39368
39725
  }
39369
39726
  }
39370
39727
 
39371
- var css_248z$1 = ".ai-chat-widget{--primary-color:#07f;--background-color:#fff;--text-color:#1f2937;--border-color:#e5e7eb;--user-message-bg:var(--primary-color);--user-message-text:#fff;--assistant-message-bg:#f3f4f6;--assistant-message-text:#374151;--input-bg:#fff;--input-border:#d1d5db;--shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);--shadow-lg:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);--button-color:#07f;--button-size:56px;--button-border-radius:28px;--button-border-width:0px;--button-border-color:#07f;--button-opacity:1;--button-backdrop-blur:0px;--button-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);--card-background:#fff;--card-border-radius:16px;--card-border-width:0px;--card-border-color:#e5e7eb;--card-opacity:1;--card-backdrop-blur:0px;--card-shadow:0 25px 50px -12px rgba(0,0,0,.25);--header-background:#07f;--header-text-color:#fff;--header-font-size:18px;--header-border-bottom-width:0px;--header-border-bottom-color:#e5e7eb;--header-opacity:1;--header-backdrop-blur:0px;--chat-background:#fff;--chat-opacity:1;--chat-backdrop-blur:0px;--welcome-font-size:16px;--welcome-color:#1f2937;--welcome-opacity:1;--bubble-user-color:#07f;--bubble-assistant-color:#f3f4f6;--bubble-border-radius:16px;--bubble-border-width:0px;--bubble-border-color:#e5e7eb;--bubble-opacity:1;--typing-animation-color:#f3f4f6;--typing-animation-opacity:1;--typing-animation-border-width:0px;--typing-animation-border-color:#e5e7eb;--typing-animation-border-radius:16px;--footer-background:#fff;--footer-border-top-width:1px;--footer-border-top-color:#e5e7eb;--footer-opacity:1;--footer-backdrop-blur:0px;--input-background:#fff;--input-border-radius:24px;--input-border-width:1.5px;--input-border-color:#d1d5db;--input-opacity:1;--input-shadow:0 1px 2px 0 rgba(0,0,0,.05);--send-button-background:#07f;--send-button-border-radius:20px;--send-button-border-width:0px;--send-button-border-color:#07f;--send-button-opacity:1;--hover-button-scale:1.05;--hover-button-opacity:0.9;--hover-input-border-color:#9ca3af;--hover-send-button-opacity:0.85;--hover-close-button-opacity:1;--active-input-border-color:#07f;--active-input-shadow:0 0 0 3px rgba(0,119,255,.1);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.ai-chat-widget.dark{--background-color:#001d3d;--text-color:#f9fafb;--border-color:#374151;--assistant-message-bg:#036;--assistant-message-text:#e5e7eb;--input-bg:#002855;--input-border:#374151}.ai-chat-widget.dark .ai-chat-message.system .ai-chat-message-content{background-color:#78350f;color:#fef3c7}.ai-chat-widget.dark .ai-chat-message.tool .ai-chat-message-content{background-color:#1e3a8a;color:#dbeafe}.ai-chat-widget-container{font-size:14px;line-height:1.5;position:fixed;z-index:9999}.ai-chat-widget-container.bottom-right{bottom:20px;right:20px}.ai-chat-widget-container.bottom-left{bottom:20px;left:20px}.ai-chat-widget-container.top-right{right:20px;top:20px}.ai-chat-widget-container.top-left{left:20px;top:20px}.ai-chat-button{align-items:center;backdrop-filter:blur(var(--button-backdrop-blur));-webkit-backdrop-filter:blur(var(--button-backdrop-blur));background-color:var(--button-color);border:var(--button-border-width) solid var(--button-border-color);border-radius:var(--button-border-radius);box-shadow:var(--button-shadow);color:#fff;cursor:pointer;display:flex;height:var(--button-size);justify-content:center;opacity:var(--button-opacity);transition:all .3s cubic-bezier(.4,0,.2,1);width:var(--button-size)}.ai-chat-button:hover{opacity:.9}.ai-chat-button:active{opacity:.8}.ai-chat-button-svg{height:50%;min-height:24px;min-width:24px;width:50%}.ai-chat-button-icon{font-size:1.5em;line-height:1}.ai-chat-window{border-radius:var(--card-border-radius);box-shadow:0 0 0 var(--card-border-width) var(--card-border-color-rgba,var(--card-border-color)),var(--card-shadow);display:flex;flex-direction:column;overflow:hidden;position:absolute}.ai-chat-window>*{position:relative;z-index:1}.ai-chat-window:before{backdrop-filter:blur(var(--card-backdrop-blur));-webkit-backdrop-filter:blur(var(--card-backdrop-blur));background-color:var(--card-background);border-radius:var(--card-border-radius);content:\"\";inset:0;opacity:var(--card-opacity);pointer-events:none;position:absolute;z-index:0}.ai-chat-widget-container.bottom-right .ai-chat-window{bottom:calc(var(--button-size, 60px) + 16px);right:0}.ai-chat-widget-container.bottom-left .ai-chat-window{bottom:calc(var(--button-size, 60px) + 16px);left:0}.ai-chat-widget-container.top-right .ai-chat-window{right:0;top:calc(var(--button-size, 60px) + 16px)}.ai-chat-widget-container.top-left .ai-chat-window{left:0;top:calc(var(--button-size, 60px) + 16px)}.ai-chat-button{z-index:1}.ai-chat-window{z-index:2}.ai-chat-window.size-small{height:500px;width:380px}.ai-chat-window.size-medium{height:650px;width:440px}.ai-chat-window.size-large{height:750px;width:520px}.ai-chat-logo{border-radius:50%;height:32px;object-fit:cover;width:32px}.ai-chat-messages::-webkit-scrollbar{width:6px}.ai-chat-messages::-webkit-scrollbar-track{background:transparent}.ai-chat-messages::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:3px}.ai-chat-messages::-webkit-scrollbar-thumb:hover{background:var(--input-border)}.ai-chat-message{display:flex;flex-direction:column;gap:4px}.ai-chat-message.user{align-items:flex-end}.ai-chat-message.assistant{align-items:flex-start}.ai-chat-message.system{align-items:center}.ai-chat-message.tool{align-items:flex-start}.ai-chat-message-content{word-wrap:break-word;border:var(--bubble-border-width) solid var(--bubble-border-color);border-radius:var(--bubble-border-radius);font-size:15px;line-height:1.6;max-width:80%;opacity:var(--bubble-opacity);padding:12px 16px}.ai-chat-message.user .ai-chat-message-content{background-color:var(--bubble-user-color);border-bottom-right-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.1);color:var(--user-message-text)}.ai-chat-message.assistant .ai-chat-message-content{background-color:var(--bubble-assistant-color,#f3f4f6);border:1px solid var(--bubble-border-color,rgba(0,0,0,.08));border-radius:var(--bubble-border-radius,16px);border-bottom-left-radius:4px;box-shadow:none;color:var(--assistant-message-text);max-width:85%;padding:12px 16px}.ai-chat-message.assistant .ai-chat-message-content p{margin:0 0 12px}.ai-chat-message.assistant .ai-chat-message-content p:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content ol,.ai-chat-message.assistant .ai-chat-message-content ul{margin:8px 0 12px;padding-left:24px}.ai-chat-message.assistant .ai-chat-message-content li{line-height:1.5;margin:6px 0}.ai-chat-message.assistant .ai-chat-message-content li::marker{color:var(--primary-color,#07f)}.ai-chat-message.assistant .ai-chat-message-content ol li::marker{font-weight:600}.ai-chat-message.assistant .ai-chat-message-content strong{font-weight:600}.ai-chat-message.assistant .ai-chat-message-content em{font-style:italic}.ai-chat-message.assistant .ai-chat-message-content code{background-color:rgba(0,0,0,.06);border-radius:4px;font-family:SF Mono,Consolas,Monaco,monospace;font-size:.9em;padding:2px 6px}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content code{background-color:hsla(0,0%,100%,.1)}.ai-chat-message.assistant .ai-chat-message-content pre{background-color:rgba(0,0,0,.06);border-radius:8px;margin:8px 0 12px;overflow-x:auto;padding:12px}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content pre{background-color:hsla(0,0%,100%,.08)}.ai-chat-message.assistant .ai-chat-message-content pre code{background-color:transparent;border-radius:0;padding:0}.ai-chat-message.assistant .ai-chat-message-content blockquote{border-left:3px solid var(--primary-color,#07f);color:var(--text-muted,#6b7280);margin:8px 0 12px;padding:4px 0 4px 12px}.ai-chat-message.assistant .ai-chat-message-content a{color:var(--primary-color,#07f);text-decoration:underline}.ai-chat-message.assistant .ai-chat-message-content a:hover{opacity:.8}.ai-chat-message.assistant .ai-chat-message-content h1,.ai-chat-message.assistant .ai-chat-message-content h2,.ai-chat-message.assistant .ai-chat-message-content h3,.ai-chat-message.assistant .ai-chat-message-content h4,.ai-chat-message.assistant .ai-chat-message-content h5,.ai-chat-message.assistant .ai-chat-message-content h6{font-weight:600;line-height:1.3;margin:16px 0 8px}.ai-chat-message.assistant .ai-chat-message-content h1:first-child,.ai-chat-message.assistant .ai-chat-message-content h2:first-child,.ai-chat-message.assistant .ai-chat-message-content h3:first-child{margin-top:0}.ai-chat-message.assistant .ai-chat-message-content hr{border:none;border-top:1px solid var(--border-color,#e5e7eb);margin:12px 0}.ai-chat-message.system .ai-chat-message-content{background-color:#fef3c7;border-radius:8px;color:#92400e;font-size:12px;font-style:italic;max-width:90%;text-align:center}.ai-chat-message.tool .ai-chat-message-content{background-color:#dbeafe;border-bottom-left-radius:4px;color:#1e40af;font-family:Courier New,monospace;font-size:13px}.ai-chat-tool-indicators{display:flex;gap:6px;margin-top:6px}.tool-indicator{align-items:center;background:#dbeafe;border-radius:50%;color:#1e40af;display:inline-flex;height:18px;justify-content:center;overflow:hidden;position:relative;width:18px}.tool-indicator .icon{font-size:12px;line-height:1;z-index:1}.tool-indicator.started:after{animation:ai-spin 1s linear infinite;border:2px solid rgba(30,64,175,.25);border-radius:50%;border-top-color:#1e40af;content:\"\";inset:0;position:absolute}@keyframes ai-spin{to{transform:rotate(1turn)}}.ai-chat-tool-message{align-items:center;background:rgba(16,185,129,.1);border:1px solid rgba(16,185,129,.2);border-radius:20px;color:#059669;display:inline-flex;gap:8px;padding:8px 14px}.ai-chat-widget.dark .ai-chat-tool-message{background:rgba(16,185,129,.15);border-color:rgba(16,185,129,.25);color:#34d399}.tool-finished{align-items:center;display:inline-flex;font-size:14px;justify-content:center}.tool-finished .tool-icon{display:none}.tool-finished .tool-check{font-size:14px;font-weight:700}.tool-name{font-size:13px;font-weight:500}.ai-chat-message-timestamp{color:rgba(0,0,0,.6);filter:invert(1) grayscale(1) contrast(1.2);mix-blend-mode:difference;padding:0 4px}.ai-chat-welcome{align-items:center;color:var(--welcome-color);display:flex;flex-direction:column;justify-content:center;min-height:200px;opacity:var(--welcome-opacity);padding:60px 32px 40px;text-align:center}.ai-chat-welcome-title{color:var(--primary-color);font-size:28px;font-weight:700;letter-spacing:-.03em;margin-bottom:12px}.ai-chat-welcome-text{color:var(--assistant-message-text);font-size:16px;line-height:1.6;max-width:280px;opacity:.7}.ai-chat-typing{align-items:center;background-color:var(--assistant-message-bg);border-radius:12px;border-bottom-left-radius:4px;display:flex;gap:4px;max-width:80px;padding:10px 14px}.ai-chat-typing-dot{animation:typingBounce 1.4s infinite;background-color:#9ca3af;border-radius:50%;height:8px;width:8px}.ai-chat-typing-dot:nth-child(2){animation-delay:.2s}.ai-chat-typing-dot:nth-child(3){animation-delay:.4s}@keyframes typingBounce{0%,60%,to{transform:translateY(0)}30%{transform:translateY(-8px)}}.ai-chat-file-button{align-items:center;background:none;border:none;border-radius:6px;color:var(--text-color);cursor:pointer;display:flex;justify-content:center;padding:8px;transition:background-color .2s}.ai-chat-file-button:hover:not(:disabled){background-color:rgba(0,0,0,.05)}.ai-chat-file-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-file-list{display:flex;flex-wrap:wrap;gap:8px;padding:8px 12px}.ai-chat-file-item{align-items:center;background-color:rgba(0,0,0,.05);border-radius:6px;display:flex;font-size:12px;gap:8px;padding:6px 10px}.ai-chat-file-extension{background-color:var(--primary-color);border-radius:3px;color:#fff;display:inline-block;font-size:10px;font-weight:600;min-width:40px;padding:2px 6px;text-align:center;text-transform:uppercase}.ai-chat-file-info{display:flex;flex:1;flex-direction:column;gap:2px;min-width:0}.ai-chat-file-name{font-weight:500;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-file-size{color:var(--text-muted);font-size:10px;opacity:.7}.ai-chat-file-remove{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;justify-content:center;opacity:.5;padding:4px;transition:opacity .15s ease}.ai-chat-file-remove:hover{opacity:1}.ai-chat-message-attachments{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}.ai-chat-message-attachment{align-items:center;background-color:rgba(0,0,0,.08);border-radius:4px;display:inline-flex;font-size:11px;gap:4px;padding:3px 8px}.ai-chat-attachment-icon{font-size:12px}.ai-chat-attachment-ext{background-color:var(--primary-color);border-radius:2px;color:#fff;display:inline-block;font-size:9px;font-weight:600;padding:1px 4px;text-transform:uppercase}.ai-chat-attachment-name{max-width:120px;opacity:.8;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-sources{background-color:rgba(0,0,0,.02);border-radius:6px;font-size:12px;margin-top:8px;overflow:hidden}.ai-chat-sources-toggle{align-items:center;background:none;border:none;cursor:pointer;display:flex;gap:6px;padding:8px 10px;text-align:left;transition:background-color .2s;width:100%}.ai-chat-sources-toggle:hover{background-color:rgba(0,0,0,.03)}.ai-chat-sources-icon{color:var(--text-muted);font-size:10px;transition:transform .2s}.ai-chat-sources-title{color:var(--text-color);flex:1;font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-source-item{border-top:1px solid rgba(0,0,0,.05);color:#6b7280;display:flex;gap:8px;padding:8px 10px}.ai-chat-source-item:last-child{border-bottom:none}.ai-chat-source-number{color:var(--primary-color);flex-shrink:0;font-weight:600}.ai-chat-source-details{display:flex;flex:1;flex-direction:column;gap:4px}.ai-chat-source-score{color:#9ca3af;font-size:11px}.ai-chat-source-content{color:#6b7280;font-size:11px;font-style:italic;line-height:1.4}.ai-chat-source-metadata{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}.ai-chat-source-meta-item{background-color:rgba(0,0,0,.05);border-radius:3px;color:#6b7280;font-size:10px;padding:2px 6px}.ai-chat-message-meta{align-items:center;display:inline-flex;gap:6px;height:20px}.ai-chat-message-timestamp{color:#71717a;font-size:11px;line-height:1}.ai-chat-feedback{gap:0}.ai-chat-feedback,.ai-chat-feedback-button{align-items:center;display:inline-flex;height:20px}.ai-chat-feedback-button{background:none!important;border:none;border-radius:0;color:#71717a;cursor:pointer;justify-content:center;padding:0 4px;transition:color .15s ease}.ai-chat-feedback-button:hover:not(:disabled){background:none!important;color:#52525b}.ai-chat-feedback-button:active:not(:disabled){opacity:.7}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.4}.ai-chat-feedback-button.active{background:none!important;color:var(--primary-color,#07f)}.ai-chat-feedback-submitted{align-items:center;animation:feedbackMorph .3s cubic-bezier(.34,1.56,.64,1);display:flex;gap:6px}.ai-chat-feedback-checkmark{animation:checkmarkPop .3s cubic-bezier(.34,1.56,.64,1);color:#10b981;font-size:16px;font-weight:700}.ai-chat-feedback-text{animation:textSlideIn .3s ease;color:#10b981;font-size:13px;font-weight:500}@keyframes feedbackMorph{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes checkmarkPop{0%{opacity:0;transform:scale(0) rotate(-45deg)}50%{transform:scale(1.3) rotate(0deg)}to{opacity:1;transform:scale(1) rotate(0deg)}}@keyframes textSlideIn{0%{opacity:0;transform:translateX(-10px)}to{opacity:1;transform:translateX(0)}}.ai-chat-error{align-items:flex-start;background-color:rgba(239,68,68,.1);border:1px solid rgba(239,68,68,.2);border-radius:12px;color:#ef4444;display:flex;font-size:14px;font-weight:500;gap:10px;line-height:1.5;margin:8px 16px;padding:12px 16px}.ai-chat-widget.dark .ai-chat-error{background-color:rgba(239,68,68,.15);border-color:rgba(239,68,68,.25);color:#fca5a5}.ai-chat-error:before{align-items:center;background:rgba(239,68,68,.2);border-radius:50%;content:\"⚠\";display:flex;flex-shrink:0;font-size:14px;font-weight:700;height:20px;justify-content:center;width:20px}.ai-chat-widget.dark .ai-chat-error:before{background:rgba(239,68,68,.25)}.ai-chat-warning{background-color:rgba(245,158,11,.1);border:1px solid rgba(245,158,11,.2);border-radius:12px;color:#d97706;font-size:13px;margin:8px 16px;padding:12px 16px}.ai-chat-widget.dark .ai-chat-warning{background-color:rgba(245,158,11,.15);border-color:rgba(245,158,11,.25);color:#fbbf24}.ai-chat-suggested-questions{bottom:80px;left:0;padding:0 20px 16px;position:absolute;right:0;z-index:5}.ai-chat-suggested-questions-list{display:flex;flex-direction:column;gap:8px}.ai-chat-suggested-question{align-items:center;background:#fff;border:1px solid rgba(0,0,0,.08);border-radius:14px;box-shadow:0 1px 3px rgba(0,0,0,.04);color:#374151;cursor:pointer;display:flex;font-size:14px;font-weight:500;gap:12px;justify-content:space-between;padding:14px 16px;text-align:left;transition:all .15s ease;width:100%}.ai-chat-suggested-question:hover{background:#f9fafb;border-color:rgba(0,0,0,.12);box-shadow:0 2px 8px rgba(0,0,0,.06)}.ai-chat-suggested-question:active{transform:scale(.98)}.ai-chat-suggested-question-text{flex:1;line-height:1.4}.ai-chat-suggested-question-icon{color:var(--primary-color,#07f);flex-shrink:0;opacity:.7;transition:transform .15s ease,opacity .15s ease}.ai-chat-suggested-question:hover .ai-chat-suggested-question-icon{opacity:1;transform:translateX(3px)}@media (max-width:480px){.ai-chat-window{border-radius:0!important;bottom:0!important;height:100%!important;left:0!important;position:fixed!important;right:0!important;top:0!important;width:100%!important}.ai-chat-widget-container{bottom:20px!important;right:20px!important}.ai-chat-suggested-question{font-size:13px;padding:9px 10px}}.ai-chat-action-approval{background:linear-gradient(135deg,#07f,#001d3d);border-radius:16px;box-shadow:0 4px 12px rgba(0,119,255,.3);color:#fff;margin:16px;padding:16px}.ai-chat-action-approval-content{align-items:flex-start;display:flex;gap:12px;margin-bottom:16px}.ai-chat-action-approval-icon{align-items:center;background:hsla(0,0%,100%,.2);border-radius:8px;display:flex;flex-shrink:0;height:40px;justify-content:center;width:40px}.ai-chat-action-approval-text{flex:1}.ai-chat-action-approval-title{font-size:15px;font-weight:600;margin-bottom:4px}.ai-chat-action-approval-description{font-size:13px;line-height:1.4;opacity:.95}.ai-chat-action-approval-buttons{display:flex;gap:8px;justify-content:flex-end}.ai-chat-action-button{align-items:center;border:none;border-radius:8px;cursor:pointer;display:flex;font-family:inherit;font-size:14px;font-weight:500;gap:6px;padding:8px 16px;transition:all .2s ease}.ai-chat-action-button:disabled{cursor:not-allowed;opacity:.6}.ai-chat-action-button-reject{background:hsla(0,0%,100%,.2);color:#fff}.ai-chat-action-button-reject:hover:not(:disabled){background:hsla(0,0%,100%,.3)}.ai-chat-action-button-approve{background:#fff;color:#07f}.ai-chat-action-button-approve:hover:not(:disabled){background:#f0f0f0;box-shadow:0 2px 8px rgba(0,0,0,.15);transform:translateY(-1px)}.ai-chat-action-spinner{animation:ai-chat-spin .6s linear infinite;border:2px solid rgba(0,119,255,.3);border-radius:50%;border-top-color:#07f;display:inline-block;height:14px;width:14px}@keyframes ai-chat-spin{to{transform:rotate(1turn)}}";
39372
- styleInject(css_248z$1);
39373
-
39374
- var css_248z = ".ai-chat-widget{--spring-bounce:cubic-bezier(0.34,1.56,0.64,1);--spring-smooth:cubic-bezier(0.4,0,0.2,1);--spring-snappy:cubic-bezier(0.2,0,0,1);--duration-fast:0.2s;--duration-normal:0.35s;--duration-slow:0.5s}.ai-chat-button{align-items:center;background:var(--button-color,var(--primary-color,#07f));border:none;border-radius:50%;box-shadow:0 2px 8px rgba(0,0,0,.15);cursor:pointer;display:flex;height:48px;justify-content:center;overflow:hidden;position:relative;transition:opacity .15s ease;width:48px}.ai-chat-button:hover{opacity:.9}.ai-chat-button:active{opacity:.8}.ai-chat-button-svg{height:20px;transition:transform .15s ease;width:20px}.ai-chat-button.is-open .ai-chat-button-svg{transform:rotate(0deg)}.ai-chat-window{animation:windowOpen var(--duration-slow) var(--spring-bounce);background:#fff;border:1px solid #e5e7eb;border-radius:16px;box-shadow:0 4px 24px rgba(0,0,0,.12),0 1px 3px rgba(0,0,0,.08);display:flex;flex-direction:column;overflow:hidden;position:absolute;transform-origin:bottom right}.ai-chat-widget.dark .ai-chat-window{background:#18181b;border-color:#27272a}@keyframes windowOpen{0%{opacity:0;transform:scale(.9) translateY(20px)}to{opacity:1;transform:scale(1) translateY(0)}}.ai-chat-window.closing{animation:windowClose var(--duration-normal) var(--spring-smooth) forwards}@keyframes windowClose{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.9) translateY(20px)}}.ai-chat-header{align-items:center;background:#fff;border-bottom:1px solid #e5e7eb;display:flex;justify-content:space-between;padding:16px 20px;position:relative;z-index:10}.ai-chat-widget.dark .ai-chat-header{background:#18181b;border-bottom-color:#27272a}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:12px}.ai-chat-logo{border-radius:10px;height:36px;object-fit:cover;width:36px}.ai-chat-title{color:#18181b;font-size:15px;font-weight:600;letter-spacing:-.01em}.ai-chat-widget.dark .ai-chat-title{color:#fafafa}.ai-chat-close-button{align-items:center;background:transparent;border:none;border-radius:8px;color:#a1a1aa;cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:all .15s ease;width:32px}.ai-chat-widget.dark .ai-chat-close-button{color:#71717a}.ai-chat-close-button:hover{background:#f4f4f5;color:#52525b}.ai-chat-widget.dark .ai-chat-close-button:hover{background:#27272a;color:#a1a1aa}.ai-chat-close-button:active{transform:scale(.95)}.ai-chat-messages{-webkit-overflow-scrolling:touch;background:#f4f4f5;display:flex;flex:1;flex-direction:column;gap:12px;overflow-x:hidden;overflow-y:auto;padding:16px 16px 90px;position:relative;scroll-behavior:smooth}.ai-chat-widget.dark .ai-chat-messages{background:#18181b}.ai-chat-messages::-webkit-scrollbar{width:4px}.ai-chat-messages::-webkit-scrollbar-track{background:transparent}.ai-chat-messages::-webkit-scrollbar-thumb{background:rgba(0,0,0,.15);border-radius:4px}.ai-chat-messages::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.25)}.ai-chat-message{animation:messageSlideIn var(--duration-normal) var(--spring-bounce);display:flex;flex-direction:column;gap:6px}@keyframes messageSlideIn{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}.ai-chat-message-content{word-wrap:break-word;border-radius:12px;font-size:14px;line-height:1.5;max-width:85%;padding:8px 14px}.ai-chat-message.user .ai-chat-message-content{background:var(--bubble-user-color,var(--primary-color,#07f));border-bottom-right-radius:4px;color:#fff;margin-left:auto}.ai-chat-message.assistant .ai-chat-message-content{background:#fff;border:1px solid #e5e7eb;border-bottom-left-radius:4px;color:#374151}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content{background:#18181b;border-color:#27272a;color:#e4e4e7}.ai-chat-typing{align-items:center;animation:messageSlideIn var(--duration-normal) var(--spring-bounce);background:#fff;border:1px solid #e5e7eb;border-radius:12px;border-bottom-left-radius:4px;display:flex;gap:4px;max-width:64px;padding:12px 16px}.ai-chat-widget.dark .ai-chat-typing{background:#18181b;border-color:#27272a}.ai-chat-typing-dot{animation:typingPulse 1.4s ease-in-out infinite;background:linear-gradient(135deg,var(--primary-color) 0,color-mix(in srgb,var(--primary-color) 70%,#000) 100%);border-radius:50%;height:8px;width:8px}.ai-chat-typing-dot:nth-child(2){animation-delay:.15s}.ai-chat-typing-dot:nth-child(3){animation-delay:.3s}@keyframes typingPulse{0%,60%,to{opacity:.4;transform:translateY(0) scale(1)}30%{opacity:1;transform:translateY(-6px) scale(1.1)}}.ai-chat-input-container{background:transparent;bottom:0;left:0;padding:0 16px 16px;position:absolute;right:0;z-index:10}.ai-chat-input-container:before{background:linear-gradient(0deg,#f4f4f5 80%,transparent);bottom:0;content:\"\";height:48px;left:0;pointer-events:none;position:absolute;right:0;z-index:-1}.ai-chat-widget.dark .ai-chat-input-container:before{background:linear-gradient(0deg,#18181b 80%,transparent)}.ai-chat-input-wrapper{align-items:center;background:#f4f4f5;border:1px solid #e5e7eb;border-radius:9999px;display:flex;gap:0;padding:4px 4px 4px 16px;position:relative;transition:all .15s ease;z-index:5}.ai-chat-widget.dark .ai-chat-input-wrapper{background:#27272a;border-color:#3f3f46}.ai-chat-input-wrapper:focus-within{border-color:var(--primary-color);box-shadow:0 0 0 2px rgba(var(--primary-color-rgb,0,119,255),.15)}.ai-chat-input{background:transparent;border:none;color:var(--text-color);flex:1;font-family:inherit;font-size:14px;line-height:1.4;max-height:100px;min-height:20px;outline:none;padding:8px 0;resize:none}.ai-chat-input::placeholder{color:rgba(0,0,0,.35)}.ai-chat-widget.dark .ai-chat-input::placeholder{color:hsla(0,0%,100%,.35)}.ai-chat-send-button{align-items:center;background:transparent;border:none;border-radius:8px;color:#a1a1aa;cursor:pointer;display:flex;flex-shrink:0;height:36px;justify-content:center;padding:0;transition:all .15s ease;width:36px}.ai-chat-widget.dark .ai-chat-send-button{color:#71717a}.ai-chat-send-button.active{background:var(--primary-color,#07f);color:#fff}.ai-chat-send-button.active:hover:not(:disabled){opacity:.9}.ai-chat-send-button:active:not(:disabled){transform:scale(.95)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.4}.ai-chat-tool-message{align-items:center;animation:toolPulse 2s ease-in-out infinite;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);background:linear-gradient(135deg,rgba(16,185,129,.15),rgba(16,185,129,.08));border:1px solid rgba(16,185,129,.2);border-radius:16px;display:inline-flex;gap:10px;padding:10px 16px}@keyframes toolPulse{0%,to{box-shadow:0 0 0 0 rgba(16,185,129,.2)}50%{box-shadow:0 0 0 8px rgba(16,185,129,0)}}.tool-finished{align-items:center;animation:toolComplete .5s var(--spring-bounce);background:linear-gradient(135deg,#10b981,#059669);border-radius:50%;color:#fff;display:inline-flex;height:28px;justify-content:center;position:relative;width:28px}@keyframes toolComplete{0%{transform:scale(0) rotate(-180deg)}to{transform:scale(1) rotate(0deg)}}.tool-indicator{align-items:center;background:linear-gradient(135deg,rgba(59,130,246,.2),rgba(59,130,246,.1));border-radius:50%;color:#3b82f6;display:inline-flex;height:24px;justify-content:center;position:relative;width:24px}.tool-indicator.started:after{animation:toolSpin .8s linear infinite;border:2px solid transparent;border-radius:50%;border-top-color:#3b82f6;content:\"\";inset:-2px;position:absolute}@keyframes toolSpin{to{transform:rotate(1turn)}}.ai-chat-welcome{align-items:center;animation:welcomeFadeIn var(--duration-slow) var(--spring-smooth);display:flex;flex-direction:column;justify-content:center;min-height:200px;padding:60px 32px 40px;text-align:center}@keyframes welcomeFadeIn{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}.ai-chat-welcome-title{color:var(--primary-color);font-size:28px;font-weight:700;letter-spacing:-.03em;margin-bottom:12px}.ai-chat-welcome-text{color:var(--text-color);font-size:16px;line-height:1.6;max-width:280px;opacity:.6}.ai-chat-suggested-questions{bottom:76px;left:0;padding:0 16px 12px;position:absolute;right:0;z-index:5}.ai-chat-suggested-questions-list{display:flex;flex-direction:column;gap:6px}.ai-chat-suggested-question{align-items:center;background:#fff;border:1px solid #e5e7eb;border-radius:10px;color:#374151;cursor:pointer;display:flex;font-size:13px;font-weight:500;gap:10px;justify-content:space-between;padding:10px 14px;text-align:left;transition:all .15s ease;width:100%}.ai-chat-widget.dark .ai-chat-suggested-question{background:#18181b;border-color:#27272a;color:#e4e4e7}.ai-chat-suggested-question:hover{background:#f4f4f5;border-color:#d4d4d8}.ai-chat-widget.dark .ai-chat-suggested-question:hover{background:#27272a;border-color:#3f3f46}.ai-chat-suggested-question:active{transform:scale(.98)}.ai-chat-suggested-question-text{flex:1;line-height:1.4}.ai-chat-suggested-question-icon{color:var(--primary-color,#07f);flex-shrink:0;opacity:.7;transition:transform .15s ease,opacity .15s ease}.ai-chat-suggested-question:hover .ai-chat-suggested-question-icon{opacity:1;transform:translateX(3px)}.ai-chat-feedback-button{align-items:center;background:rgba(0,0,0,.04);border:none;border-radius:8px;cursor:pointer;display:flex;font-size:16px;gap:4px;padding:6px 10px;transition:all var(--duration-fast) var(--spring-bounce)}.ai-chat-feedback-button:hover:not(:disabled){background:rgba(0,0,0,.08);transform:scale(1.15)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.9)}.ai-chat-feedback-button.active{background:rgba(var(--primary-color-rgb,0,119,255),.15)}@media (max-width:480px){.ai-chat-window{animation:mobileSlideUp var(--duration-normal) var(--spring-smooth);border-radius:0!important;bottom:0!important;height:100%!important;left:0!important;position:fixed!important;right:0!important;top:0!important;width:100%!important}@keyframes mobileSlideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}.ai-chat-header{padding-top:max(16px,env(safe-area-inset-top))}.ai-chat-input-container{padding-bottom:max(20px,env(safe-area-inset-bottom))}}";
39728
+ var css_248z = ".ai-chat-widget{--radius-sm:4px;--radius-md:8px;--radius-lg:12px;--radius-xl:16px;--radius-2xl:18px;--radius-pill:9999px;--radius-window-top:22px;--radius-window-bottom:44px;--radius-window-gutter:16px;--radius-chat-bubble:14px;--radius-preset-badge:13px;--radius-history-item:14px;--radius-action-badge:14px;--radius-input:62px;--space-xs:4px;--space-sm:8px;--space-md:16px;--space-lg:24px;--space-xl:32px;--text-xs:12px;--text-sm:14px;--text-md:15px;--text-lg:18px;--text-xl:22px;--text-2xl:28px;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--line-height-tight:1.3;--line-height-normal:1.4;--line-height-relaxed:1.6;--bg-primary:#fff;--bg-secondary:#f4f4f4;--bg-tertiary:#e5e7eb;--bg-hover:#e5e7eb;--text-primary:#3e3e3e;--text-secondary:#000;--text-muted:#71717a;--text-placeholder:#a1a1aa;--border-default:#d3d3d3;--border-subtle:#e5e7eb;--border-muted:#f4f4f5;--user-bg:#f4f3f0;--user-text:#000;--user-bg-hover:#e8e7e4;--agent-bg:transparent;--agent-text:#000;--input-bg:#f4f4f4;--input-border:#d3d3d3;--input-text:#000;--btn-primary-bg:#151515;--btn-primary-text:#f4f4f4;--btn-secondary-bg:transparent;--btn-secondary-text:#71717a;--spring-bounce:cubic-bezier(0.34,1.56,0.64,1);--spring-smooth:cubic-bezier(0.4,0,0.2,1);--spring-snappy:cubic-bezier(0.2,0,0,1);--duration-fast:0.15s;--duration-normal:0.25s;--duration-slow:0.35s;--shadow-sm:0 1px 2px rgba(0,0,0,.05);--shadow-md:0 2px 8px rgba(0,0,0,.1);--shadow-lg:0 4px 16px rgba(0,0,0,.12);--shadow-window:0px 0px 15px 9px rgba(0,0,0,.1);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03)}.ai-chat-widget.dark{--bg-primary:#282625;--bg-secondary:#4a4846;--bg-tertiary:#484848;--bg-hover:#484848;--text-primary:#fff;--text-secondary:#fff;--text-muted:#a1a1aa;--text-placeholder:#71717a;--border-default:#5d5b5b;--border-subtle:#5d5b5b;--border-muted:#5d5b5b;--user-bg:#484848;--user-text:#fff;--user-bg-hover:#5a5a5a;--agent-bg:transparent;--agent-text:#fff;--input-bg:#4a4846;--input-border:#5d5b5b;--input-text:#fff;--btn-primary-bg:#fff;--btn-primary-text:#312f2d;--btn-secondary-bg:transparent;--btn-secondary-text:#a1a1aa;--shadow-window:0px 0px 15px 9px rgba(0,0,0,.2);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03);--shadow-input:0px 0px 10px rgba(0,0,0,.15)}.ai-chat-widget{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.ai-chat-widget-container{font-size:var(--text-sm);line-height:1.5;position:fixed;z-index:9999}.ai-chat-widget-container.bottom-right{bottom:20px;right:20px}.ai-chat-widget-container.bottom-left{bottom:20px;left:20px}.ai-chat-widget-container.top-right{right:20px;top:20px}.ai-chat-widget-container.top-left{left:20px;top:20px}@keyframes windowOpen{0%{opacity:0;transform:scale(.9) translateY(20px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes windowClose{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.9) translateY(20px)}}@keyframes messageSlideIn{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes welcomeFadeIn{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}@keyframes typingPulse{0%,60%,to{opacity:.4;transform:translateY(0) scale(1)}30%{opacity:1;transform:translateY(-4px) scale(1.1)}}@keyframes ai-chat-gear-spin{to{transform:rotate(1turn)}}@keyframes ai-chat-tool-active{0%,to{background:var(--bg-secondary);opacity:1}50%{background:var(--bg-tertiary);opacity:1}}@keyframes feedbackMorph{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes checkmarkPop{0%{opacity:0;transform:scale(0) rotate(-45deg)}50%{transform:scale(1.3) rotate(0deg)}to{opacity:1;transform:scale(1) rotate(0deg)}}@keyframes ai-chat-history-exit{to{opacity:0;transform:translateY(-18px)}}@media (max-width:480px){.ai-chat-window{animation:mobileSlideUp var(--duration-normal) var(--spring-smooth);border-radius:0!important;bottom:0!important;height:100%!important;left:0!important;position:fixed!important;right:0!important;top:0!important;width:100%!important}@keyframes mobileSlideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}.ai-chat-header{padding-top:max(16px,env(safe-area-inset-top))}.ai-chat-input-container{padding-bottom:max(20px,env(safe-area-inset-bottom))}}.ai-chat-button{align-items:center;background:var(--button-color,var(--btn-primary-bg));border:1px solid var(--button-border-color,var(--button-color,var(--btn-primary-bg)));border-radius:50%;box-shadow:var(--shadow-button,0 0 15px 9px rgba(0,0,0,.03));color:var(--button-icon-color,var(--btn-primary-text));cursor:pointer;display:flex;height:var(--button-size,56px);justify-content:center;overflow:hidden;position:relative;transition:filter var(--duration-fast) ease,transform var(--duration-fast) ease;width:var(--button-size,56px);z-index:1}.ai-chat-button:hover{transform:scale(1.02)}.ai-chat-button:active{transform:scale(.98)}.ai-chat-button-svg{height:50%;min-height:24px;min-width:24px;transition:transform var(--duration-fast) ease;width:50%}.ai-chat-button.is-open .ai-chat-button-svg{transform:rotate(0deg)}.ai-chat-button-icon{font-size:1.5em;line-height:1}.ai-chat-window{animation:windowOpen var(--duration-slow,.35s) var(--spring-bounce,cubic-bezier(.34,1.56,.64,1));background:var(--bg-primary,#fff);border:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) var(--radius-window-bottom,44px) var(--radius-window-bottom,44px);box-shadow:var(--shadow-window,0 0 15px 5px rgba(0,0,0,.08));display:flex;flex-direction:column;overflow:hidden;position:absolute;transform-origin:bottom right;z-index:2}.ai-chat-widget.dark .ai-chat-window{background:var(--bg-primary,#282625);border-color:var(--border-default,#5d5b5b);border-width:.7px}.ai-chat-window.closing{animation:windowClose var(--duration-normal) var(--spring-smooth) forwards}.ai-chat-window.size-small{height:580px;width:380px}.ai-chat-window.size-medium{height:720px;width:440px}.ai-chat-window.size-large{height:820px;width:520px}.ai-chat-widget-container.bottom-right .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);right:0}.ai-chat-widget-container.bottom-left .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);left:0}.ai-chat-widget-container.top-right .ai-chat-window{right:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-widget-container.top-left .ai-chat-window{left:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-header{align-items:center;background:var(--bg-primary,#fff);border-bottom:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) 0 0;display:flex;justify-content:space-between;padding:18px var(--space-md,16px);position:relative;z-index:10}.ai-chat-widget.dark .ai-chat-header{background:var(--bg-primary,#282625);border-bottom-color:var(--border-default,#5d5b5b);border-bottom-width:.7px}.ai-chat-header.is-history{padding-left:var(--space-md)}.ai-chat-header.is-history .ai-chat-title{flex:1;min-width:0;overflow:hidden;padding-right:var(--space-lg);text-overflow:ellipsis;white-space:nowrap}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:var(--space-lg)}.ai-chat-header-actions{align-items:center;display:flex;gap:var(--space-sm)}.ai-chat-logo{border-radius:10px;height:36px;object-fit:cover;width:36px}.ai-chat-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-xl,22px);font-weight:var(--font-weight-bold,700);letter-spacing:-.02em}.ai-chat-widget.dark .ai-chat-title{color:var(--text-primary,#fff)}.ai-chat-close-button{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-primary);cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:32px}.ai-chat-close-button:hover{color:var(--text-muted)}.ai-chat-close-button:active{transform:scale(.95)}.ai-chat-header-button{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:all var(--duration-fast) ease;width:32px}.ai-chat-header-button:hover{background:var(--bg-secondary);color:var(--text-secondary)}.ai-chat-header-button svg{height:18px;width:18px}.ai-chat-messages{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;align-items:stretch;background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;gap:var(--space-md,16px);justify-content:flex-start;overflow-x:hidden;overflow-y:auto;padding:var(--space-lg,24px) var(--space-md,16px) 100px;position:relative;scroll-behavior:smooth;scrollbar-width:none}.ai-chat-widget.dark .ai-chat-messages{background:var(--bg-primary,#18181b)}.ai-chat-messages::-webkit-scrollbar{display:none}.ai-chat-message{animation:messageSlideIn var(--duration-normal) var(--spring-bounce);display:flex;flex-direction:column;gap:6px}.ai-chat-message-content{word-wrap:break-word;font-size:var(--text-md);line-height:var(--line-height-relaxed);max-width:85%}.ai-chat-message.user{align-items:flex-end}.ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#f4f3f0);border:none;border-radius:var(--radius-chat-bubble,15px);box-shadow:none;color:var(--user-text,#000);padding:var(--space-sm,8px) var(--space-md,16px)}.ai-chat-widget.dark .ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#484848);color:var(--user-text,#fff)}.ai-chat-message.user .ai-chat-message-meta{justify-content:flex-end;padding-right:var(--space-xs)}.ai-chat-message.assistant{align-items:flex-start}.ai-chat-message.assistant .ai-chat-message-content{background:var(--agent-bg,transparent);border:none;color:var(--agent-text,#18181b);padding:0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content{color:var(--agent-text,#fafafa)}.ai-chat-message.system{align-items:center}.ai-chat-message.system .ai-chat-message-content{background:hsla(48,96%,89%,.8);border-radius:var(--radius-md);color:#92400e;font-size:var(--text-xs);font-style:italic;max-width:90%;padding:var(--space-sm) var(--space-md);text-align:center}.ai-chat-widget.dark .ai-chat-message.system .ai-chat-message-content{background:rgba(120,53,15,.5);color:#fef3c7}.ai-chat-message.tool{align-items:flex-start}.ai-chat-message.tool .ai-chat-message-content{background:rgba(219,234,254,.8);border-radius:var(--radius-chat-bubble);border-bottom-left-radius:var(--radius-xs);color:#1e40af;font-family:Courier New,monospace;font-size:var(--text-sm);padding:var(--space-sm) var(--space-md)}.ai-chat-widget.dark .ai-chat-message.tool .ai-chat-message-content{background:rgba(30,58,138,.5);color:#dbeafe}.ai-chat-message-meta{align-items:center;color:var(--text-muted);display:flex;font-size:var(--text-xs);gap:var(--space-sm);padding-left:var(--space-xs)}.ai-chat-message-timestamp{font-size:var(--text-xs);line-height:1}.ai-chat-typing{align-items:center;animation:messageSlideIn var(--duration-normal) var(--spring-bounce);background:transparent;display:flex;gap:5px;padding:0}.ai-chat-typing-dot{animation:typingPulse 1.4s ease-in-out infinite;background:var(--text-muted);border-radius:50%;height:6px;width:6px}.ai-chat-typing-dot:nth-child(2){animation-delay:.15s}.ai-chat-typing-dot:nth-child(3){animation-delay:.3s}.ai-chat-welcome{align-items:stretch;animation:welcomeFadeIn var(--duration-slow) var(--spring-smooth);display:flex;flex-direction:column;justify-content:flex-start;padding:0;text-align:left}.ai-chat-welcome-text,.ai-chat-welcome-title{align-self:flex-start}.ai-chat-welcome-title{color:var(--text-primary);font-size:var(--text-2xl);font-weight:var(--font-weight-semibold);letter-spacing:-.02em;margin-bottom:var(--space-md)}.ai-chat-welcome-text{color:var(--text-secondary);font-size:var(--text-md);line-height:var(--line-height-relaxed);max-width:100%}.ai-chat-error{align-items:flex-start;align-self:center;background:var(--bg-secondary);border:none;border-radius:var(--radius-chat-bubble);color:var(--text-primary);display:flex;font-size:var(--text-md);font-weight:var(--font-weight-normal);gap:10px;line-height:1.5;margin:0 auto;max-width:90%;padding:10px var(--space-md)}.ai-chat-error:before{align-items:center;background:rgba(239,68,68,.15);border-radius:50%;color:#ef4444;content:\"⚠\";display:flex;flex-shrink:0;font-size:var(--text-xs);font-weight:700;height:18px;justify-content:center;margin-top:2px;width:18px}.ai-chat-widget.dark .ai-chat-error:before{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-message.assistant .ai-chat-message-content p{margin:0 0 12px}.ai-chat-message.assistant .ai-chat-message-content p:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content ol,.ai-chat-message.assistant .ai-chat-message-content ul{margin:8px 0 12px;padding-left:24px}.ai-chat-message.assistant .ai-chat-message-content li{line-height:1.5;margin:6px 0}.ai-chat-message.assistant .ai-chat-message-content strong{font-weight:var(--font-weight-semibold)}.ai-chat-message.assistant .ai-chat-message-content em{font-style:italic}.ai-chat-message.assistant .ai-chat-message-content code{background:rgba(0,0,0,.06);border-radius:var(--radius-sm);font-family:SF Mono,Consolas,Monaco,monospace;font-size:.9em;padding:2px 6px}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content code{background:hsla(0,0%,100%,.1)}.ai-chat-message.assistant .ai-chat-message-content pre{background:rgba(0,0,0,.06);border-radius:var(--radius-md);margin:8px 0 12px;overflow-x:auto;padding:var(--space-sm)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content pre{background:hsla(0,0%,100%,.08)}.ai-chat-message.assistant .ai-chat-message-content pre code{background:transparent;border-radius:0;padding:0}.ai-chat-message.assistant .ai-chat-message-content blockquote{border-left:3px solid var(--btn-primary-bg);color:var(--text-muted);margin:8px 0 12px;padding:4px 0 4px 12px}.ai-chat-message.assistant .ai-chat-message-content a{color:var(--btn-primary-bg);text-decoration:underline}.ai-chat-message.assistant .ai-chat-message-content a:hover{opacity:.8}.ai-chat-message.assistant .ai-chat-message-content h1,.ai-chat-message.assistant .ai-chat-message-content h2,.ai-chat-message.assistant .ai-chat-message-content h3,.ai-chat-message.assistant .ai-chat-message-content h4,.ai-chat-message.assistant .ai-chat-message-content h5,.ai-chat-message.assistant .ai-chat-message-content h6{font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);margin:16px 0 8px}.ai-chat-message.assistant .ai-chat-message-content h1:first-child,.ai-chat-message.assistant .ai-chat-message-content h2:first-child,.ai-chat-message.assistant .ai-chat-message-content h3:first-child{margin-top:0}.ai-chat-message.assistant .ai-chat-message-content hr{border:none;border-top:1px solid var(--border-subtle);margin:12px 0}.ai-chat-input-container{background:linear-gradient(to bottom,transparent 0,var(--bg-primary,#fff) 50%,var(--bg-primary,#fff) 100%);bottom:0;left:0;padding-top:30px;position:absolute;right:0;z-index:10}.ai-chat-widget.dark .ai-chat-input-container{background:linear-gradient(to bottom,transparent 0,var(--bg-primary,#282625) 50%,var(--bg-primary,#282625) 100%)}.ai-chat-input-container.separate{padding:0 var(--radius-window-gutter,16px) var(--radius-window-gutter,16px);padding-top:30px}.ai-chat-input-wrapper{align-items:center;background:var(--input-bg,#f4f4f4);border:1px solid var(--input-border,#d3d3d3);border-radius:var(--radius-input,62px);display:flex;gap:0;height:52px;padding:6px 6px 6px 12px;position:relative;transition:all var(--duration-fast,.15s) ease;z-index:5}.ai-chat-widget.dark .ai-chat-input-wrapper{background:var(--input-bg,#4a4846);border-color:var(--input-border,#5d5b5b);border-width:.7px;box-shadow:var(--shadow-input,0 0 10px rgba(0,0,0,.15))}.ai-chat-input-wrapper:focus-within{border-color:var(--text-muted,#a1a1aa)}.ai-chat-input{background:transparent;border:none;color:var(--input-text,#000);flex:1;font-family:inherit;font-size:var(--text-md,15px);height:20px;line-height:var(--line-height-normal,1.4);max-height:20px;min-height:20px;outline:none;overflow:hidden;padding:0 var(--space-sm,8px);resize:none}.ai-chat-widget.dark .ai-chat-input{color:var(--input-text,#fff)}.ai-chat-input::placeholder{color:var(--text-placeholder,#a1a1aa)}.ai-chat-widget.dark .ai-chat-input::placeholder{color:var(--text-placeholder,#52525b)}.ai-chat-file-button{align-items:center;background:transparent;border:none;color:var(--text-placeholder);cursor:pointer;display:flex;flex-shrink:0;height:28px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:28px}.ai-chat-file-button:hover{color:var(--text-secondary)}.ai-chat-file-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-send-button{align-items:center;background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));border:none;border-radius:50%;color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4));cursor:pointer;display:flex;flex-shrink:0;height:40px;justify-content:center;padding:0;transition:all var(--duration-fast,.15s) ease;width:40px}.ai-chat-widget.dark .ai-chat-send-button{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4))}.ai-chat-widget.dark .ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button:hover:not(:disabled){opacity:.8}.ai-chat-send-button:active:not(:disabled){transform:scale(.95)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.3}.ai-chat-file-list{display:flex;flex-wrap:wrap;gap:var(--space-sm);padding:var(--space-sm) var(--space-sm)}.ai-chat-file-item{align-items:center;background:rgba(0,0,0,.05);border-radius:6px;display:flex;font-size:var(--text-xs);gap:var(--space-sm);padding:6px 10px}.ai-chat-file-extension{background:var(--btn-primary-bg);border-radius:3px;color:var(--btn-primary-text);display:inline-block;font-size:10px;font-weight:var(--font-weight-semibold);min-width:40px;padding:2px 6px;text-align:center;text-transform:uppercase}.ai-chat-file-info{display:flex;flex:1;flex-direction:column;gap:2px;min-width:0}.ai-chat-file-name{font-weight:var(--font-weight-medium);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-file-size{color:var(--text-muted);font-size:10px;opacity:.7}.ai-chat-file-remove{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;justify-content:center;opacity:.5;padding:var(--space-xs);transition:opacity var(--duration-fast) ease}.ai-chat-file-remove:hover{opacity:1}.ai-chat-suggested-questions{align-self:flex-end;margin:0;padding:16px 0 0;width:100%}.ai-chat-suggested-questions-list{align-items:center;display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end}.ai-chat-suggested-question{background:var(--primary-color,var(--button-color,var(--user-bg,#f4f3f0)));border:none;border-radius:var(--radius-preset-badge,13px);color:var(--button-icon-color,var(--user-text,#000));cursor:pointer;font-size:14px;font-weight:400;line-height:1.3;padding:8px 14px;transition:background .15s ease,opacity .15s ease;white-space:nowrap}.ai-chat-widget.dark .ai-chat-suggested-question{background:var(--primary-color,var(--button-color,var(--user-bg,#484848)));color:var(--button-icon-color,var(--user-text,#fff))}.ai-chat-suggested-question-text{white-space:nowrap}.ai-chat-suggested-question:hover{filter:brightness(.9)}.ai-chat-widget.dark .ai-chat-suggested-question:hover{filter:brightness(1.15)}.ai-chat-suggested-question:active{transform:scale(.98)}.ai-chat-suggested-question-icon{display:none}.ai-chat-feedback-buttons{align-items:center;display:flex;gap:var(--space-xs)}.ai-chat-feedback{align-items:center;display:inline-flex;gap:0;height:20px}.ai-chat-feedback-button{align-items:center;background:transparent!important;border:none;border-radius:var(--radius-sm);color:var(--text-placeholder);cursor:pointer;display:flex;font-size:var(--text-sm);height:20px;justify-content:center;padding:var(--space-xs);transition:all var(--duration-fast) var(--spring-bounce)}.ai-chat-feedback-button:hover:not(:disabled){background:none!important;color:var(--text-secondary)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.9)}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.4}.ai-chat-feedback-button.active{background:none!important;color:var(--text-primary)}.ai-chat-feedback-submitted{align-items:center;animation:feedbackMorph .3s var(--spring-bounce);display:flex;gap:6px}.ai-chat-feedback-checkmark{animation:checkmarkPop .3s var(--spring-bounce);color:#10b981;font-size:var(--text-md);font-weight:700}.ai-chat-feedback-text{color:#10b981;font-size:var(--text-sm);font-weight:var(--font-weight-medium)}.ai-chat-history-panel{background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;overflow:hidden}.ai-chat-widget.dark .ai-chat-history-panel{background:var(--bg-primary,#18181b)}.ai-chat-history-empty,.ai-chat-history-loading{align-items:center;color:var(--text-muted);display:flex;flex:1;font-size:var(--text-sm);justify-content:center;padding:var(--space-lg);text-align:center}.ai-chat-history-list{-ms-overflow-style:none;display:flex;flex:1;flex-direction:column;gap:var(--space-sm);overflow-y:auto;padding:var(--space-md) var(--space-md) 120px;scrollbar-width:none}.ai-chat-history-list::-webkit-scrollbar{display:none}.ai-chat-history-list.exiting{animation:ai-chat-history-exit .22s var(--spring-smooth) forwards}.ai-chat-history-item{align-items:stretch;background:var(--user-bg,#f4f4f5);border:none;border-radius:var(--radius-history-item,15px);cursor:pointer;display:flex;flex-direction:column;margin:0;padding:var(--space-sm,8px) var(--space-md,16px);text-align:left;transition:background var(--duration-fast,.15s) ease;width:100%}.ai-chat-widget.dark .ai-chat-history-item{background:var(--user-bg,#27272a)}.ai-chat-history-item:hover{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item:hover{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item.active{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item.active{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item-preview{color:var(--text-primary,#18181b);font-size:var(--text-sm,14px);font-weight:var(--font-weight-medium,500);line-height:var(--line-height-normal,1.4);margin-bottom:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-widget.dark .ai-chat-history-item-preview{color:var(--text-primary,#fafafa)}.ai-chat-history-item.active .ai-chat-history-item-preview{font-weight:var(--font-weight-medium)}.ai-chat-history-item-meta{display:none}.ai-chat-tool-row{align-items:center;display:flex;gap:10px;margin:var(--space-sm) 0 6px}.ai-chat-tool-gear{align-items:center;color:var(--text-primary);display:inline-flex;height:26px;justify-content:center;width:26px}.ai-chat-tool-gear.spinning{animation:ai-chat-gear-spin .9s linear infinite}.ai-chat-tool-pills{display:flex;flex-wrap:wrap;gap:var(--space-sm)}.ai-chat-tool-pill{align-items:center;border-radius:var(--radius-pill);color:var(--button-icon-color,var(--btn-primary-text,var(--text-primary)));display:inline-flex;font-size:var(--text-sm);font-weight:var(--font-weight-medium);justify-content:center;line-height:1;padding:var(--space-sm) 14px}.ai-chat-tool-pill,.ai-chat-tool-pill.active{background:var(--primary-color,var(--button-color,var(--btn-primary-bg,var(--bg-secondary))))}.ai-chat-tool-pill.active{animation:ai-chat-tool-active 1.1s ease-in-out infinite;overflow:hidden;position:relative}.ai-chat-tool-pill.done{background:var(--primary-color,var(--button-color,var(--btn-primary-bg)));color:var(--button-icon-color,var(--btn-primary-text))}.ai-chat-tool-indicators{display:flex;gap:6px;margin-top:6px}.tool-indicator{align-items:center;background:linear-gradient(135deg,rgba(59,130,246,.2),rgba(59,130,246,.1));border-radius:50%;color:#3b82f6;display:inline-flex;height:24px;justify-content:center;position:relative;width:24px}.tool-indicator .icon{font-size:var(--text-xs);line-height:1;z-index:1}.tool-indicator.started:after{animation:ai-chat-gear-spin .8s linear infinite;border:2px solid transparent;border-radius:50%;border-top-color:#3b82f6;content:\"\";inset:-2px;position:absolute}.ai-chat-tool-message{align-items:center;background:hsla(0,0%,50%,.1);border:none;border-radius:var(--radius-pill);color:hsla(0,0%,50%,.8);display:inline-flex;font-size:12px;gap:5px;padding:4px 10px}.ai-chat-tool-message .ai-chat-tool-spinner{animation:ai-chat-tool-spin 1s linear infinite;flex-shrink:0;opacity:.6}.ai-chat-tool-message .ai-chat-tool-check{flex-shrink:0;opacity:.7}.ai-chat-tool-message .ai-chat-tool-error{color:#ef4444;flex-shrink:0;opacity:.7}.ai-chat-tool-message.error{background:rgba(239,68,68,.1);color:rgba(239,68,68,.9)}.tool-name{font-size:12px;font-weight:var(--font-weight-regular);line-height:1.2;white-space:nowrap}@keyframes ai-chat-tool-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes ai-chat-tool-check-appear{0%{opacity:0;transform:scale(.5)}to{opacity:.7;transform:scale(1)}}.ai-chat-sources{background:rgba(0,0,0,.02);border-radius:6px;font-size:var(--text-xs);margin-top:var(--space-sm);overflow:hidden}.ai-chat-sources-toggle{align-items:center;background:none;border:none;cursor:pointer;display:flex;gap:6px;padding:var(--space-sm) 10px;text-align:left;transition:background var(--duration-fast) ease;width:100%}.ai-chat-sources-toggle:hover{background:rgba(0,0,0,.03)}.ai-chat-sources-icon{color:var(--text-muted);font-size:10px;transition:transform var(--duration-fast) ease}.ai-chat-sources-title{color:var(--text-primary);flex:1;font-size:11px;font-weight:var(--font-weight-semibold);letter-spacing:.5px;text-transform:uppercase}.ai-chat-source-item{border-top:1px solid rgba(0,0,0,.05);color:var(--text-muted);display:flex;gap:var(--space-sm);padding:var(--space-sm) 10px}.ai-chat-source-item:last-child{border-bottom:none}.ai-chat-source-number{color:var(--btn-primary-bg);flex-shrink:0;font-weight:var(--font-weight-semibold)}.ai-chat-source-details{display:flex;flex:1;flex-direction:column;gap:var(--space-xs)}.ai-chat-source-score{color:var(--text-placeholder);font-size:11px}.ai-chat-source-content{color:var(--text-muted);font-size:11px;font-style:italic;line-height:var(--line-height-normal)}.ai-chat-source-metadata{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}.ai-chat-source-meta-item{background:rgba(0,0,0,.05);border-radius:3px;color:var(--text-muted);font-size:10px;padding:2px 6px}";
39375
39729
  styleInject(css_248z);
39376
39730
 
39377
39731
  // Icon components mapping
@@ -39379,17 +39733,76 @@
39379
39733
  FiMessageCircle: () => (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" }) })),
39380
39734
  FiChevronDown: () => (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "6 9 12 15 18 9" }) })),
39381
39735
  };
39382
- const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bottom-right', primaryColor, onOpen, onClose, onMessage, onError, }) => {
39736
+ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = false, previewConfig, position = 'bottom-right', primaryColor, size, headerTitle, welcomeTitle, welcomeMessage, placeholder, theme, suggestedQuestions, customStyles, onOpen, onClose, onMessage, onError, }) => {
39383
39737
  const [isOpen, setIsOpen] = reactExports.useState(false);
39384
39738
  const [autoDetectedTheme, setAutoDetectedTheme] = reactExports.useState('light');
39385
39739
  const widgetRef = reactExports.useRef(null);
39386
39740
  const containerRef = reactExports.useRef(null);
39387
- const { messages, isLoading, isTyping, error, config, sendMessage, submitFeedback, } = useChat({
39388
- widgetId,
39741
+ // Default config for preview mode
39742
+ const defaultPreviewConfig = {
39743
+ appearance: {
39744
+ primaryColor: primaryColor || '#0077FF',
39745
+ position: position || 'bottom-right',
39746
+ size: size || 'small',
39747
+ headerTitle: headerTitle || 'AI Assistant',
39748
+ welcomeTitle: welcomeTitle || 'Welcome!',
39749
+ welcomeMessage: welcomeMessage || 'Hi there! How can I help you today?',
39750
+ placeholder: placeholder || 'Ask me anything...',
39751
+ },
39752
+ settings: {
39753
+ autoOpen: false,
39754
+ persistConversation: true,
39755
+ showChatHistory: true,
39756
+ showTimestamps: true,
39757
+ showTypingIndicator: true,
39758
+ enableFileUpload: false,
39759
+ enableFeedback: true,
39760
+ showSources: false,
39761
+ sourceDisplayMode: 'none',
39762
+ },
39763
+ behavior: {
39764
+ agentic: false,
39765
+ },
39766
+ knowledgeBases: [],
39767
+ };
39768
+ // Merge preview config with defaults
39769
+ const mergedPreviewConfig = {
39770
+ ...defaultPreviewConfig,
39771
+ ...previewConfig,
39772
+ appearance: {
39773
+ ...defaultPreviewConfig.appearance,
39774
+ ...previewConfig?.appearance,
39775
+ },
39776
+ settings: {
39777
+ ...defaultPreviewConfig.settings,
39778
+ ...previewConfig?.settings,
39779
+ },
39780
+ behavior: {
39781
+ ...defaultPreviewConfig.behavior,
39782
+ ...previewConfig?.behavior,
39783
+ },
39784
+ };
39785
+ // Always call useChat hook (React rules), but use a dummy widgetId in preview mode
39786
+ // The hook will fail to load config, but we don't use its results in preview mode anyway
39787
+ const chatHook = useChat({
39788
+ widgetId: previewMode ? '__preview__' : (widgetId || '__preview__'),
39389
39789
  apiUrl,
39390
- onMessage,
39391
- onError,
39790
+ onMessage: previewMode ? undefined : onMessage,
39791
+ onError: previewMode ? undefined : onError,
39392
39792
  });
39793
+ // Extract values from hook or use preview defaults
39794
+ const messages = previewMode ? [] : chatHook.messages;
39795
+ const isLoading = previewMode ? false : chatHook.isLoading;
39796
+ const isTyping = previewMode ? false : chatHook.isTyping;
39797
+ const error = previewMode ? null : chatHook.error;
39798
+ const config = previewMode ? mergedPreviewConfig : chatHook.config;
39799
+ const sendMessage = previewMode ? (() => Promise.resolve()) : chatHook.sendMessage;
39800
+ const submitFeedback = previewMode ? (() => Promise.resolve()) : chatHook.submitFeedback;
39801
+ const conversations = previewMode ? [] : chatHook.conversations;
39802
+ const loadConversations = previewMode ? (() => { }) : chatHook.loadConversations;
39803
+ const switchConversation = previewMode ? (() => Promise.resolve()) : chatHook.switchConversation;
39804
+ const startNewConversation = previewMode ? (() => { }) : chatHook.startNewConversation;
39805
+ const conversationId = previewMode ? '' : chatHook.conversationId;
39393
39806
  // Auto-detect theme from background
39394
39807
  reactExports.useEffect(() => {
39395
39808
  if (!containerRef.current)
@@ -39427,8 +39840,8 @@
39427
39840
  }, [config, autoDetectedTheme]);
39428
39841
  // Handle auto-open
39429
39842
  reactExports.useEffect(() => {
39430
- if (config?.behavior.autoOpen) {
39431
- const delay = config.behavior.autoOpenDelay || 0;
39843
+ if (config?.settings.autoOpen) {
39844
+ const delay = config.settings.autoOpenDelay || 0;
39432
39845
  const timer = setTimeout(() => {
39433
39846
  setIsOpen(true);
39434
39847
  onOpen?.();
@@ -39437,26 +39850,6 @@
39437
39850
  }
39438
39851
  return undefined;
39439
39852
  }, [config, onOpen]);
39440
- // Handle close on outside click - always enabled for better UX
39441
- reactExports.useEffect(() => {
39442
- if (!isOpen)
39443
- return;
39444
- const handleClickOutside = (event) => {
39445
- // Check if click is outside the widget container
39446
- if (widgetRef.current && !widgetRef.current.contains(event.target)) {
39447
- setIsOpen(false);
39448
- onClose?.();
39449
- }
39450
- };
39451
- // Small delay to prevent immediate close on open
39452
- const timer = setTimeout(() => {
39453
- document.addEventListener('mousedown', handleClickOutside);
39454
- }, 150);
39455
- return () => {
39456
- clearTimeout(timer);
39457
- document.removeEventListener('mousedown', handleClickOutside);
39458
- };
39459
- }, [isOpen, onClose]);
39460
39853
  // Handle close on Escape key
39461
39854
  reactExports.useEffect(() => {
39462
39855
  if (!isOpen)
@@ -39470,31 +39863,33 @@
39470
39863
  document.addEventListener('keydown', handleEscapeKey);
39471
39864
  return () => document.removeEventListener('keydown', handleEscapeKey);
39472
39865
  }, [isOpen, onClose]);
39473
- // Determine theme - always auto-detect from background
39866
+ // Determine theme - use prop override if provided, otherwise auto-detect
39474
39867
  const appearanceConfig = config?.appearance;
39475
- const effectiveTheme = autoDetectedTheme;
39476
- // Determine position (config takes priority over prop)
39477
- const effectivePosition = config?.appearance.position || position;
39478
- // Get accent color from config or prop
39479
- const accentColor = primaryColor || appearanceConfig?.primaryColor || '#0077FF';
39868
+ const effectiveTheme = theme ?? autoDetectedTheme;
39869
+ // Determine position (prop override takes priority for live preview)
39870
+ const effectivePosition = position || config?.appearance.position || 'bottom-right';
39871
+ // Get accent color from prop or config (empty string means no accent color / vanilla mode)
39872
+ const accentColor = primaryColor ?? appearanceConfig?.primaryColor ?? '';
39873
+ // Apply prop overrides for live preview (props take priority over config)
39874
+ size || appearanceConfig?.size || 'small';
39875
+ const effectiveHeaderTitle = headerTitle ?? appearanceConfig?.headerTitle ?? '';
39876
+ const effectiveWelcomeTitle = welcomeTitle ?? appearanceConfig?.welcomeTitle ?? '';
39877
+ const effectiveWelcomeMessage = welcomeMessage ?? appearanceConfig?.welcomeMessage ?? '';
39878
+ const effectivePlaceholder = placeholder ?? appearanceConfig?.placeholder ?? '';
39480
39879
  // Generate styles using simplified theme system
39481
39880
  const simpleAppearance = {
39482
- accentColor,
39483
- size: appearanceConfig?.size || 'small',
39484
- welcomeMessage: appearanceConfig?.welcomeMessage || '',
39485
- placeholder: appearanceConfig?.placeholder || '',
39486
- headerTitle: appearanceConfig?.headerTitle || '',
39487
- };
39881
+ accentColor};
39488
39882
  // Generate theme styles from accent color
39489
39883
  const generatedStyles = generateThemeStyles(simpleAppearance, effectiveTheme);
39490
39884
  // Also apply legacy styles for backward compatibility
39491
39885
  const legacyStyles = appearanceConfig
39492
39886
  ? applyAppearanceStyles(appearanceConfig)
39493
39887
  : {};
39494
- // Merge styles (generated takes priority for new simplified system)
39495
- const customStyles = {
39888
+ // Merge styles (generated takes priority for new simplified system, then custom overrides)
39889
+ const mergedStyles = {
39496
39890
  ...legacyStyles,
39497
39891
  ...generatedStyles,
39892
+ ...customStyles,
39498
39893
  };
39499
39894
  // Debug logging for theme and styles
39500
39895
  reactExports.useEffect(() => {
@@ -39519,14 +39914,19 @@
39519
39914
  await submitFeedback(messageId, feedback);
39520
39915
  };
39521
39916
  // Don't render until config is loaded to avoid flash of unstyled content
39522
- if (!config) {
39917
+ // In preview mode, config is always available
39918
+ if (!config && !previewMode) {
39523
39919
  console.log('[ChatWidget] Not rendering - config not loaded yet');
39524
39920
  return null;
39525
39921
  }
39526
39922
  console.log('[ChatWidget] Rendering widget', { isOpen, hasConfig: !!config });
39527
39923
  // Get button icon based on state
39528
39924
  const IconComponent = isOpen ? iconComponents.FiChevronDown : iconComponents.FiMessageCircle;
39529
- return (jsxRuntimeExports.jsx("div", { ref: containerRef, className: `ai-chat-widget ${effectiveTheme}`, style: customStyles, children: jsxRuntimeExports.jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition}`, children: [isOpen && (jsxRuntimeExports.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, error: error, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback })), jsxRuntimeExports.jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", children: jsxRuntimeExports.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntimeExports.jsx(IconComponent, {}) }) })] }) }));
39925
+ return (jsxRuntimeExports.jsx("div", { ref: containerRef, className: `ai-chat-widget ${effectiveTheme}`, style: mergedStyles, children: jsxRuntimeExports.jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition}`, children: [isOpen && (jsxRuntimeExports.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, error: error, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback,
39926
+ // Chat history props (only active when persistConversation is true)
39927
+ conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, currentConversationId: conversationId,
39928
+ // Override props for live preview
39929
+ headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions })), jsxRuntimeExports.jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", children: jsxRuntimeExports.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntimeExports.jsx(IconComponent, {}) }) })] }) }));
39530
39930
  };
39531
39931
 
39532
39932
  /**