From 38572bb6ab5f4629636950cee15db17d392c6354 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Sun, 27 Sep 2026 17:37:58 -0700 Subject: [PATCH] fix(function): omit oversized display code instead of failing the execution --- apps/sim/tools/function/execute.test.ts | 19 +++++++++++++++++++ apps/sim/tools/function/execute.ts | 14 ++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/apps/sim/tools/function/execute.test.ts b/apps/sim/tools/function/execute.test.ts index 11864cb70b4..9136278f7de 100644 --- a/apps/sim/tools/function/execute.test.ts +++ b/apps/sim/tools/function/execute.test.ts @@ -5,6 +5,7 @@ import { MOUNTED_WORKSPACE_FILES_PROVENANCE_KEY, PRIVATE_SECRET_PROVENANCE_FIELD, } from '@/lib/execution/private-tool-metadata' +import { MAX_FUNCTION_CODE_LENGTH } from '@/lib/function-execution/limits' import { buildFunctionExecuteBody, functionExecuteTool } from '@/tools/function/execute' import { createLLMToolSchema, createUserToolSchema } from '@/tools/params' @@ -59,6 +60,24 @@ describe('Function Execute Tool', () => { expect(body.timeout).toBe(DEFAULT_EXECUTION_TIMEOUT_MS) }) + it('sends display code the route accepts when inlined references outgrow the source cap', () => { + const inlinedValue = 'x'.repeat(MAX_FUNCTION_CODE_LENGTH) + const body = buildFunctionExecuteBody({ + code: 'return __blockRef_0.length', + sourceCode: `return "${inlinedValue}".length`, + contextVariables: { __blockRef_0: inlinedValue }, + }) + + expect(functionExecuteBodySchema.safeParse(body).success).toBe(true) + expect(body.sourceCode).toBeUndefined() + + const withinCap = buildFunctionExecuteBody({ + code: 'return __blockRef_0', + sourceCode: 'return ', + }) + expect(withinCap.sourceCode).toBe('return ') + }) + it('preserves reference context and large-value authorization', () => { const body = buildFunctionExecuteBody({ code: 'return contextVariables.previous.result', diff --git a/apps/sim/tools/function/execute.ts b/apps/sim/tools/function/execute.ts index ee68623ca01..9d16ffcc854 100644 --- a/apps/sim/tools/function/execute.ts +++ b/apps/sim/tools/function/execute.ts @@ -10,6 +10,7 @@ import { DEFAULT_EXECUTION_TIMEOUT_MS } from '@/lib/execution/constants' import { DEFAULT_CODE_LANGUAGE } from '@/lib/execution/languages' import { PRIVATE_SECRET_PROVENANCE_FIELD } from '@/lib/execution/private-tool-metadata' import { SANDBOX_INPUT_DIR, SANDBOX_OUTPUT_DIR } from '@/lib/execution/remote-sandbox/sandbox-paths' +import { MAX_FUNCTION_CODE_LENGTH } from '@/lib/function-execution/limits' import type { UserFile } from '@/executor/types' import type { CodeExecutionInput, CodeExecutionOutput } from '@/tools/function/types' import type { InternalToolConfig } from '@/tools/types' @@ -43,7 +44,13 @@ function normalizeSandboxInputFiles(value: unknown): FunctionExecuteBody['files' return userFiles.map((file) => ({ ...file })) } -/** Builds the canonical Function protocol body for both HTTP compatibility and in-process calls. */ +/** + * Builds the canonical Function protocol body for both HTTP compatibility and in-process calls. + * + * `sourceCode` is the display copy used only to render errors, with referenced values inlined, + * so it can far outgrow the executed code. Past the route's source cap it is omitted, and errors + * fall back to the executed code, rather than failing a request whose executed code is in bounds. + */ export function buildFunctionExecuteBody(params: CodeExecutionInput): FunctionExecuteBody { const codeContent = Array.isArray(params.code) ? params.code.map((entry: { content: string }) => entry.content).join('\n') @@ -51,7 +58,10 @@ export function buildFunctionExecuteBody(params: CodeExecutionInput): FunctionEx return { code: codeContent, - sourceCode: params.sourceCode, + sourceCode: + params.sourceCode !== undefined && params.sourceCode.length <= MAX_FUNCTION_CODE_LENGTH + ? params.sourceCode + : undefined, language: params.language || DEFAULT_CODE_LANGUAGE, timeout: params.timeout || DEFAULT_EXECUTION_TIMEOUT_MS, title: params.title,