@@ -417,10 +417,6 @@ export class Serializer {
417417 blockConfig : any ,
418418 params : Record < string , any >
419419 ) {
420- // Validate user-only required fields before execution starts
421- // This catches missing API keys, credentials, and other user-provided values early
422- // Fields that are user-or-llm will be validated later after parameter merging
423-
424420 // Skip validation if the block is in trigger mode
425421 if ( block . triggerMode || blockConfig . category === 'triggers' ) {
426422 logger . info ( 'Skipping validation for block in trigger mode' , {
@@ -461,10 +457,74 @@ export class Serializer {
461457 // Iterate through the tool's parameters, not the block's subBlocks
462458 Object . entries ( currentTool . params || { } ) . forEach ( ( [ paramId , paramConfig ] ) => {
463459 if ( paramConfig . required && paramConfig . visibility === 'user-only' ) {
460+ const subBlockConfig = blockConfig . subBlocks ?. find ( ( sb : any ) => sb . id === paramId )
461+
462+ let shouldValidateParam = true
463+
464+ if ( subBlockConfig ) {
465+ const isAdvancedMode = block . advancedMode ?? false
466+ const includedByMode = shouldIncludeField ( subBlockConfig , isAdvancedMode )
467+
468+ const includedByCondition = ( ( ) => {
469+ const evalCond = (
470+ condition :
471+ | {
472+ field : string
473+ value : any
474+ not ?: boolean
475+ and ?: { field : string ; value : any ; not ?: boolean }
476+ }
477+ | ( ( ) => {
478+ field : string
479+ value : any
480+ not ?: boolean
481+ and ?: { field : string ; value : any ; not ?: boolean }
482+ } )
483+ | undefined ,
484+ values : Record < string , any >
485+ ) : boolean => {
486+ if ( ! condition ) return true
487+ const actual = typeof condition === 'function' ? condition ( ) : condition
488+ const fieldValue = values [ actual . field ]
489+
490+ const valueMatch = Array . isArray ( actual . value )
491+ ? fieldValue != null &&
492+ ( actual . not
493+ ? ! actual . value . includes ( fieldValue )
494+ : actual . value . includes ( fieldValue ) )
495+ : actual . not
496+ ? fieldValue !== actual . value
497+ : fieldValue === actual . value
498+
499+ const andMatch = ! actual . and
500+ ? true
501+ : ( ( ) => {
502+ const andFieldValue = values [ actual . and ! . field ]
503+ return Array . isArray ( actual . and ! . value )
504+ ? andFieldValue != null &&
505+ ( actual . and ! . not
506+ ? ! actual . and ! . value . includes ( andFieldValue )
507+ : actual . and ! . value . includes ( andFieldValue ) )
508+ : actual . and ! . not
509+ ? andFieldValue !== actual . and ! . value
510+ : andFieldValue === actual . and ! . value
511+ } ) ( )
512+
513+ return valueMatch && andMatch
514+ }
515+
516+ return evalCond ( subBlockConfig . condition , params )
517+ } ) ( )
518+
519+ shouldValidateParam = includedByMode && includedByCondition
520+ }
521+
522+ if ( ! shouldValidateParam ) {
523+ return
524+ }
525+
464526 const fieldValue = params [ paramId ]
465527 if ( fieldValue === undefined || fieldValue === null || fieldValue === '' ) {
466- // Find the corresponding subBlock to get the display title
467- const subBlockConfig = blockConfig . subBlocks ?. find ( ( sb : any ) => sb . id === paramId )
468528 const displayName = subBlockConfig ?. title || paramId
469529 missingFields . push ( displayName )
470530 }
0 commit comments