mirror of
https://github.com/simstudioai/sim.git
synced 2026-02-17 01:42:43 -05:00
fix(variables): Fix resolution on double < (#2016)
* Fix variable <> * Ling * Clean
This commit is contained in:
committed by
GitHub
parent
fca92a7499
commit
949f9287cf
@@ -5,6 +5,7 @@ import type { LoopScope } from '@/executor/execution/state'
|
||||
import type { BlockStateController } from '@/executor/execution/types'
|
||||
import type { ExecutionContext, NormalizedBlockOutput } from '@/executor/types'
|
||||
import type { LoopConfigWithNodes } from '@/executor/types/loop'
|
||||
import { replaceValidReferences } from '@/executor/utils/reference-validation'
|
||||
import {
|
||||
buildSentinelEndId,
|
||||
buildSentinelStartId,
|
||||
@@ -271,16 +272,14 @@ export class LoopOrchestrator {
|
||||
}
|
||||
|
||||
try {
|
||||
const referencePattern = /<([^>]+)>/g
|
||||
let evaluatedCondition = condition
|
||||
|
||||
logger.info('Evaluating loop condition', {
|
||||
originalCondition: condition,
|
||||
iteration: scope.iteration,
|
||||
workflowVariables: ctx.workflowVariables,
|
||||
})
|
||||
|
||||
evaluatedCondition = evaluatedCondition.replace(referencePattern, (match) => {
|
||||
// Use generic utility for smart variable reference replacement
|
||||
const evaluatedCondition = replaceValidReferences(condition, (match) => {
|
||||
const resolved = this.resolver.resolveSingleReference(ctx, '', match, scope)
|
||||
logger.info('Resolved variable reference in loop condition', {
|
||||
reference: match,
|
||||
|
||||
49
apps/sim/executor/utils/reference-validation.ts
Normal file
49
apps/sim/executor/utils/reference-validation.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { isLikelyReferenceSegment } from '@/lib/workflows/references'
|
||||
import { REFERENCE } from '@/executor/consts'
|
||||
|
||||
/**
|
||||
* Creates a regex pattern for matching variable references.
|
||||
* Uses [^<>]+ to prevent matching across nested brackets (e.g., "<3 <real.ref>" matches separately).
|
||||
*/
|
||||
export function createReferencePattern(): RegExp {
|
||||
return new RegExp(
|
||||
`${REFERENCE.START}([^${REFERENCE.START}${REFERENCE.END}]+)${REFERENCE.END}`,
|
||||
'g'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a regex pattern for matching environment variables {{variable}}
|
||||
*/
|
||||
export function createEnvVarPattern(): RegExp {
|
||||
return new RegExp(`\\${REFERENCE.ENV_VAR_START}([^}]+)\\${REFERENCE.ENV_VAR_END}`, 'g')
|
||||
}
|
||||
|
||||
/**
|
||||
* Combined pattern matching both <reference> and {{env_var}}
|
||||
*/
|
||||
export function createCombinedPattern(): RegExp {
|
||||
return new RegExp(
|
||||
`${REFERENCE.START}[^${REFERENCE.START}${REFERENCE.END}]+${REFERENCE.END}|` +
|
||||
`\\${REFERENCE.ENV_VAR_START}[^}]+\\${REFERENCE.ENV_VAR_END}`,
|
||||
'g'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces variable references with smart validation.
|
||||
* Distinguishes < operator from < bracket using isLikelyReferenceSegment.
|
||||
*/
|
||||
export function replaceValidReferences(
|
||||
template: string,
|
||||
replacer: (match: string) => string
|
||||
): string {
|
||||
const pattern = createReferencePattern()
|
||||
|
||||
return template.replace(pattern, (match) => {
|
||||
if (!isLikelyReferenceSegment(match)) {
|
||||
return match
|
||||
}
|
||||
return replacer(match)
|
||||
})
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { BlockType, REFERENCE } from '@/executor/consts'
|
||||
import type { ExecutionState, LoopScope } from '@/executor/execution/state'
|
||||
import type { ExecutionContext } from '@/executor/types'
|
||||
import { replaceValidReferences } from '@/executor/utils/reference-validation'
|
||||
import { BlockResolver } from '@/executor/variables/resolvers/block'
|
||||
import { EnvResolver } from '@/executor/variables/resolvers/env'
|
||||
import { LoopResolver } from '@/executor/variables/resolvers/loop'
|
||||
@@ -147,21 +148,17 @@ export class VariableResolver {
|
||||
loopScope?: LoopScope,
|
||||
block?: SerializedBlock
|
||||
): string {
|
||||
let result = template
|
||||
const resolutionContext: ResolutionContext = {
|
||||
executionContext: ctx,
|
||||
executionState: this.state,
|
||||
currentNodeId,
|
||||
loopScope,
|
||||
}
|
||||
const referenceRegex = new RegExp(
|
||||
`${REFERENCE.START}([^${REFERENCE.END}]+)${REFERENCE.END}`,
|
||||
'g'
|
||||
)
|
||||
|
||||
let replacementError: Error | null = null
|
||||
|
||||
result = result.replace(referenceRegex, (match) => {
|
||||
// Use generic utility for smart variable reference replacement
|
||||
let result = replaceValidReferences(template, (match) => {
|
||||
if (replacementError) return match
|
||||
|
||||
try {
|
||||
@@ -202,21 +199,17 @@ export class VariableResolver {
|
||||
template: string,
|
||||
loopScope?: LoopScope
|
||||
): string {
|
||||
let result = template
|
||||
const resolutionContext: ResolutionContext = {
|
||||
executionContext: ctx,
|
||||
executionState: this.state,
|
||||
currentNodeId,
|
||||
loopScope,
|
||||
}
|
||||
const referenceRegex = new RegExp(
|
||||
`${REFERENCE.START}([^${REFERENCE.END}]+)${REFERENCE.END}`,
|
||||
'g'
|
||||
)
|
||||
|
||||
let replacementError: Error | null = null
|
||||
|
||||
result = result.replace(referenceRegex, (match) => {
|
||||
// Use generic utility for smart variable reference replacement
|
||||
let result = replaceValidReferences(template, (match) => {
|
||||
if (replacementError) return match
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user