From 28b279afaccbf76bb5b6278f7e701a3020219973 Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Tue, 12 May 2026 19:57:20 -0700 Subject: [PATCH] Add convo id to mship block --- apps/sim/app/api/mothership/execute/route.ts | 1 + apps/sim/blocks/blocks/mothership.ts | 12 +++++ .../mothership/mothership-handler.test.ts | 53 ++++++++++++++++++- .../handlers/mothership/mothership-handler.ts | 6 ++- .../sim/lib/api/contracts/mothership-tasks.ts | 1 + 5 files changed, 71 insertions(+), 2 deletions(-) diff --git a/apps/sim/app/api/mothership/execute/route.ts b/apps/sim/app/api/mothership/execute/route.ts index a85ca3c860f..d8a5e73f3d7 100644 --- a/apps/sim/app/api/mothership/execute/route.ts +++ b/apps/sim/app/api/mothership/execute/route.ts @@ -171,6 +171,7 @@ export const POST = withRouteHandler(async (req: NextRequest) => { return NextResponse.json({ content: result.content, model: 'mothership', + conversationId: effectiveChatId, tokens: result.usage ? { prompt: result.usage.prompt, diff --git a/apps/sim/blocks/blocks/mothership.ts b/apps/sim/blocks/blocks/mothership.ts index 9b1818667ea..a524eb1674f 100644 --- a/apps/sim/blocks/blocks/mothership.ts +++ b/apps/sim/blocks/blocks/mothership.ts @@ -6,6 +6,7 @@ interface MothershipResponse extends ToolResponse { output: { content: string model: string + conversationId?: string tokens?: { prompt?: number completion?: number @@ -34,6 +35,12 @@ export const MothershipBlock: BlockConfig = { type: 'long-input', placeholder: 'Enter your prompt for the Mothership...', }, + { + id: 'conversationId', + title: 'Conversation ID', + type: 'short-input', + placeholder: 'e.g., user-123, session-abc, customer-456', + }, ], tools: { access: [], @@ -43,10 +50,15 @@ export const MothershipBlock: BlockConfig = { type: 'string', description: 'The prompt to send to the Mothership AI agent', }, + conversationId: { + type: 'string', + description: 'Mothership chat ID to continue; generated when omitted', + }, }, outputs: { content: { type: 'string', description: 'Generated response content' }, model: { type: 'string', description: 'Model used for generation' }, + conversationId: { type: 'string', description: 'Mothership chat ID used for this request' }, tokens: { type: 'json', description: 'Token usage statistics' }, toolCalls: { type: 'json', description: 'Tool calls made during execution' }, cost: { type: 'json', description: 'Cost of the execution' }, diff --git a/apps/sim/executor/handlers/mothership/mothership-handler.test.ts b/apps/sim/executor/handlers/mothership/mothership-handler.test.ts index 38a36c32f0e..1dde2fcebc0 100644 --- a/apps/sim/executor/handlers/mothership/mothership-handler.test.ts +++ b/apps/sim/executor/handlers/mothership/mothership-handler.test.ts @@ -84,7 +84,7 @@ describe('MothershipBlockHandler', () => { metadata: { id: BlockType.MOTHERSHIP, name: 'Mothership' }, position: { x: 0, y: 0 }, config: { tool: BlockType.MOTHERSHIP, params: {} }, - inputs: { prompt: 'string' }, + inputs: { prompt: 'string', conversationId: 'string' }, outputs: {}, enabled: true, } as SerializedBlock @@ -122,6 +122,7 @@ describe('MothershipBlockHandler', () => { JSON.stringify({ content: 'done', model: 'mothership', + conversationId: 'chat-uuid', tokens: { total: 5 }, toolCalls: [], }), @@ -137,6 +138,7 @@ describe('MothershipBlockHandler', () => { expect(result).toEqual({ content: 'done', model: 'mothership', + conversationId: 'chat-uuid', tokens: { total: 5 }, toolCalls: { list: [], count: 0 }, cost: undefined, @@ -161,6 +163,55 @@ describe('MothershipBlockHandler', () => { }) }) + it('uses a provided conversation ID as the mothership chat ID', async () => { + mockGenerateId.mockReturnValueOnce('message-uuid') + mockGenerateId.mockReturnValueOnce('request-uuid') + + fetchMock.mockResolvedValue( + new Response( + JSON.stringify({ + content: 'continued', + model: 'mothership', + conversationId: 'existing-chat-id', + tokens: {}, + toolCalls: [], + }), + { + status: 200, + headers: { 'Content-Type': 'application/json' }, + } + ) + ) + + const result = await handler.execute(context, block, { + prompt: 'Continue this thread', + conversationId: ' existing-chat-id ', + }) + + expect(result).toEqual({ + content: 'continued', + model: 'mothership', + conversationId: 'existing-chat-id', + tokens: {}, + toolCalls: { list: [], count: 0 }, + cost: undefined, + }) + + const [, options] = fetchMock.mock.calls[0] as [string, RequestInit] + const body = JSON.parse(String(options.body)) + expect(body).toEqual({ + messages: [{ role: 'user', content: 'Continue this thread' }], + workspaceId: 'workspace-1', + userId: 'user-1', + chatId: 'existing-chat-id', + messageId: 'message-uuid', + requestId: 'request-uuid', + workflowId: 'workflow-1', + executionId: 'execution-1', + }) + expect(mockGenerateId).toHaveBeenCalledTimes(2) + }) + it('propagates local aborts to the mothership request', async () => { const abortController = new AbortController() context.abortSignal = abortController.signal diff --git a/apps/sim/executor/handlers/mothership/mothership-handler.ts b/apps/sim/executor/handlers/mothership/mothership-handler.ts index 433bcc273e2..3c48d746909 100644 --- a/apps/sim/executor/handlers/mothership/mothership-handler.ts +++ b/apps/sim/executor/handlers/mothership/mothership-handler.ts @@ -33,7 +33,9 @@ export class MothershipBlockHandler implements BlockHandler { throw new Error('Prompt input is required') } const messages = [{ role: 'user' as const, content: prompt }] - const chatId = generateId() + const providedConversationId = + typeof inputs.conversationId === 'string' ? inputs.conversationId.trim() : '' + const chatId = providedConversationId || generateId() const messageId = generateId() const requestId = generateId() @@ -57,6 +59,7 @@ export class MothershipBlockHandler implements BlockHandler { requestId, workflowId: ctx.workflowId, executionId: ctx.executionId, + chatId, }) const abortController = new AbortController() @@ -135,6 +138,7 @@ export class MothershipBlockHandler implements BlockHandler { return { content: result.content || '', model: result.model || 'mothership', + conversationId: result.conversationId || chatId, tokens: result.tokens || {}, toolCalls, cost: result.cost || undefined, diff --git a/apps/sim/lib/api/contracts/mothership-tasks.ts b/apps/sim/lib/api/contracts/mothership-tasks.ts index 5ecbb278ba7..5be16920551 100644 --- a/apps/sim/lib/api/contracts/mothership-tasks.ts +++ b/apps/sim/lib/api/contracts/mothership-tasks.ts @@ -256,6 +256,7 @@ export const mothershipExecuteResponseSchema = z .object({ content: z.string().optional(), model: z.literal('mothership'), + conversationId: z.string(), tokens: z .object({ prompt: z.number().optional(),