mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-27 15:58:11 -05:00
Allow run from block for triggers
This commit is contained in:
@@ -112,19 +112,13 @@ export const ActionBar = memo(
|
||||
const isInsideSubflow = parentId && (parentType === 'loop' || parentType === 'parallel')
|
||||
|
||||
const snapshot = activeWorkflowId ? getLastExecutionSnapshot(activeWorkflowId) : null
|
||||
const hasExecutionSnapshot = !!snapshot
|
||||
const dependenciesSatisfied = (() => {
|
||||
if (!snapshot) return false
|
||||
const incomingEdges = edges.filter((edge) => edge.target === blockId)
|
||||
if (incomingEdges.length === 0) return true
|
||||
return incomingEdges.every((edge) => snapshot.executedBlocks.includes(edge.source))
|
||||
})()
|
||||
const incomingEdges = edges.filter((edge) => edge.target === blockId)
|
||||
const isTriggerBlock = incomingEdges.length === 0
|
||||
const dependenciesSatisfied =
|
||||
isTriggerBlock ||
|
||||
(snapshot && incomingEdges.every((edge) => snapshot.executedBlocks.includes(edge.source)))
|
||||
const canRunFromBlock =
|
||||
hasExecutionSnapshot &&
|
||||
dependenciesSatisfied &&
|
||||
!isNoteBlock &&
|
||||
!isInsideSubflow &&
|
||||
!isExecuting
|
||||
dependenciesSatisfied && !isNoteBlock && !isInsideSubflow && !isExecuting
|
||||
|
||||
const handleRunFromBlockClick = useCallback(() => {
|
||||
if (!activeWorkflowId || !canRunFromBlock) return
|
||||
@@ -176,9 +170,8 @@ export const ActionBar = memo(
|
||||
{(() => {
|
||||
if (disabled) return getTooltipMessage('Run from this block')
|
||||
if (isExecuting) return 'Execution in progress'
|
||||
if (!hasExecutionSnapshot) return 'Run workflow first'
|
||||
if (!dependenciesSatisfied) return 'Run upstream blocks first'
|
||||
if (isInsideSubflow) return 'Cannot run from inside subflow'
|
||||
if (!dependenciesSatisfied) return 'Run upstream blocks first'
|
||||
return 'Run from this block'
|
||||
})()}
|
||||
</Tooltip.Content>
|
||||
|
||||
@@ -1435,16 +1435,18 @@ export function useWorkflowExecution() {
|
||||
const handleRunFromBlock = useCallback(
|
||||
async (blockId: string, workflowId: string) => {
|
||||
const snapshot = getLastExecutionSnapshot(workflowId)
|
||||
if (!snapshot) {
|
||||
const workflowEdges = useWorkflowStore.getState().edges
|
||||
const incomingEdges = workflowEdges.filter((edge) => edge.target === blockId)
|
||||
const isTriggerBlock = incomingEdges.length === 0
|
||||
|
||||
if (!snapshot && !isTriggerBlock) {
|
||||
logger.error('No execution snapshot available for run-from-block', { workflowId, blockId })
|
||||
return
|
||||
}
|
||||
|
||||
const workflowEdges = useWorkflowStore.getState().edges
|
||||
const incomingEdges = workflowEdges.filter((edge) => edge.target === blockId)
|
||||
const dependenciesSatisfied =
|
||||
incomingEdges.length === 0 ||
|
||||
incomingEdges.every((edge) => snapshot.executedBlocks.includes(edge.source))
|
||||
isTriggerBlock ||
|
||||
(snapshot && incomingEdges.every((edge) => snapshot.executedBlocks.includes(edge.source)))
|
||||
|
||||
if (!dependenciesSatisfied) {
|
||||
logger.error('Upstream dependencies not satisfied for run-from-block', {
|
||||
@@ -1454,10 +1456,20 @@ export function useWorkflowExecution() {
|
||||
return
|
||||
}
|
||||
|
||||
// For trigger blocks with no snapshot, create an empty one
|
||||
const effectiveSnapshot: SerializableExecutionState = snapshot || {
|
||||
blockStates: {},
|
||||
executedBlocks: [],
|
||||
blockLogs: [],
|
||||
decisions: { router: {}, condition: {} },
|
||||
completedLoops: [],
|
||||
activeExecutionPath: [],
|
||||
}
|
||||
|
||||
logger.info('Starting run-from-block execution', {
|
||||
workflowId,
|
||||
startBlockId: blockId,
|
||||
snapshotExecutedBlocks: snapshot.executedBlocks.length,
|
||||
isTriggerBlock,
|
||||
})
|
||||
|
||||
setIsExecuting(true)
|
||||
@@ -1471,7 +1483,7 @@ export function useWorkflowExecution() {
|
||||
await executionStream.executeFromBlock({
|
||||
workflowId,
|
||||
startBlockId: blockId,
|
||||
sourceSnapshot: snapshot,
|
||||
sourceSnapshot: effectiveSnapshot,
|
||||
callbacks: {
|
||||
onExecutionStarted: (data) => {
|
||||
logger.info('Run-from-block execution started:', data)
|
||||
@@ -1579,21 +1591,23 @@ export function useWorkflowExecution() {
|
||||
|
||||
onExecutionCompleted: (data) => {
|
||||
if (data.success) {
|
||||
const mergedBlockStates: Record<string, BlockState> = { ...snapshot.blockStates }
|
||||
const mergedBlockStates: Record<string, BlockState> = {
|
||||
...effectiveSnapshot.blockStates,
|
||||
}
|
||||
for (const [bId, state] of accumulatedBlockStates) {
|
||||
mergedBlockStates[bId] = state
|
||||
}
|
||||
|
||||
const mergedExecutedBlocks = new Set([
|
||||
...snapshot.executedBlocks,
|
||||
...effectiveSnapshot.executedBlocks,
|
||||
...executedBlockIds,
|
||||
])
|
||||
|
||||
const updatedSnapshot: SerializableExecutionState = {
|
||||
...snapshot,
|
||||
...effectiveSnapshot,
|
||||
blockStates: mergedBlockStates,
|
||||
executedBlocks: Array.from(mergedExecutedBlocks),
|
||||
blockLogs: [...snapshot.blockLogs, ...accumulatedBlockLogs],
|
||||
blockLogs: [...effectiveSnapshot.blockLogs, ...accumulatedBlockLogs],
|
||||
activeExecutionPath: Array.from(mergedExecutedBlocks),
|
||||
}
|
||||
setLastExecutionSnapshot(workflowId, updatedSnapshot)
|
||||
|
||||
@@ -1012,18 +1012,17 @@ const WorkflowContent = React.memo(() => {
|
||||
}
|
||||
const block = contextMenuBlocks[0]
|
||||
const snapshot = getLastExecutionSnapshot(workflowIdParam)
|
||||
if (!snapshot) return { canRun: false, reason: 'Run workflow first' }
|
||||
|
||||
const incomingEdges = edges.filter((edge) => edge.target === block.id)
|
||||
const isTriggerBlock = incomingEdges.length === 0
|
||||
const dependenciesSatisfied =
|
||||
incomingEdges.length === 0 ||
|
||||
incomingEdges.every((edge) => snapshot.executedBlocks.includes(edge.source))
|
||||
isTriggerBlock ||
|
||||
(snapshot && incomingEdges.every((edge) => snapshot.executedBlocks.includes(edge.source)))
|
||||
const isNoteBlock = block.type === 'note'
|
||||
const isInsideSubflow =
|
||||
block.parentId && (block.parentType === 'loop' || block.parentType === 'parallel')
|
||||
|
||||
if (!dependenciesSatisfied) return { canRun: false, reason: 'Run upstream blocks first' }
|
||||
if (isInsideSubflow) return { canRun: false, reason: 'Cannot run from inside subflow' }
|
||||
if (!dependenciesSatisfied) return { canRun: false, reason: 'Run upstream blocks first' }
|
||||
if (isNoteBlock) return { canRun: false, reason: undefined }
|
||||
if (isExecuting) return { canRun: false, reason: undefined }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user