1+ import { normalizeInputFormatValue } from '@/lib/workflows/input-format'
12import { normalizeName } from '@/executor/constants'
23import type { ExecutionContext } from '@/executor/types'
34import type { OutputSchema } from '@/executor/utils/block-reference'
@@ -11,6 +12,37 @@ export interface BlockDataCollection {
1112 blockOutputSchemas : Record < string , OutputSchema >
1213}
1314
15+ /**
16+ * Triggers where inputFormat fields should be merged into outputs schema.
17+ * These are blocks where users define custom fields via inputFormat that become
18+ * valid output paths (e.g., <start.myField>, <webhook1.customField>).
19+ */
20+ const TRIGGERS_WITH_INPUT_FORMAT_OUTPUTS = [
21+ 'start_trigger' ,
22+ 'starter' ,
23+ 'api_trigger' ,
24+ 'input_trigger' ,
25+ 'generic_webhook' ,
26+ 'human_in_the_loop' ,
27+ 'approval' ,
28+ ] as const
29+
30+ function getInputFormatFields ( block : SerializedBlock ) : OutputSchema {
31+ const inputFormat = normalizeInputFormatValue ( block . config ?. params ?. inputFormat )
32+ if ( inputFormat . length === 0 ) {
33+ return { }
34+ }
35+
36+ const schema : OutputSchema = { }
37+ for ( const field of inputFormat ) {
38+ schema [ field . name ! ] = {
39+ type : ( field . type || 'any' ) as 'string' | 'number' | 'boolean' | 'object' | 'array' | 'any' ,
40+ }
41+ }
42+
43+ return schema
44+ }
45+
1446export function getBlockSchema (
1547 block : SerializedBlock ,
1648 toolConfig ?: ToolConfig
@@ -19,17 +51,31 @@ export function getBlockSchema(
1951 block . metadata ?. category === 'triggers' ||
2052 ( block . config ?. params as Record < string , unknown > | undefined ) ?. triggerMode === true
2153
22- // Triggers use saved outputs (defines the trigger payload schema)
54+ const blockType = block . metadata ?. id
55+
56+ if (
57+ isTrigger &&
58+ blockType &&
59+ TRIGGERS_WITH_INPUT_FORMAT_OUTPUTS . includes (
60+ blockType as ( typeof TRIGGERS_WITH_INPUT_FORMAT_OUTPUTS ) [ number ]
61+ )
62+ ) {
63+ const baseOutputs = ( block . outputs as OutputSchema ) || { }
64+ const inputFormatFields = getInputFormatFields ( block )
65+ const merged = { ...baseOutputs , ...inputFormatFields }
66+ if ( Object . keys ( merged ) . length > 0 ) {
67+ return merged
68+ }
69+ }
70+
2371 if ( isTrigger && block . outputs && Object . keys ( block . outputs ) . length > 0 ) {
2472 return block . outputs as OutputSchema
2573 }
2674
27- // When a tool is selected, tool outputs are the source of truth
2875 if ( toolConfig ?. outputs && Object . keys ( toolConfig . outputs ) . length > 0 ) {
2976 return toolConfig . outputs as OutputSchema
3077 }
3178
32- // Fallback to saved outputs for blocks without tools
3379 if ( block . outputs && Object . keys ( block . outputs ) . length > 0 ) {
3480 return block . outputs as OutputSchema
3581 }
0 commit comments