@@ -25,6 +25,7 @@ import {
25
25
type WorkflowNode ,
26
26
type WorkflowNodes ,
27
27
} from '../../webviews/workflow/components/nodes/Nodes'
28
+ import type { VariableNode } from '../../webviews/workflow/components/nodes/Variable_Node'
28
29
import type { ExtensionToWorkflow } from '../../webviews/workflow/services/WorkflowProtocol'
29
30
import { ChatController , type ChatSession } from '../chat/chat-view/ChatController'
30
31
import { type ContextRetriever , toStructuredMentions } from '../chat/chat-view/ContextRetriever'
@@ -59,6 +60,8 @@ export interface IndexedExecutionContext {
59
60
exitCode : string
60
61
}
61
62
>
63
+ variableValues ?: Map < string , string >
64
+ ifelseSkipPaths ?: Map < string , Set < string > >
62
65
}
63
66
64
67
/**
@@ -91,10 +94,10 @@ export async function executeWorkflow(
91
94
loopStates : new Map ( ) ,
92
95
accumulatorValues : new Map ( ) ,
93
96
cliMetadata : new Map ( ) ,
97
+ variableValues : new Map ( ) ,
98
+ ifelseSkipPaths : new Map ( ) ,
94
99
}
95
100
96
- const skipNodes = new Set < string > ( )
97
-
98
101
// Calculate all inactive nodes
99
102
const allInactiveNodes = new Set < string > ( )
100
103
for ( const node of nodes ) {
@@ -113,7 +116,11 @@ export async function executeWorkflow(
113
116
} as ExtensionToWorkflow )
114
117
115
118
for ( const node of sortedNodes ) {
116
- if ( skipNodes . has ( node . id ) ) {
119
+ const shouldSkip = Array . from ( context . ifelseSkipPaths ?. values ( ) ?? [ ] ) . some ( skipNodes =>
120
+ skipNodes . has ( node . id )
121
+ )
122
+
123
+ if ( shouldSkip ) {
117
124
continue
118
125
}
119
126
@@ -293,7 +300,22 @@ export async function executeWorkflow(
293
300
}
294
301
295
302
case NodeType . IF_ELSE : {
296
- result = await executeIfElseNode ( context , node , skipNodes )
303
+ result = await executeIfElseNode ( context , node )
304
+ break
305
+ }
306
+ case NodeType . VARIABLE : {
307
+ const inputs = combineParentOutputsByConnectionOrder ( node . id , context )
308
+ const inputValue = node . data . content
309
+ ? replaceIndexedInputs ( node . data . content , inputs , context )
310
+ : ''
311
+ const {
312
+ data : { variableName, initialValue } ,
313
+ } = node as VariableNode
314
+ let variableValue = context . variableValues ?. get ( variableName ) || initialValue || ''
315
+ variableValue = inputValue
316
+ context . variableValues ?. set ( variableName , variableValue )
317
+
318
+ result = variableValue
297
319
break
298
320
}
299
321
@@ -414,6 +436,15 @@ export function replaceIndexedInputs(
414
436
context . accumulatorValues ?. get ( varName ) || ''
415
437
)
416
438
}
439
+
440
+ // Only replace variable variables that are explicitly defined
441
+ const variableVars = context . variableValues ? Array . from ( context . variableValues . keys ( ) ) : [ ]
442
+ for ( const varName of variableVars ) {
443
+ result = result . replace (
444
+ new RegExp ( `\\$\{${ varName } }(?!\\w)` , 'g' ) ,
445
+ context . variableValues ?. get ( varName ) || ''
446
+ )
447
+ }
417
448
}
418
449
419
450
return result
@@ -758,8 +789,7 @@ async function executeCodyOutputNode(
758
789
759
790
async function executeIfElseNode (
760
791
context : IndexedExecutionContext ,
761
- node : WorkflowNode | IfElseNode ,
762
- skipNodes : Set < string >
792
+ node : WorkflowNode | IfElseNode
763
793
) : Promise < string > {
764
794
let result = ''
765
795
const parentEdges = context . edgeIndex . byTarget . get ( node . id ) || [ ]
@@ -793,10 +823,23 @@ async function executeIfElseNode(
793
823
}
794
824
795
825
// Get paths and mark nodes to skip
826
+ context . ifelseSkipPaths ?. set ( node . id , new Set < string > ( ) )
796
827
const edges = context . edgeIndex . bySource . get ( node . id ) || [ ]
797
828
const nonTakenPath = edges . find ( edge => edge . sourceHandle === ( hasResult ? 'false' : 'true' ) )
798
829
if ( nonTakenPath ) {
799
- const nodesToSkip = getInactiveNodes ( edges , nonTakenPath . target )
830
+ // Initialize ifelseSkipPaths if it's undefined
831
+ if ( ! context . ifelseSkipPaths ) {
832
+ context . ifelseSkipPaths = new Map < string , Set < string > > ( )
833
+ }
834
+
835
+ // Get or create the set of nodes to skip for this IfElse node
836
+ let skipNodes = context . ifelseSkipPaths ?. get ( node . id )
837
+
838
+ skipNodes = new Set < string > ( )
839
+ context . ifelseSkipPaths ?. set ( node . id , skipNodes )
840
+
841
+ const allEdges = Array . from ( context . edgeIndex . byId . values ( ) )
842
+ const nodesToSkip = getInactiveNodes ( allEdges , nonTakenPath . target )
800
843
for ( const nodeId of nodesToSkip ) {
801
844
skipNodes . add ( nodeId )
802
845
}
0 commit comments