Skip to content

Commit 58d0fda

Browse files
fix(serializer): default canonical modes construction (#3330)
* fix(serializer): default canonical modes construction * defaults for copilot * address bugbot comments
1 parent ecdb133 commit 58d0fda

File tree

5 files changed

+71
-29
lines changed

5 files changed

+71
-29
lines changed

apps/sim/lib/copilot/tools/server/workflow/edit-workflow/builders.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import crypto from 'crypto'
22
import { createLogger } from '@sim/logger'
33
import type { PermissionGroupConfig } from '@/lib/permission-groups/types'
44
import { getEffectiveBlockOutputs } from '@/lib/workflows/blocks/block-outputs'
5-
import { buildCanonicalIndex, isCanonicalPair } from '@/lib/workflows/subblocks/visibility'
5+
import {
6+
buildCanonicalIndex,
7+
buildDefaultCanonicalModes,
8+
isCanonicalPair,
9+
} from '@/lib/workflows/subblocks/visibility'
610
import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils'
711
import { getAllBlocks } from '@/blocks/registry'
812
import type { BlockConfig } from '@/blocks/types'
@@ -130,6 +134,12 @@ export function createBlockFromParams(
130134
}
131135
})
132136

137+
const defaultModes = buildDefaultCanonicalModes(blockConfig.subBlocks)
138+
if (Object.keys(defaultModes).length > 0) {
139+
if (!blockState.data) blockState.data = {}
140+
blockState.data.canonicalModes = defaultModes
141+
}
142+
133143
if (validatedInputs) {
134144
updateCanonicalModesForInputs(blockState, Object.keys(validatedInputs), blockConfig)
135145
}

apps/sim/lib/workflows/subblocks/visibility.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,23 @@ export function isCanonicalPair(group?: CanonicalGroup): boolean {
7575
return Boolean(group?.basicId && group?.advancedIds?.length)
7676
}
7777

78+
/**
79+
* Builds default canonical mode overrides for a block's subblocks.
80+
* All canonical pairs default to `'basic'`.
81+
*/
82+
export function buildDefaultCanonicalModes(
83+
subBlocks: SubBlockConfig[]
84+
): Record<string, 'basic' | 'advanced'> {
85+
const index = buildCanonicalIndex(subBlocks)
86+
const modes: Record<string, 'basic' | 'advanced'> = {}
87+
for (const group of Object.values(index.groupsById)) {
88+
if (isCanonicalPair(group)) {
89+
modes[group.canonicalId] = 'basic'
90+
}
91+
}
92+
return modes
93+
}
94+
7895
/**
7996
* Determine the active mode for a canonical group.
8097
*/

apps/sim/serializer/index.test.ts

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -683,34 +683,37 @@ describe('Serializer', () => {
683683
expect(slackBlock?.config.params.username).toBe('bot')
684684
})
685685

686-
it.concurrent('should fall back to legacy advancedMode when canonicalModes not set', () => {
687-
const serializer = new Serializer()
686+
it.concurrent(
687+
'should fall back to legacy advancedMode for non-credential canonical groups when canonicalModes not set',
688+
() => {
689+
const serializer = new Serializer()
688690

689-
const block: any = {
690-
id: 'slack-1',
691-
type: 'slack',
692-
name: 'Test Slack Block',
693-
position: { x: 0, y: 0 },
694-
advancedMode: true,
695-
subBlocks: {
696-
operation: { value: 'send' },
697-
destinationType: { value: 'channel' },
698-
channel: { value: 'general' },
699-
manualChannel: { value: 'C1234567890' },
700-
text: { value: 'Hello world' },
701-
username: { value: 'bot' },
702-
},
703-
outputs: {},
704-
enabled: true,
705-
}
691+
const block: any = {
692+
id: 'slack-1',
693+
type: 'slack',
694+
name: 'Test Slack Block',
695+
position: { x: 0, y: 0 },
696+
advancedMode: true,
697+
subBlocks: {
698+
operation: { value: 'send' },
699+
destinationType: { value: 'channel' },
700+
channel: { value: 'general' },
701+
manualChannel: { value: 'C1234567890' },
702+
text: { value: 'Hello world' },
703+
username: { value: 'bot' },
704+
},
705+
outputs: {},
706+
enabled: true,
707+
}
706708

707-
const serialized = serializer.serializeWorkflow({ 'slack-1': block }, [], {})
708-
const slackBlock = serialized.blocks.find((b) => b.id === 'slack-1')
709+
const serialized = serializer.serializeWorkflow({ 'slack-1': block }, [], {})
710+
const slackBlock = serialized.blocks.find((b) => b.id === 'slack-1')
709711

710-
expect(slackBlock).toBeDefined()
711-
expect(slackBlock?.config.params.channel).toBe('C1234567890')
712-
expect(slackBlock?.config.params.manualChannel).toBeUndefined()
713-
})
712+
expect(slackBlock).toBeDefined()
713+
expect(slackBlock?.config.params.channel).toBe('C1234567890')
714+
expect(slackBlock?.config.params.manualChannel).toBeUndefined()
715+
}
716+
)
714717

715718
it.concurrent('should use basic value by default when no mode specified', () => {
716719
const serializer = new Serializer()

apps/sim/serializer/index.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ function shouldSerializeSubBlock(
6161
const group = canonicalId ? canonicalIndex.groupsById[canonicalId] : undefined
6262
if (group && isCanonicalPair(group)) {
6363
const mode =
64-
canonicalModeOverrides?.[group.canonicalId] ??
65-
(displayAdvancedOptions ? 'advanced' : resolveCanonicalMode(group, values))
64+
canonicalModeOverrides?.[group.canonicalId] != null || !displayAdvancedOptions
65+
? resolveCanonicalMode(group, values, canonicalModeOverrides)
66+
: 'advanced'
6667
const matchesMode =
6768
mode === 'advanced'
6869
? group.advancedIds.includes(subBlockConfig.id)
@@ -374,8 +375,11 @@ export class Serializer {
374375

375376
Object.values(canonicalIndex.groupsById).forEach((group) => {
376377
const { basicValue, advancedValue } = getCanonicalValues(group, params)
378+
const hasExplicitOverride = canonicalModeOverrides?.[group.canonicalId] != null
377379
const pairMode =
378-
canonicalModeOverrides?.[group.canonicalId] ?? (legacyAdvancedMode ? 'advanced' : 'basic')
380+
hasExplicitOverride || !legacyAdvancedMode
381+
? resolveCanonicalMode(group, allValues, canonicalModeOverrides)
382+
: 'advanced'
379383
const chosen = pairMode === 'advanced' ? advancedValue : basicValue
380384

381385
const sourceIds = [group.basicId, ...group.advancedIds].filter(Boolean) as string[]

apps/sim/stores/workflows/utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { v4 as uuidv4 } from 'uuid'
33
import { DEFAULT_DUPLICATE_OFFSET } from '@/lib/workflows/autolayout/constants'
44
import { getEffectiveBlockOutputs } from '@/lib/workflows/blocks/block-outputs'
55
import { mergeSubblockStateWithValues } from '@/lib/workflows/subblocks'
6+
import { buildDefaultCanonicalModes } from '@/lib/workflows/subblocks/visibility'
67
import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils'
78
import { TriggerUtils } from '@/lib/workflows/triggers/triggers'
89
import { getBlock } from '@/blocks'
@@ -196,6 +197,13 @@ export function prepareBlockState(options: PrepareBlockStateOptions): BlockState
196197
preferToolOutputs: !effectiveTriggerMode,
197198
})
198199

200+
if (blockConfig.subBlocks) {
201+
const canonicalModes = buildDefaultCanonicalModes(blockConfig.subBlocks)
202+
if (Object.keys(canonicalModes).length > 0) {
203+
blockData.canonicalModes = canonicalModes
204+
}
205+
}
206+
199207
return {
200208
id,
201209
type,

0 commit comments

Comments
 (0)