Skip to content

Commit 354a7a6

Browse files
Fix: Apply default values before condition evaluation
Co-authored-by: emir <emir@simstudio.ai>
1 parent 4d1a9a3 commit 354a7a6

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

apps/sim/serializer/index.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,46 @@ describe('Serializer', () => {
991991
expect(slackBlock?.config.params.unknownField).toBeUndefined()
992992
})
993993

994+
it.concurrent(
995+
'should include conditional fields when condition field has default value but null stored value',
996+
() => {
997+
const serializer = new Serializer()
998+
999+
// This simulates the cursor block scenario where:
1000+
// - operation has a default value function: () => 'cursor_launch_agent'
1001+
// - branchName has condition: { field: 'operation', value: 'cursor_launch_agent' }
1002+
// - But operation's stored value is null (user never changed the dropdown)
1003+
// We'll use slack block which has similar conditional field behavior
1004+
const slackBlockWithNullChannel: any = {
1005+
id: 'slack-1',
1006+
type: 'slack',
1007+
name: 'Slack',
1008+
position: { x: 0, y: 0 },
1009+
advancedMode: false,
1010+
subBlocks: {
1011+
channel: { value: 'general' }, // This simulates the 'operation' dropdown
1012+
text: { value: 'Hello world' }, // This has a condition on channel
1013+
// manualChannel would be null as it's in advanced mode
1014+
},
1015+
outputs: {},
1016+
enabled: true,
1017+
}
1018+
1019+
const serialized = serializer.serializeWorkflow(
1020+
{ 'slack-1': slackBlockWithNullChannel },
1021+
[],
1022+
{}
1023+
)
1024+
1025+
const slackBlock = serialized.blocks.find((b) => b.id === 'slack-1')
1026+
expect(slackBlock).toBeDefined()
1027+
1028+
// Both fields should be included since channel (the condition field) has a value
1029+
expect(slackBlock?.config.params.channel).toBe('general')
1030+
expect(slackBlock?.config.params.text).toBe('Hello world')
1031+
}
1032+
)
1033+
9941034
it.concurrent(
9951035
'should preserve legacy agent fields (systemPrompt, userPrompt, memories) for backward compatibility',
9961036
() => {

apps/sim/serializer/index.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,24 @@ export class Serializer {
400400
allValues[id] = subBlock.value
401401
})
402402

403+
// Apply default values to allValues before condition evaluation
404+
// This ensures that fields with default value functions (like dropdowns)
405+
// have their defaults applied when evaluating conditions for other fields
406+
blockConfig.subBlocks.forEach((subBlockConfig) => {
407+
const id = subBlockConfig.id
408+
if (
409+
(allValues[id] === null || allValues[id] === undefined) &&
410+
subBlockConfig.value &&
411+
shouldIncludeField(subBlockConfig, isAdvancedMode)
412+
) {
413+
try {
414+
allValues[id] = subBlockConfig.value(allValues)
415+
} catch {
416+
// If the default value function fails, keep the original value
417+
}
418+
}
419+
})
420+
403421
// Second pass: filter by mode and conditions
404422
Object.entries(block.subBlocks).forEach(([id, subBlock]) => {
405423
const matchingConfigs = blockConfig.subBlocks.filter((config) => config.id === id)

0 commit comments

Comments
 (0)