Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import crypto from 'crypto'
import { createLogger } from '@sim/logger'
import type { PermissionGroupConfig } from '@/lib/permission-groups/types'
import { getEffectiveBlockOutputs } from '@/lib/workflows/blocks/block-outputs'
import { buildCanonicalIndex, isCanonicalPair } from '@/lib/workflows/subblocks/visibility'
import {
buildCanonicalIndex,
buildDefaultCanonicalModes,
isCanonicalPair,
} from '@/lib/workflows/subblocks/visibility'
import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils'
import { getAllBlocks } from '@/blocks/registry'
import type { BlockConfig } from '@/blocks/types'
Expand Down Expand Up @@ -130,6 +134,12 @@ export function createBlockFromParams(
}
})

const defaultModes = buildDefaultCanonicalModes(blockConfig.subBlocks)
if (Object.keys(defaultModes).length > 0) {
if (!blockState.data) blockState.data = {}
blockState.data.canonicalModes = defaultModes
}

if (validatedInputs) {
updateCanonicalModesForInputs(blockState, Object.keys(validatedInputs), blockConfig)
}
Expand Down
17 changes: 17 additions & 0 deletions apps/sim/lib/workflows/subblocks/visibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,23 @@ export function isCanonicalPair(group?: CanonicalGroup): boolean {
return Boolean(group?.basicId && group?.advancedIds?.length)
}

/**
* Builds default canonical mode overrides for a block's subblocks.
* All canonical pairs default to `'basic'`.
*/
export function buildDefaultCanonicalModes(
subBlocks: SubBlockConfig[]
): Record<string, 'basic' | 'advanced'> {
const index = buildCanonicalIndex(subBlocks)
const modes: Record<string, 'basic' | 'advanced'> = {}
for (const group of Object.values(index.groupsById)) {
if (isCanonicalPair(group)) {
modes[group.canonicalId] = 'basic'
}
}
return modes
}

/**
* Determine the active mode for a canonical group.
*/
Expand Down
53 changes: 28 additions & 25 deletions apps/sim/serializer/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -683,34 +683,37 @@ describe('Serializer', () => {
expect(slackBlock?.config.params.username).toBe('bot')
})

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

const block: any = {
id: 'slack-1',
type: 'slack',
name: 'Test Slack Block',
position: { x: 0, y: 0 },
advancedMode: true,
subBlocks: {
operation: { value: 'send' },
destinationType: { value: 'channel' },
channel: { value: 'general' },
manualChannel: { value: 'C1234567890' },
text: { value: 'Hello world' },
username: { value: 'bot' },
},
outputs: {},
enabled: true,
}
const block: any = {
id: 'slack-1',
type: 'slack',
name: 'Test Slack Block',
position: { x: 0, y: 0 },
advancedMode: true,
subBlocks: {
operation: { value: 'send' },
destinationType: { value: 'channel' },
channel: { value: 'general' },
manualChannel: { value: 'C1234567890' },
text: { value: 'Hello world' },
username: { value: 'bot' },
},
outputs: {},
enabled: true,
}

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

expect(slackBlock).toBeDefined()
expect(slackBlock?.config.params.channel).toBe('C1234567890')
expect(slackBlock?.config.params.manualChannel).toBeUndefined()
})
expect(slackBlock).toBeDefined()
expect(slackBlock?.config.params.channel).toBe('C1234567890')
expect(slackBlock?.config.params.manualChannel).toBeUndefined()
}
)

it.concurrent('should use basic value by default when no mode specified', () => {
const serializer = new Serializer()
Expand Down
10 changes: 7 additions & 3 deletions apps/sim/serializer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ function shouldSerializeSubBlock(
const group = canonicalId ? canonicalIndex.groupsById[canonicalId] : undefined
if (group && isCanonicalPair(group)) {
const mode =
canonicalModeOverrides?.[group.canonicalId] ??
(displayAdvancedOptions ? 'advanced' : resolveCanonicalMode(group, values))
canonicalModeOverrides?.[group.canonicalId] != null || !displayAdvancedOptions
? resolveCanonicalMode(group, values, canonicalModeOverrides)
: 'advanced'
const matchesMode =
mode === 'advanced'
? group.advancedIds.includes(subBlockConfig.id)
Expand Down Expand Up @@ -374,8 +375,11 @@ export class Serializer {

Object.values(canonicalIndex.groupsById).forEach((group) => {
const { basicValue, advancedValue } = getCanonicalValues(group, params)
const hasExplicitOverride = canonicalModeOverrides?.[group.canonicalId] != null
const pairMode =
canonicalModeOverrides?.[group.canonicalId] ?? (legacyAdvancedMode ? 'advanced' : 'basic')
hasExplicitOverride || !legacyAdvancedMode
? resolveCanonicalMode(group, allValues, canonicalModeOverrides)
: 'advanced'
const chosen = pairMode === 'advanced' ? advancedValue : basicValue

const sourceIds = [group.basicId, ...group.advancedIds].filter(Boolean) as string[]
Expand Down
8 changes: 8 additions & 0 deletions apps/sim/stores/workflows/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { v4 as uuidv4 } from 'uuid'
import { DEFAULT_DUPLICATE_OFFSET } from '@/lib/workflows/autolayout/constants'
import { getEffectiveBlockOutputs } from '@/lib/workflows/blocks/block-outputs'
import { mergeSubblockStateWithValues } from '@/lib/workflows/subblocks'
import { buildDefaultCanonicalModes } from '@/lib/workflows/subblocks/visibility'
import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils'
import { TriggerUtils } from '@/lib/workflows/triggers/triggers'
import { getBlock } from '@/blocks'
Expand Down Expand Up @@ -196,6 +197,13 @@ export function prepareBlockState(options: PrepareBlockStateOptions): BlockState
preferToolOutputs: !effectiveTriggerMode,
})

if (blockConfig.subBlocks) {
const canonicalModes = buildDefaultCanonicalModes(blockConfig.subBlocks)
if (Object.keys(canonicalModes).length > 0) {
blockData.canonicalModes = canonicalModes
}
}

return {
id,
type,
Expand Down