fix(ui): recall the right VAE and text encoder per model base - #9489
Open
Pfannkuchensack wants to merge 2 commits into
Open
fix(ui): recall the right VAE and text encoder per model base#9489Pfannkuchensack wants to merge 2 commits into
Pfannkuchensack wants to merge 2 commits into
Conversation
Several bases write their standalone VAE / text encoder into the shared `metadata.vae` and `metadata.qwen3_encoder` fields but recall them into their own params slot. The generic handlers did not account for that: - `VAEModel` excluded z-image, flux2 and krea-2 but not anima, so an Anima image rendered a duplicate VAE row and additionally wrote its VAE into the shared `params.vae` slot, which no Anima graph reads. - `Qwen3EncoderModel` had no base gate at all while dispatching hard into the Z-Image slots, so Anima and FLUX.2 Klein images pushed their encoder into `zImageQwen3EncoderModel` and cleared `zImageQwen3SourceModel` on the way. - The Anima handlers gated only on the currently selected base, never on the image's own `metadata.model.base`, so a Krea-2 image recalled while Anima was selected wrote its VAE into the Anima slot. Replace the growing `base !== 'x' && ...` chain with a documented `BASES_WITH_DEDICATED_VAE_HANDLER` set, rename `Qwen3EncoderModel` to `ZImageQwen3EncoderModel` and gate it on z-image, and harden both Anima handlers with `assertMetadataModelBase` (plus a base assert on the VAE, which is base-identified - the encoder is variant-identified, so it deliberately gets none). The same slot mismatch existed for FLUX.1, whose VAE lives in `params.fluxVAE`: its recall silently landed in `params.vae` and had no effect on generation. Add a dedicated `Flux1VAEModel` handler for it. Finally, `AnimaVAEModel`, `AnimaQwen3EncoderModel`, `Flux1VAEModel` and the three Z-Image handlers were missing from IMAGE_METADATA_ACTION_HANDLERS, so those parameters had neither a row nor a per-parameter recall button. List them, and add a guard test that diffs the UI list against the handler registry with an explicit allowlist, so the list cannot drift behind again.
Workflows only carry recallable parameters if the graph builds the metadata itself. `metadata_linked.py` offers two ways to do that: chaining Metadata Item Linked nodes, or a denoise node that writes its own metadata - but the latter existed only for SD, FLUX.1 and Z-Image. Add `anima_denoise_meta`, mirroring `z_image_denoise_meta`, with two Anima specifics: - The CFG value is recorded as `cfg_scale`, matching both the Anima graph builder and the UI's recall handler. Z-Image writes `guidance`, which for Anima would land in the FLUX guidance param instead. - The VAE and Qwen3 encoder are exposed as optional inputs. Anima loads both standalone, so unlike SD/FLUX they cannot be derived from the transformer field, and without them a recalled Anima image would be missing exactly the two components that are hardest to pick by hand. Unconnected inputs write nothing rather than a null the recall handlers would fail to resolve.
Pfannkuchensack
requested review from
JPPhoto,
blessedcoolant,
dunkeroni and
lstein
as code owners
August 10, 2026 19:20
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Model-specific VAEs and text encoders were recalled into the wrong Redux slot, or not recallable at all, depending on the model base. This fixes the gating, wires the missing handlers into the recall UI, and adds the Anima denoise node needed to produce that metadata from a workflow.
Several bases keep their standalone components in dedicated params slots (
params.fluxVAE,params.animaVaeModel, …) but record them in the sharedmetadata.vae/metadata.qwen3_encoderfields. Whether a handler may fire therefore depends on two axes: where the image came from (metadata.model.base) and which base is currently selected (which decides which slot is live). Neither axis was checked consistently.What was broken
params.vaeslotVAEModelexcludedz-image,flux2,krea-2— but notanimazImageQwen3SourceModelQwen3EncoderModelhad no base gate at all, yet dispatched hard into the Z-Image slotsparams.fluxVAE, the generic handler writesparams.vae— no handler ever dispatchedfluxVAESelectedIMAGE_METADATA_ACTION_HANDLERSmetadata_linked.pyhad a self-recording denoise node for SD, FLUX.1 and Z-Image, but not for AnimaThe first three were partly self-healing — the
modelSelectedlistener clears foreign slots on the next model switch — but the panel stayed wrong and a user's Z-Image encoder selection was silently dropped.Changes
features/metadata/parsing.tsxBASES_WITH_DEDICATED_VAE_HANDLERset replaces thebase !== 'x' && …chain inVAEModel, documenting per base which slot and handler own it.qwen-imageandwanare deliberately absent — they writeqwen_image_vae/wan_vae_modeland never collide.Flux1VAEModelhandler dispatchingfluxVAESelected.Qwen3EncoderModel→ZImageQwen3EncoderModel, gated onbase === 'z-image'. A variant-based check would not work here:isQwen3EncoderModelConfigis defined asvariant !== 'qwen3_06b', which Klein encoders satisfy too — and the slot choice is a property of the main model, not of the encoder.assertMetadataModelBase. The VAE additionally assertsparsed.base === 'anima'(meaningful, sinceisAnimaVAEModelConfigis base-driven); the encoder deliberately gets no base assert, since Anima encoders are identified byvariant— with a comment saying so, to stop a future cleanup from "fixing" it.ImageMetadataViewer/ImageMetadataActions.tsx— listFlux1VAEModel,ZImageVAEModel,ZImageQwen3EncoderModel,ZImageQwen3SourceModel,AnimaVAEModel,AnimaQwen3EncoderModel. ListingFlux1VAEModelis mandatory, not cosmetic: without it, addingfluxto the exclusion set would remove the FLUX.1 VAE row outright.invocations/metadata_linked.py— newanima_denoise_metanode ("Denoise - Anima + Metadata"), mirroringz_image_denoise_metawith two Anima specifics: the CFG value is recorded ascfg_scale(Z-Image writesguidance, which for Anima would land in the FLUX guidance param), and the standalone VAE / Qwen3 encoder are optional inputs, since Anima cannot derive them from the transformer field. Unconnected inputs write nothing rather than a null the recall handlers would fail to resolve.schema.tsregenerated.Tests
parsing.test.tsx: gating forAnimaVAEModel(incl. rejecting Krea-2 provenance and metadata with nomodelat all),AnimaQwen3EncoderModel(incl. pinning that any encoder base parses),ZImageQwen3EncoderModel,Flux1VAEModel; the genericVAEModelmatrix extended byfluxandanima.ImageMetadataActions.test.tsx: atoContaincheck for the six newly listed handlers, plus a guard test that diffs the whole registry against the UI list. Its allowlist is split into "hidden by design" (CreatedBy,ImageSize) and a commented snapshot of pre-existing gaps (HiDiffusion, Wan, Qwen-Image sub-models, Gemini/OpenAI/Seedream, Z-Image seed variance) — meant to shrink, not grow.test_denoise_noise_inputs.py: the seed-selection case matching the FLUX / Z-Image tests, plus one that pins the metadata keys against the recall contract (cfg_scaleset,guidanceabsent, model / VAE / encoder recorded) and one that checks unconnected component inputs are omitted.pnpm lint,pnpm lint:tsc, the full frontend suite (1809 tests / 144 files),ruff, and the touched pytest modules all pass.Out of scope
T5EncoderModelhas the same missing base gate and writes into the FLUX.1 T5 slot. Left alone deliberately.*_denoise_metacounterpart either; only Anima is added here.model(withbase: "anima") in the metadata for the Anima VAE / encoder rows to recall. The new node always writes it; a hand-built Metadata Item Linked chain that omits it will not recall those two fields.Manual verification