From 26fa84ce1b8df0463decfbce6e0be16482ef96ab Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Sun, 22 Feb 2026 16:40:43 -0800 Subject: [PATCH] docs: add widget serialization reference (widget.serialize vs widget.options.serialize) (#9102) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documents the distinction between `widget.serialize` (workflow persistence, checked by `LGraphNode.serialize()`) and `widget.options.serialize` (API prompt, checked by `executionUtil.ts`). These share a property name but live at different levels of the widget object and are consumed by different code paths — a common source of confusion when debugging serialization bugs. Includes: - Explanation of both properties with code references - Permutation table of the 4 possible combinations with real examples - Gotchas section covering the `addWidget` options bag behavior and `PrimitiveNode` dynamic widgets - Reference added to `src/lib/litegraph/AGENTS.md` Context: discovered while debugging #1757 (PrimitiveNode `control_after_generate` lost on copy-paste). ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9102-docs-add-widget-serialization-reference-widget-serialize-vs-widget-options-serialize-30f6d73d365081cd86add44bdaa20d30) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action --- docs/WIDGET_SERIALIZATION.md | 33 +++++++++++++++++++++++++++++++++ src/lib/litegraph/AGENTS.md | 4 ++++ 2 files changed, 37 insertions(+) create mode 100644 docs/WIDGET_SERIALIZATION.md diff --git a/docs/WIDGET_SERIALIZATION.md b/docs/WIDGET_SERIALIZATION.md new file mode 100644 index 000000000..f2cca7d0e --- /dev/null +++ b/docs/WIDGET_SERIALIZATION.md @@ -0,0 +1,33 @@ +# Widget Serialization: `widget.serialize` vs `widget.options.serialize` + +Two properties named `serialize` exist at different levels of a widget object. They control different serialization layers and are checked by completely different code paths. + +**`widget.serialize`** — Controls **workflow persistence**. Checked by `LGraphNode.serialize()` and `configure()` when reading/writing `widgets_values` in the workflow JSON. When `false`, the widget is skipped in both serialization and deserialization. Used for UI-only widgets (image previews, progress text, audio players). Typed as `IBaseWidget.serialize` in `src/lib/litegraph/src/types/widgets.ts`. + +**`widget.options.serialize`** — Controls **prompt/API serialization**. Checked by `executionUtil.ts` when building the API payload sent to the backend. When `false`, the widget is excluded from prompt inputs. Used for client-side-only controls (`control_after_generate`, combo filter lists) that the server doesn't need. Not currently typed in `IWidgetOptions` — set at runtime via the options bag. + +These correspond to the two data formats in `ComfyMetadata` embedded in output files (PNG, GLTF, WebM, AVIF, etc.): `widget.serialize` → `ComfyMetadataTags.WORKFLOW`, `widget.options.serialize` → `ComfyMetadataTags.PROMPT`. + +## Permutation table + +| `widget.serialize` | `widget.options.serialize` | In workflow? | In prompt? | Examples | +| ------------------ | -------------------------- | ------------ | ---------- | -------------------------------------------------------------------- | +| ✅ default | ✅ default | Yes | Yes | seed, cfg, sampler_name | +| ✅ default | ❌ false | Yes | No | control_after_generate, combo filter list | +| ❌ false | ✅ default | No | Yes | No current usage (would be a transient value computed at queue time) | +| ❌ false | ❌ false | No | No | Image/video previews, audio players, progress text | + +## Gotchas + +- `addWidget('combo', name, value, cb, { serialize: false })` puts `serialize` into `widget.options`, **not** onto `widget` directly. These are different properties consumed by different systems. +- `LGraphNode.serialize()` checks `widget.serialize === false` (line 967). It does **not** check `widget.options.serialize`. A widget with `options.serialize = false` is still included in `widgets_values`. +- `LGraphNode.serialize()` only writes `widgets_values` if `this.widgets` is truthy. Nodes that create widgets dynamically (like `PrimitiveNode`) will have no `widgets_values` in serialized output if serialized before widget creation — even if `this.widgets_values` exists on the instance from a prior `configure()` call. +- `widget.options.serialize` is not typed in `IWidgetOptions`. If you add it to the type definition, update this doc. + +## Code references + +- `widget.serialize` checked: `src/lib/litegraph/src/LGraphNode.ts` serialize() and configure() +- `widget.options.serialize` checked: `src/utils/executionUtil.ts` +- `widget.options.serialize` set: `src/scripts/widgets.ts` addValueControlWidgets() +- `widget.serialize` set: `src/composables/node/useNodeImage.ts`, `src/extensions/core/previewAny.ts`, etc. +- Metadata types: `src/types/metadataTypes.ts` diff --git a/src/lib/litegraph/AGENTS.md b/src/lib/litegraph/AGENTS.md index 49d73b505..7aecd566f 100644 --- a/src/lib/litegraph/AGENTS.md +++ b/src/lib/litegraph/AGENTS.md @@ -6,6 +6,10 @@ - Avoid repetition where possible, but not at expense of legibility - Prefer running single tests, not the whole suite, for performance +## Widget Serialization + +See `docs/WIDGET_SERIALIZATION.md` for the distinction between `widget.serialize` (workflow persistence) and `widget.options.serialize` (API prompt). These are different properties checked by different code paths — a common source of confusion. + ## Code Style - Prefer single line `if` syntax for concise expressions