From 57e62036251f38c75f5694a8d7e25c3ee3143384 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Sun, 25 Jan 2026 22:32:51 -0800 Subject: [PATCH 1/5] fix(multi-trigger): resolution paths for triggers --- apps/sim/executor/utils/block-data.ts | 44 ++++++++++++------- .../sim/executor/variables/resolvers/block.ts | 10 +---- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/apps/sim/executor/utils/block-data.ts b/apps/sim/executor/utils/block-data.ts index 6941803741..6363bd5b07 100644 --- a/apps/sim/executor/utils/block-data.ts +++ b/apps/sim/executor/utils/block-data.ts @@ -1,7 +1,9 @@ -import { getBlockOutputs } from '@/lib/workflows/blocks/block-outputs' import { normalizeName } from '@/executor/constants' import type { ExecutionContext } from '@/executor/types' import type { OutputSchema } from '@/executor/utils/block-reference' +import type { SerializedBlock } from '@/serializer/types' +import type { ToolConfig } from '@/tools/types' +import { getTool } from '@/tools/utils' export interface BlockDataCollection { blockData: Record @@ -9,6 +11,21 @@ export interface BlockDataCollection { blockOutputSchemas: Record } +export function getBlockSchema( + block: SerializedBlock, + toolConfig?: ToolConfig +): OutputSchema | undefined { + if (block.outputs && Object.keys(block.outputs).length > 0) { + return block.outputs as OutputSchema + } + + if (toolConfig?.outputs && Object.keys(toolConfig.outputs).length > 0) { + return toolConfig.outputs as OutputSchema + } + + return undefined +} + export function collectBlockData(ctx: ExecutionContext): BlockDataCollection { const blockData: Record = {} const blockNameMapping: Record = {} @@ -18,24 +35,21 @@ export function collectBlockData(ctx: ExecutionContext): BlockDataCollection { if (state.output !== undefined) { blockData[id] = state.output } + } - const workflowBlock = ctx.workflow?.blocks?.find((b) => b.id === id) - if (!workflowBlock) continue + const workflowBlocks = ctx.workflow?.blocks ?? [] + for (const block of workflowBlocks) { + const id = block.id - if (workflowBlock.metadata?.name) { - blockNameMapping[normalizeName(workflowBlock.metadata.name)] = id + if (block.metadata?.name) { + blockNameMapping[normalizeName(block.metadata.name)] = id } - const blockType = workflowBlock.metadata?.id - if (blockType) { - const params = workflowBlock.config?.params as Record | undefined - const subBlocks = params - ? Object.fromEntries(Object.entries(params).map(([k, v]) => [k, { value: v }])) - : undefined - const schema = getBlockOutputs(blockType, subBlocks) - if (schema && Object.keys(schema).length > 0) { - blockOutputSchemas[id] = schema - } + const toolId = block.config?.tool + const toolConfig = toolId ? getTool(toolId) : undefined + const schema = getBlockSchema(block, toolConfig) + if (schema && Object.keys(schema).length > 0) { + blockOutputSchemas[id] = schema } } diff --git a/apps/sim/executor/variables/resolvers/block.ts b/apps/sim/executor/variables/resolvers/block.ts index a29339b2bf..09d246e80e 100644 --- a/apps/sim/executor/variables/resolvers/block.ts +++ b/apps/sim/executor/variables/resolvers/block.ts @@ -1,10 +1,10 @@ -import { getBlockOutputs } from '@/lib/workflows/blocks/block-outputs' import { isReference, normalizeName, parseReferencePath, SPECIAL_REFERENCE_PREFIXES, } from '@/executor/constants' +import { getBlockSchema } from '@/executor/utils/block-data' import { InvalidFieldError, type OutputSchema, @@ -67,15 +67,9 @@ export class BlockResolver implements Resolver { blockData[blockId] = output } - const blockType = block.metadata?.id - const params = block.config?.params as Record | undefined - const subBlocks = params - ? Object.fromEntries(Object.entries(params).map(([k, v]) => [k, { value: v }])) - : undefined const toolId = block.config?.tool const toolConfig = toolId ? getTool(toolId) : undefined - const outputSchema = - toolConfig?.outputs ?? (blockType ? getBlockOutputs(blockType, subBlocks) : block.outputs) + const outputSchema = getBlockSchema(block, toolConfig) if (outputSchema && Object.keys(outputSchema).length > 0) { blockOutputSchemas[blockId] = outputSchema From 0c69f8b061d014dc911517dca91c37fdc5cec2c7 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Sun, 25 Jan 2026 22:44:09 -0800 Subject: [PATCH 2/5] fix trigger input format version --- apps/sim/executor/utils/start-block.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/sim/executor/utils/start-block.ts b/apps/sim/executor/utils/start-block.ts index 7df680518d..4fc5b7b7aa 100644 --- a/apps/sim/executor/utils/start-block.ts +++ b/apps/sim/executor/utils/start-block.ts @@ -378,7 +378,14 @@ function buildManualTriggerOutput( return mergeFilesIntoOutput(output, workflowInput) } -function buildIntegrationTriggerOutput(workflowInput: unknown): NormalizedBlockOutput { +function buildIntegrationTriggerOutput( + workflowInput: unknown, + structuredInput: Record, + hasStructured: boolean +): NormalizedBlockOutput { + if (hasStructured) { + return { ...structuredInput } + } return isPlainObject(workflowInput) ? (workflowInput as NormalizedBlockOutput) : {} } @@ -428,7 +435,7 @@ export function buildStartBlockOutput(options: StartBlockOutputOptions): Normali return buildManualTriggerOutput(finalInput, workflowInput) case StartBlockPath.EXTERNAL_TRIGGER: - return buildIntegrationTriggerOutput(workflowInput) + return buildIntegrationTriggerOutput(workflowInput, structuredInput, hasStructured) case StartBlockPath.LEGACY_STARTER: return buildLegacyStarterOutput( From 7ba07bc42838265b843fc9763699f0f6be25ea40 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Sun, 25 Jan 2026 22:56:13 -0800 Subject: [PATCH 3/5] fix output condition logic --- apps/sim/blocks/blocks/gmail.ts | 12 +++++++++ apps/sim/executor/utils/block-data.ts | 13 +++++++++- .../sim/lib/workflows/blocks/block-outputs.ts | 25 +++++++++++-------- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/apps/sim/blocks/blocks/gmail.ts b/apps/sim/blocks/blocks/gmail.ts index e389d3b3d9..223b69ec70 100644 --- a/apps/sim/blocks/blocks/gmail.ts +++ b/apps/sim/blocks/blocks/gmail.ts @@ -581,6 +581,18 @@ export const GmailV2Block: BlockConfig = { results: { type: 'json', description: 'Search/read summary results' }, attachments: { type: 'json', description: 'Downloaded attachments (if enabled)' }, + // Draft-specific outputs + draftId: { + type: 'string', + description: 'Draft ID', + condition: { field: 'operation', value: 'draft_gmail' }, + }, + messageId: { + type: 'string', + description: 'Gmail message ID for the draft', + condition: { field: 'operation', value: 'draft_gmail' }, + }, + // Trigger outputs (unchanged) email_id: { type: 'string', description: 'Gmail message ID' }, thread_id: { type: 'string', description: 'Gmail thread ID' }, diff --git a/apps/sim/executor/utils/block-data.ts b/apps/sim/executor/utils/block-data.ts index 6363bd5b07..0c7ec4bd1f 100644 --- a/apps/sim/executor/utils/block-data.ts +++ b/apps/sim/executor/utils/block-data.ts @@ -15,14 +15,25 @@ export function getBlockSchema( block: SerializedBlock, toolConfig?: ToolConfig ): OutputSchema | undefined { - if (block.outputs && Object.keys(block.outputs).length > 0) { + const isTrigger = + block.metadata?.category === 'triggers' || + (block.config?.params as Record | undefined)?.triggerMode === true + + // Triggers use saved outputs (defines the trigger payload schema) + if (isTrigger && block.outputs && Object.keys(block.outputs).length > 0) { return block.outputs as OutputSchema } + // When a tool is selected, tool outputs are the source of truth if (toolConfig?.outputs && Object.keys(toolConfig.outputs).length > 0) { return toolConfig.outputs as OutputSchema } + // Fallback to saved outputs for blocks without tools + if (block.outputs && Object.keys(block.outputs).length > 0) { + return block.outputs as OutputSchema + } + return undefined } diff --git a/apps/sim/lib/workflows/blocks/block-outputs.ts b/apps/sim/lib/workflows/blocks/block-outputs.ts index 12972141ae..0fecd31ed0 100644 --- a/apps/sim/lib/workflows/blocks/block-outputs.ts +++ b/apps/sim/lib/workflows/blocks/block-outputs.ts @@ -618,13 +618,6 @@ export function getToolOutputs( } } -/** - * Generates output paths for a tool-based block. - * - * @param blockConfig - The block configuration containing tools config - * @param subBlocks - SubBlock values for tool selection and condition evaluation - * @returns Array of output paths for the tool, or empty array on error - */ export function getToolOutputPaths( blockConfig: BlockConfig, subBlocks?: Record @@ -634,12 +627,22 @@ export function getToolOutputPaths( if (!outputs || Object.keys(outputs).length === 0) return [] if (subBlocks && blockConfig.outputs) { - const filteredBlockOutputs = filterOutputsByCondition(blockConfig.outputs, subBlocks) - const allowedKeys = new Set(Object.keys(filteredBlockOutputs)) - const filteredOutputs: Record = {} + for (const [key, value] of Object.entries(outputs)) { - if (allowedKeys.has(key)) { + const blockOutput = blockConfig.outputs[key] + + if (!blockOutput || typeof blockOutput !== 'object') { + filteredOutputs[key] = value + continue + } + + const condition = (blockOutput as any).condition as OutputCondition | undefined + if (condition) { + if (evaluateOutputCondition(condition, subBlocks)) { + filteredOutputs[key] = value + } + } else { filteredOutputs[key] = value } } From 5b3cc2ba0dc8bda7bba517f0b5631a47ebd5d6cb Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Sun, 25 Jan 2026 23:03:55 -0800 Subject: [PATCH 4/5] update type guard: --- apps/sim/lib/workflows/blocks/block-outputs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sim/lib/workflows/blocks/block-outputs.ts b/apps/sim/lib/workflows/blocks/block-outputs.ts index 0fecd31ed0..b00156e0cd 100644 --- a/apps/sim/lib/workflows/blocks/block-outputs.ts +++ b/apps/sim/lib/workflows/blocks/block-outputs.ts @@ -637,7 +637,7 @@ export function getToolOutputPaths( continue } - const condition = (blockOutput as any).condition as OutputCondition | undefined + const condition = 'condition' in blockOutput ? blockOutput.condition : undefined if (condition) { if (evaluateOutputCondition(condition, subBlocks)) { filteredOutputs[key] = value From 1a90c04e1c92ee87141a079fcc742c7024b9ce97 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Sun, 25 Jan 2026 23:07:45 -0800 Subject: [PATCH 5/5] fix --- apps/sim/executor/utils/start-block.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/apps/sim/executor/utils/start-block.ts b/apps/sim/executor/utils/start-block.ts index 4fc5b7b7aa..3b7982f934 100644 --- a/apps/sim/executor/utils/start-block.ts +++ b/apps/sim/executor/utils/start-block.ts @@ -383,10 +383,25 @@ function buildIntegrationTriggerOutput( structuredInput: Record, hasStructured: boolean ): NormalizedBlockOutput { + const output: NormalizedBlockOutput = {} + if (hasStructured) { - return { ...structuredInput } + for (const [key, value] of Object.entries(structuredInput)) { + output[key] = value + } } - return isPlainObject(workflowInput) ? (workflowInput as NormalizedBlockOutput) : {} + + if (isPlainObject(workflowInput)) { + for (const [key, value] of Object.entries(workflowInput)) { + if (value !== undefined && value !== null) { + output[key] = value + } else if (!Object.hasOwn(output, key)) { + output[key] = value + } + } + } + + return mergeFilesIntoOutput(output, workflowInput) } function extractSubBlocks(block: SerializedBlock): Record | undefined {