mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-21 15:24:09 +00:00
[Refactor] Move app.graphToPrompt to executionUtil (#2664)
This commit is contained in:
@@ -38,6 +38,7 @@ import {
|
||||
} from '@/types/comfyWorkflow'
|
||||
import { ExtensionManager } from '@/types/extensionTypes'
|
||||
import { ColorAdjustOptions, adjustColor } from '@/utils/colorUtil'
|
||||
import { graphToPrompt } from '@/utils/executionUtil'
|
||||
import { isImageNode } from '@/utils/litegraphUtil'
|
||||
import { deserialiseAndCreate } from '@/utils/vintageClipboard'
|
||||
|
||||
@@ -1226,176 +1227,11 @@ export class ComfyApp {
|
||||
return graph.serialize({ sortNodes })
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the current graph workflow for sending to the API.
|
||||
* Note: Node widgets are updated before serialization to prepare queueing.
|
||||
* @returns The workflow and node links
|
||||
*/
|
||||
async graphToPrompt(graph = this.graph, clean = true) {
|
||||
for (const outerNode of graph.computeExecutionOrder(false)) {
|
||||
if (outerNode.widgets) {
|
||||
for (const widget of outerNode.widgets) {
|
||||
// Allow widgets to run callbacks before a prompt has been queued
|
||||
// e.g. random seed before every gen
|
||||
widget.beforeQueued?.()
|
||||
}
|
||||
}
|
||||
|
||||
const innerNodes = outerNode.getInnerNodes
|
||||
? outerNode.getInnerNodes()
|
||||
: [outerNode]
|
||||
for (const node of innerNodes) {
|
||||
if (node.isVirtualNode) {
|
||||
// Don't serialize frontend only nodes but let them make changes
|
||||
if (node.applyToGraph) {
|
||||
node.applyToGraph()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const workflow = this.serializeGraph(graph)
|
||||
|
||||
// Remove localized_name from the workflow
|
||||
for (const node of workflow.nodes) {
|
||||
for (const slot of node.inputs) {
|
||||
delete slot.localized_name
|
||||
}
|
||||
for (const slot of node.outputs) {
|
||||
delete slot.localized_name
|
||||
}
|
||||
}
|
||||
|
||||
const output = {}
|
||||
// Process nodes in order of execution
|
||||
for (const outerNode of graph.computeExecutionOrder(false)) {
|
||||
const skipNode =
|
||||
outerNode.mode === LGraphEventMode.NEVER ||
|
||||
outerNode.mode === LGraphEventMode.BYPASS
|
||||
const innerNodes =
|
||||
!skipNode && outerNode.getInnerNodes
|
||||
? outerNode.getInnerNodes()
|
||||
: [outerNode]
|
||||
for (const node of innerNodes) {
|
||||
if (node.isVirtualNode) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (
|
||||
node.mode === LGraphEventMode.NEVER ||
|
||||
node.mode === LGraphEventMode.BYPASS
|
||||
) {
|
||||
// Don't serialize muted nodes
|
||||
continue
|
||||
}
|
||||
|
||||
const inputs = {}
|
||||
const widgets = node.widgets
|
||||
|
||||
// Store all widget values
|
||||
if (widgets) {
|
||||
for (let i = 0; i < widgets.length; i++) {
|
||||
const widget = widgets[i]
|
||||
if (!widget.options || widget.options.serialize !== false) {
|
||||
inputs[widget.name] = widget.serializeValue
|
||||
? await widget.serializeValue(node, i)
|
||||
: widget.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store all node links
|
||||
for (let i = 0; i < node.inputs.length; i++) {
|
||||
let parent = node.getInputNode(i)
|
||||
if (parent) {
|
||||
let link = node.getInputLink(i)
|
||||
while (
|
||||
parent.mode === LGraphEventMode.BYPASS ||
|
||||
parent.isVirtualNode
|
||||
) {
|
||||
let found = false
|
||||
if (parent.isVirtualNode) {
|
||||
link = parent.getInputLink(link.origin_slot)
|
||||
if (link) {
|
||||
parent = parent.getInputNode(link.target_slot)
|
||||
if (parent) {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
} else if (link && parent.mode === LGraphEventMode.BYPASS) {
|
||||
let all_inputs = [link.origin_slot]
|
||||
if (parent.inputs) {
|
||||
// @ts-expect-error convert list of strings to list of numbers
|
||||
all_inputs = all_inputs.concat(Object.keys(parent.inputs))
|
||||
for (let parent_input in all_inputs) {
|
||||
// @ts-expect-error assign string to number
|
||||
parent_input = all_inputs[parent_input]
|
||||
if (
|
||||
parent.inputs[parent_input]?.type === node.inputs[i].type
|
||||
) {
|
||||
// @ts-expect-error convert string to number
|
||||
link = parent.getInputLink(parent_input)
|
||||
if (link) {
|
||||
// @ts-expect-error convert string to number
|
||||
parent = parent.getInputNode(parent_input)
|
||||
}
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (link) {
|
||||
if (parent?.updateLink) {
|
||||
link = parent.updateLink(link)
|
||||
}
|
||||
if (link) {
|
||||
inputs[node.inputs[i].name] = [
|
||||
String(link.origin_id),
|
||||
// @ts-expect-error link.origin_slot is already number.
|
||||
parseInt(link.origin_slot)
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const node_data = {
|
||||
inputs,
|
||||
class_type: node.comfyClass
|
||||
}
|
||||
|
||||
// Ignored by the backend.
|
||||
node_data['_meta'] = {
|
||||
title: node.title
|
||||
}
|
||||
|
||||
output[String(node.id)] = node_data
|
||||
}
|
||||
}
|
||||
|
||||
// Remove inputs connected to removed nodes
|
||||
if (clean) {
|
||||
for (const o in output) {
|
||||
for (const i in output[o].inputs) {
|
||||
if (
|
||||
Array.isArray(output[o].inputs[i]) &&
|
||||
output[o].inputs[i].length === 2 &&
|
||||
!output[output[o].inputs[i][0]]
|
||||
) {
|
||||
delete output[o].inputs[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { workflow, output }
|
||||
return graphToPrompt(graph, {
|
||||
clean,
|
||||
sortNodes: useSettingStore().get('Comfy.Workflow.SortNodeIdOnSave')
|
||||
})
|
||||
}
|
||||
|
||||
#formatPromptError(error) {
|
||||
@@ -1444,7 +1280,6 @@ export class ComfyApp {
|
||||
const p = await this.graphToPrompt()
|
||||
|
||||
try {
|
||||
// @ts-expect-error Discrepancies between zod and litegraph - in progress
|
||||
const res = await api.queuePrompt(number, p)
|
||||
this.lastNodeErrors = res.node_errors
|
||||
if (this.lastNodeErrors.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user