mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
fix(func var resolution): variable ref codepath triggered
This commit is contained in:
@@ -19,7 +19,9 @@ const logger = createLogger('FunctionExecuteAPI')
|
||||
function resolveCodeVariables(
|
||||
code: string,
|
||||
params: Record<string, any>,
|
||||
envVars: Record<string, string> = {}
|
||||
envVars: Record<string, string> = {},
|
||||
blockData: Record<string, any> = {},
|
||||
blockNameMapping: Record<string, string> = {}
|
||||
): { resolvedCode: string; contextVariables: Record<string, any> } {
|
||||
let resolvedCode = code
|
||||
const contextVariables: Record<string, any> = {}
|
||||
@@ -41,11 +43,54 @@ function resolveCodeVariables(
|
||||
|
||||
// Resolve tags with <tag_name> syntax (including nested paths like <block.response.data>)
|
||||
const tagMatches = resolvedCode.match(/<([a-zA-Z_][a-zA-Z0-9_.]*[a-zA-Z0-9_])>/g) || []
|
||||
|
||||
|
||||
for (const match of tagMatches) {
|
||||
const tagName = match.slice(1, -1).trim()
|
||||
|
||||
// Handle nested paths like "getrecord.response.data"
|
||||
const tagValue = getNestedValue(params, tagName) || ''
|
||||
|
||||
// Handle nested paths like "getrecord.response.data" or "function1.response.result"
|
||||
// First try params, then blockData directly, then try with block name mapping
|
||||
let tagValue = getNestedValue(params, tagName) || getNestedValue(blockData, tagName) || ''
|
||||
|
||||
// If not found and the path starts with a block name, try mapping the block name to ID
|
||||
if (!tagValue && tagName.includes('.')) {
|
||||
const pathParts = tagName.split('.')
|
||||
const normalizedBlockName = pathParts[0] // This should already be normalized like "function1"
|
||||
|
||||
// Find the block ID by looking for a block name that normalizes to this value
|
||||
let blockId = null
|
||||
let matchedBlockName = null
|
||||
|
||||
for (const [blockName, id] of Object.entries(blockNameMapping)) {
|
||||
// Apply the same normalization logic as the UI: remove spaces and lowercase
|
||||
const normalizedName = blockName.replace(/\s+/g, '').toLowerCase()
|
||||
if (normalizedName === normalizedBlockName) {
|
||||
blockId = id
|
||||
matchedBlockName = blockName
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (blockId) {
|
||||
const remainingPath = pathParts.slice(1).join('.')
|
||||
const fullPath = `${blockId}.${remainingPath}`
|
||||
tagValue = getNestedValue(blockData, fullPath) || ''
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// If the value is a stringified JSON, parse it back to object
|
||||
if (typeof tagValue === 'string' && tagValue.length > 100 &&
|
||||
(tagValue.startsWith('{') || tagValue.startsWith('['))) {
|
||||
try {
|
||||
tagValue = JSON.parse(tagValue)
|
||||
} catch (e) {
|
||||
// Keep as string if parsing fails
|
||||
}
|
||||
}
|
||||
|
||||
// Instead of injecting large JSON directly, create a variable reference
|
||||
const safeVarName = `__tag_${tagName.replace(/[^a-zA-Z0-9_]/g, '_')}`
|
||||
@@ -89,6 +134,8 @@ export async function POST(req: NextRequest) {
|
||||
params = {},
|
||||
timeout = 5000,
|
||||
envVars = {},
|
||||
blockData = {},
|
||||
blockNameMapping = {},
|
||||
workflowId,
|
||||
isCustomTool = false,
|
||||
} = body
|
||||
@@ -106,7 +153,14 @@ export async function POST(req: NextRequest) {
|
||||
})
|
||||
|
||||
// Resolve variables in the code with workflow environment variables
|
||||
const { resolvedCode, contextVariables } = resolveCodeVariables(code, executionParams, envVars)
|
||||
logger.info(`[${requestId}] Original code:`, code.substring(0, 200))
|
||||
logger.info(`[${requestId}] Execution params keys:`, Object.keys(executionParams))
|
||||
|
||||
|
||||
const { resolvedCode, contextVariables } = resolveCodeVariables(code, executionParams, envVars, blockData, blockNameMapping)
|
||||
|
||||
logger.info(`[${requestId}] Resolved code:`, resolvedCode.substring(0, 200))
|
||||
logger.info(`[${requestId}] Context variables keys:`, Object.keys(contextVariables))
|
||||
|
||||
const executionMethod = 'vm' // Default execution method
|
||||
|
||||
|
||||
@@ -23,12 +23,29 @@ export class FunctionBlockHandler implements BlockHandler {
|
||||
? inputs.code.map((c: { content: string }) => c.content).join('\n')
|
||||
: inputs.code
|
||||
|
||||
// Extract block data for variable resolution
|
||||
const blockData: Record<string, any> = {}
|
||||
const blockNameMapping: Record<string, string> = {}
|
||||
|
||||
for (const [blockId, blockState] of context.blockStates.entries()) {
|
||||
if (blockState.output) {
|
||||
blockData[blockId] = blockState.output
|
||||
|
||||
// Try to find the block name from the workflow
|
||||
const workflowBlock = context.workflow?.blocks?.find(b => b.id === blockId)
|
||||
if (workflowBlock?.metadata?.name) {
|
||||
blockNameMapping[workflowBlock.metadata.name] = blockId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Directly use the function_execute tool which calls the API route
|
||||
logger.info(`Executing function block via API route: ${block.id}`)
|
||||
const result = await executeTool('function_execute', {
|
||||
code: codeContent,
|
||||
timeout: inputs.timeout || 5000,
|
||||
envVars: context.environmentVariables || {},
|
||||
blockData: blockData, // Pass block data for variable resolution
|
||||
blockNameMapping: blockNameMapping, // Pass block name to ID mapping
|
||||
_context: { workflowId: context.workflowId },
|
||||
})
|
||||
|
||||
|
||||
@@ -593,6 +593,7 @@ export class InputResolver {
|
||||
isInTemplateLiteral
|
||||
)
|
||||
} else {
|
||||
// The function execution API will handle variable resolution within code strings
|
||||
formattedValue =
|
||||
typeof replacementValue === 'object'
|
||||
? JSON.stringify(replacementValue)
|
||||
|
||||
@@ -45,6 +45,8 @@ export const functionExecuteTool: ToolConfig<CodeExecutionInput, CodeExecutionOu
|
||||
code: codeContent,
|
||||
timeout: params.timeout || DEFAULT_TIMEOUT,
|
||||
envVars: params.envVars || {},
|
||||
blockData: params.blockData || {},
|
||||
blockNameMapping: params.blockNameMapping || {},
|
||||
workflowId: params._context?.workflowId,
|
||||
isCustomTool: params.isCustomTool || false,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user