Skip to content

Commit 4590b5c

Browse files
committed
cleanup triggers
1 parent ba374ec commit 4590b5c

File tree

12 files changed

+1226
-613
lines changed

12 files changed

+1226
-613
lines changed

apps/sim/app/api/workflows/[id]/execute/route.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { LoggingSession } from '@/lib/logs/execution/logging-session'
1414
import { buildTraceSpans } from '@/lib/logs/execution/trace-spans/trace-spans'
1515
import { decryptSecret, generateRequestId } from '@/lib/utils'
1616
import { loadDeployedWorkflowState } from '@/lib/workflows/db-helpers'
17-
import { TriggerUtils } from '@/lib/workflows/triggers'
17+
import { StartBlockPath, TriggerUtils } from '@/lib/workflows/triggers'
1818
import {
1919
createHttpResponseFromBlock,
2020
updateWorkflowRunCounts,
@@ -313,10 +313,9 @@ export async function executeWorkflow(
313313
throw new Error(errorMsg)
314314
}
315315

316-
const startBlockId = startBlock.blockId
317-
const triggerBlock = startBlock.block
316+
const { blockId: startBlockId, block: triggerBlock, path: startPath } = startBlock
318317

319-
if (triggerBlock.type !== 'starter') {
318+
if (startPath !== StartBlockPath.LEGACY_STARTER) {
320319
const outgoingConnections = serializedWorkflow.connections.filter(
321320
(conn) => conn.source === startBlockId
322321
)

apps/sim/app/api/workspaces/route.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { and, desc, eq, isNull } from 'drizzle-orm'
44
import { NextResponse } from 'next/server'
55
import { getSession } from '@/lib/auth'
66
import { createLogger } from '@/lib/logs/console/logger'
7+
import { saveWorkflowToNormalizedTables } from '@/lib/workflows/db-helpers'
8+
import { buildDefaultWorkflowArtifacts } from '@/lib/workflows/defaults'
79

810
const logger = createLogger('Workspaces')
911

@@ -137,6 +139,13 @@ async function createWorkspace(userId: string, name: string) {
137139
`Created workspace ${workspaceId} with initial workflow ${workflowId} for user ${userId}`
138140
)
139141
})
142+
143+
const { workflowState } = buildDefaultWorkflowArtifacts()
144+
const seedResult = await saveWorkflowToNormalizedTables(workflowId, workflowState)
145+
146+
if (!seedResult.success) {
147+
throw new Error(seedResult.error || 'Failed to seed default workflow state')
148+
}
140149
} catch (error) {
141150
logger.error(`Failed to create workspace ${workspaceId} with initial workflow:`, error)
142151
throw error

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/deploy-modal.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { getEnv } from '@/lib/env'
1717
import { createLogger } from '@/lib/logs/console/logger'
1818
import { cn } from '@/lib/utils'
1919
import type { WorkflowDeploymentVersionResponse } from '@/lib/workflows/db-helpers'
20+
import { resolveStartCandidates, StartBlockPath } from '@/lib/workflows/triggers'
2021
import {
2122
DeployForm,
2223
DeploymentInfo,
@@ -120,13 +121,17 @@ export function DeployModal({
120121
let inputFormatExample = ''
121122
try {
122123
const blocks = Object.values(useWorkflowStore.getState().blocks)
124+
const candidates = resolveStartCandidates(useWorkflowStore.getState().blocks, {
125+
execution: 'api',
126+
})
123127

124-
// Check for start_trigger first, then API trigger, then legacy starter
125-
const startTriggerBlock = blocks.find((block) => block.type === 'start_trigger')
126-
const apiTriggerBlock = blocks.find((block) => block.type === 'api_trigger')
127-
const starterBlock = blocks.find((block) => block.type === 'starter')
128+
const targetCandidate =
129+
candidates.find((candidate) => candidate.path === StartBlockPath.UNIFIED) ||
130+
candidates.find((candidate) => candidate.path === StartBlockPath.SPLIT_API) ||
131+
candidates.find((candidate) => candidate.path === StartBlockPath.SPLIT_INPUT) ||
132+
candidates.find((candidate) => candidate.path === StartBlockPath.LEGACY_STARTER)
128133

129-
const targetBlock = startTriggerBlock || apiTriggerBlock || starterBlock
134+
const targetBlock = targetCandidate?.block
130135

131136
if (targetBlock) {
132137
const inputFormat = useSubBlockStore.getState().getValue(targetBlock.id, 'inputFormat')

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts

Lines changed: 56 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { v4 as uuidv4 } from 'uuid'
33
import { createLogger } from '@/lib/logs/console/logger'
44
import { buildTraceSpans } from '@/lib/logs/execution/trace-spans/trace-spans'
55
import { processStreamingBlockLogs } from '@/lib/tokenization'
6-
import { TriggerUtils } from '@/lib/workflows/triggers'
6+
import { resolveStartCandidates, StartBlockPath, TriggerUtils } from '@/lib/workflows/triggers'
77
import type { BlockOutput } from '@/blocks/types'
88
import { Executor } from '@/executor'
99
import type { BlockLog, ExecutionResult, StreamingExecution } from '@/executor/types'
@@ -824,132 +824,76 @@ export function useWorkflowExecution() {
824824

825825
startBlockId = startBlock.blockId
826826
} else {
827-
// For manual editor runs: look for Manual trigger OR API trigger
828-
const entries = Object.entries(filteredStates)
829-
830-
// Find manual triggers and API triggers
831-
const manualTriggers = TriggerUtils.findTriggersByType(filteredStates, 'manual')
832-
const apiTriggers = TriggerUtils.findTriggersByType(filteredStates, 'api')
833-
834-
logger.info('Manual run trigger check:', {
835-
manualTriggersCount: manualTriggers.length,
836-
apiTriggersCount: apiTriggers.length,
837-
manualTriggers: manualTriggers.map((t) => ({
838-
type: t.type,
839-
name: t.name,
840-
isLegacy: t.type === 'starter',
841-
})),
842-
apiTriggers: apiTriggers.map((t) => ({
843-
type: t.type,
844-
name: t.name,
845-
isLegacy: t.type === 'starter',
827+
const candidates = resolveStartCandidates(filteredStates, {
828+
execution: 'manual',
829+
})
830+
831+
logger.info('Manual run start candidates:', {
832+
count: candidates.length,
833+
paths: candidates.map((candidate) => ({
834+
path: candidate.path,
835+
type: candidate.block.type,
836+
name: candidate.block.name,
846837
})),
847838
})
848839

849-
let selectedTrigger: any = null
850-
let selectedBlockId: string | null = null
851-
852-
// Check for API triggers first (they take precedence over manual triggers)
853-
if (apiTriggers.length === 1) {
854-
selectedTrigger = apiTriggers[0]
855-
const blockEntry = entries.find(([, block]) => block === selectedTrigger)
856-
if (blockEntry) {
857-
selectedBlockId = blockEntry[0]
858-
859-
// Extract test values from the API trigger's inputFormat
860-
if (
861-
selectedTrigger.type === 'api_trigger' ||
862-
selectedTrigger.type === 'start_trigger' ||
863-
selectedTrigger.type === 'starter'
864-
) {
865-
const inputFormatValue = selectedTrigger.subBlocks?.inputFormat?.value
866-
const testInput = extractTestValuesFromInputFormat(inputFormatValue)
867-
868-
// Use the test input as workflow input
869-
if (Object.keys(testInput).length > 0) {
870-
finalWorkflowInput = testInput
871-
logger.info('Using trigger test values for manual run:', testInput)
872-
}
873-
}
874-
}
875-
} else if (apiTriggers.length > 1) {
840+
const apiCandidates = candidates.filter(
841+
(candidate) => candidate.path === StartBlockPath.SPLIT_API
842+
)
843+
if (apiCandidates.length > 1) {
876844
const error = new Error('Multiple API Trigger blocks found. Keep only one.')
877845
logger.error('Multiple API triggers found')
878846
setIsExecuting(false)
879847
throw error
880-
} else if (manualTriggers.length >= 1) {
881-
// No API trigger, check for manual triggers
882-
// Prefer manual_trigger over input_trigger for simple runs
883-
const manualTrigger = manualTriggers.find((t) => t.type === 'manual_trigger')
884-
const inputTrigger = manualTriggers.find((t) => t.type === 'input_trigger')
885-
886-
selectedTrigger = manualTrigger || inputTrigger || manualTriggers[0]
887-
const blockEntry = entries.find(([, block]) => block === selectedTrigger)
888-
if (blockEntry) {
889-
selectedBlockId = blockEntry[0]
890-
891-
// Extract test values from input trigger's inputFormat if it's an input_trigger or start_trigger
892-
if (
893-
selectedTrigger.type === 'input_trigger' ||
894-
selectedTrigger.type === 'start_trigger'
895-
) {
896-
const inputFormatValue = selectedTrigger.subBlocks?.inputFormat?.value
897-
const testInput = extractTestValuesFromInputFormat(inputFormatValue)
898-
899-
// Use the test input as workflow input
900-
if (Object.keys(testInput).length > 0) {
901-
finalWorkflowInput = testInput
902-
logger.info('Using trigger test values for manual run:', testInput)
903-
}
904-
}
905-
}
906-
} else {
907-
// Fallback: Check for legacy starter block
908-
const starterBlock = Object.values(filteredStates).find((block) => block.type === 'starter')
909-
if (starterBlock) {
910-
// Found a legacy starter block, use it as a manual trigger
911-
const blockEntry = Object.entries(filteredStates).find(
912-
([, block]) => block === starterBlock
913-
)
914-
if (blockEntry) {
915-
selectedBlockId = blockEntry[0]
916-
selectedTrigger = starterBlock
917-
logger.info('Using legacy starter block for manual run')
918-
}
919-
}
848+
}
920849

921-
if (!selectedBlockId || !selectedTrigger) {
922-
const error = new Error('Manual run requires a Manual, Input Form, or API Trigger block')
923-
logger.error('No manual/input or API triggers found for manual run')
850+
const selectedCandidate = apiCandidates[0] ?? candidates[0]
851+
852+
if (!selectedCandidate) {
853+
const error = new Error('Manual run requires a Manual, Input Form, or API Trigger block')
854+
logger.error('No manual/input or API triggers found for manual run')
855+
setIsExecuting(false)
856+
throw error
857+
}
858+
859+
startBlockId = selectedCandidate.blockId
860+
const selectedTrigger = selectedCandidate.block
861+
862+
if (selectedCandidate.path !== StartBlockPath.LEGACY_STARTER) {
863+
const outgoingConnections = workflowEdges.filter((edge) => edge.source === startBlockId)
864+
if (outgoingConnections.length === 0) {
865+
const triggerName = selectedTrigger.name || selectedTrigger.type
866+
const error = new Error(`${triggerName} must be connected to other blocks to execute`)
867+
logger.error('Trigger has no outgoing connections', { triggerName, startBlockId })
924868
setIsExecuting(false)
925869
throw error
926870
}
927871
}
928872

929-
if (selectedBlockId && selectedTrigger) {
930-
startBlockId = selectedBlockId
931-
932-
// Check if the trigger has any outgoing connections (except for legacy starter blocks)
933-
// Legacy starter blocks have their own validation in the executor
934-
if (selectedTrigger.type !== 'starter') {
935-
const outgoingConnections = workflowEdges.filter((edge) => edge.source === startBlockId)
936-
if (outgoingConnections.length === 0) {
937-
const triggerName = selectedTrigger.name || selectedTrigger.type
938-
const error = new Error(`${triggerName} must be connected to other blocks to execute`)
939-
logger.error('Trigger has no outgoing connections', { triggerName, startBlockId })
940-
setIsExecuting(false)
941-
throw error
942-
}
873+
if (
874+
selectedCandidate.path === StartBlockPath.SPLIT_API ||
875+
selectedCandidate.path === StartBlockPath.SPLIT_INPUT ||
876+
selectedCandidate.path === StartBlockPath.UNIFIED
877+
) {
878+
const inputFormatValue = selectedTrigger.subBlocks?.inputFormat?.value
879+
const testInput = extractTestValuesFromInputFormat(inputFormatValue)
880+
881+
if (Object.keys(testInput).length > 0) {
882+
finalWorkflowInput = testInput
883+
logger.info('Using trigger test values for manual run:', {
884+
startBlockId,
885+
testFields: Object.keys(testInput),
886+
path: selectedCandidate.path,
887+
})
943888
}
944-
945-
logger.info('Trigger found for manual run:', {
946-
startBlockId,
947-
triggerType: selectedTrigger.type,
948-
triggerName: selectedTrigger.name,
949-
isLegacyStarter: selectedTrigger.type === 'starter',
950-
usingTestValues: selectedTrigger.type === 'api_trigger',
951-
})
952889
}
890+
891+
logger.info('Trigger found for manual run:', {
892+
startBlockId,
893+
triggerType: selectedTrigger.type,
894+
triggerName: selectedTrigger.name,
895+
startPath: selectedCandidate.path,
896+
})
953897
}
954898

955899
// If we don't have a valid startBlockId at this point, throw an error

0 commit comments

Comments
 (0)