fix: disable control after generate during partial execution (#8774)

## Summary
Passes an isPartialExecution flag through widget
beforeQueued/afterQueued callbacks so control-after-generate widgets
skip value modifications (randomize, increment, decrement) when the user
queues selected output nodes via partial execution.

requested by @christian-byrne in notion

## Screenshots (if applicable)
before


https://github.com/user-attachments/assets/3e723087-8849-457b-9f95-b8b5fceab0ed


after


https://github.com/user-attachments/assets/d9816667-51e0-4538-a012-9c84d0944019

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8774-fix-disable-control-after-generate-during-partial-execution-3036d73d365081688ca3d6b0506d69ca)
by [Unito](https://www.unito.io)
This commit is contained in:
Terry Jia
2026-02-10 20:13:03 -05:00
committed by GitHub
parent 7f30d6b6a5
commit f7b835e6a5
4 changed files with 15 additions and 10 deletions

View File

@@ -1389,11 +1389,13 @@ export class ComfyApp {
'Comfy.Execution.PreviewMethod'
)
const isPartialExecution = !!queueNodeIds?.length
for (let i = 0; i < batchCount; i++) {
// Allow widgets to run callbacks before a prompt has been queued
// e.g. random seed before every gen
forEachNode(this.rootGraph, (node) => {
for (const widget of node.widgets ?? []) widget.beforeQueued?.()
for (const widget of node.widgets ?? [])
widget.beforeQueued?.({ isPartialExecution })
})
const p = await this.graphToPrompt(this.rootGraph)
@@ -1449,7 +1451,9 @@ export class ComfyApp {
// Allow widgets to run callbacks after a prompt has been queued
// e.g. random seed after every gen
executeWidgetsCallback(queuedNodes, 'afterQueued')
executeWidgetsCallback(queuedNodes, 'afterQueued', {
isPartialExecution
})
this.canvas.draw(true, true)
await this.ui.queue.update()
}

View File

@@ -273,8 +273,8 @@ export function addValueControlWidgets(
}
}
valueControl.beforeQueued = () => {
if (controlValueRunBefore()) {
valueControl.beforeQueued = ({ isPartialExecution } = {}) => {
if (!isPartialExecution && controlValueRunBefore()) {
// Don't run on first execution
if (valueControl[HAS_EXECUTED]) {
applyWidgetControl()
@@ -283,8 +283,8 @@ export function addValueControlWidgets(
valueControl[HAS_EXECUTED] = true
}
valueControl.afterQueued = () => {
if (!controlValueRunBefore()) {
valueControl.afterQueued = ({ isPartialExecution } = {}) => {
if (!isPartialExecution && !controlValueRunBefore()) {
applyWidgetControl()
}
}

View File

@@ -47,8 +47,8 @@ declare module '@/lib/litegraph/src/types/widgets' {
interface IBaseWidget {
onRemove?(): void
beforeQueued?(): unknown
afterQueued?(): unknown
beforeQueued?(options?: { isPartialExecution?: boolean }): unknown
afterQueued?(options?: { isPartialExecution?: boolean }): unknown
serializeValue?(node: LGraphNode, index: number): Promise<unknown> | unknown
/**

View File

@@ -83,11 +83,12 @@ export const getItemsColorOption = (items: unknown[]): ColorOption | null => {
export function executeWidgetsCallback(
nodes: LGraphNode[],
callbackName: 'onRemove' | 'beforeQueued' | 'afterQueued'
callbackName: 'onRemove' | 'beforeQueued' | 'afterQueued',
options?: { isPartialExecution?: boolean }
) {
for (const node of nodes) {
for (const widget of node.widgets ?? []) {
widget[callbackName]?.()
widget[callbackName]?.(options)
}
}
}