From 2d3d82090708abd03c52566ce3e7fb710dddca43 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Mon, 31 Aug 2026 13:21:26 -0700 Subject: [PATCH] fix(copilot): reject live table workflow requests --- .../tools/server/table/user-table.test.ts | 39 +++++++++++++------ .../copilot/tools/server/table/user-table.ts | 14 +++++++ 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/apps/sim/lib/copilot/tools/server/table/user-table.test.ts b/apps/sim/lib/copilot/tools/server/table/user-table.test.ts index 1e96164e1b5..99552ae6fa2 100644 --- a/apps/sim/lib/copilot/tools/server/table/user-table.test.ts +++ b/apps/sim/lib/copilot/tools/server/table/user-table.test.ts @@ -960,23 +960,40 @@ describe('userTableServerTool workflow scope', () => { expect(mockAddWorkflowGroup).not.toHaveBeenCalled() }) - it('does not pass a legacy deployment mode into workflow group creation', async () => { + it.each([ + { + operation: 'add_workflow_group', + args: { + tableId: 'tbl_1', + workflowId: 'workflow-1', + outputs: [{ blockId: 'block-1', path: 'content' }], + deploymentMode: 'live', + }, + }, + { + operation: 'update_workflow_group', + args: { + tableId: 'tbl_1', + groupId: 'group-1', + deploymentMode: 'live', + }, + }, + ])('rejects a legacy live deployment mode for $operation', async ({ operation, args }) => { const result = await userTableServerTool.execute( { - operation: 'add_workflow_group', - args: { - tableId: 'tbl_1', - workflowId: 'workflow-1', - outputs: [{ blockId: 'block-1', path: 'content' }], - deploymentMode: 'live', - }, + operation, + args, }, buildToolContext() ) - expect(result.success).toBe(true) - expect(mockAddWorkflowGroup).toHaveBeenCalledTimes(1) - expect(mockAddWorkflowGroup.mock.calls[0][0].group).not.toHaveProperty('deploymentMode') + expect(result).toEqual({ + success: false, + message: + 'deploymentMode "live" is not supported; table workflow groups only run the latest active deployment. Deploy the workflow, then retry without deploymentMode.', + }) + expect(mockResolveWorkflowContext).not.toHaveBeenCalled() + expect(mockAddWorkflowGroup).not.toHaveBeenCalled() }) it('conceals unknown application failures from tool output', async () => { diff --git a/apps/sim/lib/copilot/tools/server/table/user-table.ts b/apps/sim/lib/copilot/tools/server/table/user-table.ts index d48ac344d42..1abc8dadf0a 100644 --- a/apps/sim/lib/copilot/tools/server/table/user-table.ts +++ b/apps/sim/lib/copilot/tools/server/table/user-table.ts @@ -202,6 +202,20 @@ export const userTableServerTool: BaseServerTool const workspaceId = context.workspaceId const assertNotAborted = () => assertServerToolNotAborted(context, 'Request aborted before table mutation could be applied.') + + // A stale Mothership may still send the removed selector. Never report success + // after silently changing its requested semantics from draft to deployed. + if ( + (operation === 'add_workflow_group' || operation === 'update_workflow_group') && + args.deploymentMode === 'live' + ) { + return { + success: false, + message: + 'deploymentMode "live" is not supported; table workflow groups only run the latest active deployment. Deploy the workflow, then retry without deploymentMode.', + } + } + try { switch (operation) { case 'create': {