@@ -46,7 +46,11 @@ import { captureEvent } from '@/lib/posthog/client'
4646import { generateWorkflowJson } from '@/lib/workflows/operations/import-export'
4747import { ConversationListItem } from '@/app/workspace/[workspaceId]/components'
4848import { MothershipChat } from '@/app/workspace/[workspaceId]/home/components'
49- import { getWorkflowCopilotUseChatOptions , useChat } from '@/app/workspace/[workspaceId]/home/hooks'
49+ import {
50+ getMothershipUseChatOptions ,
51+ getWorkflowCopilotUseChatOptions ,
52+ useChat ,
53+ } from '@/app/workspace/[workspaceId]/home/hooks'
5054import type { FileAttachmentForApi } from '@/app/workspace/[workspaceId]/home/types'
5155import { useRegisterGlobalCommands } from '@/app/workspace/[workspaceId]/providers/global-commands-provider'
5256import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
@@ -252,26 +256,23 @@ export const Panel = memo(function Panel({ workspaceId: propWorkspaceId }: Panel
252256 )
253257 const [ isCopilotHistoryOpen , setIsCopilotHistoryOpen ] = useState ( false )
254258
255- const copilotChatTitle = useMemo (
256- ( ) =>
257- copilotChatId ? ( copilotChatList . find ( ( c ) => c . id === copilotChatId ) ?. title ?? null ) : null ,
259+ const selectedCopilotChat = useMemo (
260+ ( ) => ( copilotChatId ? ( copilotChatList . find ( ( c ) => c . id === copilotChatId ) ?? null ) : null ) ,
258261 [ copilotChatId , copilotChatList ]
259262 )
263+ const copilotChatTitle = selectedCopilotChat ?. title ?? null
260264
261265 /**
262- * A chat is read-only on this workflow page when it doesn't natively
263- * belong to the active workflow — currently the case for Mothership
264- * chats whose `workflowId` is null but whose `resources` reference this
265- * workflow. Continuing the conversation would route through the
266- * workflow copilot agent rather than the original Mothership context,
267- * so we surface the history without the input.
266+ * A selected chat is "foreign" to this workflow when it was started in
267+ * Mothership (`type === 'mothership'`) but ended up referencing this
268+ * workflow via `resources`. We keep the conversation continuable by
269+ * routing sends through the Mothership branch — i.e. the request goes
270+ * out without `workflowId`, so the server uses the broader Mothership
271+ * agent surface that originally produced the chat. The trade-off is
272+ * that resources spawned during continuation only show up in the
273+ * Mothership view; this panel shows the conversation only.
268274 */
269- const isCopilotChatReadOnly = useMemo ( ( ) => {
270- if ( ! copilotChatId || ! activeWorkflowId ) return false
271- const chat = copilotChatList . find ( ( c ) => c . id === copilotChatId )
272- if ( ! chat ) return false
273- return chat . workflowId !== activeWorkflowId
274- } , [ copilotChatId , copilotChatList , activeWorkflowId ] )
275+ const isMothershipChat = selectedCopilotChat ?. type === 'mothership'
275276
276277 const queryClient = useQueryClient ( )
277278 const loadCopilotChats = useCallback ( ( ) => {
@@ -359,6 +360,40 @@ export const Panel = memo(function Panel({ workspaceId: propWorkspaceId }: Panel
359360 [ activeWorkflowId ]
360361 )
361362
363+ const handleCopilotRequestStarted = useCallback (
364+ ( { requestId, userMessageId } : { requestId : string ; userMessageId : string } ) => {
365+ captureEvent ( posthogRef . current , 'task_request_started' , {
366+ workspace_id : workspaceId ,
367+ view : 'copilot' ,
368+ request_id : requestId ,
369+ user_message_id : userMessageId ,
370+ } )
371+ } ,
372+ [ workspaceId ]
373+ )
374+
375+ const copilotChatOptions = useMemo (
376+ ( ) =>
377+ isMothershipChat
378+ ? getMothershipUseChatOptions ( {
379+ onStreamEnd : loadCopilotChats ,
380+ onRequestStarted : handleCopilotRequestStarted ,
381+ } )
382+ : getWorkflowCopilotUseChatOptions ( {
383+ workflowId : activeWorkflowId || undefined ,
384+ onTitleUpdate : loadCopilotChats ,
385+ onToolResult : handleCopilotToolResult ,
386+ onRequestStarted : handleCopilotRequestStarted ,
387+ } ) ,
388+ [
389+ isMothershipChat ,
390+ activeWorkflowId ,
391+ loadCopilotChats ,
392+ handleCopilotToolResult ,
393+ handleCopilotRequestStarted ,
394+ ]
395+ )
396+
362397 const {
363398 messages : copilotMessages ,
364399 isSending : copilotIsSending ,
@@ -371,23 +406,7 @@ export const Panel = memo(function Panel({ workspaceId: propWorkspaceId }: Panel
371406 sendNow : copilotSendNow ,
372407 editQueuedMessage : copilotEditQueuedMessage ,
373408 getCurrentRequestId : getCopilotCurrentRequestId ,
374- } = useChat (
375- workspaceId ,
376- copilotChatId ,
377- getWorkflowCopilotUseChatOptions ( {
378- workflowId : activeWorkflowId || undefined ,
379- onTitleUpdate : loadCopilotChats ,
380- onToolResult : handleCopilotToolResult ,
381- onRequestStarted : ( { requestId, userMessageId } ) => {
382- captureEvent ( posthogRef . current , 'task_request_started' , {
383- workspace_id : workspaceId ,
384- view : 'copilot' ,
385- request_id : requestId ,
386- user_message_id : userMessageId ,
387- } )
388- } ,
389- } )
390- )
409+ } = useChat ( workspaceId , copilotChatId , copilotChatOptions )
391410
392411 const handleCopilotNewChat = useCallback ( ( ) => {
393412 if ( ! activeWorkflowId || ! workspaceId ) return
@@ -925,7 +944,6 @@ export const Panel = memo(function Panel({ workspaceId: propWorkspaceId }: Panel
925944 userId = { session ?. user ?. id }
926945 chatId = { copilotResolvedChatId }
927946 layout = 'copilot-view'
928- readOnly = { isCopilotChatReadOnly }
929947 />
930948 </ div >
931949 ) }
0 commit comments