diff --git a/server/utils/imageComfy.ts b/server/utils/imageComfy.ts index 12ad676..841fc2f 100644 --- a/server/utils/imageComfy.ts +++ b/server/utils/imageComfy.ts @@ -204,16 +204,31 @@ export async function downloadEditedImage(image: { filename: string; subfolder: } function historyError(history: Record | null, promptId: string) { - const entry = history?.[promptId] as { status?: { status_str?: string; completed?: boolean } } | undefined + const entry = history?.[promptId] as { + status?: { + status_str?: string + completed?: boolean + messages?: Array<[string, Record]> + } + } | undefined const status = entry?.status?.status_str + const fromMessages = formatExecutionError(entry?.status?.messages?.find(([type]) => type === 'execution_error')?.[1]) if (status === 'interrupted') return 'Job interrupted.' - if (status === 'error') return 'Image ComfyUI reported an execution error' + if (status === 'error') return fromMessages || 'Image ComfyUI reported an execution error' if (entry?.status?.completed && !extractEditedImage(history, promptId)) { return 'Image ComfyUI finished without an output still' } return null } +function formatExecutionError(data?: Record | null) { + if (!data) return '' + const node = String(data.node_type || data.node_id || '').trim() + const message = String(data.exception_message || data.message || '').trim() + if (node && message) return `${node}: ${message}` + return message +} + export async function waitForImageEdit(opts: { promptId: string clientId: string @@ -240,7 +255,17 @@ export async function waitForImageEdit(opts: { ws.addEventListener('message', (event) => { const payload = JSON.parse(String(event.data || '{}')) as { type?: string - data?: { value?: number; max?: number; node?: string | null; prompt_id?: string } + data?: { + value?: number + max?: number + node?: string | null + prompt_id?: string + exception_message?: string + exception_type?: string + node_id?: string + node_type?: string + message?: string + } } if (payload.type === 'progress' && payload.data) { const max = Math.max(1, Number(payload.data.max || 4)) @@ -261,7 +286,7 @@ export async function waitForImageEdit(opts: { }) } if (payload.type === 'execution_error') { - finish(null, 'Image ComfyUI reported an execution error') + finish(null, formatExecutionError(payload.data) || 'Image ComfyUI reported an execution error') } }) } catch { diff --git a/server/utils/imageWorkflow.ts b/server/utils/imageWorkflow.ts index 42f889a..1e6dc69 100644 --- a/server/utils/imageWorkflow.ts +++ b/server/utils/imageWorkflow.ts @@ -1,6 +1,5 @@ import template from '../assets/workflow_flux2_klein_edit.json' -const BYPASS = 4 const IMAGE1 = '76' const IMAGE2 = '81' const SINGLE_SAVE = '9' @@ -16,7 +15,7 @@ const DUAL_NOISE = '92:105' const DUAL_SCHEDULER = '92:115' const DUAL_CFG = '92:114' -type WorkflowNode = { class_type: string; inputs: Record; mode?: number; _meta?: { title?: string } } +type WorkflowNode = { class_type: string; inputs: Record; _meta?: { title?: string } } type WorkflowGraph = Record export interface EditParams { @@ -38,7 +37,6 @@ export function buildEditWorkflow(params: EditParams) { const prefix = params.filenamePrefix || 'aigen-edit' setImage(graph, IMAGE1, params.imageName) - setImage(graph, IMAGE2, params.referenceImageName || '') setText(graph, SINGLE_PROMPT, prompt) setText(graph, DUAL_PROMPT, prompt) setText(graph, SINGLE_NEGATIVE, negative) @@ -52,16 +50,15 @@ export function buildEditWorkflow(params: EditParams) { setInput(graph, SINGLE_SAVE, 'filename_prefix', prefix) setInput(graph, DUAL_SAVE, 'filename_prefix', prefix) - for (const [id, node] of Object.entries(graph)) { - if (!node) continue - if (id === IMAGE1) { - delete node.mode - continue - } + if (dual) { + setImage(graph, IMAGE2, params.referenceImageName || '') + } + + for (const id of Object.keys(graph)) { + if (id === IMAGE1) continue const dualNode = id === IMAGE2 || id === DUAL_SAVE || id.startsWith('92:') const singleNode = id === SINGLE_SAVE || id.startsWith('75:') - if (dual ? singleNode : dualNode) node.mode = BYPASS - else delete node.mode + if (dual ? singleNode : dualNode) delete graph[id] } return graph