From 78b7643e65143cbd592677b29266f44ae7402aad Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Thu, 18 Dec 2025 11:02:01 -0800 Subject: [PATCH] fix(condition): async execution isolated vm error (#2446) * fix(condition): async execution isolated vm error * fix tests --- .../condition/condition-handler.test.ts | 37 ++++++++++-------- .../handlers/condition/condition-handler.ts | 39 +++++++++++-------- 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/apps/sim/executor/handlers/condition/condition-handler.test.ts b/apps/sim/executor/handlers/condition/condition-handler.test.ts index b4c3eac00..7dd6e5cee 100644 --- a/apps/sim/executor/handlers/condition/condition-handler.test.ts +++ b/apps/sim/executor/handlers/condition/condition-handler.test.ts @@ -17,27 +17,32 @@ vi.mock('@/lib/core/utils/request', () => ({ generateRequestId: vi.fn(() => 'test-request-id'), })) -vi.mock('@/lib/execution/isolated-vm', () => ({ - executeInIsolatedVM: vi.fn(), +vi.mock('@/tools', () => ({ + executeTool: vi.fn(), })) -import { executeInIsolatedVM } from '@/lib/execution/isolated-vm' +import { executeTool } from '@/tools' -const mockExecuteInIsolatedVM = executeInIsolatedVM as ReturnType +const mockExecuteTool = executeTool as ReturnType -function simulateIsolatedVMExecution( - code: string, - contextVariables: Record -): { result: unknown; stdout: string; error?: { message: string; name: string } } { +/** + * Simulates what the function_execute tool does when evaluating condition code + */ +function simulateConditionExecution(code: string): { + success: boolean + output?: { result: unknown } + error?: string +} { try { - const fn = new Function(...Object.keys(contextVariables), code) - const result = fn(...Object.values(contextVariables)) - return { result, stdout: '' } + // The code is in format: "const context = {...};\nreturn Boolean(...)" + // We need to execute it and return the result + const fn = new Function(code) + const result = fn() + return { success: true, output: { result } } } catch (error: any) { return { - result: null, - stdout: '', - error: { message: error.message, name: error.name || 'Error' }, + success: false, + error: error.message, } } } @@ -143,8 +148,8 @@ describe('ConditionBlockHandler', () => { vi.clearAllMocks() - mockExecuteInIsolatedVM.mockImplementation(async ({ code, contextVariables }) => { - return simulateIsolatedVMExecution(code, contextVariables) + mockExecuteTool.mockImplementation(async (_toolId: string, params: { code: string }) => { + return simulateConditionExecution(params.code) }) }) diff --git a/apps/sim/executor/handlers/condition/condition-handler.ts b/apps/sim/executor/handlers/condition/condition-handler.ts index bd69c77f4..07b0c3336 100644 --- a/apps/sim/executor/handlers/condition/condition-handler.ts +++ b/apps/sim/executor/handlers/condition/condition-handler.ts @@ -1,10 +1,9 @@ -import { generateRequestId } from '@/lib/core/utils/request' -import { executeInIsolatedVM } from '@/lib/execution/isolated-vm' import { createLogger } from '@/lib/logs/console/logger' import type { BlockOutput } from '@/blocks/types' import { BlockType, CONDITION, DEFAULTS, EDGE } from '@/executor/constants' import type { BlockHandler, ExecutionContext } from '@/executor/types' import type { SerializedBlock } from '@/serializer/types' +import { executeTool } from '@/tools' const logger = createLogger('ConditionBlockHandler') @@ -39,32 +38,38 @@ export async function evaluateConditionExpression( } try { - const requestId = generateRequestId() + const contextSetup = `const context = ${JSON.stringify(evalContext)};` + const code = `${contextSetup}\nreturn Boolean(${resolvedConditionValue})` - const code = `return Boolean(${resolvedConditionValue})` + const result = await executeTool( + 'function_execute', + { + code, + timeout: CONDITION_TIMEOUT_MS, + envVars: {}, + _context: { + workflowId: ctx.workflowId, + workspaceId: ctx.workspaceId, + }, + }, + false, + false, + ctx + ) - const result = await executeInIsolatedVM({ - code, - params: {}, - envVars: {}, - contextVariables: { context: evalContext }, - timeoutMs: CONDITION_TIMEOUT_MS, - requestId, - }) - - if (result.error) { - logger.error(`Failed to evaluate condition: ${result.error.message}`, { + if (!result.success) { + logger.error(`Failed to evaluate condition: ${result.error}`, { originalCondition: conditionExpression, resolvedCondition: resolvedConditionValue, evalContext, error: result.error, }) throw new Error( - `Evaluation error in condition: ${result.error.message}. (Resolved: ${resolvedConditionValue})` + `Evaluation error in condition: ${result.error}. (Resolved: ${resolvedConditionValue})` ) } - return Boolean(result.result) + return Boolean(result.output?.result) } catch (evalError: any) { logger.error(`Failed to evaluate condition: ${evalError.message}`, { originalCondition: conditionExpression,