diff --git a/apps/sim/app/workspace/[workspaceId]/home/home.tsx b/apps/sim/app/workspace/[workspaceId]/home/home.tsx index 5e58dea04b9..78097c32a6e 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/home.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/home.tsx @@ -250,6 +250,15 @@ export function Home({ chatId }: HomeProps = {}) { [sendMessage] ) + useEffect(() => { + const handler = (e: Event) => { + const message = (e as CustomEvent<{ message: string }>).detail?.message + if (message) sendMessage(message) + } + window.addEventListener('mothership-send-message', handler) + return () => window.removeEventListener('mothership-send-message', handler) + }, [sendMessage]) + const handleContextAdd = useCallback( (context: ChatContext) => { let resourceType: MothershipResourceType | null = null diff --git a/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts b/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts index f63dc46be5b..01cfc0e73de 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts +++ b/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts @@ -651,6 +651,22 @@ export function useChat( ) { clientExecutionStarted.add(id) const args = data?.arguments ?? data?.input ?? {} + const targetWorkflowId = + typeof (args as Record).workflowId === 'string' + ? ((args as Record).workflowId as string) + : useWorkflowRegistry.getState().activeWorkflowId + if (targetWorkflowId) { + const meta = useWorkflowRegistry.getState().workflows[targetWorkflowId] + const wasAdded = addResource({ + type: 'workflow', + id: targetWorkflowId, + title: meta?.name ?? 'Workflow', + }) + if (!wasAdded && activeResourceIdRef.current !== targetWorkflowId) { + setActiveResourceId(targetWorkflowId) + } + onResourceEventRef.current?.() + } executeRunToolOnClient(id, name, args as Record) } break diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/notifications/notifications.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/notifications/notifications.tsx index f46ff895384..834d83054f2 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/notifications/notifications.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/notifications/notifications.tsx @@ -9,6 +9,7 @@ import { type Notification, type NotificationAction, openCopilotWithMessage, + sendMothershipMessage, useNotificationStore, } from '@/stores/notifications' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' @@ -81,7 +82,11 @@ function CountdownRing({ onPause }: { onPause: () => void }) { * Workflow error notifications auto-dismiss after {@link AUTO_DISMISS_MS}ms with a countdown * ring. Clicking the ring pauses all timers until the notification stack clears. */ -export const Notifications = memo(function Notifications() { +interface NotificationsProps { + embedded?: boolean +} + +export const Notifications = memo(function Notifications({ embedded }: NotificationsProps) { const activeWorkflowId = useWorkflowRegistry((state) => state.activeWorkflowId) const allNotifications = useNotificationStore((state) => state.notifications) @@ -112,7 +117,11 @@ export const Notifications = memo(function Notifications() { switch (action.type) { case 'copilot': - openCopilotWithMessage(action.message) + if (embedded) { + sendMothershipMessage(action.message) + } else { + openCopilotWithMessage(action.message) + } break case 'refresh': window.location.reload() @@ -133,7 +142,7 @@ export const Notifications = memo(function Notifications() { }) } }, - [removeNotification] + [embedded, removeNotification] ) useRegisterGlobalCommands(() => @@ -281,7 +290,9 @@ export const Notifications = memo(function Notifications() { onClick={() => executeAction(notification.id, notification.action!)} className='w-full rounded-[5px] px-[8px] py-[4px] font-medium text-[12px]' > - {ACTION_LABELS[notification.action!.type] ?? 'Take action'} + {embedded && notification.action!.type === 'copilot' + ? 'Fix in Mothership' + : (ACTION_LABELS[notification.action!.type] ?? 'Take action')} )} diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx index c1f78d96624..9b13576c642 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx @@ -3922,7 +3922,7 @@ const WorkflowContent = React.memo( )} - {!embedded && } + {!embedded && isWorkflowReady && isWorkflowEmpty && effectivePermissions.canEdit && ( diff --git a/apps/sim/stores/notifications/index.ts b/apps/sim/stores/notifications/index.ts index b3c034b0294..dcad513cae5 100644 --- a/apps/sim/stores/notifications/index.ts +++ b/apps/sim/stores/notifications/index.ts @@ -4,4 +4,4 @@ export type { Notification, NotificationAction, } from './types' -export { openCopilotWithMessage } from './utils' +export { openCopilotWithMessage, sendMothershipMessage } from './utils' diff --git a/apps/sim/stores/notifications/utils.ts b/apps/sim/stores/notifications/utils.ts index cf41011f668..035e5327227 100644 --- a/apps/sim/stores/notifications/utils.ts +++ b/apps/sim/stores/notifications/utils.ts @@ -3,6 +3,20 @@ import { useCopilotStore, usePanelStore } from '@/stores/panel' const logger = createLogger('NotificationUtils') +/** + * Dispatches a message to the mothership chat via a custom window event. + * The mothership `Home` component listens for this event and calls `sendMessage`. + */ +export function sendMothershipMessage(message: string): void { + const trimmed = message.trim() + if (!trimmed) { + logger.warn('sendMothershipMessage called with empty message') + return + } + window.dispatchEvent(new CustomEvent('mothership-send-message', { detail: { message: trimmed } })) + logger.info('Dispatched mothership message event', { messageLength: trimmed.length }) +} + /** * Opens the copilot panel and directly sends the message. *