Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import {
import { useCurrentWorkflow } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-current-workflow'
import {
type BlockEventHandlerConfig,
addHttpErrorConsoleEntry,
addExecutionErrorConsoleEntry as sharedAddExecutionErrorConsoleEntry,
createBlockEventHandlers,
handleExecutionCancelledConsole as sharedHandleExecutionCancelledConsole,
handleExecutionErrorConsole as sharedHandleExecutionErrorConsole,
} from '@/app/workspace/[workspaceId]/w/[workflowId]/utils/workflow-execution-utils'
import { getBlock } from '@/blocks'
import type { SerializableExecutionState } from '@/executor/execution/types'
Expand Down Expand Up @@ -159,22 +163,7 @@ export function useWorkflowExecution() {
setActiveBlocks,
])

/**
* Builds timing fields for execution-level console entries.
*/
const buildExecutionTiming = useCallback((durationMs?: number) => {
const normalizedDuration = durationMs || 0
return {
durationMs: normalizedDuration,
startedAt: new Date(Date.now() - normalizedDuration).toISOString(),
endedAt: new Date().toISOString(),
}
}, [])

/**
* Adds an execution-level error entry to the console when appropriate.
*/
const addExecutionErrorConsoleEntry = useCallback(
const handleExecutionErrorConsole = useCallback(
(params: {
workflowId?: string
executionId?: string
Expand All @@ -184,102 +173,23 @@ export function useWorkflowExecution() {
isPreExecutionError?: boolean
}) => {
if (!params.workflowId) return

const hasBlockError = params.blockLogs.some((log) => log.error)
const isPreExecutionError = params.isPreExecutionError ?? false
if (!isPreExecutionError && hasBlockError) {
return
}

const errorMessage = params.error || 'Execution failed'
const isTimeout = errorMessage.toLowerCase().includes('timed out')
const timing = buildExecutionTiming(params.durationMs)

addConsole({
input: {},
output: {},
success: false,
error: errorMessage,
durationMs: timing.durationMs,
startedAt: timing.startedAt,
executionOrder: isPreExecutionError ? 0 : Number.MAX_SAFE_INTEGER,
endedAt: timing.endedAt,
sharedHandleExecutionErrorConsole(addConsole, cancelRunningEntries, {
...params,
workflowId: params.workflowId,
blockId: isPreExecutionError
? 'validation'
: isTimeout
? 'timeout-error'
: 'execution-error',
executionId: params.executionId,
blockName: isPreExecutionError
? 'Workflow Validation'
: isTimeout
? 'Timeout Error'
: 'Execution Error',
blockType: isPreExecutionError ? 'validation' : 'error',
})
},
[addConsole, buildExecutionTiming]
[addConsole, cancelRunningEntries]
)

/**
* Adds an execution-level cancellation entry to the console.
*/
const addExecutionCancelledConsoleEntry = useCallback(
const handleExecutionCancelledConsole = useCallback(
(params: { workflowId?: string; executionId?: string; durationMs?: number }) => {
if (!params.workflowId) return

const timing = buildExecutionTiming(params.durationMs)
addConsole({
input: {},
output: {},
success: false,
error: 'Execution was cancelled',
durationMs: timing.durationMs,
startedAt: timing.startedAt,
executionOrder: Number.MAX_SAFE_INTEGER,
endedAt: timing.endedAt,
sharedHandleExecutionCancelledConsole(addConsole, cancelRunningEntries, {
...params,
workflowId: params.workflowId,
blockId: 'cancelled',
executionId: params.executionId,
blockName: 'Execution Cancelled',
blockType: 'cancelled',
})
},
[addConsole, buildExecutionTiming]
)

/**
* Handles workflow-level execution errors for console output.
*/
const handleExecutionErrorConsole = useCallback(
(params: {
workflowId?: string
executionId?: string
error?: string
durationMs?: number
blockLogs: BlockLog[]
isPreExecutionError?: boolean
}) => {
if (params.workflowId) {
cancelRunningEntries(params.workflowId)
}
addExecutionErrorConsoleEntry(params)
},
[addExecutionErrorConsoleEntry, cancelRunningEntries]
)

/**
* Handles workflow-level execution cancellations for console output.
*/
const handleExecutionCancelledConsole = useCallback(
(params: { workflowId?: string; executionId?: string; durationMs?: number }) => {
if (params.workflowId) {
cancelRunningEntries(params.workflowId)
}
addExecutionCancelledConsoleEntry(params)
},
[addExecutionCancelledConsoleEntry, cancelRunningEntries]
[addConsole, cancelRunningEntries]
)

const buildBlockEventHandlers = useCallback(
Expand Down Expand Up @@ -1319,31 +1229,43 @@ export function useWorkflowExecution() {
} else {
if (!executor) {
try {
let blockId = 'serialization'
let blockName = 'Workflow'
let blockType = 'serializer'
if (error instanceof WorkflowValidationError) {
blockId = error.blockId || blockId
blockName = error.blockName || blockName
blockType = error.blockType || blockType
const httpStatus = isRecord(error) && typeof error.httpStatus === 'number'
? error.httpStatus
: undefined
const storeAddConsole = useTerminalConsoleStore.getState().addConsole

if (httpStatus && activeWorkflowId) {
addHttpErrorConsoleEntry(storeAddConsole, {
workflowId: activeWorkflowId,
executionId: options?.executionId,
error: normalizedMessage,
httpStatus,
})
} else if (error instanceof WorkflowValidationError) {
storeAddConsole({
input: {},
output: {},
success: false,
error: normalizedMessage,
durationMs: 0,
startedAt: new Date().toISOString(),
executionOrder: Number.MAX_SAFE_INTEGER,
endedAt: new Date().toISOString(),
workflowId: activeWorkflowId || '',
blockId: error.blockId || 'serialization',
executionId: options?.executionId,
blockName: error.blockName || 'Workflow',
blockType: error.blockType || 'serializer',
})
} else {
sharedAddExecutionErrorConsoleEntry(storeAddConsole, {
workflowId: activeWorkflowId || '',
executionId: options?.executionId,
error: normalizedMessage,
blockLogs: [],
isPreExecutionError: true,
})
}

// Use MAX_SAFE_INTEGER so execution errors appear at the end of the log
useTerminalConsoleStore.getState().addConsole({
input: {},
output: {},
success: false,
error: normalizedMessage,
durationMs: 0,
startedAt: new Date().toISOString(),
executionOrder: Number.MAX_SAFE_INTEGER,
endedAt: new Date().toISOString(),
workflowId: activeWorkflowId || '',
blockId,
executionId: options?.executionId,
blockName,
blockType,
})
} catch {}
}

Expand Down Expand Up @@ -1681,8 +1603,8 @@ export function useWorkflowExecution() {
accumulatedBlockLogs,
accumulatedBlockStates,
executedBlockIds,
consoleMode: 'add',
includeStartConsoleEntry: false,
consoleMode: 'update',
includeStartConsoleEntry: true,
})

await executionStream.executeFromBlock({
Expand Down
Loading
Loading