diff --git a/invokeai/app/invocations/baseinvocation.py b/invokeai/app/invocations/baseinvocation.py index 351e22a88d8..f570e38fdf5 100644 --- a/invokeai/app/invocations/baseinvocation.py +++ b/invokeai/app/invocations/baseinvocation.py @@ -260,17 +260,23 @@ def invoke_internal(self, context: InvocationContext, services: "InvocationServi description="The id of this instance of an invocation. Must be unique among all instances of invocations.", json_schema_extra={"field_kind": FieldKind.NodeAttribute}, ) + # `is_intermediate` and `use_cache` remain node attributes - the workflow editor stores them on the node itself + # and renders them in the node footer, not in the node's input list. They declare `Input.Any` so that a graph edge + # may drive them; edge values are applied in `GraphExecutionState.next()` before the invocation runs, so both are + # resolved by the time the cache is consulted and by the time the output image is saved. is_intermediate: bool = Field( default=False, description="Whether or not this is an intermediate invocation.", json_schema_extra=InputFieldJSONSchemaExtra( - input=Input.Direct, field_kind=FieldKind.NodeAttribute, ui_type=UIType._IsIntermediate + input=Input.Any, field_kind=FieldKind.NodeAttribute, orig_required=False ).model_dump(exclude_none=True), ) use_cache: bool = Field( default=True, description="Whether or not to use the cache", - json_schema_extra={"field_kind": FieldKind.NodeAttribute}, + json_schema_extra=InputFieldJSONSchemaExtra( + input=Input.Any, field_kind=FieldKind.NodeAttribute, orig_required=False + ).model_dump(exclude_none=True), ) bottleneck: ClassVar[Bottleneck] diff --git a/invokeai/frontend/web/openapi.json b/invokeai/frontend/web/openapi.json index 6de4b71d542..e6327f76214 100644 --- a/invokeai/frontend/web/openapi.json +++ b/invokeai/frontend/web/openapi.json @@ -12665,19 +12665,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "a": { "default": 0, @@ -12879,19 +12881,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "anyOf": [ @@ -13085,19 +13089,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -13205,19 +13211,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -13524,19 +13532,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -13656,19 +13666,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -13843,19 +13855,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -13921,19 +13935,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "loras": { "anyOf": [ @@ -14028,19 +14044,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "lora": { "anyOf": [ @@ -14184,19 +14202,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "$ref": "#/components/schemas/ModelIdentifierField", @@ -14297,19 +14317,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "anyOf": [ @@ -14815,19 +14837,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "mask": { "anyOf": [ @@ -14935,19 +14959,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -15383,19 +15409,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "width": { "default": 512, @@ -15481,19 +15509,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents_a": { "anyOf": [ @@ -16298,19 +16328,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "collection": { "default": [], @@ -16385,19 +16417,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "value": { "default": false, @@ -16535,19 +16569,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "x_min": { "default": 0, @@ -17186,19 +17222,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "clip": { "anyOf": [ @@ -17465,19 +17503,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -17572,19 +17612,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image_width": { "default": 1024, @@ -17676,19 +17718,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image_width": { "default": 1024, @@ -17779,19 +17823,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image_width": { "default": 1024, @@ -17907,19 +17953,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": false, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "workflow_id": { "default": "", @@ -18049,19 +18097,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -18136,19 +18186,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": false, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -18231,19 +18283,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "source_image": { "anyOf": [ @@ -18367,19 +18421,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "source_image": { "anyOf": [ @@ -18472,19 +18528,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -18667,19 +18725,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -18928,19 +18988,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -19038,19 +19100,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -19116,19 +19180,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "$ref": "#/components/schemas/ModelIdentifierField", @@ -19210,19 +19276,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "anyOf": [ @@ -19290,19 +19358,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": false, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "item": { "anyOf": [ @@ -19447,19 +19517,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "base_image": { "anyOf": [ @@ -19588,19 +19660,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "color": { "$ref": "#/components/schemas/ColorField", @@ -19687,19 +19761,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -19783,19 +19859,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "default": "", @@ -19874,19 +19952,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "collection": { "default": [], @@ -19986,19 +20066,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "conditioning": { "anyOf": [ @@ -20103,19 +20185,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -20439,19 +20523,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -22200,19 +22286,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "generation_mode": { "anyOf": [ @@ -22933,19 +23021,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "vae": { "anyOf": [ @@ -23052,19 +23142,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "mask": { "anyOf": [ @@ -23260,19 +23352,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -23339,19 +23433,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -23506,19 +23602,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -23616,19 +23714,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -23706,19 +23806,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -23967,19 +24069,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "positive_conditioning": { "anyOf": [ @@ -24380,19 +24484,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "positive_conditioning": { "anyOf": [ @@ -24864,19 +24970,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -24938,19 +25046,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "a": { "default": 0, @@ -25379,19 +25489,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": false, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "anyOf": [ @@ -25521,19 +25633,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -25717,19 +25831,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "transformer": { "anyOf": [ @@ -25932,19 +26048,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "$ref": "#/components/schemas/ModelIdentifierField", @@ -26052,19 +26170,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "anyOf": [ @@ -26176,19 +26296,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "anyOf": [ @@ -26289,19 +26411,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -26399,19 +26523,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "mask": { "anyOf": [ @@ -27268,19 +27394,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "video": { "anyOf": [ @@ -27448,19 +27576,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "loras": { "anyOf": [ @@ -27727,19 +27857,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -27826,19 +27958,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -28007,19 +28141,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -28193,19 +28329,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "batch_group_id": { "default": "None", @@ -28272,19 +28410,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "collection": { "default": [], @@ -28359,19 +28499,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "generator": { "$ref": "#/components/schemas/FloatGeneratorField", @@ -28446,19 +28588,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "value": { "default": 0.0, @@ -28504,19 +28648,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "start": { "default": 5, @@ -28582,19 +28728,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "operation": { "default": "ADD", @@ -28707,19 +28855,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "value": { "default": 0, @@ -28787,19 +28937,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -29089,19 +29241,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "loras": { "anyOf": [ @@ -29194,19 +29348,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "lora": { "anyOf": [ @@ -29350,19 +29506,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "$ref": "#/components/schemas/ModelIdentifierField", @@ -29521,19 +29679,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "anyOf": [ @@ -29629,19 +29789,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "loras": { "anyOf": [ @@ -29736,19 +29898,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "lora": { "anyOf": [ @@ -29892,19 +30056,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "$ref": "#/components/schemas/ModelIdentifierField", @@ -30062,19 +30228,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "anyOf": [ @@ -30202,19 +30370,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -30385,19 +30555,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -30463,19 +30635,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -30620,19 +30794,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "lora": { "anyOf": [ @@ -30802,19 +30978,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -30978,19 +31156,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -31493,19 +31673,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -32008,19 +32190,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -32109,19 +32293,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -32277,19 +32463,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "images": { "anyOf": [ @@ -32368,19 +32556,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -32454,19 +32644,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "lora": { "anyOf": [ @@ -32642,19 +32834,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "anyOf": [ @@ -32846,19 +33040,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -33004,19 +33200,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -33159,19 +33357,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "clip": { "anyOf": [ @@ -33321,19 +33521,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -33399,19 +33601,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -33536,19 +33740,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "unet": { "anyOf": [ @@ -33866,19 +34072,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "anyOf": [ @@ -34128,19 +34336,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "gemma2_model": { "anyOf": [ @@ -34518,19 +34728,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "mask": { "anyOf": [ @@ -36116,19 +36328,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "anyOf": [ @@ -36256,19 +36470,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -36399,19 +36615,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -36669,19 +36887,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -37881,19 +38101,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "width": { "default": 1024, @@ -38004,19 +38226,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "default": "", @@ -38124,19 +38348,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "transformer": { "anyOf": [ @@ -38335,19 +38561,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -38413,19 +38641,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "$ref": "#/components/schemas/ModelIdentifierField", @@ -38541,19 +38771,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "anyOf": [ @@ -38622,19 +38854,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "condition": { "default": false, @@ -38741,19 +38975,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "batch_group_id": { "default": "None", @@ -38852,19 +39088,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -38975,19 +39213,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -39081,19 +39321,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -39249,19 +39491,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -39374,19 +39618,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "collection": { "anyOf": [ @@ -39522,19 +39768,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -39628,19 +39876,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -39899,19 +40149,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "generator": { "$ref": "#/components/schemas/ImageGeneratorField", @@ -40018,19 +40270,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -40123,19 +40377,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -40210,19 +40466,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -40305,19 +40563,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -40408,19 +40668,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -40620,19 +40882,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image1": { "anyOf": [ @@ -40730,19 +40994,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -40851,19 +41117,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -41065,19 +41333,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "width": { "anyOf": [ @@ -41221,19 +41491,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "base_image": { "anyOf": [ @@ -41432,19 +41704,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -41560,19 +41834,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -41645,19 +41921,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -41890,19 +42168,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -42025,19 +42305,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -42139,19 +42421,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -42256,19 +42540,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -42605,19 +42891,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "batch_group_id": { "default": "None", @@ -42684,19 +42972,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "collection": { "default": [], @@ -42771,19 +43061,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "generator": { "$ref": "#/components/schemas/IntegerGeneratorField", @@ -42857,19 +43149,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "value": { "default": 0, @@ -42915,19 +43209,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "operation": { "default": "ADD", @@ -43040,19 +43336,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "mask": { "anyOf": [ @@ -49575,19 +49873,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -49729,19 +50029,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -49824,19 +50126,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "layer_upper": { "anyOf": [ @@ -50058,19 +50362,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image_subject": { "anyOf": [ @@ -50213,19 +50519,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -50351,19 +50659,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -50500,19 +50810,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -50633,19 +50945,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": false, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "collection": { "default": [], @@ -50788,19 +51102,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "conditioning": { "anyOf": [ @@ -50904,19 +51220,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -51151,19 +51469,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "loras": { "anyOf": [ @@ -51256,19 +51576,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "lora": { "anyOf": [ @@ -51412,19 +51734,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "$ref": "#/components/schemas/ModelIdentifierField", @@ -51544,19 +51868,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "conditioning": { "anyOf": [ @@ -51642,19 +51968,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "anyOf": [ @@ -51915,19 +52243,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -51978,19 +52308,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "collection": { "anyOf": [ @@ -52097,19 +52429,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -52270,19 +52604,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -52411,19 +52747,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -52506,19 +52844,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -52579,19 +52919,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "images": { "anyOf": [ @@ -52824,19 +53166,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "loras": { "anyOf": [ @@ -52947,19 +53291,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "lora": { "anyOf": [ @@ -53147,19 +53493,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "lora": { "anyOf": [ @@ -56323,19 +56671,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -56590,19 +56940,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "anyOf": [ @@ -63108,19 +63460,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "mask1": { "anyOf": [ @@ -63218,19 +63572,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -63377,19 +63733,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -63482,19 +63840,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -63648,19 +64008,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "mask": { "anyOf": [ @@ -63756,19 +64118,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -63842,19 +64206,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "collection": { "anyOf": [ @@ -63941,19 +64307,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "tiles_with_images": { "anyOf": [ @@ -64036,19 +64404,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -64115,19 +64485,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -64178,19 +64550,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "items": { "anyOf": [ @@ -64264,19 +64638,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "anyOf": [ @@ -64359,19 +64735,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "default": "* CUSTOM LABEL *", @@ -64530,19 +64908,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "default": "* CUSTOM LABEL *", @@ -64641,19 +65021,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "default": "* CUSTOM LABEL *", @@ -64749,19 +65131,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "control_list": { "anyOf": [ @@ -64835,19 +65219,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "default": "* CUSTOM LABEL *", @@ -64946,19 +65332,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "default": "* CUSTOM LABEL *", @@ -65054,19 +65442,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "ip_adapter_list": { "anyOf": [ @@ -65141,19 +65531,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "default": "* CUSTOM LABEL *", @@ -65261,19 +65653,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "default": "* CUSTOM LABEL *", @@ -65378,19 +65772,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "custom_label": { "default": "loras", @@ -65501,19 +65897,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "unet": { "anyOf": [ @@ -65599,19 +65997,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "default": "model", @@ -65758,19 +66158,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "unet": { "anyOf": [ @@ -65873,19 +66275,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "default": "model", @@ -66040,19 +66444,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "default": "scheduler", @@ -66176,19 +66582,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "default": "* CUSTOM LABEL *", @@ -66293,19 +66701,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "default": "* CUSTOM LABEL *", @@ -66407,19 +66817,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "t2i_adapter_list": { "anyOf": [ @@ -66494,19 +66906,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "label": { "default": "vae", @@ -67151,19 +67565,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "anyOf": [ @@ -70235,19 +70651,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "a": { "default": 0, @@ -70415,19 +70833,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "noise_type": { "default": "SD", @@ -70588,19 +71008,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -70803,19 +71225,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -70920,19 +71344,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -71025,19 +71451,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "anyOf": [ @@ -71376,19 +71804,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -71531,19 +71961,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -71662,19 +72094,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "source_image": { "anyOf": [ @@ -71767,19 +72201,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "pid_decoder_model": { "anyOf": [ @@ -72597,19 +73033,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -72772,19 +73210,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -72919,19 +73359,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "style_preset": { "anyOf": [ @@ -73034,19 +73476,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "file_path": { "anyOf": [ @@ -74627,19 +75071,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -74906,19 +75352,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -75071,19 +75519,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -75170,19 +75620,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "loras": { "anyOf": [ @@ -75260,19 +75712,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "lora": { "anyOf": [ @@ -75384,19 +75838,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "$ref": "#/components/schemas/ModelIdentifierField", @@ -75568,19 +76024,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -75719,19 +76177,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "anyOf": [ @@ -76105,19 +76565,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": false, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "low": { "default": 0.0, @@ -76183,19 +76645,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": false, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "low": { "default": 0, @@ -76251,19 +76715,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": false, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "low": { "default": 0, @@ -76341,19 +76807,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "start": { "default": 0, @@ -76419,19 +76887,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "start": { "default": 0, @@ -76885,19 +77355,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "width": { "anyOf": [ @@ -77134,19 +77606,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -77280,19 +77754,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "value": { "default": 0, @@ -77457,19 +77933,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -77718,19 +78196,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -77828,19 +78308,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -77938,19 +78420,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -78072,19 +78556,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "default": "", @@ -78250,19 +78736,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "loras": { "anyOf": [ @@ -78374,19 +78862,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "lora": { "anyOf": [ @@ -78562,19 +79052,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "anyOf": [ @@ -78703,19 +79195,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -78854,19 +79348,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "style": { "default": "", @@ -78978,19 +79474,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "anyOf": [ @@ -79117,19 +79615,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": false, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -79212,19 +79712,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": false, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -79328,19 +79830,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -79429,19 +79933,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "scheduler": { "default": "euler", @@ -79583,19 +80089,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "$ref": "#/components/schemas/ModelIdentifierField", @@ -79766,19 +80274,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "clip_l": { "anyOf": [ @@ -79879,19 +80389,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "unet": { "anyOf": [ @@ -80059,19 +80571,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "anyOf": [ @@ -80287,19 +80801,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "anyOf": [ @@ -81231,19 +81747,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -81467,19 +81985,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -81611,19 +82131,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -82205,19 +82727,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "batch_group_id": { "default": "None", @@ -82284,19 +82808,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "collection": { "default": [], @@ -82371,19 +82897,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "generator": { "$ref": "#/components/schemas/StringGeneratorField", @@ -82458,19 +82986,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "value": { "default": "", @@ -82517,19 +83047,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "string_left": { "default": "", @@ -82587,19 +83119,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "string_left": { "default": "", @@ -82721,19 +83255,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "string": { "default": "", @@ -82812,19 +83348,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "string": { "default": "", @@ -82881,19 +83419,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "string": { "default": "", @@ -83082,19 +83622,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "a": { "default": 0, @@ -83329,19 +83871,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -85179,19 +85723,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "default": "", @@ -85290,19 +85836,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "default": "", @@ -85561,19 +86109,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "tile": { "anyOf": [ @@ -85736,19 +86286,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "positive_conditioning": { "anyOf": [ @@ -86494,19 +87046,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -86798,19 +87352,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "vae_model": { "anyOf": [ @@ -88737,19 +89293,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "videos": { "anyOf": [ @@ -89063,19 +89621,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "video": { "anyOf": [ @@ -89137,19 +89697,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "video": { "anyOf": [ @@ -89476,19 +90038,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "transformer": { "anyOf": [ @@ -89728,19 +90292,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "width": { "default": 1024, @@ -89857,19 +90423,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -89967,19 +90535,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -90077,19 +90647,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -90167,19 +90739,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "loras": { "anyOf": [ @@ -90257,19 +90831,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "lora": { "anyOf": [ @@ -90398,19 +90974,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "$ref": "#/components/schemas/ModelIdentifierField", @@ -90599,19 +91177,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -90913,19 +91493,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "width": { "default": 1024, @@ -91010,19 +91592,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "anyOf": [ @@ -91145,19 +91729,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "transformer": { "anyOf": [ @@ -92116,19 +92702,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": false, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "values": { "additionalProperties": true, @@ -92209,19 +92797,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": false, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "values": { "anyOf": [ @@ -92321,19 +92911,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": false, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "key": { "default": "", @@ -92643,19 +93235,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -92782,19 +93376,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -93109,19 +93705,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -93452,19 +94050,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "image": { "anyOf": [ @@ -93562,19 +94162,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -93640,19 +94242,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "loras": { "anyOf": [ @@ -93747,19 +94351,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "lora": { "anyOf": [ @@ -93903,19 +94509,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "model": { "$ref": "#/components/schemas/ModelIdentifierField", @@ -94086,19 +94694,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "latents": { "anyOf": [ @@ -94237,19 +94847,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "conditioning": { "anyOf": [ @@ -94336,19 +94948,21 @@ "default": false, "description": "Whether or not this is an intermediate invocation.", "field_kind": "node_attribute", - "input": "direct", - "orig_required": true, + "input": "any", + "orig_required": false, "title": "Is Intermediate", "type": "boolean", - "ui_hidden": false, - "ui_type": "IsIntermediate" + "ui_hidden": false }, "use_cache": { "default": true, "description": "Whether or not to use the cache", "field_kind": "node_attribute", + "input": "any", + "orig_required": false, "title": "Use Cache", - "type": "boolean" + "type": "boolean", + "ui_hidden": false }, "prompt": { "anyOf": [ diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index 6c87e0477aa..e5d16e90de8 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -1568,6 +1568,7 @@ "groupNodesByCategoryHelp": "Group nodes by category in the add node dialog", "hideLegendNodes": "Hide Field Type Legend", "hideMinimapnodes": "Hide MiniMap", + "cannotConnectToUnavailableNodeSetting": "This setting is not available on this node", "inputMayOnlyHaveOneConnection": "Input may only have one connection", "integer": "Integer", "ipAdapter": "IP-Adapter", @@ -1592,6 +1593,7 @@ "targetNodeFieldDoesNotExist": "Invalid edge: target/input field {{node}}.{{field}} does not exist", "deletedInvalidEdge": "Deleted invalid edge {{source}} -> {{target}}", "deletedMissingNodeFieldFormElement": "Deleted missing form field: node {{nodeId}} field {{fieldName}}", + "deletedMissingNodeSettingFormElement": "Deleted missing form setting: node {{nodeId}} setting {{setting}}", "noConnectionInProgress": "No connection in progress", "node": "Node", "nodeOutputs": "Node Outputs", @@ -2794,8 +2796,12 @@ "text": "Text", "divider": "Divider", "nodeField": "Node Field", + "nodeSetting": "Node Setting", "zoomToNode": "Zoom to Node", "nodeFieldTooltip": "To add a node field, click the small plus sign button on the field in the Workflow Editor, or drag the field by its name into the form.", + "nodeSettingTooltip": "To add a node setting like Use Cache or Save To Gallery, click the small plus sign button next to it in the node's footer in the Workflow Editor, or drag it by its name into the form.", + "nodeSettingNotApplicable": "This setting does not apply to this node and will be hidden.", + "nodeSettingAdminOnly": "Only an administrator can change this setting. It will be hidden.", "addToForm": "Add to Form", "removeFromForm": "Remove from Form", "label": "Label", diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/WorkflowFormPreview.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/WorkflowFormPreview.tsx index be8ee0668e9..da5df48a20b 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/WorkflowFormPreview.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/WorkflowFormPreview.tsx @@ -4,6 +4,7 @@ import { useStore } from '@nanostores/react'; import { logger } from 'app/logging/logger'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { WorkflowFieldRenderer } from 'features/controlLayers/components/CanvasWorkflowIntegration/WorkflowFieldRenderer'; +import { WorkflowNodeSettingRenderer } from 'features/controlLayers/components/CanvasWorkflowIntegration/WorkflowNodeSettingRenderer'; import { canvasWorkflowIntegrationImageFieldSelected, selectCanvasWorkflowIntegrationFieldValues, @@ -27,6 +28,7 @@ import { isDividerElement, isHeadingElement, isNodeFieldElement, + isNodeSettingElement, isTextElement, ROOT_CONTAINER_CLASS_NAME, } from 'features/nodes/types/workflow'; @@ -241,6 +243,10 @@ const FormElementComponentPreview = memo(({ id, elements }: { id: string; elemen return ; } + if (isNodeSettingElement(el)) { + return ; + } + // If we get here, it's an unknown element type // eslint-disable-next-line @typescript-eslint/no-explicit-any log.warn({ id, type: (el as any).type }, 'Unknown element type - not rendering'); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/WorkflowNodeSettingRenderer.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/WorkflowNodeSettingRenderer.tsx new file mode 100644 index 00000000000..99620786bda --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/WorkflowNodeSettingRenderer.tsx @@ -0,0 +1,108 @@ +import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library'; +import { useStore } from '@nanostores/react'; +import { logger } from 'app/logging/logger'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { useIsAdmin } from 'features/auth/hooks/useIsAdmin'; +import { getNodeSettingKey } from 'features/controlLayers/components/CanvasWorkflowIntegration/nodeSettingOverrides'; +import { + canvasWorkflowIntegrationNodeSettingChanged, + selectCanvasWorkflowIntegrationNodeSettingValues, + selectCanvasWorkflowIntegrationSelectedWorkflowId, +} from 'features/controlLayers/store/canvasWorkflowIntegrationSlice'; +import { + getIsNodeSettingPermitted, + NODE_SETTING_FIELD_NAMES, + useNodeSettingDefaultLabel, +} from 'features/nodes/hooks/useNodeSetting'; +import { $templates } from 'features/nodes/store/nodesSlice'; +import { getHasNodeFooter } from 'features/nodes/types/invocation'; +import type { NodeSettingElement } from 'features/nodes/types/workflow'; +import type { ChangeEvent } from 'react'; +import { memo, useCallback, useMemo } from 'react'; +import { useGetWorkflowQuery } from 'services/api/endpoints/workflows'; + +const log = logger('canvas-workflow-integration'); + +/** + * A Use Cache / Save To Gallery control in the canvas form preview. + * + * Unlike a node field, a node setting has no entry in `node.data.inputs` - its value is a node attribute. The preview + * therefore keeps its own override in `canvasWorkflowIntegrationSlice.nodeSettingValues`, which the executor applies + * to the invocation it builds (see `resolveNodeSettings`). Without that the control would be inert, since the graph + * is built from the workflow as saved. + */ +export const WorkflowNodeSettingRenderer = memo(({ el }: { el: NodeSettingElement }) => { + const dispatch = useAppDispatch(); + const { nodeId, setting } = el.data; + const selectedWorkflowId = useAppSelector(selectCanvasWorkflowIntegrationSelectedWorkflowId); + const nodeSettingValues = useAppSelector(selectCanvasWorkflowIntegrationNodeSettingValues); + const templates = useStore($templates); + const isAdmin = useIsAdmin(); + const defaultLabel = useNodeSettingDefaultLabel(setting); + const settingKey = getNodeSettingKey(nodeId, setting); + + const { data: workflow } = useGetWorkflowQuery(selectedWorkflowId!, { skip: !selectedWorkflowId }); + + const node = useMemo(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return workflow?.workflow.nodes.find((n: any) => n.data?.id === nodeId); + }, [workflow, nodeId]); + + // An edge drives the value, so whatever is set here would be overwritten at run time. + const isConnected = useMemo(() => { + const fieldName = NODE_SETTING_FIELD_NAMES[setting]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return Boolean(workflow?.workflow.edges.some((e: any) => e.target === nodeId && e.targetHandle === fieldName)); + }, [workflow, nodeId, setting]); + + const isChecked = useMemo(() => { + const override = nodeSettingValues?.[settingKey]; + if (override !== undefined) { + return override; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const data = node?.data as any; + return setting === 'use_cache' ? (data?.useCache ?? true) : !(data?.isIntermediate ?? false); + }, [nodeSettingValues, settingKey, node, setting]); + + const onChange = useCallback( + (e: ChangeEvent) => { + dispatch(canvasWorkflowIntegrationNodeSettingChanged({ settingKey, value: e.target.checked })); + }, + [dispatch, settingKey] + ); + + if (!node) { + log.warn({ nodeId, setting }, 'Node for node setting not found'); + return null; + } + + // Same gate as the workflow editor: the cache is a process-global, admin-only policy. + if (!getIsNodeSettingPermitted(setting, isAdmin)) { + return null; + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const template = templates[(node.data as any).type]; + if (!template || !getHasNodeFooter(template)) { + // The setting does not apply to this node - it would render as a no-op toggle, exactly as in the workflow editor. + return null; + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (setting === 'save_to_gallery' && (node.data as any).type === 'canvas_output') { + // Canvas output images go to the staging area, never straight to the gallery, so this one is not the user's to + // set here - `resolveNodeSettings` forces it. + return null; + } + + return ( + + {el.data.label || defaultLabel} + {/* An edge drives the value, so the local one is stale - show it, but don't let it be changed here */} + + + ); +}); + +WorkflowNodeSettingRenderer.displayName = 'WorkflowNodeSettingRenderer'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/nodeSettingOverrides.test.ts b/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/nodeSettingOverrides.test.ts new file mode 100644 index 00000000000..2478d828f3b --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/nodeSettingOverrides.test.ts @@ -0,0 +1,70 @@ +import { describe, expect, it } from 'vitest'; + +import { getNodeSettingKey, resolveNodeSettings } from './nodeSettingOverrides'; + +const base = { + nodeId: 'node-1', + isCanvasOutputNode: false, + isIntermediate: undefined, + useCache: undefined, + nodeSettingValues: null, + isAdmin: true, +}; + +describe('resolveNodeSettings', () => { + it('falls back to the values saved in the workflow', () => { + expect(resolveNodeSettings({ ...base, isIntermediate: true, useCache: false })).toEqual({ + is_intermediate: true, + use_cache: false, + }); + }); + + it('falls back to the backend defaults when the node carries no values', () => { + expect(resolveNodeSettings(base)).toEqual({ is_intermediate: false, use_cache: true }); + }); + + // `save_to_gallery` is the inverse of `is_intermediate`. + it.each([ + [true, false], + [false, true], + ])('applies a save_to_gallery override of %s as is_intermediate %s', (saveToGallery, isIntermediate) => { + const nodeSettingValues = { [getNodeSettingKey('node-1', 'save_to_gallery')]: saveToGallery }; + expect(resolveNodeSettings({ ...base, isIntermediate: !isIntermediate, nodeSettingValues })).toEqual({ + is_intermediate: isIntermediate, + use_cache: true, + }); + }); + + it('applies a use_cache override for an admin', () => { + const nodeSettingValues = { [getNodeSettingKey('node-1', 'use_cache')]: false }; + expect(resolveNodeSettings({ ...base, useCache: true, nodeSettingValues })).toEqual({ + is_intermediate: false, + use_cache: false, + }); + }); + + // The slice is persisted per browser, not per user, so an admin's leftover value must not be replayed. + it('ignores a use_cache override for a non-admin', () => { + const nodeSettingValues = { [getNodeSettingKey('node-1', 'use_cache')]: false }; + expect(resolveNodeSettings({ ...base, useCache: true, nodeSettingValues, isAdmin: false })).toEqual({ + is_intermediate: false, + use_cache: true, + }); + }); + + it('ignores overrides belonging to another node', () => { + const nodeSettingValues = { + [getNodeSettingKey('other-node', 'save_to_gallery')]: true, + [getNodeSettingKey('other-node', 'use_cache')]: false, + }; + expect(resolveNodeSettings({ ...base, nodeSettingValues })).toEqual({ is_intermediate: false, use_cache: true }); + }); + + // Canvas results land in the staging area; a gallery save there would produce a duplicate the canvas cannot stage. + it('keeps the canvas output node intermediate regardless of any override', () => { + const nodeSettingValues = { [getNodeSettingKey('node-1', 'save_to_gallery')]: true }; + expect( + resolveNodeSettings({ ...base, isCanvasOutputNode: true, isIntermediate: false, nodeSettingValues }) + ).toEqual({ is_intermediate: true, use_cache: true }); + }); +}); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/nodeSettingOverrides.ts b/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/nodeSettingOverrides.ts new file mode 100644 index 00000000000..00f5113931c --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/nodeSettingOverrides.ts @@ -0,0 +1,53 @@ +import type { NodeSettingName } from 'features/nodes/types/workflow'; + +/** + * Key a node setting override is stored under in `canvasWorkflowIntegrationSlice.nodeSettingValues`. + * + * Deliberately shaped like the `fieldValues` key (`"."`) but kept in its own record: node settings are + * not input fields, so they must not be written into `node.data.inputs` the way field values are. + */ +export const getNodeSettingKey = (nodeId: string, setting: NodeSettingName): string => `${nodeId}.${setting}`; + +type ResolveNodeSettingsArgs = { + /** The node's id as saved in the workflow, i.e. before canvas output ids are re-prefixed. */ + nodeId: string; + isCanvasOutputNode: boolean; + /** `node.data.isIntermediate` as saved in the workflow. */ + isIntermediate: boolean | undefined; + /** `node.data.useCache` as saved in the workflow. */ + useCache: boolean | undefined; + nodeSettingValues: Record | null | undefined; + isAdmin: boolean; +}; + +/** + * Resolve the `use_cache` / `is_intermediate` an enqueued invocation runs with, given what the workflow was saved + * with and what the user changed in the canvas form preview. + * + * Without this the preview's node settings would be inert - the graph is built from node data, which the preview does + * not own - so a form's Use Cache or Save To Gallery control would silently do nothing. + */ +export const resolveNodeSettings = ({ + nodeId, + isCanvasOutputNode, + isIntermediate, + useCache, + nodeSettingValues, + isAdmin, +}: ResolveNodeSettingsArgs): { use_cache: boolean; is_intermediate: boolean } => { + const saveToGalleryOverride = nodeSettingValues?.[getNodeSettingKey(nodeId, 'save_to_gallery')]; + // The node cache is a process-global, admin-only policy. The slice is persisted per browser, not per user, so a + // value left behind by an admin must not be replayed for whoever runs the workflow next. + const useCacheOverride = isAdmin ? nodeSettingValues?.[getNodeSettingKey(nodeId, 'use_cache')] : undefined; + + return { + // Canvas output images go to the staging area, never straight to the gallery, so this one is not the user's to + // set. The preview does not offer a control for it either. + is_intermediate: isCanvasOutputNode + ? true + : saveToGalleryOverride !== undefined + ? !saveToGalleryOverride + : (isIntermediate ?? false), + use_cache: useCacheOverride ?? useCache ?? true, + }; +}; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/useCanvasWorkflowIntegrationExecute.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/useCanvasWorkflowIntegrationExecute.tsx index 42b7d06d64b..d440ea9bac0 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/useCanvasWorkflowIntegrationExecute.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasWorkflowIntegration/useCanvasWorkflowIntegrationExecute.tsx @@ -1,5 +1,7 @@ import { logger } from 'app/logging/logger'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { useIsAdmin } from 'features/auth/hooks/useIsAdmin'; +import { resolveNodeSettings } from 'features/controlLayers/components/CanvasWorkflowIntegration/nodeSettingOverrides'; import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate'; import { selectCanvasSessionId } from 'features/controlLayers/store/canvasStagingAreaSlice'; import { @@ -7,6 +9,7 @@ import { canvasWorkflowIntegrationProcessingCompleted, canvasWorkflowIntegrationProcessingStarted, selectCanvasWorkflowIntegrationFieldValues, + selectCanvasWorkflowIntegrationNodeSettingValues, selectCanvasWorkflowIntegrationSelectedImageFieldKey, selectCanvasWorkflowIntegrationSelectedWorkflowId, selectCanvasWorkflowIntegrationSourceEntityIdentifier, @@ -28,8 +31,10 @@ export const useCanvasWorkflowIntegrationExecute = () => { const selectedWorkflowId = useAppSelector(selectCanvasWorkflowIntegrationSelectedWorkflowId); const sourceEntityIdentifier = useAppSelector(selectCanvasWorkflowIntegrationSourceEntityIdentifier); const fieldValues = useAppSelector(selectCanvasWorkflowIntegrationFieldValues); + const nodeSettingValues = useAppSelector(selectCanvasWorkflowIntegrationNodeSettingValues); const selectedImageFieldKey = useAppSelector(selectCanvasWorkflowIntegrationSelectedImageFieldKey); const canvasSessionId = useAppSelector(selectCanvasSessionId); + const isAdmin = useIsAdmin(); const [getWorkflow] = useLazyGetWorkflowQuery(); @@ -199,9 +204,16 @@ export const useCanvasWorkflowIntegrationExecute = () => { const invocation: Record = { id: nodeId, type: nodeData.type, - // Canvas output nodes are always intermediate (they go to the staging area, not gallery) - is_intermediate: isCanvasOutputNode ? true : (nodeData.isIntermediate ?? false), - use_cache: nodeData.useCache ?? true, + // Node settings are node attributes, not inputs, so the form preview's values are applied here rather than + // in the input loop below + ...resolveNodeSettings({ + nodeId: nodeData.id, + isCanvasOutputNode, + isIntermediate: nodeData.isIntermediate, + useCache: nodeData.useCache, + nodeSettingValues, + isAdmin, + }), }; // Add input values to the invocation @@ -291,6 +303,8 @@ export const useCanvasWorkflowIntegrationExecute = () => { getWorkflow, t, fieldValues, + nodeSettingValues, + isAdmin, selectedImageFieldKey, canvasSessionId, ]); diff --git a/invokeai/frontend/web/src/features/controlLayers/store/canvasWorkflowIntegrationSlice.ts b/invokeai/frontend/web/src/features/controlLayers/store/canvasWorkflowIntegrationSlice.ts index 0056885f0fa..d043556ce18 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/canvasWorkflowIntegrationSlice.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/canvasWorkflowIntegrationSlice.ts @@ -18,6 +18,10 @@ const zCanvasWorkflowIntegrationState = z.object({ }) .nullable(), fieldValues: z.record(z.string(), z.any()).nullable(), + // Node settings (Use Cache / Save To Gallery) the user changed in the form preview (format: "nodeId.setting"). + // Kept apart from `fieldValues`: these are node attributes, not inputs, so they are applied to the invocation + // itself rather than written into `node.data.inputs`. + nodeSettingValues: z.record(z.string(), z.boolean()).nullable(), // Which ImageField to use for canvas image (format: "nodeId.fieldName") selectedImageFieldKey: z.string().nullable(), isProcessing: z.boolean(), @@ -31,6 +35,7 @@ const getInitialState = (): CanvasWorkflowIntegrationState => ({ selectedWorkflowId: null, sourceEntityIdentifier: null, fieldValues: null, + nodeSettingValues: null, selectedImageFieldKey: null, isProcessing: false, }); @@ -47,12 +52,14 @@ const slice = createSlice({ state.sourceEntityIdentifier = action.payload.sourceEntityIdentifier; state.selectedWorkflowId = null; state.fieldValues = null; + state.nodeSettingValues = null; }, canvasWorkflowIntegrationClosed: (state) => { state.isOpen = false; state.selectedWorkflowId = null; state.sourceEntityIdentifier = null; state.fieldValues = null; + state.nodeSettingValues = null; state.selectedImageFieldKey = null; state.isProcessing = false; }, @@ -60,6 +67,7 @@ const slice = createSlice({ state.selectedWorkflowId = action.payload.workflowId; // Reset field values when switching workflows state.fieldValues = null; + state.nodeSettingValues = null; state.selectedImageFieldKey = null; }, canvasWorkflowIntegrationImageFieldSelected: (state, action: PayloadAction<{ fieldKey: string | null }>) => { @@ -74,8 +82,18 @@ const slice = createSlice({ } state.fieldValues[action.payload.fieldName] = action.payload.value; }, + canvasWorkflowIntegrationNodeSettingChanged: ( + state, + action: PayloadAction<{ settingKey: string; value: boolean }> + ) => { + if (!state.nodeSettingValues) { + state.nodeSettingValues = {}; + } + state.nodeSettingValues[action.payload.settingKey] = action.payload.value; + }, canvasWorkflowIntegrationFieldValuesReset: (state) => { state.fieldValues = null; + state.nodeSettingValues = null; }, canvasWorkflowIntegrationProcessingStarted: (state) => { state.isProcessing = true; @@ -92,6 +110,7 @@ export const { canvasWorkflowIntegrationWorkflowSelected, canvasWorkflowIntegrationImageFieldSelected, canvasWorkflowIntegrationFieldValueChanged, + canvasWorkflowIntegrationNodeSettingChanged, canvasWorkflowIntegrationProcessingStarted, canvasWorkflowIntegrationProcessingCompleted, } = slice.actions; @@ -106,6 +125,10 @@ export const canvasWorkflowIntegrationSliceConfig: SliceConfig = { if (!('_version' in state)) { state._version = 1; } + if (!('nodeSettingValues' in state)) { + // Persisted before node settings could be put in a form + state.nodeSettingValues = null; + } return zCanvasWorkflowIntegrationState.parse(state); }, persistDenylist: ['isOpen', 'isProcessing', 'sourceEntityIdentifier'], @@ -126,6 +149,9 @@ export const selectCanvasWorkflowIntegrationSourceEntityIdentifier = createCanva export const selectCanvasWorkflowIntegrationFieldValues = createCanvasWorkflowIntegrationSelector( (state) => state.fieldValues ); +export const selectCanvasWorkflowIntegrationNodeSettingValues = createCanvasWorkflowIntegrationSelector( + (state) => state.nodeSettingValues +); export const selectCanvasWorkflowIntegrationSelectedImageFieldKey = createCanvasWorkflowIntegrationSelector( (state) => state.selectedImageFieldKey ); diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/InvocationNodeFooter.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/InvocationNodeFooter.tsx index e025fe39fe2..ccb16bdc370 100644 --- a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/InvocationNodeFooter.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/InvocationNodeFooter.tsx @@ -1,38 +1,37 @@ -import type { ChakraProps } from '@invoke-ai/ui-library'; -import { Flex, FormControlGroup } from '@invoke-ai/ui-library'; -import { useIsExecutableNode } from 'features/nodes/hooks/useIsBatchNode'; -import { useNodeHasGalleryOutput } from 'features/nodes/hooks/useNodeHasGalleryOutput'; +import type { SystemStyleObject } from '@invoke-ai/ui-library'; +import { Flex } from '@invoke-ai/ui-library'; import { DRAG_HANDLE_CLASSNAME } from 'features/nodes/types/constants'; import { memo } from 'react'; -import SaveToGalleryCheckbox from './SaveToGalleryCheckbox'; -import UseCacheCheckbox from './UseCacheCheckbox'; +import { NodeSettingFooterControl } from './NodeSettingFooterControl'; type Props = { nodeId: string; }; -const props: ChakraProps = { w: 'unset' }; +const sx: SystemStyleObject = { + w: 'full', + borderBottomRadius: 'base', + // One row per setting, so each connection handle lines up with the label it belongs to + flexDir: 'column', + px: 2, + py: 1, + // The add/remove form element buttons are hidden by default and shown on hover + '& .node-setting-action-button': { + display: 'none', + }, + _hover: { + '& .node-setting-action-button': { + display: 'inline-flex', + }, + }, +}; const InvocationNodeFooter = ({ nodeId }: Props) => { - const hasGalleryOutput = useNodeHasGalleryOutput(); - const isExecutableNode = useIsExecutableNode(); return ( - - - {isExecutableNode && } - {isExecutableNode && hasGalleryOutput && } - + + + ); }; diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/NodeSettingAddRemoveFormRoot.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/NodeSettingAddRemoveFormRoot.tsx new file mode 100644 index 00000000000..23bd3fe98ad --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/NodeSettingAddRemoveFormRoot.tsx @@ -0,0 +1,47 @@ +import { IconButton } from '@invoke-ai/ui-library'; +import { useAddRemoveNodeSettingFormElement } from 'features/nodes/components/sidePanel/builder/use-add-remove-form-element'; +import { NO_DRAG_CLASS } from 'features/nodes/types/constants'; +import type { NodeSettingName } from 'features/nodes/types/workflow'; +import { memo, useCallback, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { PiMinusBold, PiPlusBold } from 'react-icons/pi'; + +type Props = { + nodeId: string; + setting: NodeSettingName; +}; + +export const NodeSettingAddRemoveFormRoot = memo(({ nodeId, setting }: Props) => { + const { t } = useTranslation(); + const { isAddedToRoot, addNodeSettingToRoot, removeNodeSettingFromRoot } = useAddRemoveNodeSettingFormElement( + nodeId, + setting + ); + + const description = useMemo(() => { + return isAddedToRoot ? t('workflows.builder.removeFromForm') : t('workflows.builder.addToForm'); + }, [isAddedToRoot, t]); + + const icon = useMemo(() => { + return isAddedToRoot ? : ; + }, [isAddedToRoot]); + + const onClick = useCallback(() => { + return isAddedToRoot ? removeNodeSettingFromRoot() : addNodeSettingToRoot(); + }, [isAddedToRoot, addNodeSettingToRoot, removeNodeSettingFromRoot]); + + return ( + + ); +}); + +NodeSettingAddRemoveFormRoot.displayName = 'NodeSettingAddRemoveFormRoot'; diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/NodeSettingFooterControl.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/NodeSettingFooterControl.tsx new file mode 100644 index 00000000000..751c62b22e8 --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/NodeSettingFooterControl.tsx @@ -0,0 +1,79 @@ +import type { SystemStyleObject } from '@invoke-ai/ui-library'; +import { Checkbox, Flex, FormControl, FormLabel, Spacer } from '@invoke-ai/ui-library'; +import { InputFieldHandle } from 'features/nodes/components/flow/nodes/Invocation/fields/InputFieldHandle'; +import { useNodeSettingDnd } from 'features/nodes/components/sidePanel/builder/dnd-hooks'; +import { useInputFieldTemplateSafe } from 'features/nodes/hooks/useInputFieldTemplateSafe'; +import { + NODE_SETTING_FIELD_NAMES, + useIsNodeSettingPermitted, + useNodeSetting, + useNodeSettingDefaultLabel, +} from 'features/nodes/hooks/useNodeSetting'; +import { NO_DRAG_CLASS, NO_FIT_ON_DOUBLE_CLICK_CLASS, NO_PAN_CLASS } from 'features/nodes/types/constants'; +import type { NodeSettingName } from 'features/nodes/types/workflow'; +import { memo, useRef } from 'react'; + +import { NodeSettingAddRemoveFormRoot } from './NodeSettingAddRemoveFormRoot'; + +// Mirrors `InputFieldWrapper`: one row per field. The connection handle is absolutely positioned against this row and +// keeps its static vertical position, so it lines up with the label it belongs to. +const sx: SystemStyleObject = { + position: 'relative', + w: 'full', + minH: 6, + alignItems: 'center', + // Clear the half of the handle that overlaps the node's interior + ps: 2, + '&[data-is-dragging="true"]': { + opacity: 0.3, + }, +}; + +const formControlSx: SystemStyleObject = { w: 'full', alignItems: 'center', gap: 2 }; + +type Props = { + nodeId: string; + setting: NodeSettingName; +}; + +/** + * A node attribute toggle in the node footer. + * + * The value lives on the node (`data.useCache` / `data.isIntermediate`), but the underlying field is declared on the + * backend as a connectable input, so this also hosts the field's connection handle. When an edge drives the value the + * checkbox is dropped and only the label and handle remain, matching how a connected input field renders. + */ +export const NodeSettingFooterControl = memo(({ nodeId, setting }: Props) => { + const fieldName = NODE_SETTING_FIELD_NAMES[setting]; + const label = useNodeSettingDefaultLabel(setting); + const { isChecked, onChange, isConnected } = useNodeSetting(nodeId, setting); + // The template is what the handle needs. It should always be present, but a node whose template failed to parse + // this field must not take the whole footer down with it. + const fieldTemplate = useInputFieldTemplateSafe(fieldName); + const isPermitted = useIsNodeSettingPermitted(setting); + const draggableRef = useRef(null); + const dragHandleRef = useRef(null); + const isDragging = useNodeSettingDnd(nodeId, setting, draggableRef, dragHandleRef); + + // Hiding the control here also removes the add-to-form button and the drag handle it hosts, so an unpermitted + // setting cannot be put into the form in the first place. + if (!isPermitted) { + return null; + } + + return ( + + + + {label} + + + + {!isConnected && } + + {fieldTemplate && } + + ); +}); + +NodeSettingFooterControl.displayName = 'NodeSettingFooterControl'; diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/SaveToGalleryCheckbox.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/SaveToGalleryCheckbox.tsx deleted file mode 100644 index 4e9912a87be..00000000000 --- a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/SaveToGalleryCheckbox.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Checkbox, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useAppDispatch } from 'app/store/storeHooks'; -import { useNodeHasGalleryOutput } from 'features/nodes/hooks/useNodeHasGalleryOutput'; -import { useNodeIsIntermediate } from 'features/nodes/hooks/useNodeIsIntermediate'; -import { nodeIsIntermediateChanged } from 'features/nodes/store/nodesSlice'; -import { NO_PAN_CLASS } from 'features/nodes/types/constants'; -import type { ChangeEvent } from 'react'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -const SaveToGalleryCheckbox = ({ nodeId }: { nodeId: string }) => { - const { t } = useTranslation(); - const dispatch = useAppDispatch(); - const hasGalleryOutput = useNodeHasGalleryOutput(); - const isIntermediate = useNodeIsIntermediate(); - const handleChange = useCallback( - (e: ChangeEvent) => { - dispatch( - nodeIsIntermediateChanged({ - nodeId, - isIntermediate: !e.target.checked, - }) - ); - }, - [dispatch, nodeId] - ); - - if (!hasGalleryOutput) { - return null; - } - - return ( - - {t('nodes.saveToGallery')} - - - ); -}; - -export default memo(SaveToGalleryCheckbox); diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/UseCacheCheckbox.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/UseCacheCheckbox.tsx deleted file mode 100644 index b0f1fdead32..00000000000 --- a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/UseCacheCheckbox.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { Checkbox, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useAppDispatch } from 'app/store/storeHooks'; -import { useIsAdmin } from 'features/auth/hooks/useIsAdmin'; -import { useUseCache } from 'features/nodes/hooks/useUseCache'; -import { nodeUseCacheChanged } from 'features/nodes/store/nodesSlice'; -import { NO_FIT_ON_DOUBLE_CLICK_CLASS, NO_PAN_CLASS } from 'features/nodes/types/constants'; -import type { ChangeEvent } from 'react'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -const UseCacheCheckbox = ({ nodeId }: { nodeId: string }) => { - const dispatch = useAppDispatch(); - const useCache = useUseCache(); - // Node-cache control is admin-only (single-user mode counts as admin). - const isVisible = useIsAdmin(); - - const handleChange = useCallback( - (e: ChangeEvent) => { - dispatch( - nodeUseCacheChanged({ - nodeId, - useCache: e.target.checked, - }) - ); - }, - [dispatch, nodeId] - ); - const { t } = useTranslation(); - - if (!isVisible) { - return null; - } - - return ( - - {t('invocationCache.useCache')} - - - ); -}; - -export default memo(UseCacheCheckbox); diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/ContainerElement.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/ContainerElement.tsx index 76799396086..bd8eeb33e11 100644 --- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/ContainerElement.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/ContainerElement.tsx @@ -15,6 +15,7 @@ import { FormElementEditModeContent } from 'features/nodes/components/sidePanel/ import { FormElementEditModeHeader } from 'features/nodes/components/sidePanel/builder/FormElementEditModeHeader'; import { HeadingElement } from 'features/nodes/components/sidePanel/builder/HeadingElement'; import { NodeFieldElement } from 'features/nodes/components/sidePanel/builder/NodeFieldElement'; +import { NodeSettingElement } from 'features/nodes/components/sidePanel/builder/NodeSettingElement'; import { TextElement } from 'features/nodes/components/sidePanel/builder/TextElement'; import { useElement } from 'features/nodes/components/sidePanel/builder/use-element'; import { selectFormRootElement } from 'features/nodes/store/selectors'; @@ -26,6 +27,7 @@ import { isDividerElement, isHeadingElement, isNodeFieldElement, + isNodeSettingElement, isTextElement, ROOT_CONTAINER_CLASS_NAME, } from 'features/nodes/types/workflow'; @@ -308,6 +310,10 @@ const FormElementComponent = memo(({ id }: { id: string }) => { return ; } + if (isNodeSettingElement(el)) { + return ; + } + if (isDividerElement(el)) { return ; } diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementEditModeHeader.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementEditModeHeader.tsx index c50f6f1b3ba..6c5aecb5554 100644 --- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementEditModeHeader.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementEditModeHeader.tsx @@ -10,8 +10,8 @@ import { NodeFieldElementSettings } from 'features/nodes/components/sidePanel/bu import { useMouseOverFormField } from 'features/nodes/hooks/useMouseOverNode'; import { useZoomToNode } from 'features/nodes/hooks/useZoomToNode'; import { formElementRemoved } from 'features/nodes/store/nodesSlice'; -import type { FormElement, NodeFieldElement } from 'features/nodes/types/workflow'; -import { isContainerElement, isNodeFieldElement } from 'features/nodes/types/workflow'; +import type { FormElement } from 'features/nodes/types/workflow'; +import { isContainerElement, isNodeFieldElement, isNodeSettingElement } from 'features/nodes/types/workflow'; import type { RefObject } from 'react'; import { memo, useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; @@ -56,20 +56,20 @@ export const FormElementEditModeHeader = memo(({ element, dragHandleRef, ...rest fieldName={element.data.fieldIdentifier.fieldName} fallback={null} // Do not render these buttons if the field is not found > - + )} + {isNodeSettingElement(element) && } ); }); FormElementEditModeHeader.displayName = 'FormElementEditModeHeader'; -const ZoomToNodeButton = memo(({ element }: { element: NodeFieldElement }) => { +const ZoomToNodeButton = memo(({ nodeId }: { nodeId: string }) => { const { t } = useTranslation(); - const { nodeId } = element.data.fieldIdentifier; const zoomToNode = useZoomToNode(nodeId); const mouseOverFormField = useMouseOverFormField(nodeId); diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementNodeOverlay.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementNodeOverlay.tsx new file mode 100644 index 00000000000..3d3c0362cc8 --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementNodeOverlay.tsx @@ -0,0 +1,37 @@ +import type { SystemStyleObject } from '@invoke-ai/ui-library'; +import { Box } from '@invoke-ai/ui-library'; +import { useMouseOverFormField, useMouseOverNode } from 'features/nodes/hooks/useMouseOverNode'; +import { memo } from 'react'; + +const sx: SystemStyleObject = { + position: 'absolute', + top: 0, + insetInlineEnd: 0, + bottom: 0, + insetInlineStart: 0, + borderRadius: 'base', + transitionProperty: 'none', + pointerEvents: 'none', + display: 'none', + '&[data-is-mouse-over-node-or-form-field="true"]': { + display: 'block', + bg: 'invokeBlueAlpha.100', + }, +}; + +/** + * Highlights a form element that references a node while the mouse is over that node (or vice versa), so it is easy + * to see which node a form element belongs to. Must be rendered inside a relatively-positioned element. + */ +export const FormElementNodeOverlay = memo(({ nodeId }: { nodeId: string }) => { + const mouseOverNode = useMouseOverNode(nodeId); + const mouseOverFormField = useMouseOverFormField(nodeId); + + return ( + + ); +}); +FormElementNodeOverlay.displayName = 'FormElementNodeOverlay'; diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeFieldElementEditMode.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeFieldElementEditMode.tsx index 26b96f466fb..e7bac2c6c7a 100644 --- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeFieldElementEditMode.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeFieldElementEditMode.tsx @@ -1,5 +1,5 @@ import type { SystemStyleObject } from '@invoke-ai/ui-library'; -import { Box, Divider, Flex, FormControl } from '@invoke-ai/ui-library'; +import { Divider, Flex, FormControl } from '@invoke-ai/ui-library'; import { InvocationNodeContextProvider } from 'features/nodes/components/flow/nodes/Invocation/context'; import { InputFieldGate } from 'features/nodes/components/flow/nodes/Invocation/fields/InputFieldGate'; import { InputFieldRenderer } from 'features/nodes/components/flow/nodes/Invocation/fields/InputFieldRenderer'; @@ -8,10 +8,10 @@ import { useFormElementDnd } from 'features/nodes/components/sidePanel/builder/d import { DndListDropIndicator } from 'features/nodes/components/sidePanel/builder/DndListDropIndicator'; import { FormElementEditModeContent } from 'features/nodes/components/sidePanel/builder/FormElementEditModeContent'; import { FormElementEditModeHeader } from 'features/nodes/components/sidePanel/builder/FormElementEditModeHeader'; +import { FormElementNodeOverlay } from 'features/nodes/components/sidePanel/builder/FormElementNodeOverlay'; import { NodeFieldElementDescriptionEditable } from 'features/nodes/components/sidePanel/builder/NodeFieldElementDescriptionEditable'; import { NodeFieldElementLabelEditable } from 'features/nodes/components/sidePanel/builder/NodeFieldElementLabelEditable'; import { NodeFieldElementStringDropdownSettings } from 'features/nodes/components/sidePanel/builder/NodeFieldElementStringDropdownSettings'; -import { useMouseOverFormField, useMouseOverNode } from 'features/nodes/hooks/useMouseOverNode'; import type { NodeFieldElement } from 'features/nodes/types/workflow'; import { NODE_FIELD_CLASS_NAME } from 'features/nodes/types/workflow'; import type { RefObject } from 'react'; @@ -40,7 +40,7 @@ export const NodeFieldElementEditMode = memo(({ el }: { el: NodeFieldElement }) return ( - + ); @@ -91,32 +91,3 @@ const NodeFieldElementEditModeContent = memo( } ); NodeFieldElementEditModeContent.displayName = 'NodeFieldElementEditModeContent'; - -const nodeFieldOverlaySx: SystemStyleObject = { - position: 'absolute', - top: 0, - insetInlineEnd: 0, - bottom: 0, - insetInlineStart: 0, - borderRadius: 'base', - transitionProperty: 'none', - pointerEvents: 'none', - display: 'none', - '&[data-is-mouse-over-node-or-form-field="true"]': { - display: 'block', - bg: 'invokeBlueAlpha.100', - }, -}; - -const NodeFieldElementOverlay = memo(({ nodeId }: { nodeId: string }) => { - const mouseOverNode = useMouseOverNode(nodeId); - const mouseOverFormField = useMouseOverFormField(nodeId); - - return ( - - ); -}); -NodeFieldElementOverlay.displayName = 'NodeFieldElementOverlay'; diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeSettingElement.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeSettingElement.tsx new file mode 100644 index 00000000000..de7ece40bda --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeSettingElement.tsx @@ -0,0 +1,34 @@ +import { useAppSelector } from 'app/store/storeHooks'; +import { InvocationNodeContextProvider } from 'features/nodes/components/flow/nodes/Invocation/context'; +import { NodeSettingElementEditMode } from 'features/nodes/components/sidePanel/builder/NodeSettingElementEditMode'; +import { NodeSettingElementViewMode } from 'features/nodes/components/sidePanel/builder/NodeSettingElementViewMode'; +import { useElement } from 'features/nodes/components/sidePanel/builder/use-element'; +import { selectWorkflowMode } from 'features/nodes/store/workflowLibrarySlice'; +import { isNodeSettingElement } from 'features/nodes/types/workflow'; +import { memo } from 'react'; + +export const NodeSettingElement = memo(({ id }: { id: string }) => { + const el = useElement(id); + const mode = useAppSelector(selectWorkflowMode); + + if (!el || !isNodeSettingElement(el)) { + return null; + } + + if (mode === 'view') { + return ( + + + + ); + } + + // mode === 'edit' + return ( + + + + ); +}); + +NodeSettingElement.displayName = 'NodeSettingElement'; diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeSettingElementEditMode.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeSettingElementEditMode.tsx new file mode 100644 index 00000000000..b2b8a64f5d3 --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeSettingElementEditMode.tsx @@ -0,0 +1,96 @@ +import type { SystemStyleObject } from '@invoke-ai/ui-library'; +import { Flex, FormControl, Switch, Text } from '@invoke-ai/ui-library'; +import { useContainerContext } from 'features/nodes/components/sidePanel/builder/contexts'; +import { useFormElementDnd } from 'features/nodes/components/sidePanel/builder/dnd-hooks'; +import { DndListDropIndicator } from 'features/nodes/components/sidePanel/builder/DndListDropIndicator'; +import { FormElementEditModeContent } from 'features/nodes/components/sidePanel/builder/FormElementEditModeContent'; +import { FormElementEditModeHeader } from 'features/nodes/components/sidePanel/builder/FormElementEditModeHeader'; +import { FormElementNodeOverlay } from 'features/nodes/components/sidePanel/builder/FormElementNodeOverlay'; +import { NodeSettingElementLabelEditable } from 'features/nodes/components/sidePanel/builder/NodeSettingElementLabelEditable'; +import { + useIsNodeSettingApplicable, + useIsNodeSettingPermitted, + useNodeSetting, +} from 'features/nodes/hooks/useNodeSetting'; +import type { NodeSettingElement } from 'features/nodes/types/workflow'; +import { NODE_SETTING_CLASS_NAME } from 'features/nodes/types/workflow'; +import { memo, useRef } from 'react'; +import { useTranslation } from 'react-i18next'; + +const sx: SystemStyleObject = { + position: 'relative', + borderRadius: 'base', + '&[data-parent-layout="column"]': { + w: 'full', + h: 'min-content', + }, + '&[data-parent-layout="row"]': { + flex: '1 1 0', + }, + flexDir: 'column', +}; + +export const NodeSettingElementEditMode = memo(({ el }: { el: NodeSettingElement }) => { + const draggableRef = useRef(null); + const dragHandleRef = useRef(null); + const [activeDropRegion, isDragging] = useFormElementDnd(el.id, draggableRef, dragHandleRef); + const containerCtx = useContainerContext(); + const { id } = el; + + return ( + + + + + + + + + ); +}); +NodeSettingElementEditMode.displayName = 'NodeSettingElementEditMode'; + +const NodeSettingElementEditModeContent = memo(({ el }: { el: NodeSettingElement }) => { + const { t } = useTranslation(); + const { data } = el; + const isApplicable = useIsNodeSettingApplicable(); + const isPermitted = useIsNodeSettingPermitted(data.setting); + const { isChecked, onChange, isConnected } = useNodeSetting(data.nodeId, data.setting); + + if (!isApplicable) { + // The element is hidden in view mode, so surface why it won't render while editing. + return ( + + {t('workflows.builder.nodeSettingNotApplicable')} + + ); + } + + if (!isPermitted) { + // Same treatment: the element stays in the form and can still be moved or removed here, but its value must not be + // reachable - the node cache is a process-global, admin-only policy, and a shared workflow can carry this element + // to a non-admin who would otherwise be able to flip and save it. + return ( + + {t('workflows.builder.nodeSettingAdminOnly')} + + ); + } + + return ( + + + + {/* An edge drives the value, so the local one is stale - show it, but don't let it be changed here */} + + + + ); +}); +NodeSettingElementEditModeContent.displayName = 'NodeSettingElementEditModeContent'; diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeSettingElementLabelEditable.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeSettingElementLabelEditable.tsx new file mode 100644 index 00000000000..647a50366d6 --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeSettingElementLabelEditable.tsx @@ -0,0 +1,50 @@ +import { Flex, FormLabel, Input } from '@invoke-ai/ui-library'; +import { useAppDispatch } from 'app/store/storeHooks'; +import { useEditable } from 'common/hooks/useEditable'; +import { useNodeSettingDefaultLabel } from 'features/nodes/hooks/useNodeSetting'; +import { formElementNodeSettingDataChanged } from 'features/nodes/store/nodesSlice'; +import type { NodeSettingElement } from 'features/nodes/types/workflow'; +import { memo, useCallback, useRef } from 'react'; + +export const NodeSettingElementLabelEditable = memo(({ el }: { el: NodeSettingElement }) => { + const { id, data } = el; + const dispatch = useAppDispatch(); + const defaultLabel = useNodeSettingDefaultLabel(data.setting); + const inputRef = useRef(null); + + const onChange = useCallback( + (label: string) => { + dispatch(formElementNodeSettingDataChanged({ id, changes: { label } })); + }, + [dispatch, id] + ); + + const editable = useEditable({ + value: data.label || defaultLabel, + defaultValue: defaultLabel, + inputRef, + onChange, + }); + + if (!editable.isEditing) { + return ( + + + {editable.value} + + + ); + } + + return ( + + ); +}); +NodeSettingElementLabelEditable.displayName = 'NodeSettingElementLabelEditable'; diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeSettingElementViewMode.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeSettingElementViewMode.tsx new file mode 100644 index 00000000000..c43da455190 --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/NodeSettingElementViewMode.tsx @@ -0,0 +1,52 @@ +import type { SystemStyleObject } from '@invoke-ai/ui-library'; +import { Flex, FormControl, FormLabel, Switch } from '@invoke-ai/ui-library'; +import { useContainerContext } from 'features/nodes/components/sidePanel/builder/contexts'; +import { + useIsNodeSettingApplicable, + useIsNodeSettingPermitted, + useNodeSetting, + useNodeSettingDefaultLabel, +} from 'features/nodes/hooks/useNodeSetting'; +import type { NodeSettingElement } from 'features/nodes/types/workflow'; +import { NODE_SETTING_CLASS_NAME } from 'features/nodes/types/workflow'; +import { memo } from 'react'; + +const sx: SystemStyleObject = { + pb: 2, + '&[data-parent-layout="column"]': { + w: 'full', + h: 'min-content', + }, + '&[data-parent-layout="row"]': { + flex: '1 1 0', + minW: 32, + }, +}; + +export const NodeSettingElementViewMode = memo(({ el }: { el: NodeSettingElement }) => { + const { id, data } = el; + const containerCtx = useContainerContext(); + const defaultLabel = useNodeSettingDefaultLabel(data.setting); + const isApplicable = useIsNodeSettingApplicable(); + const isPermitted = useIsNodeSettingPermitted(data.setting); + const { isChecked, onChange, isConnected } = useNodeSetting(data.nodeId, data.setting); + + // Settings that no longer apply to their node would render as no-op toggles, so hide them. Settings the user is + // not permitted to change are hidden for the same reason the node footer hides them. + if (!isApplicable || !isPermitted) { + return null; + } + + return ( + + + {data.label || defaultLabel} + + {/* An edge drives the value, so the local one is stale - show it, but don't let it be changed here */} + + + + + ); +}); +NodeSettingElementViewMode.displayName = 'NodeSettingElementViewMode'; diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/WorkflowBuilder.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/WorkflowBuilder.tsx index 513cc006028..29e396f5fc0 100644 --- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/WorkflowBuilder.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/WorkflowBuilder.tsx @@ -44,6 +44,9 @@ export const WorkflowBuilder = memo(() => { + diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/dnd-hooks.ts b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/dnd-hooks.ts index 0524f8fcfda..aea1e83882b 100644 --- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/dnd-hooks.ts +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/dnd-hooks.ts @@ -33,8 +33,14 @@ import { } from 'features/nodes/store/nodesSlice'; import { selectFormRootElementId, selectNodesSlice, selectWorkflowForm } from 'features/nodes/store/selectors'; import type { FieldInputTemplate, StatefulFieldValue } from 'features/nodes/types/field'; -import type { ElementId, FormElement } from 'features/nodes/types/workflow'; -import { buildNodeFieldElement, isContainerElement, isNodeFieldElement } from 'features/nodes/types/workflow'; +import type { ElementId, FormElement, NodeSettingName } from 'features/nodes/types/workflow'; +import { + buildNodeFieldElement, + buildNodeSettingElement, + isContainerElement, + isNodeFieldElement, + isNodeSettingElement, +} from 'features/nodes/types/workflow'; import type { RefObject } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { flushSync } from 'react-dom'; @@ -78,6 +84,21 @@ const isNodeFieldDndData = (data: Record): data is Nod return uniqueNodeFieldDndKey in data; }; +const uniqueNodeSettingDndKey = Symbol('node-setting'); +type NodeSettingDndData = { + [uniqueNodeSettingDndKey]: true; + nodeId: string; + setting: NodeSettingName; +}; +const buildNodeSettingDndData = (nodeId: string, setting: NodeSettingName): NodeSettingDndData => ({ + [uniqueNodeSettingDndKey]: true, + nodeId, + setting, +}); +const isNodeSettingDndData = (data: Record): data is NodeSettingDndData => { + return uniqueNodeSettingDndKey in data; +}; + /** * Flashes an element by changing its background color. Used to indicate that an element has been moved. * @param elementId The id of the element to flash @@ -144,6 +165,29 @@ const useNodeFieldElementExists = () => { return nodeFieldElementExists; }; +/** + * Checks if a node setting element exists in the form. + * + * @param form The form to check + * @param nodeId The id of the node + * @param setting The name of the setting + * + * @returns True if the element exists, false otherwise + */ +const useNodeSettingElementExists = () => { + const store = useAppStore(); + const nodeSettingElementExists = useCallback( + (nodeId: string, setting: NodeSettingName): boolean => { + const form = selectWorkflowForm(store.getState()); + return Object.values(form.elements) + .filter(isNodeSettingElement) + .some((el) => el.data.nodeId === nodeId && el.data.setting === setting); + }, + [store] + ); + return nodeSettingElementExists; +}; + /** * Wrapper around `getAllowedDropRegions` that provides the form state from the store. * @see {@link getAllowedDropRegions} @@ -182,6 +226,11 @@ const getSourceElement = (source: ElementDragPayload) => { return buildNodeFieldElement(nodeId, fieldName, fieldTemplate.type); } + if (isNodeSettingDndData(source.data)) { + const { nodeId, setting } = source.data; + return buildNodeSettingElement(nodeId, setting); + } + if (isFormElementDndData(source.data)) { return source.data.element; } @@ -220,7 +269,8 @@ export const useBuilderDndMonitor = () => { useEffect(() => { return monitorForElements({ - canMonitor: ({ source }) => isFormElementDndData(source.data) || isNodeFieldDndData(source.data), + canMonitor: ({ source }) => + isFormElementDndData(source.data) || isNodeFieldDndData(source.data) || isNodeSettingDndData(source.data), onDrop: ({ location, source }) => { const target = location.current.dropTargets[0]; if (!target) { @@ -392,6 +442,7 @@ export const useFormElementDnd = ( const getElement = useGetElement(); const getAllowedDropRegions = useGetAllowedDropRegions(); const nodeFieldElementExists = useNodeFieldElementExists(); + const nodeSettingElementExists = useNodeSettingElementExists(); useEffect(() => { if (isRootElement) { @@ -428,6 +479,9 @@ export const useFormElementDnd = ( if (isNodeFieldDndData(source.data) && !nodeFieldElementExists(source.data.nodeId, source.data.fieldName)) { return true; } + if (isNodeSettingDndData(source.data) && !nodeSettingElementExists(source.data.nodeId, source.data.setting)) { + return true; + } if (isFormElementDndData(source.data)) { return source.data.element.id !== getElement(elementId).parentId; } @@ -480,6 +534,7 @@ export const useFormElementDnd = ( getAllowedDropRegions, getElement, nodeFieldElementExists, + nodeSettingElementExists, isRootElement, ]); @@ -508,7 +563,11 @@ export const useRootElementDropTarget = (droppableRef: RefObject, + dragHandleRef: RefObject +) => { + const [isDragging, setIsDragging] = useState(false); + + useEffect(() => { + const draggableElement = draggableRef.current; + const dragHandleElement = dragHandleRef.current; + if (!draggableElement || !dragHandleElement) { + return; + } + return combine( + dndInputFix(draggableElement), + draggable({ + element: draggableElement, + dragHandle: dragHandleElement, + getInitialData: () => buildNodeSettingDndData(nodeId, setting), + onDragStart: () => { + setIsDragging(true); + }, + onDrop: () => { + setIsDragging(false); + }, + }) + ); + }, [dragHandleRef, draggableRef, nodeId, setting]); + + return isDragging; +}; + /** * Hook that returns whether an element is the root element. * @param elementId The id of the element diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/use-add-remove-form-element.ts b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/use-add-remove-form-element.ts index e7e32345862..8af5ecec0d3 100644 --- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/use-add-remove-form-element.ts +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/use-add-remove-form-element.ts @@ -2,8 +2,13 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useInputFieldInstance } from 'features/nodes/hooks/useInputFieldInstance'; import { useInputFieldTemplateOrThrow } from 'features/nodes/hooks/useInputFieldTemplateOrThrow'; import { formElementAdded, formElementRemoved } from 'features/nodes/store/nodesSlice'; -import { buildSelectWorkflowFormNodeElement, selectFormRootElementId } from 'features/nodes/store/selectors'; -import { buildNodeFieldElement } from 'features/nodes/types/workflow'; +import { + buildSelectWorkflowFormNodeElement, + buildSelectWorkflowFormNodeSettingElement, + selectFormRootElementId, +} from 'features/nodes/store/selectors'; +import type { NodeSettingName } from 'features/nodes/types/workflow'; +import { buildNodeFieldElement, buildNodeSettingElement } from 'features/nodes/types/workflow'; import { useCallback, useMemo } from 'react'; export const useAddRemoveFormElement = (nodeId: string, fieldName: string) => { @@ -44,3 +49,34 @@ export const useAddRemoveFormElement = (nodeId: string, fieldName: string) => { return { isAddedToRoot, addNodeFieldToRoot, removeNodeFieldFromRoot }; }; + +export const useAddRemoveNodeSettingFormElement = (nodeId: string, setting: NodeSettingName) => { + const dispatch = useAppDispatch(); + const rootElementId = useAppSelector(selectFormRootElementId); + const selectWorkflowFormNodeSettingElement = useMemo( + () => buildSelectWorkflowFormNodeSettingElement(nodeId, setting), + [nodeId, setting] + ); + const workflowFormNodeSettingElement = useAppSelector(selectWorkflowFormNodeSettingElement); + const isAddedToRoot = useMemo(() => { + return !!workflowFormNodeSettingElement; + }, [workflowFormNodeSettingElement]); + + const addNodeSettingToRoot = useCallback(() => { + const element = buildNodeSettingElement(nodeId, setting); + dispatch(formElementAdded({ element, parentId: rootElementId })); + }, [nodeId, setting, dispatch, rootElementId]); + + const removeNodeSettingFromRoot = useCallback(() => { + if (!workflowFormNodeSettingElement) { + return; + } + dispatch( + formElementRemoved({ + id: workflowFormNodeSettingElement.id, + }) + ); + }, [workflowFormNodeSettingElement, dispatch]); + + return { isAddedToRoot, addNodeSettingToRoot, removeNodeSettingFromRoot }; +}; diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useInputFieldNamesByStatus.ts b/invokeai/frontend/web/src/features/nodes/hooks/useInputFieldNamesByStatus.ts index bd7f9b1e964..b03b593197a 100644 --- a/invokeai/frontend/web/src/features/nodes/hooks/useInputFieldNamesByStatus.ts +++ b/invokeai/frontend/web/src/features/nodes/hooks/useInputFieldNamesByStatus.ts @@ -4,11 +4,14 @@ import { isNil } from 'es-toolkit/compat'; import { useInvocationNodeContext } from 'features/nodes/components/flow/nodes/Invocation/context'; import type { FieldInputTemplate } from 'features/nodes/types/field'; import { isSingleOrCollection, isStatefulFieldType } from 'features/nodes/types/field'; +import { isNodeAttributeFieldName } from 'features/nodes/types/nodeAttributeFields'; import { useMemo } from 'react'; /** * Sort input fields: unordered fields first (preserving original order), * then explicitly ordered fields sorted by ui_order ascending. + * + * Node attribute fields are dropped - they live in the node footer, not in the input list. */ const sortInputFields = (fields: FieldInputTemplate[]): string[] => { const visibleFields = fields.filter((field) => !field.ui_hidden); @@ -21,7 +24,7 @@ const sortInputFields = (fields: FieldInputTemplate[]): string[] => { return unorderedFields .concat(orderedFields) .map((f) => f.name) - .filter((fieldName) => fieldName !== 'is_intermediate'); + .filter((fieldName) => !isNodeAttributeFieldName(fieldName)); }; const isConnectionInputField = (field: FieldInputTemplate) => { diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useIsBatchNode.ts b/invokeai/frontend/web/src/features/nodes/hooks/useIsBatchNode.ts deleted file mode 100644 index 7f5bd6c69f0..00000000000 --- a/invokeai/frontend/web/src/features/nodes/hooks/useIsBatchNode.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { isBatchNodeType, isGeneratorNodeType } from 'features/nodes/types/invocation'; -import { useMemo } from 'react'; - -import { useNodeTemplateOrThrow } from './useNodeTemplateOrThrow'; - -export const useIsExecutableNode = () => { - const template = useNodeTemplateOrThrow(); - const isExecutableNode = useMemo( - () => !isBatchNodeType(template.type) && !isGeneratorNodeType(template.type), - [template] - ); - return isExecutableNode; -}; diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useNodeHasGalleryOutput.ts b/invokeai/frontend/web/src/features/nodes/hooks/useNodeHasGalleryOutput.ts deleted file mode 100644 index d1e028d2b5f..00000000000 --- a/invokeai/frontend/web/src/features/nodes/hooks/useNodeHasGalleryOutput.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { some } from 'es-toolkit/compat'; -import { useMemo } from 'react'; - -import { useNodeTemplateSafe } from './useNodeTemplateSafe'; - -/** - * True when the node produces an output that lands in the gallery — currently ImageField or - * VideoField. Used to gate the "Save in gallery" checkbox and the footer that contains it. - * - * The `image` and `video` primitive nodes are excluded because they pass through an existing - * asset without saving a new copy. - */ -export const useNodeHasGalleryOutput = (): boolean => { - const template = useNodeTemplateSafe(); - const hasGalleryOutput = useMemo( - () => - some( - template?.outputs, - (output) => - (output.type.name === 'ImageField' && template?.type !== 'image') || - (output.type.name === 'VideoField' && template?.type !== 'video') - ), - [template] - ); - - return hasGalleryOutput; -}; diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useNodeSetting.test.ts b/invokeai/frontend/web/src/features/nodes/hooks/useNodeSetting.test.ts new file mode 100644 index 00000000000..450b2f022b9 --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/hooks/useNodeSetting.test.ts @@ -0,0 +1,18 @@ +import { describe, expect, it } from 'vitest'; + +import { getIsNodeSettingPermitted } from './useNodeSetting'; + +// `use_cache` toggles the process-global invocation cache for a node, which is an admin-only policy. The form builder +// can carry a `use_cache` element into a shared workflow, so every surface that renders one - node footer, form view +// mode, form edit mode - must consult this predicate, not just the footer. +describe('getIsNodeSettingPermitted', () => { + it('permits use_cache only for admins', () => { + expect(getIsNodeSettingPermitted('use_cache', true)).toBe(true); + expect(getIsNodeSettingPermitted('use_cache', false)).toBe(false); + }); + + it('permits save_to_gallery for everyone', () => { + expect(getIsNodeSettingPermitted('save_to_gallery', true)).toBe(true); + expect(getIsNodeSettingPermitted('save_to_gallery', false)).toBe(true); + }); +}); diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useNodeSetting.ts b/invokeai/frontend/web/src/features/nodes/hooks/useNodeSetting.ts new file mode 100644 index 00000000000..d7a58e1722e --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/hooks/useNodeSetting.ts @@ -0,0 +1,97 @@ +import { useAppDispatch } from 'app/store/storeHooks'; +import { useIsAdmin } from 'features/auth/hooks/useIsAdmin'; +import { useInputFieldIsConnected } from 'features/nodes/hooks/useInputFieldIsConnected'; +import { useNodeIsIntermediate } from 'features/nodes/hooks/useNodeIsIntermediate'; +import { useNodeTemplateSafe } from 'features/nodes/hooks/useNodeTemplateSafe'; +import { useUseCache } from 'features/nodes/hooks/useUseCache'; +import { nodeIsIntermediateChanged, nodeUseCacheChanged } from 'features/nodes/store/nodesSlice'; +import { getHasNodeFooter } from 'features/nodes/types/invocation'; +import type { NodeAttributeFieldName } from 'features/nodes/types/nodeAttributeFields'; +import type { NodeSettingName } from 'features/nodes/types/workflow'; +import type { ChangeEvent } from 'react'; +import { useCallback, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; + +/** + * The backend field each node setting maps to. Note that `save_to_gallery` is the inverse of `is_intermediate`. + */ +export const NODE_SETTING_FIELD_NAMES: Record = { + use_cache: 'use_cache', + save_to_gallery: 'is_intermediate', +}; + +/** + * The label shown for a node setting when the workflow author has not provided their own. + */ +export const useNodeSettingDefaultLabel = (setting: NodeSettingName): string => { + const { t } = useTranslation(); + return useMemo( + () => (setting === 'use_cache' ? t('invocationCache.useCache') : t('nodes.saveToGallery')), + [setting, t] + ); +}; + +/** + * Whether a user may see and change a node setting. + * + * `use_cache` drives the process-global invocation cache, so it is admin-only (single-user mode counts as admin). + * + * Exported separately from the hook so the predicate can be unit-tested directly. + */ +export const getIsNodeSettingPermitted = (setting: NodeSettingName, isAdmin: boolean): boolean => + setting !== 'use_cache' || isAdmin; + +/** + * Whether the current user may see and change a node setting. + * + * This is the single gate for every path that surfaces a setting - the node footer, and the form builder's view and + * edit modes. The add-to-form and drag-into-form paths live inside the footer control, so they are gated by it too. + */ +export const useIsNodeSettingPermitted = (setting: NodeSettingName): boolean => { + const isAdmin = useIsAdmin(); + return getIsNodeSettingPermitted(setting, isAdmin); +}; + +/** + * Whether a node setting applies to the node it belongs to. A setting applies exactly when the node renders a + * footer, since that is where the setting lives on the node itself. + * + * Must be used within an `InvocationNodeContextProvider`. + */ +export const useIsNodeSettingApplicable = (): boolean => { + const template = useNodeTemplateSafe(); + return useMemo(() => (template ? getHasNodeFooter(template) : false), [template]); +}; + +/** + * Provides the checked state and change handler for a node setting, plus whether an edge is driving it. + * + * When connected, the node runs with the edge's value, so the local value is stale and must not be presented as + * something the user can change. + * + * Must be used within an `InvocationNodeContextProvider`. + */ +export const useNodeSetting = (nodeId: string, setting: NodeSettingName) => { + const dispatch = useAppDispatch(); + const useCache = useUseCache(); + const isIntermediate = useNodeIsIntermediate(); + const isConnected = useInputFieldIsConnected(NODE_SETTING_FIELD_NAMES[setting]); + + const isChecked = useMemo( + () => (setting === 'use_cache' ? useCache : !isIntermediate), + [isIntermediate, setting, useCache] + ); + + const onChange = useCallback( + (e: ChangeEvent) => { + if (setting === 'use_cache') { + dispatch(nodeUseCacheChanged({ nodeId, useCache: e.target.checked })); + } else { + dispatch(nodeIsIntermediateChanged({ nodeId, isIntermediate: !e.target.checked })); + } + }, + [dispatch, nodeId, setting] + ); + + return { isChecked, onChange, isConnected }; +}; diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useWithFooter.ts b/invokeai/frontend/web/src/features/nodes/hooks/useWithFooter.ts index 14383affd82..515a572fdaa 100644 --- a/invokeai/frontend/web/src/features/nodes/hooks/useWithFooter.ts +++ b/invokeai/frontend/web/src/features/nodes/hooks/useWithFooter.ts @@ -1,9 +1,13 @@ -import { useIsExecutableNode } from 'features/nodes/hooks/useIsBatchNode'; - -import { useNodeHasGalleryOutput } from './useNodeHasGalleryOutput'; +import { useNodeTemplateOrThrow } from 'features/nodes/hooks/useNodeTemplateOrThrow'; +import { getHasNodeFooter } from 'features/nodes/types/invocation'; +import { useMemo } from 'react'; +/** + * Whether the node renders a footer. The footer hosts the node attribute fields and their connection handles. + * + * @see {@link getHasNodeFooter} + */ export const useWithFooter = () => { - const hasGalleryOutput = useNodeHasGalleryOutput(); - const isExecutableNode = useIsExecutableNode(); - return isExecutableNode && hasGalleryOutput; + const template = useNodeTemplateOrThrow(); + return useMemo(() => getHasNodeFooter(template), [template]); }; diff --git a/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts b/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts index 25fdb606a90..f7386fc132a 100644 --- a/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts +++ b/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts @@ -87,6 +87,7 @@ import type { FormElement, HeadingElement, NodeFieldElement, + NodeSettingElement, TextElement, WorkflowCategory, WorkflowV3, @@ -96,6 +97,7 @@ import { isContainerElement, isHeadingElement, isNodeFieldElement, + isNodeSettingElement, isTextElement, } from 'features/nodes/types/workflow'; import { buildFieldInputInstance } from 'features/nodes/util/schema/buildFieldInputInstance'; @@ -327,10 +329,14 @@ const slice = createSlice({ // and add changes for each exposed field. If the remove change comes after the add change, we remove the exposed // field. for (const el of Object.values(state.form.elements)) { - if (!isNodeFieldElement(el)) { + let nodeId: string; + if (isNodeFieldElement(el)) { + nodeId = el.data.fieldIdentifier.nodeId; + } else if (isNodeSettingElement(el)) { + nodeId = el.data.nodeId; + } else { continue; } - const { nodeId } = el.data.fieldIdentifier; const removeIndex = action.payload.findLastIndex( (change) => change.type === 'remove' && change.id === nodeId ); @@ -775,6 +781,9 @@ const slice = createSlice({ formElementNodeFieldDataChanged: (state, action: FormElementDataChangedAction) => { formElementDataChangedReducer(state, action, isNodeFieldElement); }, + formElementNodeSettingDataChanged: (state, action: FormElementDataChangedAction) => { + formElementDataChangedReducer(state, action, isNodeSettingElement); + }, formElementContainerDataChanged: (state, action: FormElementDataChangedAction) => { formElementDataChangedReducer(state, action, isContainerElement); }, @@ -856,6 +865,7 @@ export const { formElementHeadingDataChanged, formElementTextDataChanged, formElementNodeFieldDataChanged, + formElementNodeSettingDataChanged, formElementContainerDataChanged, formFieldInitialValuesChanged, workflowLoaded, diff --git a/invokeai/frontend/web/src/features/nodes/store/selectors.ts b/invokeai/frontend/web/src/features/nodes/store/selectors.ts index 5e8b734fbe5..1778197e4f7 100644 --- a/invokeai/frontend/web/src/features/nodes/store/selectors.ts +++ b/invokeai/frontend/web/src/features/nodes/store/selectors.ts @@ -6,7 +6,8 @@ import type { NodesState } from 'features/nodes/store/types'; import type { FieldInputInstance } from 'features/nodes/types/field'; import type { AnyNode, InvocationNode, InvocationNodeData } from 'features/nodes/types/invocation'; import { isInvocationNode } from 'features/nodes/types/invocation'; -import { isContainerElement, isNodeFieldElement } from 'features/nodes/types/workflow'; +import type { NodeSettingName } from 'features/nodes/types/workflow'; +import { isContainerElement, isNodeFieldElement, isNodeSettingElement } from 'features/nodes/types/workflow'; import { assert } from 'tsafe'; export const selectNode = (nodesSlice: NodesState, nodeId: string): AnyNode => { @@ -93,6 +94,9 @@ export const selectFormInitialValues = createNodesSelector((workflow) => workflo export const selectNodeFieldElements = createNodesSelector((workflow) => Object.values(workflow.form.elements).filter(isNodeFieldElement) ); +const selectNodeSettingElements = createNodesSelector((workflow) => + Object.values(workflow.form.elements).filter(isNodeSettingElement) +); export const buildSelectElement = (id: string) => createNodesSelector((workflow) => workflow.form?.elements[id]); export const buildSelectWorkflowFormNodeElement = (nodeId: string, fieldName: string) => @@ -102,3 +106,7 @@ export const buildSelectWorkflowFormNodeElement = (nodeId: string, fieldName: st element.data.fieldIdentifier.nodeId === nodeId && element.data.fieldIdentifier.fieldName === fieldName ) ); +export const buildSelectWorkflowFormNodeSettingElement = (nodeId: string, setting: NodeSettingName) => + createSelector(selectNodeSettingElements, (elements) => + elements.find((element) => element.data.nodeId === nodeId && element.data.setting === setting) + ); diff --git a/invokeai/frontend/web/src/features/nodes/store/util/testUtils.ts b/invokeai/frontend/web/src/features/nodes/store/util/testUtils.ts index 67c477408f3..666743ab14a 100644 --- a/invokeai/frontend/web/src/features/nodes/store/util/testUtils.ts +++ b/invokeai/frontend/web/src/features/nodes/store/util/testUtils.ts @@ -14,6 +14,36 @@ export const buildEdge = (source: string, sourceHandle: string, target: string, export const buildNode = (template: InvocationTemplate) => buildInvocationNode({ x: 0, y: 0 }, template); +/** + * `is_intermediate` and `use_cache` are declared on every invocation by the backend's `BaseInvocation`, so every + * parsed template carries them. They are node attributes - never instantiated on a node - but they are parsed all the + * same so they can be connection targets. + */ +const nodeAttributeFieldTemplates = (useCacheDefault: boolean): InvocationTemplate['inputs'] => ({ + is_intermediate: { + name: 'is_intermediate', + title: 'Is Intermediate', + required: false, + description: 'Whether or not this is an intermediate invocation.', + fieldKind: 'input', + input: 'any', + ui_hidden: false, + type: { name: 'BooleanField', cardinality: 'SINGLE', batch: false }, + default: false, + }, + use_cache: { + name: 'use_cache', + title: 'Use Cache', + required: false, + description: 'Whether or not to use the cache', + fieldKind: 'input', + input: 'any', + ui_hidden: false, + type: { name: 'BooleanField', cardinality: 'SINGLE', batch: false }, + default: useCacheDefault, + }, +}); + export const add: InvocationTemplate = { title: 'Add Integers', type: 'add', @@ -22,6 +52,7 @@ export const add: InvocationTemplate = { description: 'Adds two numbers', outputType: 'integer_output', inputs: { + ...nodeAttributeFieldTemplates(true), a: { name: 'a', title: 'A', @@ -82,6 +113,7 @@ export const call_saved_workflow: InvocationTemplate = { category: 'workflow', outputType: 'integer_output', inputs: { + ...nodeAttributeFieldTemplates(false), workflow_id: { name: 'workflow_id', title: 'Workflow Id', @@ -132,6 +164,7 @@ export const workflow_return: InvocationTemplate = { category: 'workflow', outputType: 'workflow_return_output', inputs: { + ...nodeAttributeFieldTemplates(false), collection: { name: 'collection', title: 'Collection', @@ -177,6 +210,7 @@ export const sub: InvocationTemplate = { description: 'Subtracts two numbers', outputType: 'integer_output', inputs: { + ...nodeAttributeFieldTemplates(true), a: { name: 'a', title: 'A', @@ -236,6 +270,7 @@ export const collect: InvocationTemplate = { description: 'Collects values into a collection', outputType: 'collect_output', inputs: { + ...nodeAttributeFieldTemplates(true), collection: { name: 'collection', title: 'Collection', @@ -298,6 +333,7 @@ const scheduler: InvocationTemplate = { description: 'Selects a scheduler.', outputType: 'scheduler_output', inputs: { + ...nodeAttributeFieldTemplates(true), scheduler: { name: 'scheduler', title: 'Scheduler', @@ -355,6 +391,7 @@ export const main_model_loader: InvocationTemplate = { description: 'Loads a main model, outputting its submodels.', outputType: 'model_loader_output', inputs: { + ...nodeAttributeFieldTemplates(true), model: { name: 'model', title: 'Model', @@ -424,6 +461,7 @@ export const img_resize: InvocationTemplate = { description: 'Resizes an image to specific dimensions', outputType: 'image_output', inputs: { + ...nodeAttributeFieldTemplates(true), board: { name: 'board', title: 'Board', @@ -569,6 +607,7 @@ const iterate: InvocationTemplate = { description: 'Iterates over a list of items', outputType: 'iterate_output', inputs: { + ...nodeAttributeFieldTemplates(true), collection: { name: 'collection', title: 'Collection', @@ -666,7 +705,9 @@ export const schema = { description: 'Whether or not this is an intermediate invocation.', default: false, field_kind: 'node_attribute', - ui_type: 'IsIntermediate', + input: 'any', + orig_required: false, + ui_hidden: false, }, use_cache: { type: 'boolean', @@ -674,6 +715,9 @@ export const schema = { description: 'Whether or not to use the cache', default: false, field_kind: 'node_attribute', + input: 'any', + orig_required: false, + ui_hidden: false, }, workflow_id: { type: 'string', @@ -724,7 +768,9 @@ export const schema = { description: 'Whether or not this is an intermediate invocation.', default: false, field_kind: 'node_attribute', - ui_type: 'IsIntermediate', + input: 'any', + orig_required: false, + ui_hidden: false, }, use_cache: { type: 'boolean', @@ -732,6 +778,9 @@ export const schema = { description: 'Whether or not to use the cache', default: false, field_kind: 'node_attribute', + input: 'any', + orig_required: false, + ui_hidden: false, }, collection: { type: 'array', @@ -806,7 +855,9 @@ export const schema = { description: 'Whether or not this is an intermediate invocation.', default: false, field_kind: 'node_attribute', - ui_type: 'IsIntermediate', + input: 'any', + orig_required: false, + ui_hidden: false, }, use_cache: { type: 'boolean', @@ -814,6 +865,9 @@ export const schema = { description: 'Whether or not to use the cache', default: true, field_kind: 'node_attribute', + input: 'any', + orig_required: false, + ui_hidden: false, }, a: { type: 'integer', @@ -898,7 +952,9 @@ export const schema = { description: 'Whether or not this is an intermediate invocation.', default: false, field_kind: 'node_attribute', - ui_type: 'IsIntermediate', + input: 'any', + orig_required: false, + ui_hidden: false, }, use_cache: { type: 'boolean', @@ -906,6 +962,9 @@ export const schema = { description: 'Whether or not to use the cache', default: true, field_kind: 'node_attribute', + input: 'any', + orig_required: false, + ui_hidden: false, }, scheduler: { type: 'string', @@ -1031,7 +1090,9 @@ export const schema = { description: 'Whether or not this is an intermediate invocation.', default: false, field_kind: 'node_attribute', - ui_type: 'IsIntermediate', + input: 'any', + orig_required: false, + ui_hidden: false, }, use_cache: { type: 'boolean', @@ -1039,6 +1100,9 @@ export const schema = { description: 'Whether or not to use the cache', default: true, field_kind: 'node_attribute', + input: 'any', + orig_required: false, + ui_hidden: false, }, model: { allOf: [ @@ -1394,7 +1458,9 @@ export const schema = { description: 'Whether or not this is an intermediate invocation.', default: false, field_kind: 'node_attribute', - ui_type: 'IsIntermediate', + input: 'any', + orig_required: false, + ui_hidden: false, }, use_cache: { type: 'boolean', @@ -1402,6 +1468,9 @@ export const schema = { description: 'Whether or not to use the cache', default: true, field_kind: 'node_attribute', + input: 'any', + orig_required: false, + ui_hidden: false, }, item: { anyOf: [ @@ -1490,7 +1559,9 @@ export const schema = { description: 'Whether or not this is an intermediate invocation.', default: false, field_kind: 'node_attribute', - ui_type: 'IsIntermediate', + input: 'any', + orig_required: false, + ui_hidden: false, }, use_cache: { type: 'boolean', @@ -1498,6 +1569,9 @@ export const schema = { description: 'Whether or not to use the cache', default: true, field_kind: 'node_attribute', + input: 'any', + orig_required: false, + ui_hidden: false, }, a: { type: 'integer', @@ -1588,7 +1662,9 @@ export const schema = { description: 'Whether or not this is an intermediate invocation.', default: false, field_kind: 'node_attribute', - ui_type: 'IsIntermediate', + input: 'any', + orig_required: false, + ui_hidden: false, }, use_cache: { type: 'boolean', @@ -1596,6 +1672,9 @@ export const schema = { description: 'Whether or not to use the cache', default: true, field_kind: 'node_attribute', + input: 'any', + orig_required: false, + ui_hidden: false, }, image: { allOf: [ @@ -1757,7 +1836,9 @@ export const schema = { description: 'Whether or not this is an intermediate invocation.', default: false, field_kind: 'node_attribute', - ui_type: 'IsIntermediate', + input: 'any', + orig_required: false, + ui_hidden: false, }, use_cache: { type: 'boolean', @@ -1765,6 +1846,9 @@ export const schema = { description: 'Whether or not to use the cache', default: true, field_kind: 'node_attribute', + input: 'any', + orig_required: false, + ui_hidden: false, }, collection: { items: {}, diff --git a/invokeai/frontend/web/src/features/nodes/store/util/validateConnection.test.ts b/invokeai/frontend/web/src/features/nodes/store/util/validateConnection.test.ts index 1eef0794436..4fa3e1c58aa 100644 --- a/invokeai/frontend/web/src/features/nodes/store/util/validateConnection.test.ts +++ b/invokeai/frontend/web/src/features/nodes/store/util/validateConnection.test.ts @@ -816,6 +816,75 @@ describe(validateConnection.name, () => { }); }); + describe('node attribute fields', () => { + // `use_cache` and `is_intermediate` are parsed into every template so they can be connection targets, but they + // are only reachable on nodes that render a footer - that is where their handle lives. + const booleanPrimitive: InvocationTemplate = { + title: 'Boolean Primitive', + type: 'boolean', + version: '1.0.1', + tags: ['primitives', 'boolean'], + description: 'A boolean primitive value', + outputType: 'boolean_output', + inputs: {}, + outputs: { + value: { + fieldKind: 'output', + name: 'value', + title: 'Value', + description: 'The output boolean', + type: { name: 'BooleanField', cardinality: 'SINGLE', batch: false }, + ui_hidden: false, + }, + }, + useCache: true, + nodePack: 'invokeai', + classification: 'stable', + category: 'primitives', + }; + const templatesWithBoolean = { ...templates, boolean: booleanPrimitive }; + + it.each(['use_cache', 'is_intermediate'])( + 'should accept a connection to %s on a node that renders a footer', + (targetHandle) => { + const n1 = buildNode(booleanPrimitive); + const n2 = buildNode(img_resize); + const c = { source: n1.id, sourceHandle: 'value', target: n2.id, targetHandle }; + const r = validateConnection(c, [n1, n2], [], templatesWithBoolean, null); + expect(r).toEqual(null); + } + ); + + it.each(['use_cache', 'is_intermediate'])( + 'should reject a connection to %s on a node with no footer', + (targetHandle) => { + // `add` has no gallery output, so it renders no footer and there is no handle to attach to + const n1 = buildNode(booleanPrimitive); + const n2 = buildNode(add); + const c = { source: n1.id, sourceHandle: 'value', target: n2.id, targetHandle }; + const r = validateConnection(c, [n1, n2], [], templatesWithBoolean, null); + expect(r).toEqual('nodes.cannotConnectToUnavailableNodeSetting'); + } + ); + + it('should still reject a type mismatch on a reachable node attribute field', () => { + const n1 = buildNode(add); + const n2 = buildNode(img_resize); + const c = { source: n1.id, sourceHandle: 'value', target: n2.id, targetHandle: 'use_cache' }; + const r = validateConnection(c, [n1, n2], [], templatesWithBoolean, null); + expect(r).toEqual('nodes.fieldTypesMustMatch'); + }); + + it('should not create field instances for node attribute fields', () => { + // The value lives on the node itself; an instance would be a second, conflicting source of truth + const node = buildNode(img_resize); + expect(node.data.inputs.use_cache).toBeUndefined(); + expect(node.data.inputs.is_intermediate).toBeUndefined(); + expect(node.data.useCache).toBe(true); + expect(node.data.isIntermediate).toBe(true); + }); + }); + describe('non-strict mode', () => { it('should reject connections from self to self in non-strict mode', () => { const c = { source: 'add', sourceHandle: 'value', target: 'add', targetHandle: 'a' }; diff --git a/invokeai/frontend/web/src/features/nodes/store/util/validateConnection.ts b/invokeai/frontend/web/src/features/nodes/store/util/validateConnection.ts index 710e49de7cf..68b721250e4 100644 --- a/invokeai/frontend/web/src/features/nodes/store/util/validateConnection.ts +++ b/invokeai/frontend/web/src/features/nodes/store/util/validateConnection.ts @@ -11,7 +11,13 @@ import { getHasCycles } from 'features/nodes/store/util/getHasCycles'; import { validateConnectionTypes } from 'features/nodes/store/util/validateConnectionTypes'; import type { FieldType } from 'features/nodes/types/field'; import type { AnyEdge, AnyNode, InvocationNode } from 'features/nodes/types/invocation'; -import { getInvocationNodeInputTemplate, isConnectorNode, isInvocationNode } from 'features/nodes/types/invocation'; +import { + getHasNodeFooter, + getInvocationNodeInputTemplate, + isConnectorNode, + isInvocationNode, +} from 'features/nodes/types/invocation'; +import { isNodeAttributeFieldName } from 'features/nodes/types/nodeAttributeFields'; import type { SetNonNullable } from 'type-fest'; type Connection = SetNonNullable; @@ -300,6 +306,13 @@ export const validateConnection: ValidateConnectionFunc = ( return 'nodes.cannotConnectToDirectInput'; } + if (isNodeAttributeFieldName(c.targetHandle) && !getHasNodeFooter(targetTemplate)) { + // Node attribute fields are exposed in the node footer. Without a footer there is no handle to attach to and + // no way for the user to see the connection, so the edge would be invisible and - for batch and generator + // nodes, which `buildNodesGraph` drops entirely - have no effect at all. + return 'nodes.cannotConnectToUnavailableNodeSetting'; + } + if (!effectiveSource) { if (sourceNode && isConnectorNode(sourceNode) && c.sourceHandle === CONNECTOR_OUTPUT_HANDLE) { const existingTerminalTargetEdges = getConnectorTerminalTargetEdges(sourceNode.id, nodes, filteredEdges).filter( diff --git a/invokeai/frontend/web/src/features/nodes/types/invocation.ts b/invokeai/frontend/web/src/features/nodes/types/invocation.ts index 4013e2518cd..d60d2b11cbc 100644 --- a/invokeai/frontend/web/src/features/nodes/types/invocation.ts +++ b/invokeai/frontend/web/src/features/nodes/types/invocation.ts @@ -178,10 +178,10 @@ export const zAnyEdge = z.union([zDefaultInvocationNodeEdge, zCollapsedInvocatio export type AnyEdge = z.infer; // #endregion -export const isBatchNodeType = (type: string) => +const isBatchNodeType = (type: string) => ['image_batch', 'string_batch', 'integer_batch', 'float_batch'].includes(type); -export const isGeneratorNodeType = (type: string) => +const isGeneratorNodeType = (type: string) => ['image_generator', 'string_generator', 'integer_generator', 'float_generator'].includes(type); export const isBatchNode = (node: InvocationNode) => isBatchNodeType(node.data.type); @@ -191,6 +191,29 @@ export const isExecutableNode = (node: InvocationNode) => { return !isBatchNode(node) && !isGeneratorNode(node); }; +/** + * True when the node produces an output that lands in the gallery - currently ImageField or VideoField. + * + * The `image` and `video` primitive nodes are excluded because they pass through an existing asset without saving a + * new copy. + */ +const getNodeHasGalleryOutput = (template: InvocationTemplate): boolean => + Object.values(template.outputs).some( + (output) => + (output.type.name === 'ImageField' && template.type !== 'image') || + (output.type.name === 'VideoField' && template.type !== 'video') + ); + +/** + * True when the node renders a footer. + * + * The footer hosts the node attribute fields (`use_cache`, `is_intermediate`), including their connection handles. + * A node without a footer therefore has nowhere to attach an edge for those fields, so this predicate also decides + * whether such a connection may be made at all. + */ +export const getHasNodeFooter = (template: InvocationTemplate): boolean => + !isBatchNodeType(template.type) && !isGeneratorNodeType(template.type) && getNodeHasGalleryOutput(template); + export const getInvocationNodeInputTemplate = ( nodeData: Pick & Partial>, template: InvocationTemplate, diff --git a/invokeai/frontend/web/src/features/nodes/types/nodeAttributeFields.ts b/invokeai/frontend/web/src/features/nodes/types/nodeAttributeFields.ts new file mode 100644 index 00000000000..9895f182653 --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/types/nodeAttributeFields.ts @@ -0,0 +1,16 @@ +/** + * Node attribute fields are declared on every invocation by the backend's `BaseInvocation`, but the workflow editor + * treats them differently from ordinary inputs: + * + * - Their value lives on the node itself (`node.data.useCache` / `node.data.isIntermediate`), never in + * `node.data.inputs`. No field instance is ever created for them. + * - They are parsed into invocation templates all the same, because a template entry is what connection validation + * and the connection handle need. + * - They are filtered out of the node's input list and rendered in the node footer instead. + */ +const NODE_ATTRIBUTE_FIELD_NAMES = ['use_cache', 'is_intermediate'] as const; + +export type NodeAttributeFieldName = (typeof NODE_ATTRIBUTE_FIELD_NAMES)[number]; + +export const isNodeAttributeFieldName = (fieldName: string): fieldName is NodeAttributeFieldName => + NODE_ATTRIBUTE_FIELD_NAMES.includes(fieldName as NodeAttributeFieldName); diff --git a/invokeai/frontend/web/src/features/nodes/types/workflow.ts b/invokeai/frontend/web/src/features/nodes/types/workflow.ts index bfb7b92b18f..c35ff4c08b0 100644 --- a/invokeai/frontend/web/src/features/nodes/types/workflow.ts +++ b/invokeai/frontend/web/src/features/nodes/types/workflow.ts @@ -175,6 +175,40 @@ export const buildNodeFieldElement = ( return element; }; +const NODE_SETTING_TYPE = 'node-setting'; +export const NODE_SETTING_CLASS_NAME = `form-builder-${NODE_SETTING_TYPE}`; +/** + * Node settings are node-level toggles that are not input fields, so they cannot be represented as node field + * elements. They live directly on the node's data instead of in its inputs. + */ +const zNodeSettingName = z.enum(['use_cache', 'save_to_gallery']); +export type NodeSettingName = z.infer; +const zNodeSettingData = z.object({ + nodeId: z.string().trim().min(1), + setting: zNodeSettingName, + // Unlike node fields, there is nowhere on the node to store a user-provided label, so it is stored on the element. + label: z.string().default(''), +}); +const zNodeSettingElement = zElementBase.extend({ + type: z.literal(NODE_SETTING_TYPE), + data: zNodeSettingData, +}); +export type NodeSettingElement = z.infer; +export const isNodeSettingElement = (el: FormElement): el is NodeSettingElement => el.type === NODE_SETTING_TYPE; +export const buildNodeSettingElement = ( + nodeId: NodeSettingElement['data']['nodeId'], + setting: NodeSettingElement['data']['setting'], + parentId?: NodeSettingElement['parentId'] +): NodeSettingElement => { + const element: NodeSettingElement = { + id: getPrefixedId(NODE_SETTING_TYPE, '-'), + type: NODE_SETTING_TYPE, + parentId, + data: { nodeId, setting, label: '' }, + }; + return element; +}; + const HEADING_TYPE = 'heading'; export const HEADING_CLASS_NAME = `form-builder-${HEADING_TYPE}`; const zHeadingElement = zElementBase.extend({ @@ -262,7 +296,14 @@ export const buildContainer = ( return element; }; -const zFormElement = z.union([zContainerElement, zNodeFieldElement, zHeadingElement, zTextElement, zDividerElement]); +const zFormElement = z.union([ + zContainerElement, + zNodeFieldElement, + zNodeSettingElement, + zHeadingElement, + zTextElement, + zDividerElement, +]); export type FormElement = z.infer; diff --git a/invokeai/frontend/web/src/features/nodes/util/node/buildInvocationNode.ts b/invokeai/frontend/web/src/features/nodes/util/node/buildInvocationNode.ts index 2af152e6bb8..e2b32d6e081 100644 --- a/invokeai/frontend/web/src/features/nodes/util/node/buildInvocationNode.ts +++ b/invokeai/frontend/web/src/features/nodes/util/node/buildInvocationNode.ts @@ -3,6 +3,7 @@ import { reduce } from 'es-toolkit/compat'; import { SHARED_NODE_PROPERTIES } from 'features/nodes/types/constants'; import type { FieldInputInstance } from 'features/nodes/types/field'; import type { InvocationNode, InvocationTemplate } from 'features/nodes/types/invocation'; +import { isNodeAttributeFieldName } from 'features/nodes/types/nodeAttributeFields'; import { buildFieldInputInstance } from 'features/nodes/util/schema/buildFieldInputInstance'; import { v4 as uuidv4 } from 'uuid'; @@ -13,6 +14,13 @@ export const buildInvocationNode = (position: XYPosition, template: InvocationTe const inputs = reduce( template.inputs, (inputsAccumulator, inputTemplate, inputName) => { + if (isNodeAttributeFieldName(inputName)) { + // Node attribute fields have a template so they can be connection targets, but their value lives on the node + // (`data.useCache` / `data.isIntermediate`). Creating an instance here would give them a second, conflicting + // source of truth. `updateNode` derives its allowed keys from this object, so it drops them too. + return inputsAccumulator; + } + const fieldId = uuidv4(); const inputFieldValue: FieldInputInstance = buildFieldInputInstance(fieldId, inputTemplate); diff --git a/invokeai/frontend/web/src/features/nodes/util/node/getSortedFilteredFieldNames.ts b/invokeai/frontend/web/src/features/nodes/util/node/getSortedFilteredFieldNames.ts index 9a64fca1710..c9472c232ab 100644 --- a/invokeai/frontend/web/src/features/nodes/util/node/getSortedFilteredFieldNames.ts +++ b/invokeai/frontend/web/src/features/nodes/util/node/getSortedFilteredFieldNames.ts @@ -1,5 +1,6 @@ import { isNil } from 'es-toolkit/compat'; import type { FieldInputTemplate, FieldOutputTemplate } from 'features/nodes/types/field'; +import { isNodeAttributeFieldName } from 'features/nodes/types/nodeAttributeFields'; export const getSortedFilteredFieldNames = (fields: FieldInputTemplate[] | FieldOutputTemplate[]): string[] => { const visibleFields = fields.filter((field) => !field.ui_hidden); @@ -10,9 +11,9 @@ export const getSortedFilteredFieldNames = (fields: FieldInputTemplate[] | Field .sort((a, b) => (a.ui_order ?? 0) - (b.ui_order ?? 0)); const unorderedFields = visibleFields.filter((f) => isNil(f.ui_order)); - // concat the lists, and return the field names, skipping `is_intermediate` + // concat the lists, and return the field names, skipping node attribute fields - they live in the node footer return orderedFields .concat(unorderedFields) .map((f) => f.name) - .filter((fieldName) => fieldName !== 'is_intermediate'); + .filter((fieldName) => !isNodeAttributeFieldName(fieldName)); }; diff --git a/invokeai/frontend/web/src/features/nodes/util/schema/parseSchema.ts b/invokeai/frontend/web/src/features/nodes/util/schema/parseSchema.ts index 47be2c62ec7..4f80f1f26d3 100644 --- a/invokeai/frontend/web/src/features/nodes/util/schema/parseSchema.ts +++ b/invokeai/frontend/web/src/features/nodes/util/schema/parseSchema.ts @@ -29,9 +29,11 @@ import { isCollectionFieldType, parseFieldType } from './parseFieldType'; const log = logger('system'); -const RESERVED_INPUT_FIELD_NAMES = ['id', 'type', 'use_cache']; +// `use_cache` and `is_intermediate` are deliberately absent here. They are node attributes, but they are still parsed +// into the template so they can be connection targets - see `nodeAttributeFields.ts`. They never get a field instance +// and are filtered out of the node's input list at render time. +const RESERVED_INPUT_FIELD_NAMES = ['id', 'type']; const RESERVED_OUTPUT_FIELD_NAMES = ['type']; -const RESERVED_FIELD_TYPES = ['IsIntermediate']; const invocationDenylist: string[] = ['graph', 'linear_ui_output']; @@ -45,13 +47,6 @@ const isReservedInputField = (nodeType: string, fieldName: string) => { return false; }; -const isReservedFieldType = (fieldType: string) => { - if (RESERVED_FIELD_TYPES.includes(fieldType)) { - return true; - } - return false; -}; - const isAllowedOutputField = (nodeType: string, fieldName: string) => { if (RESERVED_OUTPUT_FIELD_NAMES.includes(fieldName)) { return false; @@ -147,11 +142,6 @@ export const parseSchema = ( return inputsAccumulator; } - if (isReservedFieldType(fieldType.name)) { - log.trace({ node: type, field: propertyName, schema: parseify(property) }, 'Skipped reserved input field'); - return inputsAccumulator; - } - if (isStatefulFieldType(fieldType) && originalFieldType && !objectEquals(originalFieldType, fieldType)) { fieldType.originalType = deepClone(originalFieldType); } diff --git a/invokeai/frontend/web/src/features/nodes/util/workflow/validateWorkflow.test.ts b/invokeai/frontend/web/src/features/nodes/util/workflow/validateWorkflow.test.ts index 7d5abf34e5e..dc678b14c30 100644 --- a/invokeai/frontend/web/src/features/nodes/util/workflow/validateWorkflow.test.ts +++ b/invokeai/frontend/web/src/features/nodes/util/workflow/validateWorkflow.test.ts @@ -10,7 +10,12 @@ import { } from 'features/nodes/store/util/testUtils'; import type { InvocationTemplate } from 'features/nodes/types/invocation'; import type { WorkflowV3 } from 'features/nodes/types/workflow'; -import { buildNodeFieldElement, getDefaultForm, isNodeFieldElement } from 'features/nodes/types/workflow'; +import { + buildNodeFieldElement, + buildNodeSettingElement, + getDefaultForm, + isNodeFieldElement, +} from 'features/nodes/types/workflow'; import { buildInvocationNode } from 'features/nodes/util/node/buildInvocationNode'; import { buildFieldInputInstance } from 'features/nodes/util/schema/buildFieldInputInstance'; import { validateWorkflow } from 'features/nodes/util/workflow/validateWorkflow'; @@ -504,6 +509,45 @@ describe('validateWorkflow', () => { expect(updatedElement.data.fieldIdentifier.fieldName).toBe('images'); }); + it('should retain node setting form elements whose node still exists', async () => { + const workflow = getWorkflow(); + const element = buildNodeSettingElement('afad11b4-bb5c-45d1-b956-6c8e2357ee11', 'save_to_gallery'); + addElement({ form: workflow.form, element, parentId: workflow.form.rootElementId }); + + const validationResult = await validateWorkflow({ + workflow, + templates: { img_resize, main_model_loader }, + checkImageAccess: resolveTrue, + checkVideoAccess: resolveTrue, + checkBoardAccess: resolveTrue, + checkModelAccess: resolveTrue, + }); + + expect(validationResult.workflow.form.elements[element.id]).toBeDefined(); + }); + + it('should delete node setting form elements whose node no longer exists', async () => { + const workflow = getWorkflow(); + const element = buildNodeSettingElement('does-not-exist', 'use_cache'); + addElement({ form: workflow.form, element, parentId: workflow.form.rootElementId }); + + const validationResult = await validateWorkflow({ + workflow, + templates: { img_resize, main_model_loader }, + checkImageAccess: resolveTrue, + checkVideoAccess: resolveTrue, + checkBoardAccess: resolveTrue, + checkModelAccess: resolveTrue, + }); + + const { form } = validationResult.workflow; + expect(form.elements[element.id]).toBeUndefined(); + // The dangling child reference must be cleaned up too, else the form fails structure validation on the next load + const rootElement = form.elements[form.rootElementId]; + expect(rootElement?.type === 'container' && rootElement.data.children).toEqual([]); + expect(validationResult.warnings.length).toBe(1); + }); + it('should refresh call_saved_workflow dynamic inputs while loading a stale serialized workflow', async () => { const workflow = getWorkflow(); const callNode = buildInvocationNode({ x: 0, y: 0 }, call_saved_workflow); diff --git a/invokeai/frontend/web/src/features/nodes/util/workflow/validateWorkflow.ts b/invokeai/frontend/web/src/features/nodes/util/workflow/validateWorkflow.ts index 4775b2cfc4d..65fe0285327 100644 --- a/invokeai/frontend/web/src/features/nodes/util/workflow/validateWorkflow.ts +++ b/invokeai/frontend/web/src/features/nodes/util/workflow/validateWorkflow.ts @@ -1,6 +1,10 @@ import { parseify } from 'common/util/serialize'; import { getSavedWorkflowDynamicFields } from 'features/nodes/components/flow/nodes/Invocation/callSavedWorkflowFormUtils'; -import { addElement, getIsFormEmpty } from 'features/nodes/components/sidePanel/builder/form-manipulation'; +import { + addElement, + getIsFormEmpty, + removeElement, +} from 'features/nodes/components/sidePanel/builder/form-manipulation'; import { CALL_SAVED_WORKFLOW_DYNAMIC_FIELD_PREFIX } from 'features/nodes/store/nodesSlice'; import type { Templates } from 'features/nodes/store/types'; import { validateConnection } from 'features/nodes/store/util/validateConnection'; @@ -19,6 +23,7 @@ import { buildNodeFieldElement, getDefaultForm, isNodeFieldElement, + isNodeSettingElement, isWorkflowInvocationNode, } from 'features/nodes/types/workflow'; import { @@ -419,5 +424,21 @@ export const validateWorkflow = async (args: ValidateWorkflowArgs): Promise id === nodeId); + if (!node) { + removeElement({ form: _workflow.form, id: element.id }); + warnings.push({ + message: t('nodes.deletedMissingNodeSettingFormElement', { nodeId, setting }), + data: { nodeId, setting }, + }); + } + } + return { workflow: _workflow, warnings }; }; diff --git a/tests/test_node_graph.py b/tests/test_node_graph.py index 93e198b3763..e4013d5eb0a 100644 --- a/tests/test_node_graph.py +++ b/tests/test_node_graph.py @@ -18,6 +18,8 @@ ) from invokeai.app.invocations.math import AddInvocation from invokeai.app.invocations.primitives import ( + BooleanInvocation, + BooleanOutput, ColorInvocation, FloatCollectionInvocation, FloatInvocation, @@ -529,6 +531,52 @@ def test_graph_validates(): assert g.is_valid() is True +@pytest.mark.parametrize("field", ["use_cache", "is_intermediate"]) +def test_graph_validates_edges_into_node_attribute_fields(field: str): + # `use_cache` and `is_intermediate` are node attributes, but they are ordinary pydantic fields declaring + # `Input.Any`, so the workflow editor may drive them with an edge. + g = Graph() + n1 = BooleanInvocation(id="1", value=True) + n2 = ESRGANInvocation(id="2") + g.add_node(n1) + g.add_node(n2) + g.add_edge(create_edge("1", "value", "2", field)) + + assert g.is_valid() is True + + +def test_graph_rejects_type_mismatched_edge_into_node_attribute_field(): + g = Graph() + n1 = IntegerInvocation(id="1", value=1) + n2 = ESRGANInvocation(id="2") + g.add_node(n1) + g.add_node(n2) + + with pytest.raises(InvalidEdgeError): + g.add_edge(create_edge("1", "value", "2", "use_cache")) + + +def test_graph_execution_state_applies_node_attribute_edges_before_invoking(): + # The cache is consulted inside `_invoke_internal`, which runs after `next()` has applied edge values, so a + # connected `use_cache` is resolved by the time it is read. + g = Graph() + n1 = BooleanInvocation(id="1", value=False) + n2 = ESRGANInvocation(id="2") + g.add_node(n1) + g.add_node(n2) + g.add_edge(create_edge("1", "value", "2", "use_cache")) + + state = GraphExecutionState(graph=g) + source = state.next() + assert isinstance(source, BooleanInvocation) + state.complete(source.id, BooleanOutput(value=False)) + + prepared = state.next() + assert isinstance(prepared, ESRGANInvocation) + # The node's own default is True; the edge value won before the invocation was handed out + assert prepared.use_cache is False + + def test_graph_invalid_if_edges_reference_missing_nodes(): g = Graph() n1 = TextToImageTestInvocation(id="1", prompt="Banana sushi")