11'use client'
22
3- import { useCallback , useEffect , useLayoutEffect , useRef , useState } from 'react'
3+ import { useCallback , useEffect , useRef , useState } from 'react'
44import { createLogger } from '@sim/logger'
55import { useParams , useRouter } from 'next/navigation'
66import { PanelLeft } from '@/components/emcn/icons'
@@ -11,21 +11,10 @@ import {
1111 LandingWorkflowSeedStorage ,
1212} from '@/lib/core/utils/browser-storage'
1313import { persistImportedWorkflow } from '@/lib/workflows/operations/import-export'
14- import { MessageActions } from '@/app/workspace/[workspaceId]/components'
1514import { useChatHistory , useMarkTaskRead } from '@/hooks/queries/tasks'
1615import type { ChatContext } from '@/stores/panel'
17- import {
18- assistantMessageHasRenderableContent ,
19- ChatMessageAttachments ,
20- MessageContent ,
21- MothershipView ,
22- QueuedMessages ,
23- TemplatePrompts ,
24- UserInput ,
25- UserMessageContent ,
26- } from './components'
27- import { PendingTagIndicator } from './components/message-content/components/special-tags'
28- import { useAutoScroll , useChat , useMothershipResize } from './hooks'
16+ import { MothershipChat , MothershipView , TemplatePrompts , UserInput } from './components'
17+ import { getMothershipUseChatOptions , useChat , useMothershipResize } from './hooks'
2918import type { FileAttachmentForApi , MothershipResource , MothershipResourceType } from './types'
3019
3120const logger = createLogger ( 'Home' )
@@ -173,7 +162,11 @@ export function Home({ chatId }: HomeProps = {}) {
173162 sendNow,
174163 editQueuedMessage,
175164 streamingFile,
176- } = useChat ( workspaceId , chatId , { onResourceEvent : handleResourceEvent } )
165+ } = useChat (
166+ workspaceId ,
167+ chatId ,
168+ getMothershipUseChatOptions ( { onResourceEvent : handleResourceEvent } )
169+ )
177170
178171 const [ editingInputValue , setEditingInputValue ] = useState ( '' )
179172 const [ prevChatId , setPrevChatId ] = useState ( chatId )
@@ -285,22 +278,7 @@ export function Home({ chatId }: HomeProps = {}) {
285278 [ addResource , handleResourceEvent ]
286279 )
287280
288- const { ref : scrollContainerRef , scrollToBottom } = useAutoScroll ( isSending )
289-
290281 const hasMessages = messages . length > 0
291- const initialScrollDoneRef = useRef ( false )
292-
293- useLayoutEffect ( ( ) => {
294- if ( ! hasMessages ) {
295- initialScrollDoneRef . current = false
296- return
297- }
298- if ( initialScrollDoneRef . current ) return
299- if ( resources . length > 0 && isResourceCollapsed ) return
300-
301- initialScrollDoneRef . current = true
302- scrollToBottom ( )
303- } , [ hasMessages , resources . length , isResourceCollapsed , scrollToBottom ] )
304282
305283 useEffect ( ( ) => {
306284 if ( hasMessages ) return
@@ -354,90 +332,23 @@ export function Home({ chatId }: HomeProps = {}) {
354332 return (
355333 < div className = 'relative flex h-full bg-[var(--bg)]' >
356334 < div className = 'flex h-full min-w-[320px] flex-1 flex-col' >
357- < div
358- ref = { scrollContainerRef }
359- className = 'min-h-0 flex-1 overflow-y-auto overflow-x-hidden px-6 pt-4 pb-8 [scrollbar-gutter:stable]'
360- >
361- < div className = 'mx-auto max-w-[42rem] space-y-6' >
362- { messages . map ( ( msg , index ) => {
363- if ( msg . role === 'user' ) {
364- const hasAttachments = msg . attachments && msg . attachments . length > 0
365- return (
366- < div key = { msg . id } className = 'flex flex-col items-end gap-[6px] pt-3' >
367- { hasAttachments && (
368- < ChatMessageAttachments
369- attachments = { msg . attachments ! }
370- align = 'end'
371- className = 'max-w-[70%]'
372- />
373- ) }
374- < div className = 'max-w-[70%] overflow-hidden rounded-[16px] bg-[var(--surface-5)] px-3.5 py-2' >
375- < UserMessageContent content = { msg . content } contexts = { msg . contexts } />
376- </ div >
377- </ div >
378- )
379- }
380-
381- const hasAnyBlocks = Boolean ( msg . contentBlocks ?. length )
382- const hasRenderableAssistant = assistantMessageHasRenderableContent (
383- msg . contentBlocks ?? [ ] ,
384- msg . content ?? ''
385- )
386- const isLastAssistant = msg . role === 'assistant' && index === messages . length - 1
387- const isThisStreaming = isSending && isLastAssistant
388-
389- if ( ! hasAnyBlocks && ! msg . content ?. trim ( ) && isThisStreaming ) {
390- return < PendingTagIndicator key = { msg . id } />
391- }
392-
393- if ( ! hasRenderableAssistant && ! msg . content ?. trim ( ) && ! isThisStreaming ) {
394- return null
395- }
396-
397- const isLastMessage = index === messages . length - 1
398-
399- return (
400- < div key = { msg . id } className = 'group/msg relative pb-5' >
401- { ! isThisStreaming && ( msg . content || msg . contentBlocks ?. length ) && (
402- < div className = 'absolute right-0 bottom-0 z-10' >
403- < MessageActions content = { msg . content } requestId = { msg . requestId } />
404- </ div >
405- ) }
406- < MessageContent
407- blocks = { msg . contentBlocks || [ ] }
408- fallbackContent = { msg . content }
409- isStreaming = { isThisStreaming }
410- onOptionSelect = { isLastMessage ? sendMessage : undefined }
411- />
412- </ div >
413- )
414- } ) }
415- </ div >
416- </ div >
417-
418- < div
419- className = { `flex-shrink-0 px-[24px] pb-[16px]${ isInputEntering ? ' animate-slide-in-bottom' : '' } ` }
420- onAnimationEnd = { isInputEntering ? ( ) => setIsInputEntering ( false ) : undefined }
421- >
422- < div className = 'mx-auto max-w-[42rem]' >
423- < QueuedMessages
424- messageQueue = { messageQueue }
425- onRemove = { removeFromQueue }
426- onSendNow = { sendNow }
427- onEdit = { handleEditQueuedMessage }
428- />
429- < UserInput
430- onSubmit = { handleSubmit }
431- isSending = { isSending }
432- onStopGeneration = { stopGeneration }
433- isInitialView = { false }
434- userId = { session ?. user ?. id }
435- onContextAdd = { handleContextAdd }
436- editValue = { editingInputValue }
437- onEditValueConsumed = { clearEditingValue }
438- />
439- </ div >
440- </ div >
335+ < MothershipChat
336+ messages = { messages }
337+ isSending = { isSending }
338+ onSubmit = { handleSubmit }
339+ onStopGeneration = { stopGeneration }
340+ messageQueue = { messageQueue }
341+ onRemoveQueuedMessage = { removeFromQueue }
342+ onSendQueuedMessage = { sendNow }
343+ onEditQueuedMessage = { handleEditQueuedMessage }
344+ userId = { session ?. user ?. id }
345+ onContextAdd = { handleContextAdd }
346+ editValue = { editingInputValue }
347+ onEditValueConsumed = { clearEditingValue }
348+ animateInput = { isInputEntering }
349+ onInputAnimationEnd = { isInputEntering ? ( ) => setIsInputEntering ( false ) : undefined }
350+ initialScrollBlocked = { resources . length > 0 && isResourceCollapsed }
351+ />
441352 </ div >
442353
443354 { /* Resize handle — zero-width flex child whose absolute child straddles the border */ }
0 commit comments