Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
530fd46
fix(ui): recall the right VAE and text encoder per model base
Pfannkuchensack Aug 10, 2026
59892d0
feat(nodes): add an Anima denoise node that records its own metadata
Pfannkuchensack Aug 10, 2026
84ea23e
Merge branch 'main' into fix/metadata-recall-anima-gating
Pfannkuchensack Aug 14, 2026
0d34668
Merge branch 'main' into fix/metadata-recall-anima-gating
JPPhoto Aug 18, 2026
465d0db
Merge branch 'main' into fix/metadata-recall-anima-gating
Pfannkuchensack Aug 18, 2026
902944e
Merge branch 'main' into fix/metadata-recall-anima-gating
JPPhoto Aug 18, 2026
91983cf
fix(ui): gate shared-field metadata recall on image provenance
Pfannkuchensack Aug 19, 2026
b25870b
Merge branch 'main' into fix/metadata-recall-anima-gating
Pfannkuchensack Aug 19, 2026
8feb730
fix(ui): accept 16-channel Wan VAEs for Anima recall
Pfannkuchensack Aug 20, 2026
8799228
fix(ui): reparse and revalidate metadata rows when the base changes
Pfannkuchensack Aug 20, 2026
5af9c7d
fix(ui): recall Anima VAE submodels
JPPhoto Aug 21, 2026
0068148
fix(ui): align VAE slot domains between picker, default and recall
Pfannkuchensack Aug 21, 2026
2665674
Chore typegen
Pfannkuchensack Aug 21, 2026
359787a
Fix export
Pfannkuchensack Aug 21, 2026
67f1972
fix(ui): drop the now-dead flux+flux2 VAE predicate
Pfannkuchensack Aug 21, 2026
279a81a
fix(ui): gate Qwen3 encoder recall on the variant, not just the type
Pfannkuchensack Aug 21, 2026
9eb2c08
fix(ui): validate Anima component slots and gate VAE recall on proven…
Pfannkuchensack Aug 22, 2026
9b34d60
Merge branch 'main' into fix/metadata-recall-anima-gating
Pfannkuchensack Aug 23, 2026
99f8bdc
Merge branch 'main' into fix/metadata-recall-anima-gating
lstein Aug 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions invokeai/app/invocations/metadata_linked.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from pydantic import model_validator

from invokeai.app.invocations.anima_denoise import AnimaDenoiseInvocation
from invokeai.app.invocations.baseinvocation import (
BaseInvocation,
BaseInvocationOutput,
Expand Down Expand Up @@ -34,6 +35,7 @@
LoRAField,
LoRALoaderOutput,
ModelIdentifierField,
Qwen3EncoderField,
SDXLLoRALoaderOutput,
UNetField,
VAEField,
Expand Down Expand Up @@ -793,6 +795,82 @@ def _loras_to_json(obj: Union[Any, list[Any]]):
return LatentsMetaOutput(**params, metadata=MetadataField.model_validate(md))


@invocation(
"anima_denoise_meta",
title=f"{AnimaDenoiseInvocation.UIConfig.title} + Metadata",
tags=["anima", "latents", "denoise", "txt2img", "t2i", "t2l", "img2img", "i2i", "l2l"],
category="metadata",
version="1.0.0",
classification=Classification.Prototype,
)
class AnimaDenoiseMetaInvocation(AnimaDenoiseInvocation, WithMetadata):
"""Run denoising process with an Anima transformer model + metadata."""

# Anima loads its VAE and text encoder as standalone models, so - unlike SD/FLUX, where they come out of
# the main model - they cannot be derived from the transformer field. Accept them here so a workflow can
# record the full component set the recall UI expects, without chaining extra Metadata Item Linked nodes.
vae: Optional[VAEField] = InputField(
default=None,
description="Optional. The Anima VAE, recorded to metadata so recall can restore the VAE selection.",
input=Input.Connection,
title="VAE",
)
qwen3_encoder: Optional[Qwen3EncoderField] = InputField(
default=None,
description="Optional. The Anima Qwen3 encoder, recorded to metadata so recall can restore the encoder "
"selection.",
input=Input.Connection,
title="Qwen3 Encoder",
)

def invoke(self, context: InvocationContext) -> LatentsMetaOutput:
def _loras_to_json(obj: Union[Any, list[Any]]):
if not isinstance(obj, list):
obj = [obj]

output: list[dict[str, Any]] = []
for item in obj:
output.append(
LoRAMetadataField(
model=item.lora,
weight=item.weight,
).model_dump(exclude_none=True, exclude={"id", "type", "is_intermediate", "use_cache"})
)
return output

obj = super().invoke(context)

md: Dict[str, Any] = {} if self.metadata is None else self.metadata.root
md.update({"width": obj.width})
md.update({"height": obj.height})
md.update({"steps": self.steps})
# Anima's CFG value is recorded as `cfg_scale`, matching what the Anima graph builder writes and what
# the UI's CFGScale recall handler reads - not as `guidance`, which is FLUX's guidance-embeds scale.
md.update({"cfg_scale": self.guidance_scale})
md.update({"denoising_start": self.denoising_start})
md.update({"denoising_end": self.denoising_end})
md.update({"scheduler": self.scheduler})
md.update({"model": self.transformer.transformer})
md.update(
{
"seed": self.noise.seed
if self.noise is not None and self.noise.seed is not None and (self.latents is None or self.add_noise)
else self.seed
}
)
if self.vae is not None:
md.update({"vae": self.vae.vae})
if self.qwen3_encoder is not None:
md.update({"qwen3_encoder": self.qwen3_encoder.text_encoder})
if len(self.transformer.loras) > 0:
md.update({"loras": _loras_to_json(self.transformer.loras)})

params = obj.__dict__.copy()
del params["type"]

return LatentsMetaOutput(**params, metadata=MetadataField.model_validate(md))


@invocation(
"metadata_to_vae",
title="Metadata To VAE",
Expand Down
Loading
Loading