@messenger-box/tailwind-ui-inbox 10.0.3-alpha.70 → 10.0.3-alpha.72

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.
Files changed (155) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/lib/components/AIAgent/AIAgent.d.ts +14 -0
  3. package/lib/components/AIAgent/AIAgent.d.ts.map +1 -0
  4. package/lib/components/AIAgent/AIAgent.js +1148 -0
  5. package/lib/components/AIAgent/AIAgent.js.map +1 -0
  6. package/lib/components/AIAgent/index.d.ts +2 -0
  7. package/lib/components/AIAgent/index.d.ts.map +1 -0
  8. package/lib/components/InboxMessage/InputComponent.d.ts +9 -0
  9. package/lib/components/InboxMessage/InputComponent.d.ts.map +1 -0
  10. package/lib/components/InboxMessage/InputComponent.js +210 -0
  11. package/lib/components/InboxMessage/InputComponent.js.map +1 -0
  12. package/lib/components/InboxMessage/LeftSidebar.d.ts +2 -0
  13. package/lib/components/InboxMessage/LeftSidebar.d.ts.map +1 -1
  14. package/lib/components/InboxMessage/LeftSidebar.js +16 -5
  15. package/lib/components/InboxMessage/LeftSidebar.js.map +1 -1
  16. package/lib/components/InboxMessage/MessageInput.d.ts.map +1 -1
  17. package/lib/components/InboxMessage/MessageInput.js +14 -10
  18. package/lib/components/InboxMessage/MessageInput.js.map +1 -1
  19. package/lib/components/InboxMessage/MessageInputComponent.d.ts +9 -0
  20. package/lib/components/InboxMessage/MessageInputComponent.d.ts.map +1 -0
  21. package/lib/components/InboxMessage/MessageInputComponent.js +173 -0
  22. package/lib/components/InboxMessage/MessageInputComponent.js.map +1 -0
  23. package/lib/components/InboxMessage/Messages.d.ts +3 -1
  24. package/lib/components/InboxMessage/Messages.d.ts.map +1 -1
  25. package/lib/components/InboxMessage/Messages.js +16 -60
  26. package/lib/components/InboxMessage/Messages.js.map +1 -1
  27. package/lib/components/InboxMessage/MessagesBuilderUi.d.ts +17 -0
  28. package/lib/components/InboxMessage/MessagesBuilderUi.d.ts.map +1 -0
  29. package/lib/components/InboxMessage/MessagesBuilderUi.js +162 -0
  30. package/lib/components/InboxMessage/MessagesBuilderUi.js.map +1 -0
  31. package/lib/components/InboxMessage/UploadImageButton.d.ts +1 -0
  32. package/lib/components/InboxMessage/UploadImageButton.d.ts.map +1 -1
  33. package/lib/components/InboxMessage/UploadImageButton.js +3 -3
  34. package/lib/components/InboxMessage/UploadImageButton.js.map +1 -1
  35. package/lib/components/InboxMessage/index.d.ts +3 -0
  36. package/lib/components/InboxMessage/index.d.ts.map +1 -1
  37. package/lib/components/InboxMessage/message-widgets/CommonMessage.d.ts.map +1 -1
  38. package/lib/components/InboxMessage/message-widgets/CommonMessage.js +11 -6
  39. package/lib/components/InboxMessage/message-widgets/CommonMessage.js.map +1 -1
  40. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts +14 -0
  41. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts.map +1 -0
  42. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js +1525 -0
  43. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js.map +1 -0
  44. package/lib/components/InboxMessage/message-widgets/PlainMessage.d.ts.map +1 -1
  45. package/lib/components/InboxMessage/message-widgets/PlainMessage.js +6 -3
  46. package/lib/components/InboxMessage/message-widgets/PlainMessage.js.map +1 -1
  47. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.d.ts +2 -0
  48. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.d.ts.map +1 -1
  49. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js +225 -26
  50. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js.map +1 -1
  51. package/lib/components/InboxMessage/message-widgets/index.d.ts +1 -0
  52. package/lib/components/InboxMessage/message-widgets/index.d.ts.map +1 -1
  53. package/lib/components/index.d.ts +2 -1
  54. package/lib/components/index.d.ts.map +1 -1
  55. package/lib/compute.d.ts.map +1 -1
  56. package/lib/compute.js +79 -3
  57. package/lib/compute.js.map +1 -1
  58. package/lib/config/env-config.d.ts +6 -0
  59. package/lib/config/env-config.d.ts.map +1 -1
  60. package/lib/config/env-config.js +19 -1
  61. package/lib/config/env-config.js.map +1 -1
  62. package/lib/container/AiInbox.d.ts +15 -0
  63. package/lib/container/AiInbox.d.ts.map +1 -0
  64. package/lib/container/AiInbox.js +1520 -0
  65. package/lib/container/AiInbox.js.map +1 -0
  66. package/lib/container/AiInboxWithLoader.d.ts +36 -0
  67. package/lib/container/AiInboxWithLoader.d.ts.map +1 -0
  68. package/lib/container/AiInboxWithLoader.js +300 -0
  69. package/lib/container/AiInboxWithLoader.js.map +1 -0
  70. package/lib/container/AiLandingInput.d.ts +4 -0
  71. package/lib/container/AiLandingInput.d.ts.map +1 -0
  72. package/lib/container/AiLandingInput.js +164 -0
  73. package/lib/container/AiLandingInput.js.map +1 -0
  74. package/lib/container/Inbox.d.ts.map +1 -1
  75. package/lib/container/Inbox.js +177 -58
  76. package/lib/container/Inbox.js.map +1 -1
  77. package/lib/container/InboxAiMessagesLoader.d.ts +36 -0
  78. package/lib/container/InboxAiMessagesLoader.d.ts.map +1 -0
  79. package/lib/container/InboxAiMessagesLoader.js +47 -0
  80. package/lib/container/InboxAiMessagesLoader.js.map +1 -0
  81. package/lib/container/InboxContainer.d.ts +12 -0
  82. package/lib/container/InboxContainer.d.ts.map +1 -0
  83. package/lib/container/InboxContainer.js +31 -0
  84. package/lib/container/InboxContainer.js.map +1 -0
  85. package/lib/container/InboxTemplate1.d.ts +15 -0
  86. package/lib/container/InboxTemplate1.d.ts.map +1 -0
  87. package/lib/container/InboxTemplate1.js +1375 -0
  88. package/lib/container/InboxTemplate1.js.map +1 -0
  89. package/lib/container/InboxTemplate1WithLoader.d.ts +36 -0
  90. package/lib/container/InboxTemplate1WithLoader.d.ts.map +1 -0
  91. package/lib/container/InboxTemplate2.d.ts +15 -0
  92. package/lib/container/InboxTemplate2.d.ts.map +1 -0
  93. package/lib/container/InboxTemplate2.js +1426 -0
  94. package/lib/container/InboxTemplate2.js.map +1 -0
  95. package/lib/container/InboxWithAiLoader.d.ts +15 -0
  96. package/lib/container/InboxWithAiLoader.d.ts.map +1 -0
  97. package/lib/container/InboxWithAiLoader.js +56 -0
  98. package/lib/container/InboxWithAiLoader.js.map +1 -0
  99. package/lib/container/ServiceInbox.js +1 -1
  100. package/lib/container/ServiceInbox.js.map +1 -1
  101. package/lib/container/ThreadMessages.js +1 -1
  102. package/lib/container/ThreadMessages.js.map +1 -1
  103. package/lib/container/ThreadMessagesInbox.js +1 -1
  104. package/lib/container/ThreadMessagesInbox.js.map +1 -1
  105. package/lib/container/Threads.js +1 -1
  106. package/lib/container/Threads.js.map +1 -1
  107. package/lib/container/index.d.ts +4 -1
  108. package/lib/container/index.d.ts.map +1 -1
  109. package/lib/index.js +1 -1
  110. package/lib/machines/aiAgentMachine.d.ts +3 -0
  111. package/lib/machines/aiAgentMachine.d.ts.map +1 -0
  112. package/lib/machines/aiAgentMachine.js +1040 -0
  113. package/lib/machines/aiAgentMachine.js.map +1 -0
  114. package/lib/machines/types.d.ts +77 -0
  115. package/lib/machines/types.d.ts.map +1 -0
  116. package/lib/routes.json +40 -0
  117. package/lib/templates/InboxWithAi.d.ts +15 -0
  118. package/lib/templates/InboxWithAi.d.ts.map +1 -0
  119. package/lib/templates/InboxWithAi.js +405 -0
  120. package/lib/templates/InboxWithAi.js.map +1 -0
  121. package/lib/templates/InboxWithAi.tsx +502 -0
  122. package/package.json +7 -5
  123. package/src/components/AIAgent/AIAgent.tsx +1351 -0
  124. package/src/components/AIAgent/README.md +82 -0
  125. package/src/components/AIAgent/index.ts +1 -0
  126. package/src/components/InboxMessage/InputComponent.tsx +263 -0
  127. package/src/components/InboxMessage/LeftSidebar.tsx +14 -4
  128. package/src/components/InboxMessage/MessageInput.tsx +73 -66
  129. package/src/components/InboxMessage/MessageInputComponent.tsx +245 -0
  130. package/src/components/InboxMessage/Messages.tsx +24 -68
  131. package/src/components/InboxMessage/MessagesBuilderUi.tsx +205 -0
  132. package/src/components/InboxMessage/UploadImageButton.tsx +3 -2
  133. package/src/components/InboxMessage/index.ts +3 -0
  134. package/src/components/InboxMessage/message-widgets/CommonMessage.tsx +39 -21
  135. package/src/components/InboxMessage/message-widgets/ModernMessageGroup.tsx +1968 -0
  136. package/src/components/InboxMessage/message-widgets/PlainMessage.tsx +6 -2
  137. package/src/components/InboxMessage/message-widgets/SlackLikeMessageGroup.tsx +337 -53
  138. package/src/components/InboxMessage/message-widgets/index.ts +1 -0
  139. package/src/components/index.ts +4 -0
  140. package/src/compute.ts +83 -2
  141. package/src/config/env-config.ts +6 -0
  142. package/src/container/AiInbox.tsx +1796 -0
  143. package/src/container/AiInboxWithLoader.tsx +356 -0
  144. package/src/container/AiLandingInput.tsx +168 -0
  145. package/src/container/Inbox.tsx +280 -130
  146. package/src/container/InboxAiMessagesLoader.tsx +68 -0
  147. package/src/container/InboxContainer.tsx +35 -0
  148. package/src/container/InboxTemplate1.tsx +1542 -0
  149. package/src/container/InboxTemplate1WithLoader.tsx +338 -0
  150. package/src/container/InboxTemplate2.tsx +1606 -0
  151. package/src/container/InboxWithAiLoader.tsx +76 -0
  152. package/src/container/index.ts +15 -1
  153. package/src/machines/aiAgentMachine.ts +1248 -0
  154. package/src/machines/types.ts +59 -0
  155. package/src/templates/InboxWithAi.tsx +502 -0
@@ -0,0 +1,1148 @@
1
+ import React__default,{useState,useRef,useMemo,useCallback,useEffect}from'react';import {useMachine}from'@xstate/react';import {aiAgentMachine}from'../../machines/aiAgentMachine.js';import {InputComponent}from'../InboxMessage/InputComponent.js';import {isToday,isYesterday,format}from'date-fns';import {useTranslation}from'react-i18next';import {ModernMessageGroupComponent}from'../InboxMessage/message-widgets/ModernMessageGroup.js';import {useUploadFiles}from'@messenger-box/platform-client';import {useSelector,shallowEqual}from'react-redux';import {userSelector}from'@adminide-stack/user-auth0-client';import {objectId}from'@messenger-box/core';import {useApolloClient}from'@apollo/client/index.js';import {useSendMessagesMutation,useMessagesQuery,MessagesDocument,OnChatMessageAddedDocument}from'common/graphql';import {config}from'../../config/env-config.js';import {orderBy,uniqBy}from'lodash-es';import {useParams}from'@remix-run/react';import {SubscriptionHandler}from'../InboxMessage/SubscriptionHandler.js';const {
2
+ MESSAGES_PER_PAGE
3
+ } = config;
4
+ const AIAgent = ({
5
+ channelId,
6
+ onSendMessage,
7
+ placeholder = 'Ask me anything...',
8
+ className = '',
9
+ currentUser,
10
+ isDesktopView = false,
11
+ isSmallScreen = false
12
+ }) => {
13
+ const [state, send] = useMachine(aiAgentMachine);
14
+ useApolloClient();
15
+ const {
16
+ startUpload
17
+ } = useUploadFiles();
18
+ const [sendMsg] = useSendMessagesMutation();
19
+ useSelector(userSelector, shallowEqual);
20
+ const {
21
+ id: pathChannelId
22
+ } = useParams();
23
+ // Get channelId from props or path params
24
+ const actualChannelId = channelId || pathChannelId;
25
+ // Direct message query from InboxWithAiLoader.tsx
26
+ const messagesQuery = useMessagesQuery({
27
+ variables: {
28
+ channelId: actualChannelId?.toString(),
29
+ parentId: null,
30
+ limit: MESSAGES_PER_PAGE
31
+ },
32
+ skip: !actualChannelId,
33
+ fetchPolicy: 'cache-and-network',
34
+ errorPolicy: 'all',
35
+ notifyOnNetworkStatusChange: true,
36
+ returnPartialData: true,
37
+ pollInterval: 0,
38
+ context: {
39
+ cacheKey: 'messages-list'
40
+ }
41
+ });
42
+ const {
43
+ messages: aiMessages,
44
+ error,
45
+ isTyping
46
+ } = state.context;
47
+ const {
48
+ t
49
+ } = useTranslation('translations');
50
+ const [isOpen, setIsOpen] = useState(false);
51
+ const [selectedElement, setSelectedElement] = useState(null);
52
+ const [currentProcessingMessage, setCurrentProcessingMessage] = useState(null);
53
+ const [processedMessageIds, setProcessedMessageIds] = useState(new Set());
54
+ const [activeTab, setActiveTab] = useState('chat');
55
+ const bottomRef = useRef(null);
56
+ // New state variables for message display control
57
+ const [displayedMessageCount, setDisplayedMessageCount] = useState(1); // Initially show only 1 message
58
+ const [hasMoreMessages, setHasMoreMessages] = useState(false);
59
+ // Get regular messages from direct query
60
+ const {
61
+ data: messagesData,
62
+ loading: messageLoading,
63
+ fetchMore: fetchMoreMessages,
64
+ subscribeToMore
65
+ } = messagesQuery;
66
+ const regularMessages = useMemo(() => {
67
+ if (!messagesData?.messages?.data) return [];
68
+ return orderBy(uniqBy(messagesData.messages.data || [], 'id'), ['createdAt'], ['asc']);
69
+ }, [messagesData?.messages?.data]);
70
+ const onOpen = element => {
71
+ setSelectedElement(element);
72
+ setIsOpen(true);
73
+ };
74
+ const onClose = () => {
75
+ setIsOpen(false);
76
+ setSelectedElement(null);
77
+ };
78
+ // Enhanced scroll to bottom function
79
+ const scrollToBottom = useCallback((behavior = 'smooth', delay = 0) => {
80
+ setTimeout(() => {
81
+ if (bottomRef.current) {
82
+ bottomRef.current.scrollIntoView({
83
+ behavior,
84
+ block: 'end',
85
+ inline: 'nearest'
86
+ });
87
+ }
88
+ }, delay);
89
+ }, []);
90
+ // Updated handleSend function from InboxWithAi.tsx
91
+ const handleSend = useCallback(async (message, files = []) => {
92
+ // Allow sending if there's either a message or files
93
+ if ((!message || !message.trim()) && (!files || files.length === 0)) return;
94
+ if (!actualChannelId) return;
95
+ try {
96
+ const postId = objectId();
97
+ const currentDate = new Date();
98
+ const createOptimisticMessage = files => ({
99
+ __typename: 'Post',
100
+ id: postId,
101
+ message,
102
+ createdAt: currentDate.toISOString(),
103
+ updatedAt: currentDate.toISOString(),
104
+ author: {
105
+ __typename: 'UserAccount',
106
+ id: currentUser?.id,
107
+ givenName: currentUser?.profile?.given_name || '',
108
+ familyName: currentUser?.profile?.family_name || '',
109
+ email: currentUser?.profile?.email || '',
110
+ username: currentUser?.profile?.nickname || '',
111
+ fullName: currentUser?.profile?.name || '',
112
+ picture: currentUser?.profile?.picture || '',
113
+ alias: [currentUser?.authUserId ?? ''],
114
+ tokens: []
115
+ },
116
+ isDelivered: false,
117
+ // Will be true once confirmed by server
118
+ isRead: false,
119
+ type: 'Simple',
120
+ parentId: null,
121
+ fromServer: false,
122
+ channel: {
123
+ __typename: 'Channel',
124
+ id: actualChannelId
125
+ },
126
+ propsConfiguration: {
127
+ __typename: 'MachineConfiguration',
128
+ id: null,
129
+ resource: '',
130
+ contents: null,
131
+ keys: null,
132
+ target: null,
133
+ overrides: null
134
+ },
135
+ props: {},
136
+ files: {
137
+ __typename: 'FilesInfo',
138
+ data: files || [],
139
+ totalCount: files?.length || 0
140
+ },
141
+ replies: {
142
+ __typename: 'Messages',
143
+ data: [],
144
+ totalCount: 0
145
+ }
146
+ });
147
+ const optimisticMessage = createOptimisticMessage(files);
148
+ if (files?.length > 0) {
149
+ const uploadResponse = await startUpload({
150
+ file: files,
151
+ saveUploadedFile: {
152
+ variables: {
153
+ postId
154
+ }
155
+ },
156
+ createUploadLink: {
157
+ variables: {
158
+ postId
159
+ }
160
+ }
161
+ });
162
+ const uploadedFiles = uploadResponse.data;
163
+ if (uploadedFiles) {
164
+ const fileIds = uploadedFiles.map(f => f.id);
165
+ await sendMsg({
166
+ variables: {
167
+ postId,
168
+ channelId: actualChannelId,
169
+ content: message,
170
+ files: fileIds
171
+ },
172
+ optimisticResponse: {
173
+ __typename: 'Mutation',
174
+ sendMessage: createOptimisticMessage(uploadedFiles)
175
+ },
176
+ update: (cache, {
177
+ data: mutationData
178
+ }) => {
179
+ if (!mutationData?.sendMessage) return;
180
+ // Update messages cache optimistically
181
+ const messagesQuery = {
182
+ query: MessagesDocument,
183
+ variables: {
184
+ channelId: actualChannelId.toString(),
185
+ parentId: null,
186
+ limit: MESSAGES_PER_PAGE
187
+ }
188
+ };
189
+ try {
190
+ const existingData = cache.readQuery(messagesQuery);
191
+ if (existingData?.messages) {
192
+ cache.writeQuery({
193
+ ...messagesQuery,
194
+ data: {
195
+ messages: {
196
+ ...existingData.messages,
197
+ data: [...(existingData.messages.data || []), mutationData.sendMessage],
198
+ totalCount: (existingData.messages.totalCount || 0) + 1
199
+ }
200
+ }
201
+ });
202
+ }
203
+ } catch (error) {
204
+ console.debug('Cache update failed (expected on first message):', error);
205
+ }
206
+ }
207
+ });
208
+ }
209
+ } else {
210
+ await sendMsg({
211
+ variables: {
212
+ channelId: actualChannelId,
213
+ content: message
214
+ },
215
+ optimisticResponse: {
216
+ __typename: 'Mutation',
217
+ sendMessage: optimisticMessage
218
+ },
219
+ update: (cache, {
220
+ data: mutationData
221
+ }) => {
222
+ if (!mutationData?.sendMessage) return;
223
+ // Update messages cache optimistically
224
+ const messagesQuery = {
225
+ query: MessagesDocument,
226
+ variables: {
227
+ channelId: actualChannelId.toString(),
228
+ parentId: null,
229
+ limit: MESSAGES_PER_PAGE
230
+ }
231
+ };
232
+ try {
233
+ const existingData = cache.readQuery(messagesQuery);
234
+ if (existingData?.messages) {
235
+ cache.writeQuery({
236
+ ...messagesQuery,
237
+ data: {
238
+ messages: {
239
+ ...existingData.messages,
240
+ data: [...(existingData.messages.data || []), mutationData.sendMessage],
241
+ totalCount: (existingData.messages.totalCount || 0) + 1
242
+ }
243
+ }
244
+ });
245
+ }
246
+ } catch (error) {
247
+ console.debug('Cache update failed (expected on first message):', error);
248
+ }
249
+ }
250
+ });
251
+ }
252
+ // Send message to AI agent machine
253
+ send({
254
+ type: 'SEND_MESSAGE',
255
+ message: message.trim()
256
+ });
257
+ // Ensure we scroll to the newest message immediately
258
+ scrollToBottom('smooth', 0);
259
+ // When sending new messages, increment the displayed count to show the new message
260
+ // This ensures we show both the existing last message and the new message
261
+ setDisplayedMessageCount(prev => {
262
+ const newCount = Math.max(prev + 1, 2);
263
+ console.log('🔄 Message sent: Updating displayedMessageCount', {
264
+ previous: prev,
265
+ new: newCount,
266
+ reason: 'New message sent'
267
+ });
268
+ return newCount;
269
+ });
270
+ // Call the optional onSendMessage prop if provided
271
+ if (onSendMessage) {
272
+ await onSendMessage(message, files);
273
+ }
274
+ } catch (error) {
275
+ console.error('Error sending message:', error);
276
+ }
277
+ }, [actualChannelId, currentUser, startUpload, sendMsg, send, onSendMessage]);
278
+ // Debug effect to track AI messages changes
279
+ useEffect(() => {
280
+ console.log('🤖 AI messages state changed:', aiMessages.length);
281
+ if (aiMessages.length > 0) {
282
+ console.log('🤖 Latest AI message:', aiMessages[aiMessages.length - 1]);
283
+ // Clear processing message if we have new AI responses
284
+ if (currentProcessingMessage !== null) {
285
+ console.log('🤖 AI response received, clearing processing message');
286
+ setCurrentProcessingMessage(null);
287
+ }
288
+ // Auto-scroll to bottom when new AI response appears
289
+ scrollToBottom('smooth', 200);
290
+ } else {
291
+ console.log('🤖 No AI messages in state - this might indicate an issue');
292
+ }
293
+ }, [aiMessages, currentProcessingMessage]);
294
+ // Debug effect to track machine state changes
295
+ useEffect(() => {
296
+ console.log('🤖 Machine state changed:', state.value);
297
+ console.log('🤖 Machine context:', {
298
+ messagesCount: state.context.messages.length,
299
+ hasMessageToRespondTo: !!state.context.messageToRespondTo,
300
+ messageToRespondTo: state.context.messageToRespondTo
301
+ });
302
+ // Check if we're in processing state but no AI response is being generated
303
+ if (state.value === 'processing' && !state.context.messageToRespondTo) {
304
+ console.log('🤖 ⚠️ WARNING: In processing state but no messageToRespondTo!');
305
+ }
306
+ // Auto-scroll when AI starts processing
307
+ if (state.value === 'processing') {
308
+ scrollToBottom('smooth', 100);
309
+ }
310
+ }, [state.value, state.context, scrollToBottom]);
311
+ // Send regular messages to AI agent machine for context
312
+ useEffect(() => {
313
+ if (regularMessages && regularMessages.length > 0) {
314
+ send({
315
+ type: 'UPDATE_REGULAR_MESSAGES',
316
+ messages: regularMessages
317
+ });
318
+ }
319
+ }, [regularMessages, send]);
320
+ // Reset processed messages when regular messages change completely
321
+ useEffect(() => {
322
+ if (regularMessages && regularMessages.length > 0) {
323
+ // Check if we have completely new messages (different IDs)
324
+ new Set(regularMessages.map(msg => msg.id));
325
+ const hasNewMessages = !regularMessages.every(msg => processedMessageIds.has(msg.id));
326
+ if (hasNewMessages) {
327
+ console.log('🤖 New messages detected, resetting processed state');
328
+ setProcessedMessageIds(new Set());
329
+ setCurrentProcessingMessage(null);
330
+ }
331
+ }
332
+ }, [regularMessages]);
333
+ // Sequential auto-response logic - respond to each message one at a time
334
+ useEffect(() => {
335
+ if (regularMessages && regularMessages.length > 0) {
336
+ console.log('🤖 Regular messages detected:', regularMessages.length);
337
+ console.log('🤖 Current AI messages:', aiMessages.length);
338
+ console.log('🤖 Already processed message IDs:', Array.from(processedMessageIds));
339
+ // Find messages that don't have AI responses yet and haven't been processed
340
+ const messagesWithoutAIResponses = regularMessages.filter((msg, index) => {
341
+ // Check if this message already has an AI response
342
+ const hasAIResponse = aiMessages.length > index;
343
+ // Check if this message has already been processed
344
+ const alreadyProcessed = processedMessageIds.has(msg.id);
345
+ return !hasAIResponse && !alreadyProcessed;
346
+ });
347
+ if (messagesWithoutAIResponses.length > 0) {
348
+ console.log(`🤖 Found ${messagesWithoutAIResponses.length} messages to process`);
349
+ // Simplified: Just process the first message and let the machine handle the rest
350
+ const firstMsg = messagesWithoutAIResponses[0];
351
+ console.log(`🤖 Starting with first message: ${firstMsg.message?.substring(0, 50)}...`);
352
+ // Mark this message as being processed
353
+ setProcessedMessageIds(prev => new Set([...prev, firstMsg.id]));
354
+ setCurrentProcessingMessage(0);
355
+ // Send the first message to AI
356
+ send({
357
+ type: 'AUTO_RESPOND_TO_MESSAGE',
358
+ message: firstMsg.message,
359
+ isAutoResponse: true
360
+ });
361
+ } else {
362
+ console.log('🤖 All messages already have AI responses or are being processed');
363
+ setCurrentProcessingMessage(null);
364
+ }
365
+ }
366
+ }, [regularMessages.length, aiMessages.length, processedMessageIds.size]); // Only depend on lengths and processed count
367
+ // Process next message when machine becomes idle (after completing AI response)
368
+ useEffect(() => {
369
+ // Only run when machine is idle and we have messages to process
370
+ if (state.matches('idle') && regularMessages && regularMessages.length > 0) {
371
+ console.log('🤖 Machine idle, checking for next message to process...');
372
+ console.log('🤖 Current state - AI messages:', aiMessages.length, 'Processed IDs:', processedMessageIds.size);
373
+ // Find the next message that needs an AI response
374
+ const nextMessageIndex = regularMessages.findIndex((msg, index) => {
375
+ const hasAIResponse = aiMessages.length > index;
376
+ const alreadyProcessed = processedMessageIds.has(msg.id);
377
+ const needsResponse = !hasAIResponse && !alreadyProcessed;
378
+ console.log(`🤖 Message ${index + 1} "${msg.message?.substring(0, 30)}..." - hasAIResponse: ${hasAIResponse}, alreadyProcessed: ${alreadyProcessed}, needsResponse: ${needsResponse}`);
379
+ return needsResponse;
380
+ });
381
+ if (nextMessageIndex !== -1) {
382
+ console.log(`🤖 Found next message to process: ${nextMessageIndex + 1}: ${regularMessages[nextMessageIndex].message?.substring(0, 50)}...`);
383
+ // Check if this message is a duplicate of a previous one
384
+ const currentMessage = regularMessages[nextMessageIndex];
385
+ const previousMessageIndex = regularMessages.findIndex((prevMsg, prevIndex) => prevIndex < nextMessageIndex && prevMsg.message === currentMessage.message);
386
+ if (previousMessageIndex !== -1 && aiMessages.length > previousMessageIndex) {
387
+ // This is a duplicate message, mark it as processed without sending to AI
388
+ console.log(`🤖 Duplicate message detected: "${currentMessage.message}" - reusing AI response from message ${previousMessageIndex + 1}`);
389
+ setProcessedMessageIds(prev => new Set([...prev, currentMessage.id]));
390
+ setCurrentProcessingMessage(null);
391
+ // Continue with next message immediately
392
+ setTimeout(() => {
393
+ send({
394
+ type: 'CONTINUE_PROCESSING'
395
+ });
396
+ }, 100);
397
+ } else {
398
+ // Mark this message as being processed
399
+ setProcessedMessageIds(prev => new Set([...prev, currentMessage.id]));
400
+ setCurrentProcessingMessage(nextMessageIndex);
401
+ // Send to AI
402
+ console.log(`🤖 Sending message to AI: "${currentMessage.message}"`);
403
+ send({
404
+ type: 'AUTO_RESPOND_TO_MESSAGE',
405
+ message: currentMessage.message,
406
+ isAutoResponse: true
407
+ });
408
+ }
409
+ } else {
410
+ // Check if we actually have all responses
411
+ const totalMessagesNeedingResponses = regularMessages.length;
412
+ const messagesWithResponses = aiMessages.length;
413
+ const messagesProcessed = processedMessageIds.size;
414
+ console.log(`🤖 No more messages to process. Summary:`, {
415
+ totalMessages: totalMessagesNeedingResponses,
416
+ messagesWithResponses,
417
+ messagesProcessed,
418
+ allHaveResponses: messagesWithResponses >= totalMessagesNeedingResponses
419
+ });
420
+ if (messagesWithResponses >= totalMessagesNeedingResponses) {
421
+ console.log('🤖 All messages have been processed successfully');
422
+ setCurrentProcessingMessage(null);
423
+ } else {
424
+ console.log('🤖 ⚠️ Discrepancy detected: Some messages may not have proper AI responses');
425
+ // Force a reset to try again
426
+ setProcessedMessageIds(new Set());
427
+ setCurrentProcessingMessage(null);
428
+ }
429
+ }
430
+ }
431
+ }, [state.value, regularMessages, aiMessages.length, processedMessageIds.size, send]);
432
+ // Reset processing state when regularMessages change significantly
433
+ useEffect(() => {
434
+ if (regularMessages && regularMessages.length > 0) {
435
+ // Reset processing state when we get new messages
436
+ setProcessedMessageIds(new Set());
437
+ setCurrentProcessingMessage(null);
438
+ console.log('🤖 Reset processing state for new messages');
439
+ }
440
+ }, [regularMessages.length]); // Only depend on length to avoid unnecessary resets
441
+ // Only reset displayed message count on initial load, not when new messages arrive
442
+ useEffect(() => {
443
+ if (regularMessages && regularMessages.length > 0) {
444
+ // Only reset to show last message if this is the first time we're getting messages
445
+ // or if we're currently showing more messages than we have
446
+ if (displayedMessageCount === 1 || displayedMessageCount > regularMessages.length) {
447
+ console.log('🔄 Resetting displayedMessageCount to 1:', {
448
+ reason: 'Initial load or count mismatch',
449
+ currentDisplayed: displayedMessageCount,
450
+ regularMessagesLength: regularMessages.length
451
+ });
452
+ setDisplayedMessageCount(1);
453
+ }
454
+ }
455
+ }, [regularMessages.length, displayedMessageCount]);
456
+ const handleRetry = useCallback(() => {
457
+ send({
458
+ type: 'RETRY'
459
+ });
460
+ }, [send]);
461
+ const handleClearError = useCallback(() => {
462
+ send({
463
+ type: 'CLEAR_ERROR'
464
+ });
465
+ }, [send]);
466
+ // Merge AI agent messages with regular messages from query
467
+ const allMessages = useMemo(() => {
468
+ if (!regularMessages) return [];
469
+ console.log('🔄 Merging messages - AI messages:', aiMessages.length, 'Regular messages:', regularMessages.length);
470
+ console.log('🔄 AI messages content:', aiMessages.map(m => ({
471
+ id: m.id,
472
+ content: m.content.substring(0, 50) + '...',
473
+ sender: m.sender
474
+ })));
475
+ const regularMessagesFormatted = (regularMessages || []).map((m, idx) => ({
476
+ id: m.id || `regular-${idx}`,
477
+ message: m.message || m.content || '',
478
+ createdAt: new Date(m.createdAt || Date.now()),
479
+ sender: 'user',
480
+ author: m.author,
481
+ isUserMessage: true // Explicitly mark as user message
482
+ }));
483
+ const aiMessagesFormatted = (aiMessages || []).map(m => ({
484
+ id: m.id,
485
+ message: m.content,
486
+ createdAt: new Date(m.timestamp || Date.now()),
487
+ sender: 'ai',
488
+ isUserMessage: false // Explicitly mark as AI message
489
+ }));
490
+ // Show ALL user messages immediately, interleave AI responses as they arrive
491
+ const interleavedMessages = [];
492
+ console.log('🔄 Starting message interleaving...');
493
+ console.log('🔄 Regular messages count:', regularMessagesFormatted.length);
494
+ console.log('🔄 AI messages count:', aiMessagesFormatted.length);
495
+ for (let i = 0; i < regularMessagesFormatted.length; i++) {
496
+ const userMsg = regularMessagesFormatted[i];
497
+ console.log(`🔄 Processing user message ${i + 1}:`, {
498
+ id: userMsg.id,
499
+ message: userMsg.message.substring(0, 50),
500
+ sender: userMsg.sender,
501
+ isUserMessage: userMsg.isUserMessage,
502
+ author: userMsg.author
503
+ });
504
+ interleavedMessages.push(userMsg);
505
+ console.log(`🔄 Added user message ${i + 1}: ${userMsg.message.substring(0, 50)}...`);
506
+ // Check if this message is a duplicate of a previous one
507
+ const isDuplicate = i > 0 && regularMessagesFormatted.slice(0, i).some(prevMsg => prevMsg.message === userMsg.message);
508
+ if (isDuplicate) {
509
+ // Find the first occurrence of this message to get its AI response
510
+ const firstOccurrenceIndex = regularMessagesFormatted.findIndex(msg => msg.message === userMsg.message);
511
+ const hasAIResponseForFirst = firstOccurrenceIndex < aiMessagesFormatted.length;
512
+ if (hasAIResponseForFirst) {
513
+ // Reuse the AI response from the first occurrence
514
+ const aiResponse = aiMessagesFormatted[firstOccurrenceIndex];
515
+ const adjustedCreatedAt = new Date(userMsg.createdAt.getTime() + 1);
516
+ const finalAiResponse = {
517
+ ...aiResponse,
518
+ createdAt: adjustedCreatedAt,
519
+ id: `duplicate-${aiResponse.id}-${i}`,
520
+ isDuplicate: true
521
+ };
522
+ interleavedMessages.push(finalAiResponse);
523
+ console.log(`🔄 Added duplicate AI response for message ${i + 1} (reusing from message ${firstOccurrenceIndex + 1}):`, {
524
+ id: finalAiResponse.id,
525
+ message: finalAiResponse.message.substring(0, 50),
526
+ sender: finalAiResponse.sender,
527
+ isUserMessage: finalAiResponse.isUserMessage,
528
+ isDuplicate: finalAiResponse.isDuplicate
529
+ });
530
+ } else {
531
+ // First occurrence doesn't have AI response yet, show loading
532
+ const loadingMessage = {
533
+ id: `loading-duplicate-${i}`,
534
+ message: 'Loading...',
535
+ // Shorter text since we show visual loader
536
+ createdAt: new Date(userMsg.createdAt.getTime() + 1),
537
+ sender: 'ai',
538
+ isLoading: true,
539
+ isProcessing: false,
540
+ isUserMessage: false,
541
+ isDuplicate: true
542
+ };
543
+ interleavedMessages.push(loadingMessage);
544
+ console.log(`🔄 Added loading indicator for duplicate message ${i + 1}:`, {
545
+ id: loadingMessage.id,
546
+ message: loadingMessage.message,
547
+ isDuplicate: loadingMessage.isDuplicate
548
+ });
549
+ }
550
+ } else {
551
+ // This is not a duplicate, handle normally
552
+ if (i < aiMessagesFormatted.length) {
553
+ const aiResponse = aiMessagesFormatted[i];
554
+ // Ensure AI response sorts after corresponding user message
555
+ const adjustedCreatedAt = new Date(userMsg.createdAt.getTime() + 1);
556
+ const finalAiResponse = {
557
+ ...aiResponse,
558
+ createdAt: adjustedCreatedAt
559
+ };
560
+ interleavedMessages.push(finalAiResponse);
561
+ console.log(`🔄 Added AI response for message ${i + 1}:`, {
562
+ id: finalAiResponse.id,
563
+ message: finalAiResponse.message.substring(0, 50),
564
+ sender: finalAiResponse.sender,
565
+ isUserMessage: finalAiResponse.isUserMessage
566
+ });
567
+ } else {
568
+ // Add a loading indicator for messages waiting for AI responses
569
+ const loadingMessage = {
570
+ id: `loading-${i}`,
571
+ message: 'Loading...',
572
+ // Shorter text since we show visual loader
573
+ createdAt: new Date(userMsg.createdAt.getTime() + 1),
574
+ sender: 'ai',
575
+ isLoading: true,
576
+ isProcessing: currentProcessingMessage === i,
577
+ isUserMessage: false // Explicitly mark as not a user message
578
+ };
579
+ interleavedMessages.push(loadingMessage);
580
+ console.log(`🔄 Added loading indicator for message ${i + 1}:`, {
581
+ id: loadingMessage.id,
582
+ message: loadingMessage.message,
583
+ sender: loadingMessage.sender,
584
+ isUserMessage: loadingMessage.isUserMessage,
585
+ isProcessing: loadingMessage.isProcessing
586
+ });
587
+ }
588
+ }
589
+ }
590
+ console.log('🔄 Final interleaved messages:', interleavedMessages.length);
591
+ console.log('🔄 Message structure:', interleavedMessages.map(m => ({
592
+ sender: m.sender,
593
+ isUserMessage: m.isUserMessage,
594
+ message: m.message.substring(0, 30) + '...'
595
+ })));
596
+ return interleavedMessages;
597
+ }, [aiMessages, regularMessages, currentUser, currentProcessingMessage]);
598
+ // Update hasMoreMessages when allMessages changes
599
+ useEffect(() => {
600
+ if (allMessages && allMessages.length > 0) {
601
+ // Count complete conversation pairs instead of individual messages
602
+ const conversationPairs = Math.ceil(allMessages.length / 2);
603
+ console.log('🔄 Conversation pairs calculation:', {
604
+ totalMessages: allMessages.length,
605
+ conversationPairs,
606
+ displayedMessageCount,
607
+ hasMore: conversationPairs > displayedMessageCount
608
+ });
609
+ // Show "Load Past Messages" whenever there are more conversation pairs
610
+ // than currently displayed (including initial view)
611
+ const hasMore = conversationPairs > displayedMessageCount;
612
+ setHasMoreMessages(hasMore);
613
+ // Ensure we always show at least the last conversation
614
+ if (displayedMessageCount === 0) {
615
+ setDisplayedMessageCount(1);
616
+ }
617
+ } else {
618
+ setHasMoreMessages(false);
619
+ }
620
+ }, [allMessages, displayedMessageCount]);
621
+ // Function to load more past messages
622
+ const loadMoreMessages = useCallback(() => {
623
+ if (allMessages && allMessages.length > 0) {
624
+ // Load more conversation pairs (5 pairs = 10 messages)
625
+ const conversationPairs = Math.ceil(allMessages.length / 2);
626
+ setDisplayedMessageCount(prev => Math.min(prev + 5, conversationPairs));
627
+ }
628
+ }, [allMessages]);
629
+ // Function to reset to showing only last message
630
+ useCallback(() => {
631
+ setDisplayedMessageCount(1);
632
+ }, []);
633
+ // Build list with date separators similar to MessagesBuilderUi
634
+ const messageListWithDates = useMemo(() => {
635
+ let currentDate = '';
636
+ const res = [];
637
+ allMessages?.forEach(msg => {
638
+ const date = new Date(msg.createdAt);
639
+ let msgDate;
640
+ if (isToday(date)) msgDate = t('tailwind_ui_inbox.today');else if (isYesterday(date)) msgDate = t('tailwind_ui_inbox.yesterday');else msgDate = format(date, 'eee, do MMMM');
641
+ if (msgDate !== currentDate) {
642
+ res.push({
643
+ type: 'date',
644
+ content: msgDate
645
+ });
646
+ currentDate = msgDate;
647
+ }
648
+ res.push(msg);
649
+ });
650
+ if (allMessages && allMessages.length > 0) {
651
+ const todayLabel = t('tailwind_ui_inbox.today');
652
+ if (currentDate !== todayLabel) {
653
+ res.push({
654
+ type: 'date',
655
+ content: todayLabel
656
+ });
657
+ }
658
+ }
659
+ return res;
660
+ }, [allMessages, t]);
661
+ // Group messages by date sections for Slack-like rendering
662
+ const messagesByDate = useMemo(() => {
663
+ const sections = [];
664
+ let currentSection = {
665
+ date: null,
666
+ messages: []
667
+ };
668
+ messageListWithDates.forEach(item => {
669
+ if (item?.type === 'date') {
670
+ if (currentSection.messages.length > 0) {
671
+ sections.push(currentSection);
672
+ }
673
+ currentSection = {
674
+ date: item.content,
675
+ messages: []
676
+ };
677
+ } else {
678
+ currentSection.messages.push(item);
679
+ }
680
+ });
681
+ if (currentSection.messages.length > 0) {
682
+ sections.push(currentSection);
683
+ }
684
+ return sections;
685
+ }, [messageListWithDates]);
686
+ // Limit messages to display based on displayedMessageCount (conversation pairs)
687
+ const limitedMessagesByDate = useMemo(() => {
688
+ if (!messagesByDate || messagesByDate.length === 0) return [];
689
+ // Calculate how many conversation pairs we should show
690
+ let conversationPairs = 0;
691
+ const limitedSections = [];
692
+ // Start from the end (most recent messages) and work backwards
693
+ for (let i = messagesByDate.length - 1; i >= 0; i--) {
694
+ const section = messagesByDate[i];
695
+ const sectionMessages = [...section.messages];
696
+ // Count conversation pairs in this section
697
+ let sectionPairs = 0;
698
+ for (let j = 0; j < sectionMessages.length; j++) {
699
+ const currentMsg = sectionMessages[j];
700
+ if (currentMsg.sender === 'user' || currentMsg.isUserMessage) {
701
+ // Check if there's an AI response following this user message
702
+ if (j + 1 < sectionMessages.length) {
703
+ const nextMsg = sectionMessages[j + 1];
704
+ if (nextMsg.sender === 'ai' || !nextMsg.isUserMessage) {
705
+ sectionPairs++;
706
+ j++; // Skip the AI response since we counted it as a pair
707
+ }
708
+ } else {
709
+ sectionPairs++; // User message without AI response still counts
710
+ }
711
+ } else if (currentMsg.sender === 'ai' || !currentMsg.isUserMessage) {
712
+ // AI message without preceding user message counts as half a pair
713
+ sectionPairs += 0.5;
714
+ }
715
+ }
716
+ // If this section would exceed our limit, only take what we can fit
717
+ if (conversationPairs + sectionPairs > displayedMessageCount) {
718
+ const remainingPairs = displayedMessageCount - conversationPairs;
719
+ if (remainingPairs > 0) {
720
+ // Take only the last N conversation pairs from this section
721
+ const limitedMessages = sectionMessages.slice(-Math.floor(remainingPairs * 2));
722
+ limitedSections.unshift({
723
+ ...section,
724
+ messages: limitedMessages
725
+ });
726
+ conversationPairs += remainingPairs;
727
+ }
728
+ break;
729
+ } else {
730
+ // We can fit this entire section
731
+ limitedSections.unshift(section);
732
+ conversationPairs += sectionPairs;
733
+ }
734
+ }
735
+ return limitedSections;
736
+ }, [messagesByDate, displayedMessageCount]);
737
+ // Ensure we show complete conversation pairs (user message + AI response)
738
+ const completeConversationMessages = useMemo(() => {
739
+ if (!limitedMessagesByDate || limitedMessagesByDate.length === 0) return [];
740
+ const completeSections = [];
741
+ limitedMessagesByDate.forEach(section => {
742
+ const completeMessages = [];
743
+ const sectionMessages = [...section.messages];
744
+ console.log('🔄 Processing section for complete conversations:', {
745
+ sectionDate: section.date,
746
+ totalMessages: sectionMessages.length,
747
+ messages: sectionMessages.map(m => ({
748
+ sender: m.sender,
749
+ isUserMessage: m.isUserMessage,
750
+ message: m.message?.substring(0, 30) + '...'
751
+ }))
752
+ });
753
+ // Group messages into conversation pairs
754
+ for (let i = 0; i < sectionMessages.length; i++) {
755
+ const currentMsg = sectionMessages[i];
756
+ // If this is a user message, look for its AI response
757
+ if (currentMsg.sender === 'user' || currentMsg.isUserMessage) {
758
+ completeMessages.push(currentMsg);
759
+ // Look for the corresponding AI response (next message should be AI)
760
+ if (i + 1 < sectionMessages.length) {
761
+ const nextMsg = sectionMessages[i + 1];
762
+ if (nextMsg.sender === 'ai' || !nextMsg.isUserMessage) {
763
+ completeMessages.push(nextMsg);
764
+ i++; // Skip the next message since we've already added it
765
+ }
766
+ }
767
+ } else if (currentMsg.sender === 'ai' || !currentMsg.isUserMessage) {
768
+ // If this is an AI message without a preceding user message, still show it
769
+ completeMessages.push(currentMsg);
770
+ }
771
+ }
772
+ console.log('🔄 Complete messages for section:', {
773
+ sectionDate: section.date,
774
+ completeMessages: completeMessages.map(m => ({
775
+ sender: m.sender,
776
+ isUserMessage: m.isUserMessage,
777
+ message: m.message?.substring(0, 30) + '...'
778
+ }))
779
+ });
780
+ if (completeMessages.length > 0) {
781
+ completeSections.push({
782
+ ...section,
783
+ messages: completeMessages
784
+ });
785
+ }
786
+ });
787
+ return completeSections;
788
+ }, [limitedMessagesByDate]);
789
+ // Auto scroll to bottom when messages, typing status, or AI responses change
790
+ useEffect(() => {
791
+ scrollToBottom('smooth', 100);
792
+ }, [completeConversationMessages?.length, isTyping, aiMessages.length, scrollToBottom]);
793
+ // Auto scroll when processing message changes (shows loading indicators)
794
+ useEffect(() => {
795
+ if (currentProcessingMessage !== null) {
796
+ scrollToBottom('smooth', 150);
797
+ }
798
+ }, [currentProcessingMessage, scrollToBottom]);
799
+ return React__default.createElement("div", {
800
+ className: `flex flex-col h-full ${className}`
801
+ }, React__default.createElement("div", {
802
+ className: "border-b border-gray-200 bg-white"
803
+ }, React__default.createElement("div", {
804
+ className: "flex items-center justify-between px-4 py-3"
805
+ }, React__default.createElement("div", {
806
+ className: "flex space-x-6"
807
+ }, React__default.createElement("button", {
808
+ onClick: () => setActiveTab('chat'),
809
+ className: `relative ${activeTab === 'chat' ? 'text-blue-600 font-medium' : 'text-gray-500 hover:text-gray-700'} text-sm transition-colors`
810
+ }, React__default.createElement("span", null, "Chat"), activeTab === 'chat' && React__default.createElement("div", {
811
+ className: "absolute bottom-0 left-0 w-full h-0.5 bg-blue-600"
812
+ })), React__default.createElement("button", {
813
+ onClick: () => setActiveTab('history'),
814
+ className: `relative ${activeTab === 'history' ? 'text-blue-600 font-medium' : 'text-gray-500 hover:text-gray-700'} text-sm transition-colors`
815
+ }, React__default.createElement("span", null, "History"), activeTab === 'history' && React__default.createElement("div", {
816
+ className: "absolute bottom-0 left-0 w-full h-0.5 bg-blue-600"
817
+ }))), React__default.createElement("button", {
818
+ onClick: () => {
819
+ // Reset to show only the last message for new chat
820
+ setDisplayedMessageCount(1);
821
+ setHasMoreMessages(false);
822
+ // Clear processing state
823
+ setProcessedMessageIds(new Set());
824
+ setCurrentProcessingMessage(null);
825
+ // Clear AI messages by sending update event to the machine
826
+ send({
827
+ type: 'UPDATE',
828
+ value: {
829
+ messages: []
830
+ }
831
+ });
832
+ },
833
+ className: "px-4 py-2 text-sm text-gray-700 border border-gray-300 rounded-lg hover:bg-gray-200 transition-colors",
834
+ style: {
835
+ borderRadius: '10px'
836
+ }
837
+ }, "New Chat"))), activeTab === 'history' ? (/* History Tab Content */
838
+ React__default.createElement("div", {
839
+ className: "flex-1 overflow-y-auto bg-white"
840
+ }, React__default.createElement("div", {
841
+ className: "px-4 py-3 border-b border-gray-200"
842
+ }, React__default.createElement("div", {
843
+ className: "relative"
844
+ }, React__default.createElement("div", {
845
+ className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"
846
+ }, React__default.createElement("svg", {
847
+ className: "h-5 w-5 text-gray-400",
848
+ fill: "none",
849
+ viewBox: "0 0 24 24",
850
+ stroke: "currentColor"
851
+ }, React__default.createElement("path", {
852
+ strokeLinecap: "round",
853
+ strokeLinejoin: "round",
854
+ strokeWidth: 2,
855
+ d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
856
+ }))), React__default.createElement("input", {
857
+ type: "text",
858
+ placeholder: "Search messages...",
859
+ className: "block w-full pl-10 pr-12 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
860
+ }), React__default.createElement("div", {
861
+ className: "absolute inset-y-0 right-0 pr-3 flex items-center"
862
+ }, React__default.createElement("button", {
863
+ className: "text-gray-400 hover:text-gray-600"
864
+ }, React__default.createElement("svg", {
865
+ className: "h-5 w-5",
866
+ fill: "none",
867
+ viewBox: "0 0 24 24",
868
+ stroke: "currentColor"
869
+ }, React__default.createElement("path", {
870
+ strokeLinecap: "round",
871
+ strokeLinejoin: "round",
872
+ strokeWidth: 2,
873
+ d: "M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z"
874
+ })))))), React__default.createElement("div", {
875
+ className: "px-4 py-2"
876
+ }, regularMessages && regularMessages.length > 0 ? regularMessages.map((msg, index) => {
877
+ new Date(msg.createdAt);
878
+ return React__default.createElement("div", {
879
+ key: msg.id || index,
880
+ className: "mb-4"
881
+ }, React__default.createElement("div", {
882
+ className: "flex items-center justify-end mb-2"
883
+ }, React__default.createElement("button", {
884
+ className: "text-blue-600 text-sm underline hover:text-blue-800 flex items-center"
885
+ }, React__default.createElement("svg", {
886
+ className: "w-4 h-4 mr-1",
887
+ fill: "none",
888
+ viewBox: "0 0 24 24",
889
+ stroke: "currentColor"
890
+ }, React__default.createElement("path", {
891
+ strokeLinecap: "round",
892
+ strokeLinejoin: "round",
893
+ strokeWidth: 2,
894
+ d: "M15 19l-7-7 7-7"
895
+ })), "Restore to this point")), React__default.createElement(ModernMessageGroupComponent, {
896
+ messages: [{
897
+ id: msg.id,
898
+ message: msg.message || msg.content || 'No message content',
899
+ author: msg.author || {
900
+ id: 'user',
901
+ givenName: 'User',
902
+ familyName: '',
903
+ fullName: 'User',
904
+ username: 'user',
905
+ email: '',
906
+ picture: null,
907
+ alias: [],
908
+ tokens: []
909
+ },
910
+ createdAt: msg.createdAt,
911
+ type: 'Simple',
912
+ isDelivered: false,
913
+ isRead: false,
914
+ parentId: null,
915
+ fromServer: null,
916
+ updatedAt: msg.createdAt,
917
+ propsConfiguration: null,
918
+ props: null,
919
+ files: null,
920
+ replies: null,
921
+ channel: null,
922
+ isPinned: false
923
+ }],
924
+ currentUser: currentUser,
925
+ onOpen: onOpen,
926
+ onMessageClick: () => {},
927
+ isDesktopView: isDesktopView,
928
+ isSmallScreen: isSmallScreen
929
+ }));
930
+ }) :
931
+ // Fallback entries when no messages
932
+ React__default.createElement(React__default.Fragment, null, React__default.createElement("div", {
933
+ className: "mb-4"
934
+ }, React__default.createElement("div", {
935
+ className: "flex items-center justify-end mb-2"
936
+ }, React__default.createElement("button", {
937
+ className: "text-blue-600 text-sm underline hover:text-blue-800 flex items-center"
938
+ }, React__default.createElement("svg", {
939
+ className: "w-4 h-4 mr-1",
940
+ fill: "none",
941
+ viewBox: "0 0 24 24",
942
+ stroke: "currentColor"
943
+ }, React__default.createElement("path", {
944
+ strokeLinecap: "round",
945
+ strokeLinejoin: "round",
946
+ strokeWidth: 2,
947
+ d: "M15 19l-7-7 7-7"
948
+ })), "Restore to this point")), React__default.createElement("div", {
949
+ className: "bg-gray-100 rounded-lg p-3"
950
+ }, React__default.createElement("p", {
951
+ className: "text-sm text-gray-900"
952
+ }, "Sample message for demonstration"))))))) : (/* Chat Tab Content */
953
+ React__default.createElement("div", {
954
+ className: "flex-1 overflow-y-auto bg-white"
955
+ }, React__default.createElement("div", {
956
+ className: `w-full pb-4 pt-2 ${isDesktopView ? 'space-y-3 max-w-full mx-auto' : isSmallScreen ? 'space-y-2' : 'space-y-2'}`
957
+ }, hasMoreMessages && React__default.createElement("div", {
958
+ className: "px-4 py-3 text-center"
959
+ }, React__default.createElement("button", {
960
+ onClick: loadMoreMessages,
961
+ className: "px-4 py-2 text-sm text-gray-600 bg-gray-100 border border-gray-300 rounded-lg hover:bg-gray-200 transition-colors"
962
+ }, "Load Past Messages")), (!completeConversationMessages || completeConversationMessages.length === 0) && React__default.createElement("div", {
963
+ className: "px-4 py-8 text-center"
964
+ }, React__default.createElement("div", {
965
+ className: "text-gray-500 text-lg font-medium mb-2"
966
+ }, "Describe your idea and I'll help you create it step by step"), React__default.createElement("div", {
967
+ className: "text-gray-400 text-sm"
968
+ }, "Start a new conversation by typing your message below")), completeConversationMessages?.map((section, sectionIndex) => React__default.createElement("div", {
969
+ key: `section-${sectionIndex}`,
970
+ className: "w-full px-4"
971
+ }, section.date && React__default.createElement("div", {
972
+ className: "flex items-center justify-center my-3"
973
+ }, React__default.createElement("div", {
974
+ className: "flex-grow border-t border-gray-200"
975
+ }), React__default.createElement("div", {
976
+ className: "mx-4 px-3 py-1 bg-white border border-gray-200 rounded-full text-xs font-medium text-gray-600"
977
+ }, section.date), React__default.createElement("div", {
978
+ className: "flex-grow border-t border-gray-200"
979
+ })), React__default.createElement("div", {
980
+ className: `${isDesktopView ? 'mb-2' : 'mb-1'}`
981
+ }, section.messages.map((msg, msgIndex) => React__default.createElement("div", {
982
+ key: msg.id || msgIndex,
983
+ className: "mb-3"
984
+ }, msg.isAIMessage && React__default.createElement("div", {
985
+ className: "flex items-center mb-2"
986
+ }, React__default.createElement("div", {
987
+ className: "w-2 h-2 bg-blue-500 rounded-full mr-2"
988
+ }), React__default.createElement("span", {
989
+ className: "text-xs text-blue-600 font-medium"
990
+ }, "AI Assistant")), msg.isLoading ?
991
+ // Show loader for loading messages
992
+ React__default.createElement("div", {
993
+ className: "flex items-center space-x-2 bg-gray-50 border border-gray-200 px-4 py-3 rounded-lg"
994
+ }, React__default.createElement("div", {
995
+ className: "w-4 h-4 border-2 border-gray-300 border-t-gray-500 rounded-full animate-spin"
996
+ }), React__default.createElement("span", {
997
+ className: "text-sm text-gray-600"
998
+ }, msg.isProcessing ? 'AI is thinking...' : 'Thinking...')) :
999
+ // Show normal message for non-loading messages
1000
+ React__default.createElement(ModernMessageGroupComponent, {
1001
+ messages: [{
1002
+ id: msg.id,
1003
+ message: msg.message,
1004
+ author: msg.sender === 'user' ? msg.author : {
1005
+ id: 'ai-assistant',
1006
+ givenName: 'AI',
1007
+ familyName: 'Assistant',
1008
+ fullName: 'AI Assistant',
1009
+ username: 'ai-assistant',
1010
+ email: 'ai@assistant.com',
1011
+ picture: null,
1012
+ alias: [],
1013
+ tokens: []
1014
+ },
1015
+ createdAt: msg.createdAt,
1016
+ type: 'Simple',
1017
+ isDelivered: false,
1018
+ isRead: false,
1019
+ parentId: null,
1020
+ fromServer: null,
1021
+ updatedAt: msg.createdAt,
1022
+ propsConfiguration: null,
1023
+ props: null,
1024
+ files: null,
1025
+ replies: null,
1026
+ channel: null,
1027
+ isPinned: false
1028
+ }],
1029
+ currentUser: currentUser,
1030
+ onOpen: onOpen,
1031
+ onMessageClick: () => {},
1032
+ isDesktopView: isDesktopView,
1033
+ isSmallScreen: isSmallScreen
1034
+ })))))), isTyping && React__default.createElement("div", {
1035
+ className: "px-4"
1036
+ }, React__default.createElement("div", {
1037
+ className: "flex justify-start"
1038
+ }, React__default.createElement("div", {
1039
+ className: "bg-gray-50 border border-gray-200 px-4 py-3 rounded-lg"
1040
+ }, React__default.createElement("div", {
1041
+ className: "flex items-center space-x-2"
1042
+ }, React__default.createElement("div", {
1043
+ className: "w-4 h-4 border-2 border-gray-300 border-t-gray-500 rounded-full animate-spin"
1044
+ }), React__default.createElement("span", {
1045
+ className: "text-sm text-gray-600"
1046
+ }, "AI is thinking..."))))), React__default.createElement("div", {
1047
+ ref: bottomRef
1048
+ })), React__default.createElement(SubscriptionHandler, {
1049
+ subscribeToMore: subscribeToMore,
1050
+ document: OnChatMessageAddedDocument,
1051
+ variables: {
1052
+ channelId: actualChannelId?.toString()
1053
+ },
1054
+ enabled: !!actualChannelId && !!subscribeToMore,
1055
+ updateQuery: (prev, {
1056
+ subscriptionData
1057
+ }) => {
1058
+ console.log('Subscription updateQuery called:', {
1059
+ prev,
1060
+ subscriptionData
1061
+ });
1062
+ if (!subscriptionData.data) {
1063
+ console.log('No subscription data, returning prev');
1064
+ return prev;
1065
+ }
1066
+ const newMessage = subscriptionData.data.chatMessageAdded;
1067
+ console.log('New message received via subscription:', newMessage);
1068
+ return {
1069
+ ...prev,
1070
+ messages: {
1071
+ ...prev?.messages,
1072
+ data: uniqBy([...(prev?.messages?.data || []), newMessage], 'id'),
1073
+ totalCount: (prev?.messages?.totalCount || 0) + 1
1074
+ }
1075
+ };
1076
+ },
1077
+ onError: error => {
1078
+ console.error('Subscription error:', error);
1079
+ }
1080
+ }))), error && React__default.createElement("div", {
1081
+ className: "mx-4 mb-4 p-3 bg-red-50 border border-red-200 rounded-lg"
1082
+ }, React__default.createElement("div", {
1083
+ className: "flex items-center justify-between"
1084
+ }, React__default.createElement("div", {
1085
+ className: "text-red-800 text-sm"
1086
+ }, error), React__default.createElement("div", {
1087
+ className: "flex space-x-2"
1088
+ }, React__default.createElement("button", {
1089
+ onClick: handleRetry,
1090
+ className: "px-2 py-1 text-xs bg-red-100 text-red-700 rounded hover:bg-red-200 transition-colors"
1091
+ }, "Retry"), React__default.createElement("button", {
1092
+ onClick: handleClearError,
1093
+ className: "px-2 py-1 text-xs bg-gray-100 text-gray-700 rounded hover:bg-gray-200 transition-colors"
1094
+ }, "Dismiss")))), activeTab === 'chat' && React__default.createElement("div", {
1095
+ className: "border-t border-gray-200 bg-white"
1096
+ }, currentProcessingMessage !== null && React__default.createElement("div", {
1097
+ className: "px-4 py-2 border-b border-blue-100 bg-blue-50"
1098
+ }, React__default.createElement("div", {
1099
+ className: "flex items-center space-x-2 text-sm text-blue-700"
1100
+ }, React__default.createElement("div", {
1101
+ className: "flex space-x-1"
1102
+ }, React__default.createElement("div", {
1103
+ className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce"
1104
+ }), React__default.createElement("div", {
1105
+ className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce",
1106
+ style: {
1107
+ animationDelay: '0.1s'
1108
+ }
1109
+ }), React__default.createElement("div", {
1110
+ className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce",
1111
+ style: {
1112
+ animationDelay: '0.2s'
1113
+ }
1114
+ })), React__default.createElement("span", null, "AI is processing message ", currentProcessingMessage + 1, " of ", regularMessages.length))), React__default.createElement(InputComponent, {
1115
+ channelId: actualChannelId,
1116
+ handleSend: handleSend,
1117
+ placeholder: placeholder
1118
+ })), isOpen ? React__default.createElement("div", null, React__default.createElement("div", {
1119
+ className: "fixed inset-0 bg-black bg-opacity-50 z-40",
1120
+ onClick: onClose
1121
+ }), React__default.createElement("div", {
1122
+ className: "fixed z-50 left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2"
1123
+ }, React__default.createElement("div", {
1124
+ className: "bg-white w-[1036px] h-[700px] rounded-lg shadow-xl",
1125
+ style: {
1126
+ boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)'
1127
+ }
1128
+ }, React__default.createElement("div", {
1129
+ className: "flex justify-between border-b border-gray-300 pb-4 pt-4"
1130
+ }, React__default.createElement("button", {
1131
+ onClick: onClose,
1132
+ className: "w-8 ml-3 text-black hover:text-black focus:outline-none"
1133
+ }, React__default.createElement("svg", {
1134
+ className: "w-6 h-6",
1135
+ fill: "none",
1136
+ stroke: "currentColor",
1137
+ viewBox: "0 0 24 24"
1138
+ }, React__default.createElement("path", {
1139
+ strokeLinecap: "round",
1140
+ strokeLinejoin: "round",
1141
+ strokeWidth: 2,
1142
+ d: "M6 18L18 6M6 6l12 12"
1143
+ })))), React__default.createElement("div", {
1144
+ className: "p-4"
1145
+ }, React__default.createElement("div", {
1146
+ className: "text-sm text-gray-700"
1147
+ }, selectedElement?.author?.username))))) : null);
1148
+ };export{AIAgent};//# sourceMappingURL=AIAgent.js.map