Skip to content

feat(ui): add Use Cache and Save To Gallery to the form builder, make them connectable - #9456

Open
Pfannkuchensack wants to merge 2 commits into
invoke-ai:mainfrom
Pfannkuchensack:feat/node-settings-form-and-connections
Open

feat(ui): add Use Cache and Save To Gallery to the form builder, make them connectable#9456
Pfannkuchensack wants to merge 2 commits into
invoke-ai:mainfrom
Pfannkuchensack:feat/node-settings-form-and-connections

Conversation

@Pfannkuchensack

Copy link
Copy Markdown
Collaborator

Summary

Feature (frontend + backend). Adds the two node footer toggles — Use Cache and Save To Gallery — to the workflow form builder, and makes their underlying fields connectable.

Why

Every other node control can be placed in a workflow's form. These two could not, because they are node attributes: their value lives on node.data.useCache / node.data.isIntermediate, not in node.data.inputs, so the existing node-field form element cannot address them.

How

1. A node-setting form element (features/nodes/types/workflow.ts)

Parallel to node-field, holding { nodeId, setting, label }. Added to the form the same way node fields are: a +/ button revealed on hover in the node footer, or by dragging the setting's label into the form. The label is editable on double-click — two nodes' "Use Cache" entries would otherwise be indistinguishable in a form.

Rendered as a Switch to match how BooleanField inputs render. Settings that no longer apply to their node are hidden in view mode and flagged in edit mode; use_cache stays admin-only, mirroring the node footer.

2. The fields become connection targets

BaseInvocation already declares both as ordinary pydantic fields, so the backend change is small: both now declare Input.Any, and is_intermediate drops its ui_type=_IsIntermediate, which had made it parse as its own field type that no BooleanField output could connect to.

The interesting part is that this needs no workflow migration:

before after
In invocation template filtered out parsed in (needed for handle + connection validation)
In node's input list still filtered out (rendered in the footer instead)
Field instance in node.data.inputs none still nonebuildInvocationNode skips them, and updateNode derives its allowed keys from there
Value storage node.data.useCache unchanged
buildNodesGraph writes the literal unchanged — the edge is emitted from state.edges and the backend overwrites the literal on resolution

Edge values are applied in GraphExecutionState.next() before the invocation is handed to the invoker, so a connected use_cache is resolved by the time the cache is consulted, and a connected is_intermediate by the time the image is saved.

3. Guards against edges that would do nothing

The footer hosts the handles, and useWithFooter only renders it for executable nodes with a gallery output. Connections to node attribute fields on any other node are rejected — there would be no handle to attach to, and buildNodesGraph drops batch and generator nodes entirely.

When an edge drives a setting, the node's checkbox is removed (matching how a connected input field renders) and the form's toggle is disabled, since the local value is no longer what the node runs with.

4. Layout

The footer became one row per setting so each connection handle lines up with its own label, following InputFieldWrapper. This makes affected nodes ~16px taller. UseCacheCheckbox / SaveToGalleryCheckbox are consolidated into one NodeSettingFooterControl; useIsBatchNode and useNodeHasGalleryOutput were absorbed into shared predicates in types/invocation.ts.

Notes for reviewers

  • use_cache is only reachable on nodes with a gallery output. That is pre-existing (useWithFooter = isExecutableNode && hasGalleryOutput) and this PR deliberately does not widen it — the connection guard just matches reality. Happy to change it if that gate is considered a bug.
  • The is_intermediate inversion remains. An edge carries is_intermediate, the UI says "Save To Gallery". Connecting a boolean node means thinking inverted. Fixing that properly means either a dedicated renderer or renaming the backend field to save_to_gallery; both felt out of scope here.
  • The Canvas workflow integration preview skips node settings — it renders a saved workflow, not the editor state the toggle would write to.

Related Issues / Discussions

QA Instructions

Form builder

  1. Workflow editor → a node with a gallery output (e.g. Latents to Image). Hover the footer → + buttons appear next to both settings.
  2. Click + on Use Cache → it appears in the form; the button becomes .
  3. Toggle it in the form → the node's checkbox follows, and vice versa.
  4. Double-click the label in the form builder → rename it; the custom label persists after reload.
  5. Drag the setting by its label into the form → same result as +.
  6. Delete the node → its settings disappear from the form.

Connections
7. Add a Boolean Primitive, drag from its Value output onto the Use Cache handle on the footer's left edge → the edge connects, and the checkbox disappears (the edge now supplies the value).
8. If the setting is also in the form, its toggle is now disabled.
9. Try connecting to a node with no gallery output (e.g. Add Integers) → no handle is offered.
10. Invoke → the connected value is what the node runs with.

Regression
11. Confirm use_cache / is_intermediate do not appear in any node's input list.
12. Load a workflow saved before this PR → unchanged; no migration warnings.

Merge Plan

Nothing special.

Checklist

  • The PR has a short but descriptive title, suitable for a changelog
  • Tests added / updated (if applicable)
  • ❗Changes to a redux slice have a corresponding migration — n/a, additive only (see Merge Plan)
  • Documentation added / updated (if applicable)
  • Updated What's New copy (if doing a release after this PR)

… them connectable

The two node footer toggles were the only node controls that could not be
added to a workflow's form, because they are node attributes stored on
`node.data` rather than input fields in `node.data.inputs`.

Add a `node-setting` form element type for them, with an add/remove button and
drag handle in the node footer mirroring how node fields are added. The label is
editable, since two nodes' "Use Cache" entries would otherwise be
indistinguishable in a form.

Also expose the underlying fields as connection targets. `BaseInvocation`
already declares `is_intermediate` and `use_cache` as pydantic fields, so they
only needed `Input.Any` and, for `is_intermediate`, dropping the `_IsIntermediate`
ui_type that prevented a BooleanField output from connecting. The frontend now
parses them into invocation templates - required for handles and connection
validation - but still filters them out of the node's input list and never
creates field instances for them. Their value keeps living on the node, so
`buildNodesGraph` is unchanged and no workflow migration is needed. Graph
execution applies edge values in `GraphExecutionState.next()`, before the cache
is consulted and before the output image is saved.

Node attribute fields are only reachable on nodes that render a footer, so
connections to them are rejected elsewhere - otherwise the edge would have no
handle to attach to and, on batch and generator nodes, no effect at all. When an
edge drives a setting, the node's checkbox is dropped and the form's toggle is
disabled, since the local value is no longer what the node runs with.
@github-actions github-actions Bot added python PRs that change python files invocations PRs that change invocations frontend PRs that change frontend files python-tests PRs that change python tests labels Aug 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend PRs that change frontend files invocations PRs that change invocations python PRs that change python files python-tests PRs that change python tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant