mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-11 16:30:57 +00:00
## Summary Preview as Text (`PreviewAny`) nodes were re-executing on every prompt submission because the rendered preview text was being echoed back to the backend as input values, mutating the cache signature. ## Changes - **What**: Set `widget.options.serialize = false` on the three widgets the `Comfy.PreviewAny` extension adds (`preview_markdown`, `preview_text`, `previewMode`) so they are excluded from the API prompt sent to the backend. ## Root cause The extension was setting `widget.serialize = false`, which only controls **workflow JSON** persistence (checked in `LGraphNode.serialize`). The **API prompt** serializer in `executionUtil.graphToPrompt` checks `widget.options.serialize` instead — a distinct property documented in litegraph's `WIDGET_SERIALIZATION` convention. After `onExecuted` writes the rendered text into the widget value, the next `graphToPrompt` call serialized that text into `inputs.preview_text` / `inputs.preview_markdown`. The backend cache signature in `comfy_execution/caching.py` hashes all keys in `node["inputs"]`, so the changing text invalidated the cache and forced a redundant execution every time. ## Review Focus Two commits, red-green TDD: 1. `test:` failing unit + e2e tests asserting the desired behavior. 2. `fix:` adds `options.serialize = false` to make them pass. Tests verify the widgets are excluded from the API prompt; e2e additionally simulates a prior execution populating widget values to mirror the real bug condition. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-12010-fix-stop-PreviewAny-widgets-from-triggering-re-execution-3586d73d3650810585cdd077f3ac64f5) by [Unito](https://www.unito.io)
43 lines
1.4 KiB
TypeScript
43 lines
1.4 KiB
TypeScript
import {
|
|
comfyPageFixture as test,
|
|
comfyExpect as expect
|
|
} from '../fixtures/ComfyPage'
|
|
|
|
test.describe('Preview as Text node', () => {
|
|
test('does not include preview widget values in the API prompt', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.page.evaluate(() => {
|
|
const node = window.LiteGraph!.createNode('PreviewAny')!
|
|
node.pos = [500, 200]
|
|
window.app!.graph.add(node)
|
|
})
|
|
|
|
// Simulate a previous execution: backend returned text and the frontend
|
|
// populated the preview widget values. The next prompt submission must
|
|
// NOT echo those values back as inputs (which would change the cache
|
|
// signature and trigger a redundant re-execution).
|
|
await comfyPage.page.evaluate(() => {
|
|
const node = window.app!.graph.nodes.find((n) => n.type === 'PreviewAny')!
|
|
for (const widget of node.widgets ?? []) {
|
|
if (widget.name?.startsWith('preview_')) {
|
|
widget.value = 'rendered preview content from previous execution'
|
|
}
|
|
}
|
|
})
|
|
|
|
const apiWorkflow = await comfyPage.workflow.getExportedWorkflow({
|
|
api: true
|
|
})
|
|
|
|
const previewEntry = Object.values(apiWorkflow).find(
|
|
(n) => n.class_type === 'PreviewAny'
|
|
)
|
|
expect(previewEntry).toBeDefined()
|
|
|
|
expect(previewEntry!.inputs).not.toHaveProperty('preview_markdown')
|
|
expect(previewEntry!.inputs).not.toHaveProperty('preview_text')
|
|
expect(previewEntry!.inputs).not.toHaveProperty('previewMode')
|
|
})
|
|
})
|