Merge remote-tracking branch 'origin/main' into js/async_nodes

This commit is contained in:
Jacob Segal
2025-07-16 10:41:50 -07:00
36 changed files with 4947 additions and 1058 deletions

View File

@@ -1,5 +1,11 @@
import { LiteGraph } from '@comfyorg/litegraph'
import { LGraphNode, type NodeId } from '@comfyorg/litegraph/dist/LGraphNode'
import {
type ExecutableLGraphNode,
type ExecutionId,
LGraphNode,
LiteGraph,
SubgraphNode
} from '@comfyorg/litegraph'
import { type NodeId } from '@comfyorg/litegraph/dist/LGraphNode'
import { t } from '@/i18n'
import {
@@ -14,6 +20,8 @@ import { useNodeDefStore } from '@/stores/nodeDefStore'
import { useToastStore } from '@/stores/toastStore'
import { useWidgetStore } from '@/stores/widgetStore'
import { ComfyExtension } from '@/types/comfy'
import { ExecutableGroupNodeChildDTO } from '@/utils/executableGroupNodeChildDTO'
import { GROUP } from '@/utils/executableGroupNodeDto'
import { deserialiseAndCreate, serialise } from '@/utils/vintageClipboard'
import { api } from '../../scripts/api'
@@ -27,8 +35,6 @@ type GroupNodeWorkflowData = {
nodes: ComfyNode[]
}
const GROUP = Symbol()
// v1 Prefix + Separator: workflow/
// v2 Prefix + Separator: workflow> (ComfyUI_frontend v1.2.63)
const PREFIX = 'workflow'
@@ -814,6 +820,7 @@ export class GroupNodeHandler {
innerNodeIndex++
) {
const innerNode = this.innerNodes[innerNodeIndex]
innerNode.graph ??= this.node.graph
for (const w of innerNode.widgets ?? []) {
if (w.type === 'converted-widget') {
@@ -900,7 +907,20 @@ export class GroupNodeHandler {
return link
}
this.node.getInnerNodes = () => {
/** @internal Used to flatten the subgraph before execution. Recursive; call with no args. */
this.node.getInnerNodes = (
computedNodeDtos: Map<ExecutionId, ExecutableLGraphNode>,
/** The path of subgraph node IDs. */
subgraphNodePath: readonly NodeId[] = [],
/** The list of nodes to add to. */
nodes: ExecutableLGraphNode[] = [],
/** The set of visited nodes. */
visited = new Set<LGraphNode>()
): ExecutableLGraphNode[] => {
if (visited.has(this.node))
throw new Error('RecursionError: while flattening subgraph')
visited.add(this.node)
if (!this.innerNodes) {
// @ts-expect-error fixme ts strict error
this.node.setInnerNodes(
@@ -911,6 +931,8 @@ export class GroupNodeHandler {
innerNode.configure(n)
// @ts-expect-error fixme ts strict error
innerNode.id = `${this.node.id}:${i}`
// @ts-expect-error fixme ts strict error
innerNode.graph = this.node.graph
return innerNode
})
)
@@ -918,7 +940,31 @@ export class GroupNodeHandler {
this.updateInnerWidgets()
return this.innerNodes
const subgraphInstanceIdPath = [...subgraphNodePath, this.node.id]
// Assertion: Deprecated, does not matter.
const subgraphNode = (this.node.graph?.getNodeById(
subgraphNodePath.at(-1)
) ?? undefined) as SubgraphNode | undefined
for (const node of this.innerNodes) {
node.graph ??= this.node.graph
// Create minimal DTOs rather than cloning the node
const currentId = String(node.id)
node.id = currentId.split(':').at(-1)
const aVeryRealNode = new ExecutableGroupNodeChildDTO(
node,
subgraphInstanceIdPath,
computedNodeDtos,
subgraphNode
)
node.id = currentId
aVeryRealNode.groupNodeHandler = this
nodes.push(aVeryRealNode)
}
return nodes
}
// @ts-expect-error fixme ts strict error
@@ -1506,6 +1552,9 @@ export class GroupNodeHandler {
this.linkOutputs(node, i)
app.graph.remove(node)
// Set internal ID to what is expected after workflow is reloaded
node.id = `${this.node.id}:${i}`
}
this.linkInputs()
@@ -1611,8 +1660,14 @@ async function convertSelectedNodesToGroupNode() {
if (nodes.length === 1) {
throw new Error('Please select multiple nodes to convert to group node')
}
if (nodes.some((n) => GroupNodeHandler.isGroupNode(n))) {
throw new Error('Selected nodes contain a group node')
for (const node of nodes) {
if (node instanceof SubgraphNode) {
throw new Error('Selected nodes contain a subgraph node')
}
if (GroupNodeHandler.isGroupNode(node)) {
throw new Error('Selected nodes contain a group node')
}
}
return await GroupNodeHandler.fromNodes(nodes)
}