@messenger-box/tailwind-ui-inbox 10.0.3-alpha.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +104 -0
- package/LICENSE +21 -0
- package/jest.config.js +9 -0
- package/lib/cdm-locales/en/translations.json +31 -0
- package/lib/cdm-locales/es/translations.json +31 -0
- package/lib/components/AIAgent/AIAgent.d.ts +21 -0
- package/lib/components/AIAgent/AIAgent.d.ts.map +1 -0
- package/lib/components/AIAgent/AIAgent.js +904 -0
- package/lib/components/AIAgent/AIAgent.js.map +1 -0
- package/lib/components/AIAgent/index.d.ts +2 -0
- package/lib/components/AIAgent/index.d.ts.map +1 -0
- package/lib/components/InboxMessage/CommonMessage.d.ts +8 -0
- package/lib/components/InboxMessage/CommonMessage.d.ts.map +1 -0
- package/lib/components/InboxMessage/CommonMessage.js +35 -0
- package/lib/components/InboxMessage/CommonMessage.js.map +1 -0
- package/lib/components/InboxMessage/ConversationItem.d.ts +14 -0
- package/lib/components/InboxMessage/ConversationItem.d.ts.map +1 -0
- package/lib/components/InboxMessage/ConversationItem.js +200 -0
- package/lib/components/InboxMessage/ConversationItem.js.map +1 -0
- package/lib/components/InboxMessage/InputComponent.d.ts +12 -0
- package/lib/components/InboxMessage/InputComponent.d.ts.map +1 -0
- package/lib/components/InboxMessage/InputComponent.js +359 -0
- package/lib/components/InboxMessage/InputComponent.js.map +1 -0
- package/lib/components/InboxMessage/LeftSidebar.d.ts +20 -0
- package/lib/components/InboxMessage/LeftSidebar.d.ts.map +1 -0
- package/lib/components/InboxMessage/LeftSidebar.js +102 -0
- package/lib/components/InboxMessage/LeftSidebar.js.map +1 -0
- package/lib/components/InboxMessage/MessageInput.d.ts +9 -0
- package/lib/components/InboxMessage/MessageInput.d.ts.map +1 -0
- package/lib/components/InboxMessage/MessageInput.js +154 -0
- package/lib/components/InboxMessage/MessageInput.js.map +1 -0
- package/lib/components/InboxMessage/MessageInputComponent.d.ts +9 -0
- package/lib/components/InboxMessage/MessageInputComponent.d.ts.map +1 -0
- package/lib/components/InboxMessage/Messages.d.ts +17 -0
- package/lib/components/InboxMessage/Messages.d.ts.map +1 -0
- package/lib/components/InboxMessage/Messages.js +99 -0
- package/lib/components/InboxMessage/Messages.js.map +1 -0
- package/lib/components/InboxMessage/MessagesBuilderUi.d.ts +17 -0
- package/lib/components/InboxMessage/MessagesBuilderUi.d.ts.map +1 -0
- package/lib/components/InboxMessage/Popover.d.ts +3 -0
- package/lib/components/InboxMessage/Popover.d.ts.map +1 -0
- package/lib/components/InboxMessage/Popover.js +31 -0
- package/lib/components/InboxMessage/Popover.js.map +1 -0
- package/lib/components/InboxMessage/RightSidebar.d.ts +9 -0
- package/lib/components/InboxMessage/RightSidebar.d.ts.map +1 -0
- package/lib/components/InboxMessage/RightSidebar.js +9 -0
- package/lib/components/InboxMessage/RightSidebar.js.map +1 -0
- package/lib/components/InboxMessage/RightSidebarAi.d.ts +23 -0
- package/lib/components/InboxMessage/RightSidebarAi.d.ts.map +1 -0
- package/lib/components/InboxMessage/RightSidebarAi.js +9 -0
- package/lib/components/InboxMessage/RightSidebarAi.js.map +1 -0
- package/lib/components/InboxMessage/ServiceConversationItem.d.ts +12 -0
- package/lib/components/InboxMessage/ServiceConversationItem.d.ts.map +1 -0
- package/lib/components/InboxMessage/ServiceConversationItem.js +185 -0
- package/lib/components/InboxMessage/ServiceConversationItem.js.map +1 -0
- package/lib/components/InboxMessage/ServiceInboxItem.d.ts +12 -0
- package/lib/components/InboxMessage/ServiceInboxItem.d.ts.map +1 -0
- package/lib/components/InboxMessage/ServiceInboxItem.js +182 -0
- package/lib/components/InboxMessage/ServiceInboxItem.js.map +1 -0
- package/lib/components/InboxMessage/SubscriptionHandler.d.ts +19 -0
- package/lib/components/InboxMessage/SubscriptionHandler.d.ts.map +1 -0
- package/lib/components/InboxMessage/SubscriptionHandler.js +41 -0
- package/lib/components/InboxMessage/SubscriptionHandler.js.map +1 -0
- package/lib/components/InboxMessage/UploadImageButton.d.ts +7 -0
- package/lib/components/InboxMessage/UploadImageButton.d.ts.map +1 -0
- package/lib/components/InboxMessage/UploadImageButton.js +34 -0
- package/lib/components/InboxMessage/UploadImageButton.js.map +1 -0
- package/lib/components/InboxMessage/UserModalContent.d.ts +3 -0
- package/lib/components/InboxMessage/UserModalContent.d.ts.map +1 -0
- package/lib/components/InboxMessage/UserModalContent.js +60 -0
- package/lib/components/InboxMessage/UserModalContent.js.map +1 -0
- package/lib/components/InboxMessage/index.d.ts +17 -0
- package/lib/components/InboxMessage/index.d.ts.map +1 -0
- package/lib/components/InboxMessage/message-widgets/CommonMessage.d.ts +11 -0
- package/lib/components/InboxMessage/message-widgets/CommonMessage.d.ts.map +1 -0
- package/lib/components/InboxMessage/message-widgets/CommonMessage.js +44 -0
- package/lib/components/InboxMessage/message-widgets/CommonMessage.js.map +1 -0
- package/lib/components/InboxMessage/message-widgets/ErrorFixCard.d.ts +11 -0
- package/lib/components/InboxMessage/message-widgets/ErrorFixCard.d.ts.map +1 -0
- package/lib/components/InboxMessage/message-widgets/ErrorFixCard.js +194 -0
- package/lib/components/InboxMessage/message-widgets/ErrorFixCard.js.map +1 -0
- package/lib/components/InboxMessage/message-widgets/MessageCard.d.ts +8 -0
- package/lib/components/InboxMessage/message-widgets/MessageCard.d.ts.map +1 -0
- package/lib/components/InboxMessage/message-widgets/MessageSliceRenderer.d.ts +12 -0
- package/lib/components/InboxMessage/message-widgets/MessageSliceRenderer.d.ts.map +1 -0
- package/lib/components/InboxMessage/message-widgets/MessageSliceRenderer.js +37 -0
- package/lib/components/InboxMessage/message-widgets/MessageSliceRenderer.js.map +1 -0
- package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts +18 -0
- package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts.map +1 -0
- package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js +1082 -0
- package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js.map +1 -0
- package/lib/components/InboxMessage/message-widgets/PlainMessage.d.ts +8 -0
- package/lib/components/InboxMessage/message-widgets/PlainMessage.d.ts.map +1 -0
- package/lib/components/InboxMessage/message-widgets/PlainMessage.js +14 -0
- package/lib/components/InboxMessage/message-widgets/PlainMessage.js.map +1 -0
- package/lib/components/InboxMessage/message-widgets/PropertyMessageWidget.d.ts +9 -0
- package/lib/components/InboxMessage/message-widgets/PropertyMessageWidget.d.ts.map +1 -0
- package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.d.ts +14 -0
- package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.d.ts.map +1 -0
- package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js +333 -0
- package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js.map +1 -0
- package/lib/components/InboxMessage/message-widgets/index.d.ts +4 -0
- package/lib/components/InboxMessage/message-widgets/index.d.ts.map +1 -0
- package/lib/components/ModelConfigPanel.d.ts +37 -0
- package/lib/components/ModelConfigPanel.d.ts.map +1 -0
- package/lib/components/ModelConfigPanel.js +317 -0
- package/lib/components/ModelConfigPanel.js.map +1 -0
- package/lib/components/filler-components/RightSiderBar.d.ts +24 -0
- package/lib/components/filler-components/RightSiderBar.d.ts.map +1 -0
- package/lib/components/filler-components/RightSiderBar.js +335 -0
- package/lib/components/filler-components/RightSiderBar.js.map +1 -0
- package/lib/components/inbox/FilesList.d.ts +20 -0
- package/lib/components/inbox/FilesList.d.ts.map +1 -0
- package/lib/components/inbox/FilesList.js +68 -0
- package/lib/components/inbox/FilesList.js.map +1 -0
- package/lib/components/inbox/MessageItem.d.ts +17 -0
- package/lib/components/inbox/MessageItem.d.ts.map +1 -0
- package/lib/components/inbox/MessageItem.js +50 -0
- package/lib/components/inbox/MessageItem.js.map +1 -0
- package/lib/components/inbox/ThreadItem.d.ts +11 -0
- package/lib/components/inbox/ThreadItem.d.ts.map +1 -0
- package/lib/components/inbox/ThreadItem.js +147 -0
- package/lib/components/inbox/ThreadItem.js.map +1 -0
- package/lib/components/inbox/index.d.ts +4 -0
- package/lib/components/inbox/index.d.ts.map +1 -0
- package/lib/components/index.d.ts +7 -0
- package/lib/components/index.d.ts.map +1 -0
- package/lib/components/live-code-editor/hybrid-live-editor.d.ts +20 -0
- package/lib/components/live-code-editor/hybrid-live-editor.d.ts.map +1 -0
- package/lib/components/live-code-editor/hybrid-live-editor.js +68 -0
- package/lib/components/live-code-editor/hybrid-live-editor.js.map +1 -0
- package/lib/components/live-code-editor/index.d.ts +4 -0
- package/lib/components/live-code-editor/index.d.ts.map +1 -0
- package/lib/components/live-code-editor/live-code-editor.d.ts +14 -0
- package/lib/components/live-code-editor/live-code-editor.d.ts.map +1 -0
- package/lib/components/live-code-editor/live-code-editor.js +207 -0
- package/lib/components/live-code-editor/live-code-editor.js.map +1 -0
- package/lib/components/slot-fill/chat-message-filler.d.ts +4 -0
- package/lib/components/slot-fill/chat-message-filler.d.ts.map +1 -0
- package/lib/components/slot-fill/chat-message-filler.js +5 -0
- package/lib/components/slot-fill/chat-message-filler.js.map +1 -0
- package/lib/components/slot-fill/chat-message-slot.d.ts +11 -0
- package/lib/components/slot-fill/chat-message-slot.d.ts.map +1 -0
- package/lib/components/slot-fill/chat-message-slot.js +6 -0
- package/lib/components/slot-fill/chat-message-slot.js.map +1 -0
- package/lib/components/slot-fill/index.d.ts +4 -0
- package/lib/components/slot-fill/index.d.ts.map +1 -0
- package/lib/components/slot-fill/right-sidebar-filler.d.ts +4 -0
- package/lib/components/slot-fill/right-sidebar-filler.d.ts.map +1 -0
- package/lib/components/slot-fill/right-sidebar-filler.js +13 -0
- package/lib/components/slot-fill/right-sidebar-filler.js.map +1 -0
- package/lib/components/ui/button.d.ts +9 -0
- package/lib/components/ui/button.d.ts.map +1 -0
- package/lib/compute.d.ts +8 -0
- package/lib/compute.d.ts.map +1 -0
- package/lib/compute.js +137 -0
- package/lib/compute.js.map +1 -0
- package/lib/config/env-config.d.ts +13 -0
- package/lib/config/env-config.d.ts.map +1 -0
- package/lib/config/env-config.js +34 -0
- package/lib/config/env-config.js.map +1 -0
- package/lib/config/index.d.ts +2 -0
- package/lib/config/index.d.ts.map +1 -0
- package/lib/constants/breakpoints.d.ts +8 -0
- package/lib/constants/breakpoints.d.ts.map +1 -0
- package/lib/constants/index.d.ts +3 -0
- package/lib/constants/index.d.ts.map +1 -0
- package/lib/container/AiInbox.d.ts +15 -0
- package/lib/container/AiInbox.d.ts.map +1 -0
- package/lib/container/AiInboxWithLoader.d.ts +36 -0
- package/lib/container/AiInboxWithLoader.d.ts.map +1 -0
- package/lib/container/AiLandingInput.d.ts +4 -0
- package/lib/container/AiLandingInput.d.ts.map +1 -0
- package/lib/container/AiLandingInput.js +101 -0
- package/lib/container/AiLandingInput.js.map +1 -0
- package/lib/container/Inbox.d.ts +15 -0
- package/lib/container/Inbox.d.ts.map +1 -0
- package/lib/container/Inbox.js +955 -0
- package/lib/container/Inbox.js.map +1 -0
- package/lib/container/InboxAiMessagesLoader.d.ts +15 -0
- package/lib/container/InboxAiMessagesLoader.d.ts.map +1 -0
- package/lib/container/InboxAiMessagesLoader.js +30 -0
- package/lib/container/InboxAiMessagesLoader.js.map +1 -0
- package/lib/container/InboxContainer.d.ts +12 -0
- package/lib/container/InboxContainer.d.ts.map +1 -0
- package/lib/container/InboxContainer.js +31 -0
- package/lib/container/InboxContainer.js.map +1 -0
- package/lib/container/InboxTemplate1.d.ts +15 -0
- package/lib/container/InboxTemplate1.d.ts.map +1 -0
- package/lib/container/InboxTemplate1WithLoader.d.ts +36 -0
- package/lib/container/InboxTemplate1WithLoader.d.ts.map +1 -0
- package/lib/container/InboxTemplate2.d.ts +15 -0
- package/lib/container/InboxTemplate2.d.ts.map +1 -0
- package/lib/container/InboxWithAiLoader.d.ts +15 -0
- package/lib/container/InboxWithAiLoader.d.ts.map +1 -0
- package/lib/container/InboxWithAiLoader.js +56 -0
- package/lib/container/InboxWithAiLoader.js.map +1 -0
- package/lib/container/InboxWithLoader.d.ts +36 -0
- package/lib/container/InboxWithLoader.d.ts.map +1 -0
- package/lib/container/InboxWithLoader.js +277 -0
- package/lib/container/InboxWithLoader.js.map +1 -0
- package/lib/container/ServiceInbox.d.ts +9 -0
- package/lib/container/ServiceInbox.d.ts.map +1 -0
- package/lib/container/ServiceInbox.js +144 -0
- package/lib/container/ServiceInbox.js.map +1 -0
- package/lib/container/ThreadMessages.d.ts +13 -0
- package/lib/container/ThreadMessages.d.ts.map +1 -0
- package/lib/container/ThreadMessages.js +314 -0
- package/lib/container/ThreadMessages.js.map +1 -0
- package/lib/container/ThreadMessagesInbox.d.ts +14 -0
- package/lib/container/ThreadMessagesInbox.d.ts.map +1 -0
- package/lib/container/ThreadMessagesInbox.js +341 -0
- package/lib/container/ThreadMessagesInbox.js.map +1 -0
- package/lib/container/Threads.d.ts +8 -0
- package/lib/container/Threads.d.ts.map +1 -0
- package/lib/container/Threads.js +231 -0
- package/lib/container/Threads.js.map +1 -0
- package/lib/container/ThreadsInbox.d.ts +21 -0
- package/lib/container/ThreadsInbox.d.ts.map +1 -0
- package/lib/container/ThreadsInbox.js +244 -0
- package/lib/container/ThreadsInbox.js.map +1 -0
- package/lib/container/apply-footer-styles.d.ts +2 -0
- package/lib/container/apply-footer-styles.d.ts.map +1 -0
- package/lib/container/apply-footer-styles.js +16 -0
- package/lib/container/apply-footer-styles.js.map +1 -0
- package/lib/container/index.d.ts +13 -0
- package/lib/container/index.d.ts.map +1 -0
- package/lib/enums/index.d.ts +2 -0
- package/lib/enums/index.d.ts.map +1 -0
- package/lib/enums/messenger-slot-fill-name-enum.d.ts +5 -0
- package/lib/enums/messenger-slot-fill-name-enum.d.ts.map +1 -0
- package/lib/enums/messenger-slot-fill-name-enum.js +5 -0
- package/lib/enums/messenger-slot-fill-name-enum.js.map +1 -0
- package/lib/hooks/index.d.ts +3 -0
- package/lib/hooks/index.d.ts.map +1 -0
- package/lib/hooks/use-file-sync.d.ts +16 -0
- package/lib/hooks/use-file-sync.d.ts.map +1 -0
- package/lib/hooks/use-file-sync.js +63 -0
- package/lib/hooks/use-file-sync.js.map +1 -0
- package/lib/hooks/usePersistentModelConfig.d.ts +15 -0
- package/lib/hooks/usePersistentModelConfig.d.ts.map +1 -0
- package/lib/hooks/usePersistentModelConfig.js +46 -0
- package/lib/hooks/usePersistentModelConfig.js.map +1 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -0
- package/lib/interfaces/index.d.ts +2 -0
- package/lib/interfaces/index.d.ts.map +1 -0
- package/lib/interfaces/message-widgets.interface.d.ts +21 -0
- package/lib/interfaces/message-widgets.interface.d.ts.map +1 -0
- package/lib/machines/aiAgentMachine.d.ts +3 -0
- package/lib/machines/aiAgentMachine.d.ts.map +1 -0
- package/lib/machines/aiAgentMachine.js +1083 -0
- package/lib/machines/aiAgentMachine.js.map +1 -0
- package/lib/machines/aiAgentMachine.simple.d.ts +3 -0
- package/lib/machines/aiAgentMachine.simple.d.ts.map +1 -0
- package/lib/machines/aiAgentMachine.simple.js +108 -0
- package/lib/machines/aiAgentMachine.simple.js.map +1 -0
- package/lib/machines/index.d.ts +3 -0
- package/lib/machines/index.d.ts.map +1 -0
- package/lib/machines/types.d.ts +77 -0
- package/lib/machines/types.d.ts.map +1 -0
- package/lib/module.d.ts +7 -0
- package/lib/module.d.ts.map +1 -0
- package/lib/module.js +26 -0
- package/lib/module.js.map +1 -0
- package/lib/routes.json +98 -0
- package/lib/styles/responsive.css +76 -0
- package/lib/templates/InboxWithAi.d.ts +15 -0
- package/lib/templates/InboxWithAi.d.ts.map +1 -0
- package/lib/templates/InboxWithAi.js +440 -0
- package/lib/templates/InboxWithAi.js.map +1 -0
- package/lib/templates/InboxWithAi.tsx +533 -0
- package/lib/templates/index.d.ts +2 -0
- package/lib/templates/index.d.ts.map +1 -0
- package/lib/templates/index.ts +1 -0
- package/lib/utils/utils.d.ts +2 -0
- package/lib/utils/utils.d.ts.map +1 -0
- package/lib/utils/utils.js +3 -0
- package/lib/utils/utils.js.map +1 -0
- package/package.json +62 -0
- package/rollup.config.mjs +35 -0
- package/src/cdm-locales/en/translations.json +31 -0
- package/src/cdm-locales/es/translations.json +31 -0
- package/src/components/AIAgent/AIAgent.tsx +1103 -0
- package/src/components/AIAgent/AIAgent.tsx.bk +1365 -0
- package/src/components/AIAgent/README.md +82 -0
- package/src/components/AIAgent/index.ts +1 -0
- package/src/components/InboxMessage/CommonMessage.tsx +40 -0
- package/src/components/InboxMessage/ConversationItem.tsx +255 -0
- package/src/components/InboxMessage/InputComponent.tsx +462 -0
- package/src/components/InboxMessage/LeftSidebar.tsx +140 -0
- package/src/components/InboxMessage/MessageInput.tsx +209 -0
- package/src/components/InboxMessage/MessageInputComponent.tsx +245 -0
- package/src/components/InboxMessage/Messages.tsx +137 -0
- package/src/components/InboxMessage/MessagesBuilderUi.tsx +205 -0
- package/src/components/InboxMessage/Popover.tsx +42 -0
- package/src/components/InboxMessage/RightSidebar.tsx +22 -0
- package/src/components/InboxMessage/RightSidebarAi.tsx +37 -0
- package/src/components/InboxMessage/ServiceConversationItem.tsx +234 -0
- package/src/components/InboxMessage/ServiceInboxItem.tsx +223 -0
- package/src/components/InboxMessage/SubscriptionHandler.tsx +55 -0
- package/src/components/InboxMessage/UploadImageButton.tsx +46 -0
- package/src/components/InboxMessage/UserModalContent.tsx +60 -0
- package/src/components/InboxMessage/index.ts +16 -0
- package/src/components/InboxMessage/message-widgets/CommonMessage.tsx +69 -0
- package/src/components/InboxMessage/message-widgets/ErrorFixCard.tsx +240 -0
- package/src/components/InboxMessage/message-widgets/MessageCard.tsx +127 -0
- package/src/components/InboxMessage/message-widgets/MessageSliceRenderer.tsx +40 -0
- package/src/components/InboxMessage/message-widgets/ModernMessageGroup.tsx +1295 -0
- package/src/components/InboxMessage/message-widgets/PlainMessage.tsx +18 -0
- package/src/components/InboxMessage/message-widgets/PropertyMessageWidget.tsx +29 -0
- package/src/components/InboxMessage/message-widgets/SlackLikeMessageGroup.tsx +492 -0
- package/src/components/InboxMessage/message-widgets/index.ts +3 -0
- package/src/components/ModelConfigPanel.tsx +345 -0
- package/src/components/filler-components/RightSiderBar.tsx +408 -0
- package/src/components/inbox/FilesList.tsx +89 -0
- package/src/components/inbox/MessageItem.tsx +50 -0
- package/src/components/inbox/ThreadItem.tsx +295 -0
- package/src/components/inbox/index.ts +3 -0
- package/src/components/index.ts +22 -0
- package/src/components/live-code-editor/hybrid-live-editor.tsx +105 -0
- package/src/components/live-code-editor/index.ts +3 -0
- package/src/components/live-code-editor/live-code-editor.tsx +257 -0
- package/src/components/slot-fill/chat-message-filler.tsx +18 -0
- package/src/components/slot-fill/chat-message-slot.tsx +18 -0
- package/src/components/slot-fill/index.ts +3 -0
- package/src/components/slot-fill/right-sidebar-filler.tsx +39 -0
- package/src/components/ui/button.tsx +32 -0
- package/src/compute.ts +134 -0
- package/src/config/env-config.ts +17 -0
- package/src/config/index.ts +1 -0
- package/src/constants/breakpoints.ts +7 -0
- package/src/constants/index.ts +5 -0
- package/src/container/AiInbox.tsx +1819 -0
- package/src/container/AiInboxWithLoader.tsx +356 -0
- package/src/container/AiLandingInput.tsx +221 -0
- package/src/container/Inbox.tsx +1092 -0
- package/src/container/InboxAiMessagesLoader.tsx +44 -0
- package/src/container/InboxContainer.tsx +35 -0
- package/src/container/InboxTemplate1.tsx +1542 -0
- package/src/container/InboxTemplate1WithLoader.tsx +338 -0
- package/src/container/InboxTemplate2.tsx +1606 -0
- package/src/container/InboxWithAiLoader.tsx +76 -0
- package/src/container/InboxWithLoader.tsx +341 -0
- package/src/container/ServiceInbox.tsx +190 -0
- package/src/container/ThreadMessages.tsx +371 -0
- package/src/container/ThreadMessagesInbox.tsx +450 -0
- package/src/container/Threads.tsx +270 -0
- package/src/container/ThreadsInbox.tsx +354 -0
- package/src/container/apply-footer-styles.ts +17 -0
- package/src/container/index.ts +31 -0
- package/src/enums/index.ts +1 -0
- package/src/enums/messenger-slot-fill-name-enum.ts +4 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/use-file-sync.ts +91 -0
- package/src/hooks/usePersistentModelConfig.ts +63 -0
- package/src/index.ts +37 -0
- package/src/interfaces/index.ts +1 -0
- package/src/interfaces/message-widgets.interface.ts +21 -0
- package/src/machines/aiAgentMachine.simple.ts +89 -0
- package/src/machines/aiAgentMachine.ts +1296 -0
- package/src/machines/aiAgentMachine.ts.bk +1296 -0
- package/src/machines/index.ts +2 -0
- package/src/machines/types.ts +59 -0
- package/src/module.tsx +32 -0
- package/src/styles/responsive.css +76 -0
- package/src/templates/InboxWithAi.tsx +533 -0
- package/src/templates/index.ts +1 -0
- package/src/utils/utils.ts +3 -0
- package/tsconfig.json +14 -0
- package/webpack.config.js +92 -0
|
@@ -0,0 +1,1103 @@
|
|
|
1
|
+
import React, { useCallback, useMemo, useRef, useState, useEffect } from 'react';
|
|
2
|
+
import { useActor, useMachine } from '@xstate/react';
|
|
3
|
+
import { aiAgentMachine } from '../../machines/aiAgentMachine.simple';
|
|
4
|
+
import { InputComponent } from '../InboxMessage/InputComponent';
|
|
5
|
+
import { format, isToday, isYesterday, formatDistanceToNow } from 'date-fns';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
import { ModernMessageGroupComponent } from '../InboxMessage/message-widgets/ModernMessageGroup';
|
|
8
|
+
import { useUploadFiles } from '@messenger-box/platform-client';
|
|
9
|
+
import { IFileInfo, PostTypeEnum, ISandboxError } from 'common';
|
|
10
|
+
import { useSelector, shallowEqual } from 'react-redux';
|
|
11
|
+
import { Store, userSelector } from '@adminide-stack/user-auth0-client';
|
|
12
|
+
import { IUserState } from '@adminide-stack/core';
|
|
13
|
+
import { objectId } from '@messenger-box/core';
|
|
14
|
+
import { useApolloClient } from '@apollo/client';
|
|
15
|
+
import {
|
|
16
|
+
useSendMessagesMutation,
|
|
17
|
+
MessagesDocument,
|
|
18
|
+
useMessagesQuery,
|
|
19
|
+
OnChatMessageAddedDocument as CHAT_MESSAGE_ADDED,
|
|
20
|
+
useGenerateAiCodeMutation,
|
|
21
|
+
useOnChatMessageAddedSubscription,
|
|
22
|
+
useSandboxErrorSubscription,
|
|
23
|
+
useRecreateSandboxMutation,
|
|
24
|
+
} from 'common/graphql';
|
|
25
|
+
import { config } from '../../config';
|
|
26
|
+
import { orderBy, uniqBy } from 'lodash-es';
|
|
27
|
+
import { useParams, useNavigate } from '@remix-run/react';
|
|
28
|
+
import { RoomType } from 'common';
|
|
29
|
+
import { SubscriptionHandler } from '../InboxMessage/SubscriptionHandler';
|
|
30
|
+
import { usePersistentModelConfig } from '../../hooks/usePersistentModelConfig';
|
|
31
|
+
|
|
32
|
+
const { MESSAGES_PER_PAGE } = config;
|
|
33
|
+
|
|
34
|
+
interface AIAgentProps {
|
|
35
|
+
channelId?: string;
|
|
36
|
+
onSendMessage?: (message: string, files?: File[]) => Promise<void>;
|
|
37
|
+
placeholder?: string;
|
|
38
|
+
className?: string;
|
|
39
|
+
currentUser?: any;
|
|
40
|
+
channelName?: string;
|
|
41
|
+
isDesktopView?: boolean;
|
|
42
|
+
isSmallScreen?: boolean;
|
|
43
|
+
messages?: any[];
|
|
44
|
+
setMessages?: (messages: any[]) => void;
|
|
45
|
+
selectedPost?: any;
|
|
46
|
+
setSelectedPost?: (selectedPost: any) => void;
|
|
47
|
+
setIsLoading?: (isLoading: boolean) => void;
|
|
48
|
+
isLoading?: boolean;
|
|
49
|
+
[key: string]: any; // Allow other props to be passed through to Inbox
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const AIAgent: React.FC<AIAgentProps> = ({
|
|
53
|
+
channelId,
|
|
54
|
+
onSendMessage,
|
|
55
|
+
placeholder = 'Ask me anything...',
|
|
56
|
+
className = '',
|
|
57
|
+
currentUser,
|
|
58
|
+
isDesktopView = false,
|
|
59
|
+
isSmallScreen = false,
|
|
60
|
+
setMessages,
|
|
61
|
+
setSelectedPost,
|
|
62
|
+
messages,
|
|
63
|
+
selectedPost,
|
|
64
|
+
setIsLoading,
|
|
65
|
+
isLoading,
|
|
66
|
+
}) => {
|
|
67
|
+
const [state, send] = useMachine(aiAgentMachine);
|
|
68
|
+
const apolloClient = useApolloClient();
|
|
69
|
+
const { startUpload } = useUploadFiles();
|
|
70
|
+
const [sendMsg] = useSendMessagesMutation();
|
|
71
|
+
const auth: any = useSelector<Store.Auth, IUserState>(userSelector, shallowEqual);
|
|
72
|
+
const { id: pathChannelId } = useParams();
|
|
73
|
+
const navigate = useNavigate();
|
|
74
|
+
const { modelConfig, updateModelConfig, getValidatedConfig, hasApiKey } = usePersistentModelConfig();
|
|
75
|
+
// const [isLoading, setIsLoading] = useState(false);
|
|
76
|
+
const [errorData, setError] = useState<string | null>(null);
|
|
77
|
+
// Get channelId from props or path params
|
|
78
|
+
const actualChannelId = channelId || pathChannelId;
|
|
79
|
+
const [generateAiCode] = useGenerateAiCodeMutation();
|
|
80
|
+
const [recreateSandbox] = useRecreateSandboxMutation();
|
|
81
|
+
const { data: chatMessageAddedData } = useOnChatMessageAddedSubscription({
|
|
82
|
+
variables: { channelId: actualChannelId?.toString() || '' },
|
|
83
|
+
skip: !actualChannelId,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Subscribe to sandbox errors if projectId is provided
|
|
87
|
+
const { data: sandboxErrorData } = useSandboxErrorSubscription({
|
|
88
|
+
variables: { projectId: actualChannelId?.toString() || '' },
|
|
89
|
+
skip: !actualChannelId,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Direct message query from InboxWithAiLoader.tsx
|
|
93
|
+
const messagesQuery = useMessagesQuery({
|
|
94
|
+
variables: {
|
|
95
|
+
props: {
|
|
96
|
+
projectId: actualChannelId?.toString(),
|
|
97
|
+
},
|
|
98
|
+
parentId: null,
|
|
99
|
+
limit: MESSAGES_PER_PAGE,
|
|
100
|
+
},
|
|
101
|
+
skip: !actualChannelId,
|
|
102
|
+
fetchPolicy: 'cache-and-network',
|
|
103
|
+
errorPolicy: 'all',
|
|
104
|
+
notifyOnNetworkStatusChange: true,
|
|
105
|
+
returnPartialData: true,
|
|
106
|
+
pollInterval: 0,
|
|
107
|
+
context: {
|
|
108
|
+
cacheKey: 'messages-list',
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const { messages: aiMessages, error, isTyping } = state.context;
|
|
113
|
+
const { t } = useTranslation('translations');
|
|
114
|
+
|
|
115
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
116
|
+
const [selectedElement, setSelectedElement] = useState<any>(null);
|
|
117
|
+
const [activeTab, setActiveTab] = useState<'chat' | 'history'>('chat');
|
|
118
|
+
const bottomRef = useRef<HTMLDivElement | null>(null);
|
|
119
|
+
const [sandboxErrors, setSandboxErrors] = useState<ISandboxError[]>([]);
|
|
120
|
+
const [currentFiles, setCurrentFiles] = useState<Record<string, string>>({});
|
|
121
|
+
const [canvasLayers, setCanvasLayers] = useState<any[]>([]);
|
|
122
|
+
// New state variables for message display control
|
|
123
|
+
const [isSuccessThinking, setIsSuccessThinking] = useState(false);
|
|
124
|
+
const successThinkingTimeoutRef = useRef<any>(null);
|
|
125
|
+
|
|
126
|
+
// Get regular messages from direct query
|
|
127
|
+
const {
|
|
128
|
+
data: messagesData,
|
|
129
|
+
loading: messageLoading,
|
|
130
|
+
refetch: refetchMessages,
|
|
131
|
+
fetchMore: fetchMoreMessages,
|
|
132
|
+
subscribeToMore,
|
|
133
|
+
} = messagesQuery;
|
|
134
|
+
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
if (actualChannelId) {
|
|
137
|
+
refetchMessages({
|
|
138
|
+
limit: MESSAGES_PER_PAGE,
|
|
139
|
+
props: {
|
|
140
|
+
projectId: actualChannelId?.toString(),
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}, [actualChannelId, refetchMessages]);
|
|
145
|
+
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
if (chatMessageAddedData?.chatMessageAdded) {
|
|
148
|
+
console.log(
|
|
149
|
+
'chatMessageAddedData?.chatMessageAdded',
|
|
150
|
+
JSON.stringify(chatMessageAddedData?.chatMessageAdded, null, 2),
|
|
151
|
+
);
|
|
152
|
+
// handleGenerateAiCode(chatMessageAddedData.chatMessageAdded.id);
|
|
153
|
+
// Stop the success thinking loader once a new message arrives
|
|
154
|
+
if (isSuccessThinking) {
|
|
155
|
+
setIsSuccessThinking(false);
|
|
156
|
+
if (successThinkingTimeoutRef.current) {
|
|
157
|
+
clearTimeout(successThinkingTimeoutRef.current);
|
|
158
|
+
successThinkingTimeoutRef.current = null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}, [chatMessageAddedData?.chatMessageAdded]);
|
|
163
|
+
|
|
164
|
+
useEffect(() => {
|
|
165
|
+
if (messagesData?.messages?.data?.length == 1) {
|
|
166
|
+
handleGenerateAiCode(messagesData.messages.data[0].id);
|
|
167
|
+
}
|
|
168
|
+
// console.log('messagesData?.messages?.data',JSON.stringify(messagesData?.messages?.data,null,2))
|
|
169
|
+
}, [messagesData?.messages?.data]);
|
|
170
|
+
|
|
171
|
+
// Handle sandbox error subscription updates
|
|
172
|
+
useEffect(() => {
|
|
173
|
+
if (sandboxErrorData?.sandboxError) {
|
|
174
|
+
const errorData = sandboxErrorData.sandboxError;
|
|
175
|
+
console.log('Sandbox error received:', errorData);
|
|
176
|
+
setSandboxErrors((prev) => [...prev, errorData.error]);
|
|
177
|
+
}
|
|
178
|
+
}, [sandboxErrorData]);
|
|
179
|
+
|
|
180
|
+
const regularMessages = useMemo(() => {
|
|
181
|
+
if (!messagesData?.messages?.data) return [];
|
|
182
|
+
return orderBy(uniqBy(messagesData.messages.data || [], 'id'), ['createdAt'], ['asc']);
|
|
183
|
+
}, [messagesData?.messages?.data]);
|
|
184
|
+
|
|
185
|
+
// Send regular messages to AI agent machine for context
|
|
186
|
+
useEffect(() => {
|
|
187
|
+
if (regularMessages && regularMessages.length > 0) {
|
|
188
|
+
send({ type: 'UPDATE_REGULAR_MESSAGES', messages: regularMessages });
|
|
189
|
+
setMessages(regularMessages);
|
|
190
|
+
const currentMessage = regularMessages?.[regularMessages.length - 1];
|
|
191
|
+
setSelectedPost(regularMessages[regularMessages.length - 1]);
|
|
192
|
+
setCurrentFiles(currentMessage?.propsConfiguration?.contents?.fragment?.files ?? {});
|
|
193
|
+
let canvasLayers = currentMessage?.propsConfiguration?.contents?.fragment?.canvasLayers ?? [];
|
|
194
|
+
const summary = currentMessage?.propsConfiguration?.contents?.fragment?.summary ?? null;
|
|
195
|
+
// If not in direct field, try to extract from summary
|
|
196
|
+
if (!canvasLayers && summary) {
|
|
197
|
+
const canvasLayersMatch = summary?.match(/<canvas_layers>([\s\S]*?)<\/canvas_layers>/);
|
|
198
|
+
if (canvasLayersMatch) {
|
|
199
|
+
try {
|
|
200
|
+
canvasLayers = JSON.parse(canvasLayersMatch[1]);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.error('Failed to parse canvas layers from summary:', error);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// Update canvas layers if available
|
|
207
|
+
if (canvasLayers && Array.isArray(canvasLayers)) {
|
|
208
|
+
setCanvasLayers(canvasLayers);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
console.log('currenmessage', currentMessage);
|
|
212
|
+
if (currentMessage?.propsConfiguration?.contents?.role === 'ASSISTANT') {
|
|
213
|
+
//setIsLoading(false);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
scrollToBottom('smooth', 0);
|
|
217
|
+
}
|
|
218
|
+
}, [regularMessages, send]);
|
|
219
|
+
|
|
220
|
+
const handleGenerateAiCode = useCallback(
|
|
221
|
+
(messageId: string) => {
|
|
222
|
+
generateAiCode({
|
|
223
|
+
variables: {
|
|
224
|
+
messageId: messageId,
|
|
225
|
+
modelConfig: modelConfig,
|
|
226
|
+
},
|
|
227
|
+
onCompleted: (res) => {
|
|
228
|
+
if (res.generateAiCode.success) {
|
|
229
|
+
console.log('generated_result', res);
|
|
230
|
+
// Show AI is thinking loader on success
|
|
231
|
+
if (successThinkingTimeoutRef.current) {
|
|
232
|
+
clearTimeout(successThinkingTimeoutRef.current);
|
|
233
|
+
successThinkingTimeoutRef.current = null;
|
|
234
|
+
}
|
|
235
|
+
setIsSuccessThinking(true);
|
|
236
|
+
// Fallback auto-hide after 15s in case no subsequent event arrives
|
|
237
|
+
successThinkingTimeoutRef.current = setTimeout(() => {
|
|
238
|
+
setIsSuccessThinking(false);
|
|
239
|
+
// setIsLoading(false);
|
|
240
|
+
successThinkingTimeoutRef.current = null;
|
|
241
|
+
}, 15000);
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
onError: (err) => {
|
|
245
|
+
console.log('err', JSON.stringify(err, null, 2));
|
|
246
|
+
// Also ensure loader is hidden on error
|
|
247
|
+
if (successThinkingTimeoutRef.current) {
|
|
248
|
+
clearTimeout(successThinkingTimeoutRef.current);
|
|
249
|
+
successThinkingTimeoutRef.current = null;
|
|
250
|
+
}
|
|
251
|
+
setIsSuccessThinking(false);
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
},
|
|
255
|
+
[generateAiCode, modelConfig],
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
const onOpen = (element?: any) => {
|
|
259
|
+
setSelectedElement(element);
|
|
260
|
+
setIsOpen(true);
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const onClose = () => {
|
|
264
|
+
setIsOpen(false);
|
|
265
|
+
setSelectedElement(null);
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
// Enhanced scroll to bottom function
|
|
269
|
+
const scrollToBottom = useCallback((behavior: ScrollBehavior = 'smooth', delay: number = 0) => {
|
|
270
|
+
setTimeout(() => {
|
|
271
|
+
if (bottomRef.current) {
|
|
272
|
+
bottomRef.current.scrollIntoView({
|
|
273
|
+
behavior,
|
|
274
|
+
block: 'end',
|
|
275
|
+
inline: 'nearest',
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}, delay);
|
|
279
|
+
}, []);
|
|
280
|
+
|
|
281
|
+
const recreateSandboxForFragment = useCallback(
|
|
282
|
+
async (messageId: string) => {
|
|
283
|
+
if (!actualChannelId) {
|
|
284
|
+
console.error('No project ID available for sandbox recreation');
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
try {
|
|
289
|
+
setIsLoading(true);
|
|
290
|
+
setError(null);
|
|
291
|
+
|
|
292
|
+
const response = await recreateSandbox({
|
|
293
|
+
variables: {
|
|
294
|
+
projectId: actualChannelId,
|
|
295
|
+
messageId,
|
|
296
|
+
},
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
if (response.data?.recreateSandbox?.success) {
|
|
300
|
+
console.log('Sandbox recreation initiated successfully');
|
|
301
|
+
// The subscription will handle updating the UI with the new sandbox URL
|
|
302
|
+
} else {
|
|
303
|
+
const errorMsg = response.data?.recreateSandbox?.message || 'Failed to recreate sandbox';
|
|
304
|
+
throw new Error(errorMsg);
|
|
305
|
+
}
|
|
306
|
+
} catch (err) {
|
|
307
|
+
console.error('Error recreating sandbox:', err);
|
|
308
|
+
setError(err instanceof Error ? err.message : 'Failed to recreate sandbox');
|
|
309
|
+
setIsLoading(false);
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
[recreateSandbox, actualChannelId],
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
// Updated handleSend function from InboxWithAi.tsx
|
|
316
|
+
const handleSend = useCallback(
|
|
317
|
+
async (message: string, files: any[] = []) => {
|
|
318
|
+
// Allow sending if there's either a message or files
|
|
319
|
+
if ((!message || !message.trim()) && (!files || files.length === 0)) return;
|
|
320
|
+
|
|
321
|
+
const validated = getValidatedConfig();
|
|
322
|
+
if (!validated && !hasApiKey) {
|
|
323
|
+
// No API key/config; do nothing (AiLandingInput would prompt config UI)
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Start the AI thinking loader immediately on send
|
|
328
|
+
if (successThinkingTimeoutRef.current) {
|
|
329
|
+
clearTimeout(successThinkingTimeoutRef.current);
|
|
330
|
+
successThinkingTimeoutRef.current = null;
|
|
331
|
+
}
|
|
332
|
+
setIsSuccessThinking(true);
|
|
333
|
+
setIsLoading(true);
|
|
334
|
+
// Safety auto-stop in case no event arrives
|
|
335
|
+
successThinkingTimeoutRef.current = setTimeout(() => {
|
|
336
|
+
setIsSuccessThinking(false);
|
|
337
|
+
successThinkingTimeoutRef.current = null;
|
|
338
|
+
}, 15000);
|
|
339
|
+
|
|
340
|
+
// If we already have a channel, send message (with optional file upload) similar to Inbox
|
|
341
|
+
if (actualChannelId) {
|
|
342
|
+
try {
|
|
343
|
+
const postId = objectId();
|
|
344
|
+
const channelId = objectId();
|
|
345
|
+
const currentDate = new Date();
|
|
346
|
+
|
|
347
|
+
const createOptimisticMessage = (uploadedFiles?: any[]) => ({
|
|
348
|
+
__typename: 'Post' as const,
|
|
349
|
+
id: postId,
|
|
350
|
+
message,
|
|
351
|
+
createdAt: currentDate.toISOString(),
|
|
352
|
+
updatedAt: currentDate.toISOString(),
|
|
353
|
+
author: {
|
|
354
|
+
__typename: 'UserAccount' as const,
|
|
355
|
+
id: auth?.id,
|
|
356
|
+
givenName: auth?.profile?.given_name || '',
|
|
357
|
+
familyName: auth?.profile?.family_name || '',
|
|
358
|
+
email: auth?.profile?.email || '',
|
|
359
|
+
username: auth?.profile?.nickname || '',
|
|
360
|
+
fullName: auth?.profile?.name || '',
|
|
361
|
+
picture: auth?.profile?.picture || '',
|
|
362
|
+
alias: [auth?.authUserId ?? ''],
|
|
363
|
+
tokens: [],
|
|
364
|
+
},
|
|
365
|
+
isDelivered: false,
|
|
366
|
+
isRead: false,
|
|
367
|
+
type: 'TEXT' as PostTypeEnum,
|
|
368
|
+
parentId: null,
|
|
369
|
+
fromServer: false,
|
|
370
|
+
channel: {
|
|
371
|
+
__typename: 'Channel' as const,
|
|
372
|
+
id: actualChannelId,
|
|
373
|
+
},
|
|
374
|
+
propsConfiguration: {
|
|
375
|
+
__typename: 'MachineConfiguration' as const,
|
|
376
|
+
id: null,
|
|
377
|
+
resource: '' as any,
|
|
378
|
+
contents: null,
|
|
379
|
+
keys: null,
|
|
380
|
+
target: null,
|
|
381
|
+
overrides: null,
|
|
382
|
+
},
|
|
383
|
+
props: {},
|
|
384
|
+
files: {
|
|
385
|
+
__typename: 'FilesInfo' as const,
|
|
386
|
+
data: uploadedFiles || [],
|
|
387
|
+
totalCount: uploadedFiles?.length || 0,
|
|
388
|
+
},
|
|
389
|
+
replies: {
|
|
390
|
+
__typename: 'Messages' as const,
|
|
391
|
+
data: [],
|
|
392
|
+
totalCount: 0,
|
|
393
|
+
},
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
const cacheMessagesQuery = {
|
|
397
|
+
query: MessagesDocument,
|
|
398
|
+
variables: {
|
|
399
|
+
// Match variables used in useMessagesQuery above
|
|
400
|
+
props: { projectId: actualChannelId.toString() },
|
|
401
|
+
parentId: null,
|
|
402
|
+
limit: MESSAGES_PER_PAGE,
|
|
403
|
+
},
|
|
404
|
+
} as const;
|
|
405
|
+
|
|
406
|
+
const extraProps = {
|
|
407
|
+
projectId: actualChannelId,
|
|
408
|
+
template: modelConfig?.template || 'vite-react',
|
|
409
|
+
role: 'USER',
|
|
410
|
+
sendNotificationWithProjectId: true,
|
|
411
|
+
} as any;
|
|
412
|
+
|
|
413
|
+
if (files?.length > 0) {
|
|
414
|
+
const uploadResponse = await startUpload({
|
|
415
|
+
file: files,
|
|
416
|
+
saveUploadedFile: { variables: { postId } },
|
|
417
|
+
createUploadLink: { variables: { postId } },
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
const uploadedFiles = uploadResponse.data as unknown as IFileInfo[];
|
|
421
|
+
const fileIds = (uploadedFiles || []).map((f: any) => f.id);
|
|
422
|
+
|
|
423
|
+
await sendMsg({
|
|
424
|
+
variables: {
|
|
425
|
+
postId,
|
|
426
|
+
channelId: actualChannelId,
|
|
427
|
+
content: message,
|
|
428
|
+
files: fileIds,
|
|
429
|
+
extraProps,
|
|
430
|
+
},
|
|
431
|
+
optimisticResponse: {
|
|
432
|
+
__typename: 'Mutation',
|
|
433
|
+
sendMessage: createOptimisticMessage(uploadedFiles),
|
|
434
|
+
},
|
|
435
|
+
update: (cache, { data: mutationData }) => {
|
|
436
|
+
if (!mutationData?.sendMessage) return;
|
|
437
|
+
if (mutationData?.sendMessage?.id) {
|
|
438
|
+
handleGenerateAiCode(mutationData.sendMessage.id);
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
});
|
|
442
|
+
} else {
|
|
443
|
+
await sendMsg({
|
|
444
|
+
variables: { channelId: actualChannelId, content: message, extraProps },
|
|
445
|
+
optimisticResponse: {
|
|
446
|
+
__typename: 'Mutation',
|
|
447
|
+
sendMessage: createOptimisticMessage(),
|
|
448
|
+
},
|
|
449
|
+
update: (cache, { data: mutationData }) => {
|
|
450
|
+
if (!mutationData?.sendMessage) return;
|
|
451
|
+
console.log('mutationData', JSON.stringify(mutationData, null, 2));
|
|
452
|
+
if (mutationData?.sendMessage?.id) {
|
|
453
|
+
handleGenerateAiCode(mutationData.sendMessage.id);
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Scroll to bottom after send
|
|
460
|
+
scrollToBottom('smooth', 0);
|
|
461
|
+
} catch (error) {
|
|
462
|
+
console.error('Error sending message from AIAgent:', error);
|
|
463
|
+
setIsLoading(false);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
// If no channelId, we skip sending here.
|
|
469
|
+
},
|
|
470
|
+
[actualChannelId, auth, startUpload, sendMsg, scrollToBottom, getValidatedConfig, hasApiKey, modelConfig],
|
|
471
|
+
);
|
|
472
|
+
|
|
473
|
+
const fixError = useCallback(
|
|
474
|
+
(errorMessage: string) => {
|
|
475
|
+
// Use sendMessage to fix the error, which will use createProject flow
|
|
476
|
+
return handleSend(errorMessage);
|
|
477
|
+
},
|
|
478
|
+
[handleSend],
|
|
479
|
+
);
|
|
480
|
+
|
|
481
|
+
const handleRetry = useCallback(() => {
|
|
482
|
+
send({ type: 'RETRY' });
|
|
483
|
+
}, [send]);
|
|
484
|
+
|
|
485
|
+
const handleClearError = useCallback(() => {
|
|
486
|
+
send({ type: 'CLEAR_ERROR' });
|
|
487
|
+
}, [send]);
|
|
488
|
+
|
|
489
|
+
// Use only default/regular messages and ignore AI messages
|
|
490
|
+
const allMessages = useMemo(() => {
|
|
491
|
+
if (!regularMessages) return [] as any[];
|
|
492
|
+
|
|
493
|
+
const regularMessagesFormatted = (regularMessages || []).map((m, idx) => ({
|
|
494
|
+
id: m.id || `regular-${idx}`,
|
|
495
|
+
message: (m as any).message || (m as any).content || '',
|
|
496
|
+
createdAt: new Date((m as any).createdAt || Date.now()),
|
|
497
|
+
propsConfiguration: (m as any).propsConfiguration,
|
|
498
|
+
props: (m as any).props,
|
|
499
|
+
files: (m as any).files,
|
|
500
|
+
sender: 'user',
|
|
501
|
+
author: (m as any).author,
|
|
502
|
+
isUserMessage: true,
|
|
503
|
+
}));
|
|
504
|
+
|
|
505
|
+
return regularMessagesFormatted;
|
|
506
|
+
}, [regularMessages, currentUser]);
|
|
507
|
+
|
|
508
|
+
// Build list with date separators similar to MessagesBuilderUi
|
|
509
|
+
const messageListWithDates = useMemo(() => {
|
|
510
|
+
let currentDate = '';
|
|
511
|
+
const res: any[] = [];
|
|
512
|
+
|
|
513
|
+
allMessages?.forEach((msg: any) => {
|
|
514
|
+
const date = new Date(msg.createdAt);
|
|
515
|
+
let msgDate: string;
|
|
516
|
+
if (isToday(date)) msgDate = t('tailwind_ui_inbox.today');
|
|
517
|
+
else if (isYesterday(date)) msgDate = t('tailwind_ui_inbox.yesterday');
|
|
518
|
+
else msgDate = format(date, 'eee, do MMMM');
|
|
519
|
+
|
|
520
|
+
if (msgDate !== currentDate) {
|
|
521
|
+
res.push({ type: 'date', content: msgDate });
|
|
522
|
+
currentDate = msgDate;
|
|
523
|
+
}
|
|
524
|
+
res.push(msg);
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
if (allMessages && allMessages.length > 0) {
|
|
528
|
+
const todayLabel = t('tailwind_ui_inbox.today');
|
|
529
|
+
if (currentDate !== todayLabel) {
|
|
530
|
+
res.push({ type: 'date', content: todayLabel });
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
return res;
|
|
535
|
+
}, [allMessages, t]);
|
|
536
|
+
|
|
537
|
+
// Group messages by date sections for Slack-like rendering
|
|
538
|
+
const messagesByDate = useMemo(() => {
|
|
539
|
+
const sections: { date: string | null; messages: any[] }[] = [];
|
|
540
|
+
let currentSection: { date: string | null; messages: any[] } = { date: null, messages: [] };
|
|
541
|
+
|
|
542
|
+
messageListWithDates.forEach((item: any) => {
|
|
543
|
+
if (item?.type === 'date') {
|
|
544
|
+
if (currentSection.messages.length > 0) {
|
|
545
|
+
sections.push(currentSection);
|
|
546
|
+
}
|
|
547
|
+
currentSection = { date: item.content, messages: [] };
|
|
548
|
+
} else {
|
|
549
|
+
currentSection.messages.push(item);
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
if (currentSection.messages.length > 0) {
|
|
554
|
+
sections.push(currentSection);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
return sections;
|
|
558
|
+
}, [messageListWithDates]);
|
|
559
|
+
|
|
560
|
+
// Show all messages without limiting
|
|
561
|
+
const limitedMessagesByDate = useMemo(() => {
|
|
562
|
+
if (!messagesByDate || messagesByDate.length === 0) return [];
|
|
563
|
+
return messagesByDate;
|
|
564
|
+
}, [messagesByDate]);
|
|
565
|
+
|
|
566
|
+
// Ensure we show complete conversation pairs (user message + AI response)
|
|
567
|
+
const completeConversationMessages = useMemo(() => {
|
|
568
|
+
if (!limitedMessagesByDate || limitedMessagesByDate.length === 0) return [];
|
|
569
|
+
|
|
570
|
+
const completeSections: { date: string | null; messages: any[] }[] = [];
|
|
571
|
+
|
|
572
|
+
limitedMessagesByDate.forEach((section) => {
|
|
573
|
+
const completeMessages: any[] = [];
|
|
574
|
+
const sectionMessages = [...section.messages];
|
|
575
|
+
|
|
576
|
+
console.log('🔄 Processing section for complete conversations:', {
|
|
577
|
+
sectionDate: section.date,
|
|
578
|
+
totalMessages: sectionMessages.length,
|
|
579
|
+
messages: sectionMessages.map((m) => ({
|
|
580
|
+
sender: m.sender,
|
|
581
|
+
isUserMessage: m.isUserMessage,
|
|
582
|
+
message: m.message?.substring(0, 30) + '...',
|
|
583
|
+
})),
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
// Group messages into conversation pairs
|
|
587
|
+
for (let i = 0; i < sectionMessages.length; i++) {
|
|
588
|
+
const currentMsg = sectionMessages[i];
|
|
589
|
+
|
|
590
|
+
// If this is a user message, look for its AI response
|
|
591
|
+
if (currentMsg.sender === 'user' || currentMsg.isUserMessage) {
|
|
592
|
+
completeMessages.push(currentMsg);
|
|
593
|
+
|
|
594
|
+
// Look for the corresponding AI response (next message should be AI)
|
|
595
|
+
if (i + 1 < sectionMessages.length) {
|
|
596
|
+
const nextMsg = sectionMessages[i + 1];
|
|
597
|
+
if (nextMsg.sender === 'ai' || !nextMsg.isUserMessage) {
|
|
598
|
+
completeMessages.push(nextMsg);
|
|
599
|
+
i++; // Skip the next message since we've already added it
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
} else if (currentMsg.sender === 'ai' || !currentMsg.isUserMessage) {
|
|
603
|
+
// If this is an AI message without a preceding user message, still show it
|
|
604
|
+
completeMessages.push(currentMsg);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
console.log('🔄 Complete messages for section:', {
|
|
609
|
+
sectionDate: section.date,
|
|
610
|
+
completeMessages: completeMessages.map((m) => ({
|
|
611
|
+
sender: m.sender,
|
|
612
|
+
isUserMessage: m.isUserMessage,
|
|
613
|
+
message: m.message?.substring(0, 30) + '...',
|
|
614
|
+
})),
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
if (completeMessages.length > 0) {
|
|
618
|
+
completeSections.push({ ...section, messages: completeMessages });
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
return completeSections;
|
|
623
|
+
}, [limitedMessagesByDate]);
|
|
624
|
+
|
|
625
|
+
// Auto scroll to bottom when messages, typing status, or AI responses change
|
|
626
|
+
useEffect(() => {
|
|
627
|
+
// scrollToBottom('smooth', 100);
|
|
628
|
+
}, [completeConversationMessages?.length, isTyping, aiMessages.length, scrollToBottom]);
|
|
629
|
+
|
|
630
|
+
// Cleanup any pending timeout on unmount
|
|
631
|
+
useEffect(() => {
|
|
632
|
+
return () => {
|
|
633
|
+
if (successThinkingTimeoutRef.current) {
|
|
634
|
+
clearTimeout(successThinkingTimeoutRef.current);
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
}, []);
|
|
638
|
+
|
|
639
|
+
const extractCleanContent = useCallback((summary: string): string => {
|
|
640
|
+
console.log('summary...........', summary);
|
|
641
|
+
if (!summary) return 'Project generated successfully!';
|
|
642
|
+
|
|
643
|
+
const summeryData = summary
|
|
644
|
+
.replace(/<canvas_layers>[\s\S]*?<\/canvas_layers>/g, '')
|
|
645
|
+
.replace(/<task_summary>([\s\S]*?)<\/task_summary>/g, '');
|
|
646
|
+
if (summeryData && summeryData.trim() !== '' && summeryData.trim()?.length > 0) {
|
|
647
|
+
return summeryData || 'Project generated successfully!';
|
|
648
|
+
}
|
|
649
|
+
// Extract content from <task_summary> tags
|
|
650
|
+
const taskSummaryMatch = summary.match(/<task_summary>([\s\S]*?)<\/task_summary>/);
|
|
651
|
+
if (taskSummaryMatch) {
|
|
652
|
+
// const removedCanvasLayers = summary.replace(/<canvas_layers>[\s\S]*?<\/canvas_layers>/g, '').replace(/<task_summary>([\s\S]*?)<\/task_summary>/g, '');
|
|
653
|
+
return taskSummaryMatch?.[1]?.trim() ?? 'Project generated successfully!';
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// If no task_summary tags, remove canvas_layers and return the rest
|
|
657
|
+
const withoutCanvasLayers = summary.replace(/<canvas_layers>[\s\S]*?<\/canvas_layers>/g, '').trim();
|
|
658
|
+
return withoutCanvasLayers || 'Project generated successfully!';
|
|
659
|
+
}, []);
|
|
660
|
+
|
|
661
|
+
return (
|
|
662
|
+
<div className={`flex flex-col h-full ${className}`}>
|
|
663
|
+
{/* Header with Tabs */}
|
|
664
|
+
<div className="border-b border-gray-200 bg-white">
|
|
665
|
+
<div className="flex items-center justify-between px-4 py-3">
|
|
666
|
+
{/* Tabs */}
|
|
667
|
+
<div className="flex space-x-6">
|
|
668
|
+
<button
|
|
669
|
+
onClick={() => setActiveTab('chat')}
|
|
670
|
+
className={`relative ${
|
|
671
|
+
activeTab === 'chat' ? 'text-blue-600 font-medium' : 'text-gray-500 hover:text-gray-700'
|
|
672
|
+
} text-sm transition-colors`}
|
|
673
|
+
>
|
|
674
|
+
<span>Chat</span>
|
|
675
|
+
{activeTab === 'chat' && (
|
|
676
|
+
<div className="absolute bottom-0 left-0 w-full h-0.5 bg-blue-600"></div>
|
|
677
|
+
)}
|
|
678
|
+
</button>
|
|
679
|
+
<button
|
|
680
|
+
onClick={() => setActiveTab('history')}
|
|
681
|
+
className={`relative ${
|
|
682
|
+
activeTab === 'history'
|
|
683
|
+
? 'text-blue-600 font-medium'
|
|
684
|
+
: 'text-gray-500 hover:text-gray-700'
|
|
685
|
+
} text-sm transition-colors`}
|
|
686
|
+
>
|
|
687
|
+
<span>History</span>
|
|
688
|
+
{activeTab === 'history' && (
|
|
689
|
+
<div className="absolute bottom-0 left-0 w-full h-0.5 bg-blue-600"></div>
|
|
690
|
+
)}
|
|
691
|
+
</button>
|
|
692
|
+
</div>
|
|
693
|
+
|
|
694
|
+
{/* New Chat Button */}
|
|
695
|
+
{/* <button
|
|
696
|
+
onClick={() => {
|
|
697
|
+
// Clear AI messages by sending update event to the machine
|
|
698
|
+
send({ type: 'UPDATE', value: { messages: [] } });
|
|
699
|
+
}}
|
|
700
|
+
className="px-4 py-2 text-sm text-gray-700 border border-gray-300 rounded-lg hover:bg-gray-200 transition-colors"
|
|
701
|
+
style={{ borderRadius: '10px' }}
|
|
702
|
+
>
|
|
703
|
+
New Chat
|
|
704
|
+
</button> */}
|
|
705
|
+
</div>
|
|
706
|
+
</div>
|
|
707
|
+
|
|
708
|
+
{/* Tab Content */}
|
|
709
|
+
{activeTab === 'history' ? (
|
|
710
|
+
/* History Tab Content */
|
|
711
|
+
<div className="flex-1 overflow-y-auto bg-white">
|
|
712
|
+
{/* Search Bar */}
|
|
713
|
+
<div className="px-4 py-3 border-b border-gray-200">
|
|
714
|
+
<div className="relative">
|
|
715
|
+
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
|
716
|
+
<svg
|
|
717
|
+
className="h-5 w-5 text-gray-400"
|
|
718
|
+
fill="none"
|
|
719
|
+
viewBox="0 0 24 24"
|
|
720
|
+
stroke="currentColor"
|
|
721
|
+
>
|
|
722
|
+
<path
|
|
723
|
+
strokeLinecap="round"
|
|
724
|
+
strokeLinejoin="round"
|
|
725
|
+
strokeWidth={2}
|
|
726
|
+
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
|
727
|
+
/>
|
|
728
|
+
</svg>
|
|
729
|
+
</div>
|
|
730
|
+
<input
|
|
731
|
+
type="text"
|
|
732
|
+
placeholder="Search messages..."
|
|
733
|
+
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"
|
|
734
|
+
/>
|
|
735
|
+
<div className="absolute inset-y-0 right-0 pr-3 flex items-center">
|
|
736
|
+
<button className="text-gray-400 hover:text-gray-600">
|
|
737
|
+
<svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
738
|
+
<path
|
|
739
|
+
strokeLinecap="round"
|
|
740
|
+
strokeLinejoin="round"
|
|
741
|
+
strokeWidth={2}
|
|
742
|
+
d="M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z"
|
|
743
|
+
/>
|
|
744
|
+
</svg>
|
|
745
|
+
</button>
|
|
746
|
+
</div>
|
|
747
|
+
</div>
|
|
748
|
+
</div>
|
|
749
|
+
|
|
750
|
+
{/* Message History List */}
|
|
751
|
+
<div className="px-4 py-2">
|
|
752
|
+
{regularMessages && regularMessages.length > 0 ? (
|
|
753
|
+
regularMessages
|
|
754
|
+
.filter((msg: any) => (msg as any)?.propsConfiguration?.contents?.role === 'USER')
|
|
755
|
+
.map((msg: any, index: number) => {
|
|
756
|
+
const messageTime = new Date(msg.createdAt);
|
|
757
|
+
|
|
758
|
+
return (
|
|
759
|
+
<div key={msg.id || index} className="mb-4">
|
|
760
|
+
{/* Restore to this point button */}
|
|
761
|
+
<div className="flex items-center justify-end mb-2">
|
|
762
|
+
<button className="text-blue-600 text-sm underline hover:text-blue-800 flex items-center">
|
|
763
|
+
<svg
|
|
764
|
+
className="w-4 h-4 mr-1"
|
|
765
|
+
fill="none"
|
|
766
|
+
viewBox="0 0 24 24"
|
|
767
|
+
stroke="currentColor"
|
|
768
|
+
>
|
|
769
|
+
<path
|
|
770
|
+
strokeLinecap="round"
|
|
771
|
+
strokeLinejoin="round"
|
|
772
|
+
strokeWidth={2}
|
|
773
|
+
d="M15 19l-7-7 7-7"
|
|
774
|
+
/>
|
|
775
|
+
</svg>
|
|
776
|
+
Restore to this point
|
|
777
|
+
</button>
|
|
778
|
+
</div>
|
|
779
|
+
|
|
780
|
+
{/* Message using same container as Chat tab */}
|
|
781
|
+
<ModernMessageGroupComponent
|
|
782
|
+
messages={[
|
|
783
|
+
{
|
|
784
|
+
id: msg.id,
|
|
785
|
+
//message: msg.message || msg.content || 'No message content',
|
|
786
|
+
message:
|
|
787
|
+
(msg as any)?.propsConfiguration?.contents?.role ===
|
|
788
|
+
'ASSISTANT'
|
|
789
|
+
? msg.propsConfiguration?.contents?.fragment?.summary
|
|
790
|
+
? extractCleanContent(
|
|
791
|
+
msg.propsConfiguration?.contents?.fragment
|
|
792
|
+
?.summary,
|
|
793
|
+
)
|
|
794
|
+
: msg.message
|
|
795
|
+
: msg.message,
|
|
796
|
+
author: msg.author || {
|
|
797
|
+
id: 'user',
|
|
798
|
+
givenName: 'User',
|
|
799
|
+
familyName: '',
|
|
800
|
+
fullName: 'User',
|
|
801
|
+
username: 'user',
|
|
802
|
+
email: '',
|
|
803
|
+
picture: null,
|
|
804
|
+
alias: [],
|
|
805
|
+
tokens: [],
|
|
806
|
+
},
|
|
807
|
+
createdAt: msg.createdAt,
|
|
808
|
+
type: 'Simple' as any,
|
|
809
|
+
isDelivered: false,
|
|
810
|
+
isRead: false,
|
|
811
|
+
parentId: null,
|
|
812
|
+
fromServer: null,
|
|
813
|
+
updatedAt: msg.createdAt,
|
|
814
|
+
propsConfiguration: msg.propsConfiguration,
|
|
815
|
+
props: msg.props,
|
|
816
|
+
files: msg.files,
|
|
817
|
+
replies: null,
|
|
818
|
+
channel: null,
|
|
819
|
+
isPinned: false,
|
|
820
|
+
},
|
|
821
|
+
]}
|
|
822
|
+
currentUser={currentUser as any}
|
|
823
|
+
onOpen={onOpen}
|
|
824
|
+
onMessageClick={(msg) => setSelectedPost(msg)}
|
|
825
|
+
isDesktopView={isDesktopView}
|
|
826
|
+
isSmallScreen={isSmallScreen}
|
|
827
|
+
/>
|
|
828
|
+
</div>
|
|
829
|
+
);
|
|
830
|
+
})
|
|
831
|
+
) : (
|
|
832
|
+
// Fallback entries when no messages
|
|
833
|
+
<>
|
|
834
|
+
{/* History Entry 1 */}
|
|
835
|
+
<div className="mb-4">
|
|
836
|
+
<div className="flex items-center justify-end mb-2">
|
|
837
|
+
<button className="text-blue-600 text-sm underline hover:text-blue-800 flex items-center">
|
|
838
|
+
<svg
|
|
839
|
+
className="w-4 h-4 mr-1"
|
|
840
|
+
fill="none"
|
|
841
|
+
viewBox="0 0 24 24"
|
|
842
|
+
stroke="currentColor"
|
|
843
|
+
>
|
|
844
|
+
<path
|
|
845
|
+
strokeLinecap="round"
|
|
846
|
+
strokeLinejoin="round"
|
|
847
|
+
strokeWidth={2}
|
|
848
|
+
d="M15 19l-7-7 7-7"
|
|
849
|
+
/>
|
|
850
|
+
</svg>
|
|
851
|
+
Restore to this point
|
|
852
|
+
</button>
|
|
853
|
+
</div>
|
|
854
|
+
<div className="bg-gray-100 rounded-lg p-3">
|
|
855
|
+
<p className="text-sm text-gray-900">Sample message for demonstration</p>
|
|
856
|
+
</div>
|
|
857
|
+
</div>
|
|
858
|
+
</>
|
|
859
|
+
)}
|
|
860
|
+
</div>
|
|
861
|
+
</div>
|
|
862
|
+
) : (
|
|
863
|
+
/* Chat Tab Content */
|
|
864
|
+
<div className="flex-1 overflow-y-auto bg-white">
|
|
865
|
+
{/* Messages Display - Styled like MessagesBuilderUi */}
|
|
866
|
+
<div
|
|
867
|
+
className={`w-full pb-4 pt-2 ${
|
|
868
|
+
isDesktopView ? 'space-y-3 max-w-full mx-auto' : isSmallScreen ? 'space-y-2' : 'space-y-2'
|
|
869
|
+
}`}
|
|
870
|
+
>
|
|
871
|
+
{/* Load Past Messages Button */}
|
|
872
|
+
{/* Load Past Messages disabled to show all messages */}
|
|
873
|
+
|
|
874
|
+
{/* Show placeholder when no messages */}
|
|
875
|
+
{(!completeConversationMessages || completeConversationMessages.length === 0) && (
|
|
876
|
+
<div className="px-4 py-8 text-center">
|
|
877
|
+
<div className="text-gray-500 text-lg font-medium mb-2">
|
|
878
|
+
Describe your idea and I'll help you create it step by step
|
|
879
|
+
</div>
|
|
880
|
+
<div className="text-gray-400 text-sm">
|
|
881
|
+
Start a new conversation by typing your message below
|
|
882
|
+
</div>
|
|
883
|
+
</div>
|
|
884
|
+
)}
|
|
885
|
+
|
|
886
|
+
{completeConversationMessages?.map((section, sectionIndex) => (
|
|
887
|
+
<div key={`section-${sectionIndex}`} className="w-full px-4">
|
|
888
|
+
{section.date && (
|
|
889
|
+
<div className="flex items-center justify-center my-3">
|
|
890
|
+
<div className="flex-grow border-t border-gray-200"></div>
|
|
891
|
+
<div className="mx-4 px-3 py-1 bg-white border border-gray-200 rounded-full text-xs font-medium text-gray-600">
|
|
892
|
+
{section.date}
|
|
893
|
+
</div>
|
|
894
|
+
<div className="flex-grow border-t border-gray-200"></div>
|
|
895
|
+
</div>
|
|
896
|
+
)}
|
|
897
|
+
|
|
898
|
+
<div className={`${isDesktopView ? 'mb-2' : 'mb-1'}`}>
|
|
899
|
+
{section.messages.map((msg: any, msgIndex: number) => (
|
|
900
|
+
<div key={msg.id || msgIndex} className="mb-3">
|
|
901
|
+
{/* AI Message Indicator */}
|
|
902
|
+
{msg.isAIMessage && (
|
|
903
|
+
<div className="flex items-center mb-2">
|
|
904
|
+
<div className="w-2 h-2 bg-blue-500 rounded-full mr-2"></div>
|
|
905
|
+
<span className="text-xs text-blue-600 font-medium">
|
|
906
|
+
AI Assistant
|
|
907
|
+
</span>
|
|
908
|
+
</div>
|
|
909
|
+
)}
|
|
910
|
+
|
|
911
|
+
{msg.isLoading ? (
|
|
912
|
+
// Show loader for loading messages
|
|
913
|
+
<div className="flex items-center space-x-2 bg-gray-50 border border-gray-200 px-4 py-3 rounded-lg">
|
|
914
|
+
<div className="w-4 h-4 border-2 border-gray-300 border-t-gray-500 rounded-full animate-spin"></div>
|
|
915
|
+
<span className="text-sm text-gray-600">
|
|
916
|
+
{msg.isProcessing ? 'Thinking...' : 'Thinking...'}
|
|
917
|
+
</span>
|
|
918
|
+
</div>
|
|
919
|
+
) : (
|
|
920
|
+
// Show normal message for non-loading messages
|
|
921
|
+
<ModernMessageGroupComponent
|
|
922
|
+
messages={[
|
|
923
|
+
{
|
|
924
|
+
id: msg.id,
|
|
925
|
+
// message: msg.message,
|
|
926
|
+
message:
|
|
927
|
+
(msg as any)?.propsConfiguration?.contents?.role ===
|
|
928
|
+
'ASSISTANT'
|
|
929
|
+
? msg.propsConfiguration?.contents?.fragment
|
|
930
|
+
?.summary
|
|
931
|
+
? extractCleanContent(
|
|
932
|
+
msg.propsConfiguration?.contents?.fragment
|
|
933
|
+
?.summary,
|
|
934
|
+
)
|
|
935
|
+
: msg.message
|
|
936
|
+
: msg.message,
|
|
937
|
+
author:
|
|
938
|
+
msg.sender === 'user'
|
|
939
|
+
? msg.author
|
|
940
|
+
: {
|
|
941
|
+
id: 'ai-assistant',
|
|
942
|
+
givenName: 'AI',
|
|
943
|
+
familyName: 'Assistant',
|
|
944
|
+
fullName: 'AI Assistant',
|
|
945
|
+
username: 'ai-assistant',
|
|
946
|
+
email: 'ai@assistant.com',
|
|
947
|
+
picture: null,
|
|
948
|
+
alias: [],
|
|
949
|
+
tokens: [],
|
|
950
|
+
},
|
|
951
|
+
createdAt: msg.createdAt,
|
|
952
|
+
type: 'Simple' as any,
|
|
953
|
+
isDelivered: false,
|
|
954
|
+
isRead: false,
|
|
955
|
+
parentId: null,
|
|
956
|
+
fromServer: null,
|
|
957
|
+
updatedAt: msg.createdAt,
|
|
958
|
+
propsConfiguration: msg.propsConfiguration,
|
|
959
|
+
props: msg.props,
|
|
960
|
+
files: msg.files,
|
|
961
|
+
replies: null,
|
|
962
|
+
channel: null,
|
|
963
|
+
isPinned: false,
|
|
964
|
+
},
|
|
965
|
+
]}
|
|
966
|
+
currentUser={currentUser as any}
|
|
967
|
+
onOpen={onOpen}
|
|
968
|
+
onMessageClick={(msg) => setSelectedPost(msg)}
|
|
969
|
+
isDesktopView={isDesktopView}
|
|
970
|
+
isSmallScreen={isSmallScreen}
|
|
971
|
+
sandboxErrors={sandboxErrors}
|
|
972
|
+
currentFiles={currentFiles}
|
|
973
|
+
onFixError={fixError}
|
|
974
|
+
onRecreateSandbox={recreateSandboxForFragment}
|
|
975
|
+
/>
|
|
976
|
+
)}
|
|
977
|
+
</div>
|
|
978
|
+
))}
|
|
979
|
+
</div>
|
|
980
|
+
</div>
|
|
981
|
+
))}
|
|
982
|
+
|
|
983
|
+
{/* Typing indicator */}
|
|
984
|
+
{(isTyping || isSuccessThinking || isLoading) && (
|
|
985
|
+
<div className="px-4">
|
|
986
|
+
<div className="flex justify-start">
|
|
987
|
+
<div className="bg-gray-50 border border-gray-200 px-4 py-3 rounded-lg">
|
|
988
|
+
<div className="flex items-center space-x-2">
|
|
989
|
+
<div className="w-4 h-4 border-2 border-gray-300 border-t-gray-500 rounded-full animate-spin"></div>
|
|
990
|
+
<span className="text-sm text-gray-600">Thinking...</span>
|
|
991
|
+
</div>
|
|
992
|
+
</div>
|
|
993
|
+
</div>
|
|
994
|
+
</div>
|
|
995
|
+
)}
|
|
996
|
+
|
|
997
|
+
<div ref={bottomRef} />
|
|
998
|
+
</div>
|
|
999
|
+
|
|
1000
|
+
{/* Subscription Handler for real-time message updates */}
|
|
1001
|
+
<SubscriptionHandler
|
|
1002
|
+
subscribeToMore={subscribeToMore}
|
|
1003
|
+
document={CHAT_MESSAGE_ADDED}
|
|
1004
|
+
variables={{ channelId: actualChannelId?.toString() }}
|
|
1005
|
+
enabled={!!actualChannelId && !!subscribeToMore}
|
|
1006
|
+
updateQuery={(prev: any, { subscriptionData }: any) => {
|
|
1007
|
+
console.log('Subscription updateQuery called:', { prev, subscriptionData });
|
|
1008
|
+
if (!subscriptionData.data) {
|
|
1009
|
+
console.log('No subscription data, returning prev');
|
|
1010
|
+
return prev;
|
|
1011
|
+
}
|
|
1012
|
+
const newMessage = subscriptionData.data.chatMessageAdded;
|
|
1013
|
+
|
|
1014
|
+
console.log('New message received via subscription:', newMessage);
|
|
1015
|
+
|
|
1016
|
+
return {
|
|
1017
|
+
...prev,
|
|
1018
|
+
messages: {
|
|
1019
|
+
...prev?.messages,
|
|
1020
|
+
data: uniqBy([...(prev?.messages?.data || []), newMessage], 'id'),
|
|
1021
|
+
totalCount: (prev?.messages?.totalCount || 0) + 1,
|
|
1022
|
+
},
|
|
1023
|
+
};
|
|
1024
|
+
}}
|
|
1025
|
+
onError={(error) => {
|
|
1026
|
+
console.error('Subscription error:', error);
|
|
1027
|
+
}}
|
|
1028
|
+
/>
|
|
1029
|
+
</div>
|
|
1030
|
+
)}
|
|
1031
|
+
|
|
1032
|
+
{/* Error Display */}
|
|
1033
|
+
{error && (
|
|
1034
|
+
<div className="mx-4 mb-4 p-3 bg-red-50 border border-red-200 rounded-lg">
|
|
1035
|
+
<div className="flex items-center justify-between">
|
|
1036
|
+
<div className="text-red-800 text-sm">{error}</div>
|
|
1037
|
+
<div className="flex space-x-2">
|
|
1038
|
+
<button
|
|
1039
|
+
onClick={handleRetry}
|
|
1040
|
+
className="px-2 py-1 text-xs bg-red-100 text-red-700 rounded hover:bg-red-200 transition-colors"
|
|
1041
|
+
>
|
|
1042
|
+
Retry
|
|
1043
|
+
</button>
|
|
1044
|
+
<button
|
|
1045
|
+
onClick={handleClearError}
|
|
1046
|
+
className="px-2 py-1 text-xs bg-gray-100 text-gray-700 rounded hover:bg-gray-200 transition-colors"
|
|
1047
|
+
>
|
|
1048
|
+
Dismiss
|
|
1049
|
+
</button>
|
|
1050
|
+
</div>
|
|
1051
|
+
</div>
|
|
1052
|
+
</div>
|
|
1053
|
+
)}
|
|
1054
|
+
|
|
1055
|
+
{/* Input Area - Only show for Chat tab */}
|
|
1056
|
+
{activeTab === 'chat' && (
|
|
1057
|
+
<div className="border-t border-gray-200 bg-white">
|
|
1058
|
+
{/* Removed temporary test button */}
|
|
1059
|
+
<InputComponent
|
|
1060
|
+
channelId={actualChannelId}
|
|
1061
|
+
handleSend={handleSend}
|
|
1062
|
+
placeholder={placeholder}
|
|
1063
|
+
modelConfig={modelConfig}
|
|
1064
|
+
onModelConfigChange={updateModelConfig}
|
|
1065
|
+
/>
|
|
1066
|
+
</div>
|
|
1067
|
+
)}
|
|
1068
|
+
|
|
1069
|
+
{/* Optional Modal for user content like MessagesBuilderUi */}
|
|
1070
|
+
{isOpen ? (
|
|
1071
|
+
<div>
|
|
1072
|
+
<div className="fixed inset-0 bg-black bg-opacity-50 z-40" onClick={onClose} />
|
|
1073
|
+
<div className="fixed z-50 left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2">
|
|
1074
|
+
<div
|
|
1075
|
+
className="bg-white w-[1036px] h-[700px] rounded-lg shadow-xl"
|
|
1076
|
+
style={{ boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)' }}
|
|
1077
|
+
>
|
|
1078
|
+
<div className="flex justify-between border-b border-gray-300 pb-4 pt-4">
|
|
1079
|
+
<button
|
|
1080
|
+
onClick={onClose}
|
|
1081
|
+
className="w-8 ml-3 text-black hover:text-black focus:outline-none"
|
|
1082
|
+
>
|
|
1083
|
+
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
1084
|
+
<path
|
|
1085
|
+
strokeLinecap="round"
|
|
1086
|
+
strokeLinejoin="round"
|
|
1087
|
+
strokeWidth={2}
|
|
1088
|
+
d="M6 18L18 6M6 6l12 12"
|
|
1089
|
+
/>
|
|
1090
|
+
</svg>
|
|
1091
|
+
</button>
|
|
1092
|
+
</div>
|
|
1093
|
+
<div className="p-4">
|
|
1094
|
+
{/* Keep minimal until full UserModalContent is needed */}
|
|
1095
|
+
<div className="text-sm text-gray-700">{selectedElement?.author?.username}</div>
|
|
1096
|
+
</div>
|
|
1097
|
+
</div>
|
|
1098
|
+
</div>
|
|
1099
|
+
</div>
|
|
1100
|
+
) : null}
|
|
1101
|
+
</div>
|
|
1102
|
+
);
|
|
1103
|
+
};
|