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 @@ -91,8 +91,7 @@ export function FieldFormat({
placeholder = 'fieldName',
showType = true,
showValue = false,
valuePlaceholder = 'Enter test value',
config,
valuePlaceholder = 'Enter default value',
}: FieldFormatProps) {
const [storeValue, setStoreValue] = useSubBlockValue<Field[]>(blockId, subBlockId)
const valueInputRefs = useRef<Record<string, HTMLInputElement | HTMLTextAreaElement>>({})
Expand Down Expand Up @@ -454,7 +453,6 @@ export function FieldFormat({
)
}

// Export specific components for backward compatibility
export function InputFormat(props: Omit<FieldFormatProps, 'title' | 'placeholder'>) {
return <FieldFormat {...props} title='Input' placeholder='firstName' />
}
Expand Down
9 changes: 9 additions & 0 deletions apps/sim/blocks/blocks/schedule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,15 @@ export const ScheduleBlock: BlockConfig = {
condition: { field: 'scheduleType', value: ['minutes', 'hourly'], not: true },
},

{
id: 'inputFormat',
title: 'Input Format',
type: 'input-format',
description:
'Define input parameters that will be available when the schedule triggers. Use Value to set default values for scheduled executions.',
mode: 'trigger',
},

{
id: 'scheduleSave',
type: 'schedule-save',
Expand Down
52 changes: 29 additions & 23 deletions apps/sim/serializer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,7 @@ export class Serializer {

// Second pass: filter by mode and conditions
Object.entries(block.subBlocks).forEach(([id, subBlock]) => {
// Find the corresponding subblock config to check its mode and condition
const subBlockConfig = blockConfig.subBlocks.find((config) => config.id === id)
const matchingConfigs = blockConfig.subBlocks.filter((config) => config.id === id)

// Include field if it matches current mode OR if it's the starter inputFormat with values
const hasStarterInputFormatValues =
Expand All @@ -417,13 +416,17 @@ export class Serializer {
const isLegacyAgentField =
isAgentBlock && ['systemPrompt', 'userPrompt', 'memories'].includes(id)

// Check if field's condition is met (conditionally-hidden fields should be excluded)
const conditionMet = subBlockConfig
? evaluateCondition(subBlockConfig.condition, allValues)
: true
const anyConditionMet =
matchingConfigs.length === 0
? true
: matchingConfigs.some(
(config) =>
shouldIncludeField(config, isAdvancedMode) &&
evaluateCondition(config.condition, allValues)
)

if (
(subBlockConfig && shouldIncludeField(subBlockConfig, isAdvancedMode) && conditionMet) ||
(matchingConfigs.length > 0 && anyConditionMet) ||
hasStarterInputFormatValues ||
isLegacyAgentField
) {
Expand Down Expand Up @@ -540,26 +543,26 @@ export class Serializer {
// Iterate through the tool's parameters, not the block's subBlocks
Object.entries(currentTool.params || {}).forEach(([paramId, paramConfig]) => {
if (paramConfig.required && paramConfig.visibility === 'user-only') {
const subBlockConfig = blockConfig.subBlocks?.find((sb: any) => sb.id === paramId)
const matchingConfigs = blockConfig.subBlocks?.filter((sb: any) => sb.id === paramId) || []

let shouldValidateParam = true

if (subBlockConfig) {
if (matchingConfigs.length > 0) {
const isAdvancedMode = block.advancedMode ?? false
const includedByMode = shouldIncludeField(subBlockConfig, isAdvancedMode)

// Check visibility condition
const includedByCondition = evaluateCondition(subBlockConfig.condition, params)
shouldValidateParam = matchingConfigs.some((subBlockConfig: any) => {
const includedByMode = shouldIncludeField(subBlockConfig, isAdvancedMode)

// Check if field is required based on its required condition (if it's a condition object)
const isRequired = (() => {
if (!subBlockConfig.required) return false
if (typeof subBlockConfig.required === 'boolean') return subBlockConfig.required
// If required is a condition object, evaluate it
return evaluateCondition(subBlockConfig.required, params)
})()
const includedByCondition = evaluateCondition(subBlockConfig.condition, params)

shouldValidateParam = includedByMode && includedByCondition && isRequired
const isRequired = (() => {
if (!subBlockConfig.required) return false
if (typeof subBlockConfig.required === 'boolean') return subBlockConfig.required
return evaluateCondition(subBlockConfig.required, params)
})()

return includedByMode && includedByCondition && isRequired
})
}

if (!shouldValidateParam) {
Expand All @@ -568,7 +571,12 @@ export class Serializer {

const fieldValue = params[paramId]
if (fieldValue === undefined || fieldValue === null || fieldValue === '') {
const displayName = subBlockConfig?.title || paramId
const activeConfig = matchingConfigs.find(
(config: any) =>
shouldIncludeField(config, block.advancedMode ?? false) &&
evaluateCondition(config.condition, params)
)
const displayName = activeConfig?.title || paramId
missingFields.push(displayName)
}
}
Expand Down Expand Up @@ -596,8 +604,6 @@ export class Serializer {
const accessibleIds = new Set<string>(ancestorIds)
accessibleIds.add(blockId)

// Only add starter block if it's actually upstream (already in ancestorIds)
// Don't add it just because it exists on the canvas
if (starterBlock && ancestorIds.includes(starterBlock.id)) {
accessibleIds.add(starterBlock.id)
}
Expand Down
Loading