diff --git a/apps/sim/executor/execution/block-executor.ts b/apps/sim/executor/execution/block-executor.ts index 20beded80..e760c2582 100644 --- a/apps/sim/executor/execution/block-executor.ts +++ b/apps/sim/executor/execution/block-executor.ts @@ -331,6 +331,22 @@ export class BlockExecutor { } return filtered } + + const isTrigger = + block.metadata?.category === 'triggers' || + block.config?.params?.triggerMode === true || + block.metadata?.id === BlockType.STARTER + + if (isTrigger) { + const filtered: NormalizedBlockOutput = {} + const internalKeys = ['webhook', 'workflowId', 'input'] + for (const [key, value] of Object.entries(output)) { + if (internalKeys.includes(key)) continue + filtered[key] = value + } + return filtered + } + return output } diff --git a/apps/sim/executor/handlers/trigger/trigger-handler.test.ts b/apps/sim/executor/handlers/trigger/trigger-handler.test.ts index 1e6874b5b..0ae4eae63 100644 --- a/apps/sim/executor/handlers/trigger/trigger-handler.test.ts +++ b/apps/sim/executor/handlers/trigger/trigger-handler.test.ts @@ -205,7 +205,6 @@ describe('TriggerBlockHandler', () => { const result = await handler.execute(mockContext, scheduleBlock, {}) - // Schedule triggers typically don't have input data, just trigger the workflow expect(result).toEqual({}) }) diff --git a/apps/sim/executor/handlers/trigger/trigger-handler.ts b/apps/sim/executor/handlers/trigger/trigger-handler.ts index 43809f21a..fd0508f7c 100644 --- a/apps/sim/executor/handlers/trigger/trigger-handler.ts +++ b/apps/sim/executor/handlers/trigger/trigger-handler.ts @@ -31,10 +31,7 @@ export class TriggerBlockHandler implements BlockHandler { const existingState = ctx.blockStates.get(block.id) if (existingState?.output && Object.keys(existingState.output).length > 0) { - const existingOutput = existingState.output as any - const existingProvider = existingOutput?.webhook?.data?.provider - - return existingOutput + return existingState.output } const starterBlock = ctx.workflow?.blocks?.find((b) => b.metadata?.id === 'starter') @@ -44,88 +41,8 @@ export class TriggerBlockHandler implements BlockHandler { const starterOutput = starterState.output if (starterOutput.webhook?.data) { - const webhookData = starterOutput.webhook?.data || {} - const provider = webhookData.provider - - if (provider === 'github') { - const payloadSource = webhookData.payload || {} - return { - ...payloadSource, - webhook: starterOutput.webhook, - } - } - - if (provider === 'microsoft-teams') { - const providerData = (starterOutput as any)[provider] || webhookData[provider] || {} - const payloadSource = providerData?.message?.raw || webhookData.payload || {} - return { - ...payloadSource, - [provider]: providerData, - webhook: starterOutput.webhook, - } - } - - if (provider === 'airtable') { - return starterOutput - } - - const result: any = { - input: starterOutput.input, - } - - for (const [key, value] of Object.entries(starterOutput)) { - if (key !== 'webhook' && key !== provider) { - result[key] = value - } - } - - if (provider && starterOutput[provider]) { - const providerData = starterOutput[provider] - - for (const [key, value] of Object.entries(providerData)) { - if (typeof value === 'object' && value !== null) { - if (!result[key]) { - result[key] = value - } - } - } - - result[provider] = providerData - } else if (provider && webhookData[provider]) { - const providerData = webhookData[provider] - - for (const [key, value] of Object.entries(providerData)) { - if (typeof value === 'object' && value !== null) { - if (!result[key]) { - result[key] = value - } - } - } - - result[provider] = providerData - } else if ( - provider && - (provider === 'gmail' || provider === 'outlook') && - webhookData.payload?.email - ) { - const emailData = webhookData.payload.email - - for (const [key, value] of Object.entries(emailData)) { - if (!result[key]) { - result[key] = value - } - } - - result.email = emailData - - if (webhookData.payload.timestamp) { - result.timestamp = webhookData.payload.timestamp - } - } - - if (starterOutput.webhook) result.webhook = starterOutput.webhook - - return result + const { webhook, workflowId, ...cleanOutput } = starterOutput + return cleanOutput } return starterOutput diff --git a/apps/sim/lib/webhooks/utils.server.ts b/apps/sim/lib/webhooks/utils.server.ts index 64f2de2ec..e3e4b9c86 100644 --- a/apps/sim/lib/webhooks/utils.server.ts +++ b/apps/sim/lib/webhooks/utils.server.ts @@ -749,7 +749,6 @@ export async function formatWebhookInput( } } - // Fallback for unknown Telegram update types logger.warn('Unknown Telegram update type', { updateId: body.update_id, bodyKeys: Object.keys(body || {}), @@ -778,7 +777,6 @@ export async function formatWebhookInput( if (foundWebhook.provider === 'twilio_voice') { return { - // Root-level properties matching trigger outputs for easy access callSid: body.CallSid, accountSid: body.AccountSid, from: body.From, @@ -792,8 +790,6 @@ export async function formatWebhookInput( speechResult: body.SpeechResult, recordingUrl: body.RecordingUrl, recordingSid: body.RecordingSid, - - // Additional fields from Twilio payload called: body.Called, caller: body.Caller, toCity: body.ToCity, @@ -830,14 +826,48 @@ export async function formatWebhookInput( if (foundWebhook.provider === 'gmail') { if (body && typeof body === 'object' && 'email' in body) { - return body + const email = body.email as Record + const timestamp = body.timestamp + return { + ...email, + email, + ...(timestamp !== undefined && { timestamp }), + webhook: { + data: { + provider: 'gmail', + path: foundWebhook.path, + providerConfig: foundWebhook.providerConfig, + payload: body, + headers: Object.fromEntries(request.headers.entries()), + method: request.method, + }, + }, + workflowId: foundWorkflow.id, + } } return body } if (foundWebhook.provider === 'outlook') { if (body && typeof body === 'object' && 'email' in body) { - return body + const email = body.email as Record + const timestamp = body.timestamp + return { + ...email, + email, + ...(timestamp !== undefined && { timestamp }), + webhook: { + data: { + provider: 'outlook', + path: foundWebhook.path, + providerConfig: foundWebhook.providerConfig, + payload: body, + headers: Object.fromEntries(request.headers.entries()), + method: request.method, + }, + }, + workflowId: foundWorkflow.id, + } } return body } @@ -926,19 +956,16 @@ export async function formatWebhookInput( } if (foundWebhook.provider === 'microsoft-teams') { - // Check if this is a Microsoft Graph change notification if (body?.value && Array.isArray(body.value) && body.value.length > 0) { return await formatTeamsGraphNotification(body, foundWebhook, foundWorkflow, request) } - // Microsoft Teams outgoing webhook - Teams sending data to us const messageText = body?.text || '' const messageId = body?.id || '' const timestamp = body?.timestamp || body?.localTimestamp || '' const from = body?.from || {} const conversation = body?.conversation || {} - // Construct the message object const messageObj = { raw: { attachments: body?.attachments || [], @@ -951,14 +978,12 @@ export async function formatWebhookInput( }, } - // Construct the from object const fromObj = { id: from.id || '', name: from.name || '', aadObjectId: from.aadObjectId || '', } - // Construct the conversation object const conversationObj = { id: conversation.id || '', name: conversation.name || '', @@ -968,13 +993,11 @@ export async function formatWebhookInput( conversationType: conversation.conversationType || '', } - // Construct the activity object const activityObj = body || {} return { - input: messageText, // Primary workflow input - the message text + input: messageText, - // Top-level properties for direct access with syntax from: fromObj, message: messageObj, activity: activityObj, @@ -995,11 +1018,9 @@ export async function formatWebhookInput( } if (foundWebhook.provider === 'slack') { - // Slack input formatting logic - check for valid event const event = body?.event if (event && body?.type === 'event_callback') { - // Extract event text with fallbacks for different event types let input = '' if (event.text) { @@ -1010,13 +1031,12 @@ export async function formatWebhookInput( input = 'Slack event received' } - // Create the event object for easier access const eventObj = { event_type: event.type || '', channel: event.channel || '', - channel_name: '', // Could be resolved via additional API calls if needed + channel_name: '', user: event.user || '', - user_name: '', // Could be resolved via additional API calls if needed + user_name: '', text: event.text || '', timestamp: event.ts || event.event_ts || '', team_id: body.team_id || event.team || '', @@ -1024,12 +1044,9 @@ export async function formatWebhookInput( } return { - input, // Primary workflow input - the event content + input, - // // // Top-level properties for backward compatibility with syntax event: eventObj, - - // Keep the nested structure for the new slack.event.text syntax slack: { event: eventObj, }, @@ -1047,7 +1064,6 @@ export async function formatWebhookInput( } } - // Fallback for unknown Slack event types logger.warn('Unknown Slack event type', { type: body?.type, hasEvent: !!body?.event, @@ -1283,9 +1299,7 @@ export async function formatWebhookInput( } return { - // Expose raw GitHub payload at the root ...body, - // Include webhook metadata alongside webhook: { data: { provider: 'github', @@ -1364,10 +1378,7 @@ export async function formatWebhookInput( } if (foundWebhook.provider === 'linear') { - // Linear webhook payload structure: - // { action, type, webhookId, webhookTimestamp, organizationId, createdAt, actor, data, updatedFrom? } return { - // Extract top-level fields from Linear payload action: body.action || '', type: body.type || '', webhookId: body.webhookId || '', @@ -1377,8 +1388,6 @@ export async function formatWebhookInput( actor: body.actor || null, data: body.data || null, updatedFrom: body.updatedFrom || null, - - // Keep webhook metadata webhook: { data: { provider: 'linear', @@ -1393,7 +1402,6 @@ export async function formatWebhookInput( } } - // Jira webhook format if (foundWebhook.provider === 'jira') { const { extractIssueData, extractCommentData, extractWorklogData } = await import( '@/triggers/jira/utils' @@ -1445,7 +1453,6 @@ export async function formatWebhookInput( } if (foundWebhook.provider === 'calendly') { - // Calendly webhook payload format matches the trigger outputs return { event: body.event, created_at: body.created_at, @@ -1466,9 +1473,7 @@ export async function formatWebhookInput( } if (foundWebhook.provider === 'circleback') { - // Circleback webhook payload - meeting notes, action items, transcript return { - // Top-level fields from Circleback payload id: body.id, name: body.name, createdAt: body.createdAt, @@ -1482,10 +1487,7 @@ export async function formatWebhookInput( actionItems: body.actionItems || [], transcript: body.transcript || [], insights: body.insights || {}, - - // Full meeting object for convenience meeting: body, - webhook: { data: { provider: 'circleback', @@ -1501,9 +1503,7 @@ export async function formatWebhookInput( } if (foundWebhook.provider === 'grain') { - // Grain webhook payload structure: { type, user_id, data: {...} } return { - // Top-level fields from Grain payload type: body.type, user_id: body.user_id, data: body.data || {},