feat: move board logic to save_image node

- Remove the add-to-board node
- Create `BoardField` field type & add it to `save_image` node
- Add UI for `BoardField`
- Tighten up some loose types
- Make `save_image` node, in workflow editor, default to not intermediate
- Patch bump `save_image`
This commit is contained in:
psychedelicious 2023-09-22 12:09:24 +10:00 committed by Kent Keirsey
parent 627444e17c
commit 43fbac26df
15 changed files with 245 additions and 124 deletions

View File

@ -88,6 +88,8 @@ class FieldDescriptions:
num_1 = "The first number" num_1 = "The first number"
num_2 = "The second number" num_2 = "The second number"
mask = "The mask to use for the operation" mask = "The mask to use for the operation"
board = "The board to save the image to"
image = "The image to process"
class Input(str, Enum): class Input(str, Enum):
@ -173,6 +175,7 @@ class UIType(str, Enum):
WorkflowField = "WorkflowField" WorkflowField = "WorkflowField"
IsIntermediate = "IsIntermediate" IsIntermediate = "IsIntermediate"
MetadataField = "MetadataField" MetadataField = "MetadataField"
BoardField = "BoardField"
# endregion # endregion
@ -656,6 +659,8 @@ def invocation(
:param Optional[str] title: Adds a title to the invocation. Use if the auto-generated title isn't quite right. Defaults to None. :param Optional[str] title: Adds a title to the invocation. Use if the auto-generated title isn't quite right. Defaults to None.
:param Optional[list[str]] tags: Adds tags to the invocation. Invocations may be searched for by their tags. Defaults to None. :param Optional[list[str]] tags: Adds tags to the invocation. Invocations may be searched for by their tags. Defaults to None.
:param Optional[str] category: Adds a category to the invocation. Used to group the invocations in the UI. Defaults to None. :param Optional[str] category: Adds a category to the invocation. Used to group the invocations in the UI. Defaults to None.
:param Optional[str] version: Adds a version to the invocation. Must be a valid semver string. Defaults to None.
:param Optional[bool] use_cache: Whether or not to use the invocation cache. Defaults to True. The user may override this in the workflow editor.
""" """
def wrapper(cls: Type[GenericBaseInvocation]) -> Type[GenericBaseInvocation]: def wrapper(cls: Type[GenericBaseInvocation]) -> Type[GenericBaseInvocation]:

View File

@ -1,54 +0,0 @@
# Copyright (c) 2022 Kyle Schouviller (https://github.com/kyle0654)
from invokeai.app.invocations.metadata import CoreMetadata
from invokeai.app.invocations.primitives import ImageField
from .baseinvocation import BaseInvocation, FieldDescriptions, InputField, InvocationContext, invocation, invocation_output, OutputField, BaseInvocationOutput
@invocation_output("image_to_board_output")
class ImageToBoardOutput(BaseInvocationOutput):
image: ImageField = OutputField(description="The image that was associated")
board_name: str = OutputField(description="Board this image was associated with")
@invocation(
"image_to_board",
title="Associate Image with Board",
tags=["primitives", "board"],
category="primitives",
version="1.0.0",
use_cache=False,
)
class ImageToBoardInvocation(BaseInvocation):
"""Associates an image with a board so you view it in the board's gallery."""
image: ImageField = InputField(description="The image to associate")
board_name: str = InputField(description="Name of the board you'd like associate this image with")
metadata: CoreMetadata = InputField(
default=None,
description=FieldDescriptions.core_metadata,
ui_hidden=True,
)
def invoke(self, context: InvocationContext) -> ImageToBoardOutput:
board_id = None
page = 0
page_size = 10
while not board_id:
boards = context.services.boards.get_many(page * page_size, page_size)
board_id = next(board.board_id for board in boards.items if board.board_name == self.board_name)
page += 1
if len(boards < page_size):
break
context.services.board_images.add_image_to_board(
board_id=board_id,
image_name=self.image.image_name,
)
return ImageToBoardOutput(
image=self.image,
board_id=board_id
)

View File

@ -8,12 +8,12 @@ import numpy
from PIL import Image, ImageChops, ImageFilter, ImageOps from PIL import Image, ImageChops, ImageFilter, ImageOps
from invokeai.app.invocations.metadata import CoreMetadata from invokeai.app.invocations.metadata import CoreMetadata
from invokeai.app.invocations.primitives import ColorField, ImageField, ImageOutput from invokeai.app.invocations.primitives import BoardField, ColorField, ImageField, ImageOutput
from invokeai.backend.image_util.invisible_watermark import InvisibleWatermark from invokeai.backend.image_util.invisible_watermark import InvisibleWatermark
from invokeai.backend.image_util.safety_checker import SafetyChecker from invokeai.backend.image_util.safety_checker import SafetyChecker
from ..models.image import ImageCategory, ResourceOrigin from ..models.image import ImageCategory, ResourceOrigin
from .baseinvocation import BaseInvocation, FieldDescriptions, InputField, InvocationContext, invocation from .baseinvocation import BaseInvocation, FieldDescriptions, Input, InputField, InvocationContext, invocation
@invocation("show_image", title="Show Image", tags=["image"], category="image", version="1.0.0") @invocation("show_image", title="Show Image", tags=["image"], category="image", version="1.0.0")
@ -972,13 +972,14 @@ class ImageChannelMultiplyInvocation(BaseInvocation):
title="Save Image", title="Save Image",
tags=["primitives", "image"], tags=["primitives", "image"],
category="primitives", category="primitives",
version="1.0.0", version="1.0.1",
use_cache=False, use_cache=False,
) )
class SaveImageInvocation(BaseInvocation): class SaveImageInvocation(BaseInvocation):
"""Saves an image. Unlike an image primitive, this invocation stores a copy of the image.""" """Saves an image. Unlike an image primitive, this invocation stores a copy of the image."""
image: ImageField = InputField(description="The image to load") image: ImageField = InputField(description=FieldDescriptions.image)
board: Optional[BoardField] = InputField(default=None, description=FieldDescriptions.board, input=Input.Direct)
metadata: CoreMetadata = InputField( metadata: CoreMetadata = InputField(
default=None, default=None,
description=FieldDescriptions.core_metadata, description=FieldDescriptions.core_metadata,
@ -999,6 +1000,12 @@ class SaveImageInvocation(BaseInvocation):
workflow=self.workflow, workflow=self.workflow,
) )
if self.board:
context.services.board_images.add_image_to_board(
board_id=self.board.board_id,
image_name=image_dto.image_name,
)
return ImageOutput( return ImageOutput(
image=ImageField(image_name=image_dto.image_name), image=ImageField(image_name=image_dto.image_name),
width=image_dto.width, width=image_dto.width,

View File

@ -226,6 +226,12 @@ class ImageField(BaseModel):
image_name: str = Field(description="The name of the image") image_name: str = Field(description="The name of the image")
class BoardField(BaseModel):
"""A board primitive field"""
board_id: str = Field(description="The id of the board")
@invocation_output("image_output") @invocation_output("image_output")
class ImageOutput(BaseInvocationOutput): class ImageOutput(BaseInvocationOutput):
"""Base class for nodes that output a single image""" """Base class for nodes that output a single image"""

View File

@ -701,6 +701,8 @@
"addNodeToolTip": "Add Node (Shift+A, Space)", "addNodeToolTip": "Add Node (Shift+A, Space)",
"animatedEdges": "Animated Edges", "animatedEdges": "Animated Edges",
"animatedEdgesHelp": "Animate selected edges and edges connected to selected nodes", "animatedEdgesHelp": "Animate selected edges and edges connected to selected nodes",
"boardField": "Board",
"boardFieldDescription": "A gallery board",
"boolean": "Booleans", "boolean": "Booleans",
"booleanCollection": "Boolean Collection", "booleanCollection": "Boolean Collection",
"booleanCollectionDescription": "A collection of booleans.", "booleanCollectionDescription": "A collection of booleans.",

View File

@ -16,6 +16,7 @@ import SchedulerInputField from './inputs/SchedulerInputField';
import StringInputField from './inputs/StringInputField'; import StringInputField from './inputs/StringInputField';
import VaeModelInputField from './inputs/VaeModelInputField'; import VaeModelInputField from './inputs/VaeModelInputField';
import IPAdapterModelInputField from './inputs/IPAdapterModelInputField'; import IPAdapterModelInputField from './inputs/IPAdapterModelInputField';
import BoardInputField from './inputs/BoardInputField';
type InputFieldProps = { type InputFieldProps = {
nodeId: string; nodeId: string;
@ -99,6 +100,16 @@ const InputFieldRenderer = ({ nodeId, fieldName }: InputFieldProps) => {
); );
} }
if (field?.type === 'BoardField' && fieldTemplate?.type === 'BoardField') {
return (
<BoardInputField
nodeId={nodeId}
field={field}
fieldTemplate={fieldTemplate}
/>
);
}
if ( if (
field?.type === 'MainModelField' && field?.type === 'MainModelField' &&
fieldTemplate?.type === 'MainModelField' fieldTemplate?.type === 'MainModelField'

View File

@ -0,0 +1,64 @@
import { SelectItem } from '@mantine/core';
import { useAppDispatch } from 'app/store/storeHooks';
import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect';
import { fieldBoardValueChanged } from 'features/nodes/store/nodesSlice';
import {
BoardInputFieldTemplate,
BoardInputFieldValue,
FieldComponentProps,
} from 'features/nodes/types/types';
import { memo, useCallback } from 'react';
import { useListAllBoardsQuery } from 'services/api/endpoints/boards';
const BoardInputFieldComponent = (
props: FieldComponentProps<BoardInputFieldValue, BoardInputFieldTemplate>
) => {
const { nodeId, field } = props;
const dispatch = useAppDispatch();
const { data, hasBoards } = useListAllBoardsQuery(undefined, {
selectFromResult: ({ data }) => {
const boards: SelectItem[] = [
{
label: 'None',
value: 'none',
},
];
data?.forEach(({ board_id, board_name }) => {
boards.push({
label: board_name,
value: board_id,
});
});
return {
data: boards,
hasBoards: boards.length > 1,
};
},
});
const handleChange = useCallback(
(v: string | null) => {
dispatch(
fieldBoardValueChanged({
nodeId,
fieldName: field.name,
value: v && v !== 'none' ? { board_id: v } : undefined,
})
);
},
[dispatch, field.name, nodeId]
);
return (
<IAIMantineSearchableSelect
className="nowheel nodrag"
value={field.value?.board_id ?? 'none'}
data={data}
onChange={handleChange}
disabled={!hasBoards}
/>
);
};
export default memo(BoardInputFieldComponent);

View File

@ -65,11 +65,6 @@ const SchedulerInputField = (
return ( return (
<IAIMantineSearchableSelect <IAIMantineSearchableSelect
className="nowheel nodrag" className="nowheel nodrag"
sx={{
'.mantine-Select-dropdown': {
width: '14rem !important',
},
}}
value={field.value} value={field.value}
data={data} data={data}
onChange={handleChange} onChange={handleChange}

View File

@ -143,7 +143,7 @@ export const useBuildNodeData = () => {
notes: '', notes: '',
isOpen: true, isOpen: true,
embedWorkflow: false, embedWorkflow: false,
isIntermediate: true, isIntermediate: type === 'save_image' ? false : true,
inputs, inputs,
outputs, outputs,
useCache: template.useCache, useCache: template.useCache,

View File

@ -30,6 +30,7 @@ import {
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { DRAG_HANDLE_CLASSNAME } from '../types/constants'; import { DRAG_HANDLE_CLASSNAME } from '../types/constants';
import { import {
BoardInputFieldValue,
BooleanInputFieldValue, BooleanInputFieldValue,
ColorInputFieldValue, ColorInputFieldValue,
ControlNetModelInputFieldValue, ControlNetModelInputFieldValue,
@ -494,6 +495,12 @@ const nodesSlice = createSlice({
) => { ) => {
fieldValueReducer(state, action); fieldValueReducer(state, action);
}, },
fieldBoardValueChanged: (
state,
action: FieldValueAction<BoardInputFieldValue>
) => {
fieldValueReducer(state, action);
},
fieldImageValueChanged: ( fieldImageValueChanged: (
state, state,
action: FieldValueAction<ImageInputFieldValue> action: FieldValueAction<ImageInputFieldValue>
@ -897,6 +904,7 @@ export const {
imageCollectionFieldValueChanged, imageCollectionFieldValueChanged,
fieldStringValueChanged, fieldStringValueChanged,
fieldNumberValueChanged, fieldNumberValueChanged,
fieldBoardValueChanged,
fieldBooleanValueChanged, fieldBooleanValueChanged,
fieldImageValueChanged, fieldImageValueChanged,
fieldColorValueChanged, fieldColorValueChanged,

View File

@ -1,4 +1,9 @@
import { FieldType, FieldUIConfig } from './types'; import {
FieldType,
FieldTypeMap,
FieldTypeMapWithNumber,
FieldUIConfig,
} from './types';
import { t } from 'i18next'; import { t } from 'i18next';
export const HANDLE_TOOLTIP_OPEN_DELAY = 500; export const HANDLE_TOOLTIP_OPEN_DELAY = 500;
@ -28,7 +33,7 @@ export const COLLECTION_TYPES: FieldType[] = [
'ColorCollection', 'ColorCollection',
]; ];
export const POLYMORPHIC_TYPES = [ export const POLYMORPHIC_TYPES: FieldType[] = [
'IntegerPolymorphic', 'IntegerPolymorphic',
'BooleanPolymorphic', 'BooleanPolymorphic',
'FloatPolymorphic', 'FloatPolymorphic',
@ -40,7 +45,7 @@ export const POLYMORPHIC_TYPES = [
'ColorPolymorphic', 'ColorPolymorphic',
]; ];
export const MODEL_TYPES = [ export const MODEL_TYPES: FieldType[] = [
'IPAdapterModelField', 'IPAdapterModelField',
'ControlNetModelField', 'ControlNetModelField',
'LoRAModelField', 'LoRAModelField',
@ -54,7 +59,7 @@ export const MODEL_TYPES = [
'ClipField', 'ClipField',
]; ];
export const COLLECTION_MAP = { export const COLLECTION_MAP: FieldTypeMapWithNumber = {
integer: 'IntegerCollection', integer: 'IntegerCollection',
boolean: 'BooleanCollection', boolean: 'BooleanCollection',
number: 'FloatCollection', number: 'FloatCollection',
@ -71,7 +76,7 @@ export const isCollectionItemType = (
): itemType is keyof typeof COLLECTION_MAP => ): itemType is keyof typeof COLLECTION_MAP =>
Boolean(itemType && itemType in COLLECTION_MAP); Boolean(itemType && itemType in COLLECTION_MAP);
export const SINGLE_TO_POLYMORPHIC_MAP = { export const SINGLE_TO_POLYMORPHIC_MAP: FieldTypeMapWithNumber = {
integer: 'IntegerPolymorphic', integer: 'IntegerPolymorphic',
boolean: 'BooleanPolymorphic', boolean: 'BooleanPolymorphic',
number: 'FloatPolymorphic', number: 'FloatPolymorphic',
@ -84,7 +89,7 @@ export const SINGLE_TO_POLYMORPHIC_MAP = {
ColorField: 'ColorPolymorphic', ColorField: 'ColorPolymorphic',
}; };
export const POLYMORPHIC_TO_SINGLE_MAP = { export const POLYMORPHIC_TO_SINGLE_MAP: FieldTypeMap = {
IntegerPolymorphic: 'integer', IntegerPolymorphic: 'integer',
BooleanPolymorphic: 'boolean', BooleanPolymorphic: 'boolean',
FloatPolymorphic: 'float', FloatPolymorphic: 'float',
@ -96,7 +101,7 @@ export const POLYMORPHIC_TO_SINGLE_MAP = {
ColorPolymorphic: 'ColorField', ColorPolymorphic: 'ColorField',
}; };
export const TYPES_WITH_INPUT_COMPONENTS = [ export const TYPES_WITH_INPUT_COMPONENTS: FieldType[] = [
'string', 'string',
'StringPolymorphic', 'StringPolymorphic',
'boolean', 'boolean',
@ -117,6 +122,7 @@ export const TYPES_WITH_INPUT_COMPONENTS = [
'SDXLMainModelField', 'SDXLMainModelField',
'Scheduler', 'Scheduler',
'IPAdapterModelField', 'IPAdapterModelField',
'BoardField',
]; ];
export const isPolymorphicItemType = ( export const isPolymorphicItemType = (
@ -240,6 +246,11 @@ export const FIELDS: Record<FieldType, FieldUIConfig> = {
description: t('nodes.imageFieldDescription'), description: t('nodes.imageFieldDescription'),
title: t('nodes.imageField'), title: t('nodes.imageField'),
}, },
BoardField: {
color: 'purple.500',
description: t('nodes.imageFieldDescription'),
title: t('nodes.imageField'),
},
ImagePolymorphic: { ImagePolymorphic: {
color: 'purple.500', color: 'purple.500',
description: t('nodes.imagePolymorphicDescription'), description: t('nodes.imagePolymorphicDescription'),

View File

@ -72,6 +72,7 @@ export type FieldUIConfig = {
// TODO: Get this from the OpenAPI schema? may be tricky... // TODO: Get this from the OpenAPI schema? may be tricky...
export const zFieldType = z.enum([ export const zFieldType = z.enum([
'BoardField',
'boolean', 'boolean',
'BooleanCollection', 'BooleanCollection',
'BooleanPolymorphic', 'BooleanPolymorphic',
@ -119,6 +120,10 @@ export const zFieldType = z.enum([
]); ]);
export type FieldType = z.infer<typeof zFieldType>; export type FieldType = z.infer<typeof zFieldType>;
export type FieldTypeMap = { [key in FieldType]?: FieldType };
export type FieldTypeMapWithNumber = {
[key in FieldType | 'number']?: FieldType;
};
export const zReservedFieldType = z.enum([ export const zReservedFieldType = z.enum([
'WorkflowField', 'WorkflowField',
@ -187,6 +192,11 @@ export const zImageField = z.object({
}); });
export type ImageField = z.infer<typeof zImageField>; export type ImageField = z.infer<typeof zImageField>;
export const zBoardField = z.object({
board_id: z.string().trim().min(1),
});
export type BoardField = z.infer<typeof zBoardField>;
export const zLatentsField = z.object({ export const zLatentsField = z.object({
latents_name: z.string().trim().min(1), latents_name: z.string().trim().min(1),
seed: z.number().int().optional(), seed: z.number().int().optional(),
@ -494,6 +504,12 @@ export const zImageInputFieldValue = zInputFieldValueBase.extend({
}); });
export type ImageInputFieldValue = z.infer<typeof zImageInputFieldValue>; export type ImageInputFieldValue = z.infer<typeof zImageInputFieldValue>;
export const zBoardInputFieldValue = zInputFieldValueBase.extend({
type: z.literal('BoardField'),
value: zBoardField.optional(),
});
export type BoardInputFieldValue = z.infer<typeof zBoardInputFieldValue>;
export const zImagePolymorphicInputFieldValue = zInputFieldValueBase.extend({ export const zImagePolymorphicInputFieldValue = zInputFieldValueBase.extend({
type: z.literal('ImagePolymorphic'), type: z.literal('ImagePolymorphic'),
value: zImageField.optional(), value: zImageField.optional(),
@ -630,6 +646,7 @@ export type SchedulerInputFieldValue = z.infer<
>; >;
export const zInputFieldValue = z.discriminatedUnion('type', [ export const zInputFieldValue = z.discriminatedUnion('type', [
zBoardInputFieldValue,
zBooleanCollectionInputFieldValue, zBooleanCollectionInputFieldValue,
zBooleanInputFieldValue, zBooleanInputFieldValue,
zBooleanPolymorphicInputFieldValue, zBooleanPolymorphicInputFieldValue,
@ -770,6 +787,11 @@ export type BooleanPolymorphicInputFieldTemplate = Omit<
type: 'BooleanPolymorphic'; type: 'BooleanPolymorphic';
}; };
export type BoardInputFieldTemplate = InputFieldTemplateBase & {
default: BoardField;
type: 'BoardField';
};
export type ImageInputFieldTemplate = InputFieldTemplateBase & { export type ImageInputFieldTemplate = InputFieldTemplateBase & {
default: ImageField; default: ImageField;
type: 'ImageField'; type: 'ImageField';
@ -952,6 +974,7 @@ export type WorkflowInputFieldTemplate = InputFieldTemplateBase & {
* maximum length, pattern to match, etc). * maximum length, pattern to match, etc).
*/ */
export type InputFieldTemplate = export type InputFieldTemplate =
| BoardInputFieldTemplate
| BooleanCollectionInputFieldTemplate | BooleanCollectionInputFieldTemplate
| BooleanPolymorphicInputFieldTemplate | BooleanPolymorphicInputFieldTemplate
| BooleanInputFieldTemplate | BooleanInputFieldTemplate

View File

@ -62,6 +62,8 @@ import {
ConditioningField, ConditioningField,
IPAdapterInputFieldTemplate, IPAdapterInputFieldTemplate,
IPAdapterModelInputFieldTemplate, IPAdapterModelInputFieldTemplate,
BoardInputFieldTemplate,
InputFieldTemplate,
} from '../types/types'; } from '../types/types';
import { ControlField } from 'services/api/types'; import { ControlField } from 'services/api/types';
@ -450,6 +452,19 @@ const buildIPAdapterModelInputFieldTemplate = ({
return template; return template;
}; };
const buildBoardInputFieldTemplate = ({
schemaObject,
baseField,
}: BuildInputFieldArg): BoardInputFieldTemplate => {
const template: BoardInputFieldTemplate = {
...baseField,
type: 'BoardField',
default: schemaObject.default ?? undefined,
};
return template;
};
const buildImageInputFieldTemplate = ({ const buildImageInputFieldTemplate = ({
schemaObject, schemaObject,
baseField, baseField,
@ -851,7 +866,10 @@ export const getFieldType = (
return; return;
}; };
const TEMPLATE_BUILDER_MAP = { const TEMPLATE_BUILDER_MAP: {
[key in FieldType]?: (arg: BuildInputFieldArg) => InputFieldTemplate;
} = {
BoardField: buildBoardInputFieldTemplate,
boolean: buildBooleanInputFieldTemplate, boolean: buildBooleanInputFieldTemplate,
BooleanCollection: buildBooleanCollectionInputFieldTemplate, BooleanCollection: buildBooleanCollectionInputFieldTemplate,
BooleanPolymorphic: buildBooleanPolymorphicInputFieldTemplate, BooleanPolymorphic: buildBooleanPolymorphicInputFieldTemplate,
@ -937,7 +955,13 @@ export const buildInputFieldTemplate = (
return; return;
} }
return TEMPLATE_BUILDER_MAP[fieldType]({ const builder = TEMPLATE_BUILDER_MAP[fieldType];
if (!builder) {
return;
}
return builder({
schemaObject: fieldSchema, schemaObject: fieldSchema,
baseField, baseField,
}); });

View File

@ -1,7 +1,10 @@
import { InputFieldTemplate, InputFieldValue } from '../types/types'; import { FieldType, InputFieldTemplate, InputFieldValue } from '../types/types';
const FIELD_VALUE_FALLBACK_MAP = { const FIELD_VALUE_FALLBACK_MAP: {
[key in FieldType]: InputFieldValue['value'];
} = {
enum: '', enum: '',
BoardField: undefined,
boolean: false, boolean: false,
BooleanCollection: [], BooleanCollection: [],
BooleanPolymorphic: false, BooleanPolymorphic: false,

View File

@ -804,6 +804,17 @@ export type components = {
*/ */
image_count: number; image_count: number;
}; };
/**
* BoardField
* @description A board primitive field
*/
BoardField: {
/**
* Board Id
* @description The id of the board
*/
board_id: string;
};
/** Body_add_image_to_board */ /** Body_add_image_to_board */
Body_add_image_to_board: { Body_add_image_to_board: {
/** /**
@ -1287,6 +1298,11 @@ export type components = {
* @default true * @default true
*/ */
use_cache?: boolean; use_cache?: boolean;
/**
* CLIP
* @description CLIP (tokenizer, text encoder, LoRAs) and skipped layer count
*/
clip?: components["schemas"]["ClipField"];
/** /**
* Skipped Layers * Skipped Layers
* @description Number of layers to skip in text encoder * @description Number of layers to skip in text encoder
@ -1299,11 +1315,6 @@ export type components = {
* @enum {string} * @enum {string}
*/ */
type: "clip_skip"; type: "clip_skip";
/**
* CLIP
* @description CLIP (tokenizer, text encoder, LoRAs) and skipped layer count
*/
clip?: components["schemas"]["ClipField"];
}; };
/** /**
* ClipSkipInvocationOutput * ClipSkipInvocationOutput
@ -7550,6 +7561,16 @@ export type components = {
* @default false * @default false
*/ */
use_cache?: boolean; use_cache?: boolean;
/**
* Image
* @description The image to process
*/
image?: components["schemas"]["ImageField"];
/**
* Board
* @description The board to save the image to
*/
board?: components["schemas"]["BoardField"];
/** /**
* Metadata * Metadata
* @description Optional core metadata to be written to image * @description Optional core metadata to be written to image
@ -7561,11 +7582,6 @@ export type components = {
* @enum {string} * @enum {string}
*/ */
type: "save_image"; type: "save_image";
/**
* Image
* @description The image to load
*/
image?: components["schemas"]["ImageField"];
}; };
/** /**
* Scale Latents * Scale Latents
@ -7862,16 +7878,6 @@ export type components = {
* @description The ID of the session associated with this queue item. The session doesn't exist in graph_executions until the queue item is executed. * @description The ID of the session associated with this queue item. The session doesn't exist in graph_executions until the queue item is executed.
*/ */
session_id: string; session_id: string;
/**
* Field Values
* @description The field values that were used for this queue item
*/
field_values?: components["schemas"]["NodeFieldValue"][];
/**
* Queue Id
* @description The id of the queue with which this item is associated
*/
queue_id: string;
/** /**
* Error * Error
* @description The error message if this queue item errored * @description The error message if this queue item errored
@ -7897,6 +7903,16 @@ export type components = {
* @description When this queue item was completed * @description When this queue item was completed
*/ */
completed_at?: string; completed_at?: string;
/**
* Queue Id
* @description The id of the queue with which this item is associated
*/
queue_id: string;
/**
* Field Values
* @description The field values that were used for this queue item
*/
field_values?: components["schemas"]["NodeFieldValue"][];
/** /**
* Session * Session
* @description The fully-populated session to be executed * @description The fully-populated session to be executed
@ -7936,16 +7952,6 @@ export type components = {
* @description The ID of the session associated with this queue item. The session doesn't exist in graph_executions until the queue item is executed. * @description The ID of the session associated with this queue item. The session doesn't exist in graph_executions until the queue item is executed.
*/ */
session_id: string; session_id: string;
/**
* Field Values
* @description The field values that were used for this queue item
*/
field_values?: components["schemas"]["NodeFieldValue"][];
/**
* Queue Id
* @description The id of the queue with which this item is associated
*/
queue_id: string;
/** /**
* Error * Error
* @description The error message if this queue item errored * @description The error message if this queue item errored
@ -7971,6 +7977,16 @@ export type components = {
* @description When this queue item was completed * @description When this queue item was completed
*/ */
completed_at?: string; completed_at?: string;
/**
* Queue Id
* @description The id of the queue with which this item is associated
*/
queue_id: string;
/**
* Field Values
* @description The field values that were used for this queue item
*/
field_values?: components["schemas"]["NodeFieldValue"][];
}; };
/** SessionQueueStatus */ /** SessionQueueStatus */
SessionQueueStatus: { SessionQueueStatus: {
@ -9052,7 +9068,7 @@ export type components = {
* If a field should be provided a data type that does not exactly match the python type of the field, use this to provide the type that should be used instead. See the node development docs for detail on adding a new field type, which involves client-side changes. * If a field should be provided a data type that does not exactly match the python type of the field, use this to provide the type that should be used instead. See the node development docs for detail on adding a new field type, which involves client-side changes.
* @enum {string} * @enum {string}
*/ */
UIType: "boolean" | "ColorField" | "ConditioningField" | "ControlField" | "float" | "ImageField" | "integer" | "LatentsField" | "string" | "BooleanCollection" | "ColorCollection" | "ConditioningCollection" | "ControlCollection" | "FloatCollection" | "ImageCollection" | "IntegerCollection" | "LatentsCollection" | "StringCollection" | "BooleanPolymorphic" | "ColorPolymorphic" | "ConditioningPolymorphic" | "ControlPolymorphic" | "FloatPolymorphic" | "ImagePolymorphic" | "IntegerPolymorphic" | "LatentsPolymorphic" | "StringPolymorphic" | "MainModelField" | "SDXLMainModelField" | "SDXLRefinerModelField" | "ONNXModelField" | "VaeModelField" | "LoRAModelField" | "ControlNetModelField" | "IPAdapterModelField" | "UNetField" | "VaeField" | "ClipField" | "Collection" | "CollectionItem" | "enum" | "Scheduler" | "WorkflowField" | "IsIntermediate" | "MetadataField"; UIType: "boolean" | "ColorField" | "ConditioningField" | "ControlField" | "float" | "ImageField" | "integer" | "LatentsField" | "string" | "BooleanCollection" | "ColorCollection" | "ConditioningCollection" | "ControlCollection" | "FloatCollection" | "ImageCollection" | "IntegerCollection" | "LatentsCollection" | "StringCollection" | "BooleanPolymorphic" | "ColorPolymorphic" | "ConditioningPolymorphic" | "ControlPolymorphic" | "FloatPolymorphic" | "ImagePolymorphic" | "IntegerPolymorphic" | "LatentsPolymorphic" | "StringPolymorphic" | "MainModelField" | "SDXLMainModelField" | "SDXLRefinerModelField" | "ONNXModelField" | "VaeModelField" | "LoRAModelField" | "ControlNetModelField" | "IPAdapterModelField" | "UNetField" | "VaeField" | "ClipField" | "Collection" | "CollectionItem" | "enum" | "Scheduler" | "WorkflowField" | "IsIntermediate" | "MetadataField" | "BoardField";
/** /**
* UIComponent * UIComponent
* @description The type of UI component to use for a field, used to override the default components, which are inferred from the field type. * @description The type of UI component to use for a field, used to override the default components, which are inferred from the field type.
@ -9095,30 +9111,12 @@ export type components = {
/** Ui Order */ /** Ui Order */
ui_order?: number; ui_order?: number;
}; };
/**
* StableDiffusionOnnxModelFormat
* @description An enumeration.
* @enum {string}
*/
StableDiffusionOnnxModelFormat: "olive" | "onnx";
/**
* StableDiffusion2ModelFormat
* @description An enumeration.
* @enum {string}
*/
StableDiffusion2ModelFormat: "checkpoint" | "diffusers";
/** /**
* CLIPVisionModelFormat * CLIPVisionModelFormat
* @description An enumeration. * @description An enumeration.
* @enum {string} * @enum {string}
*/ */
CLIPVisionModelFormat: "diffusers"; CLIPVisionModelFormat: "diffusers";
/**
* StableDiffusion1ModelFormat
* @description An enumeration.
* @enum {string}
*/
StableDiffusion1ModelFormat: "checkpoint" | "diffusers";
/** /**
* StableDiffusionXLModelFormat * StableDiffusionXLModelFormat
* @description An enumeration. * @description An enumeration.
@ -9131,6 +9129,24 @@ export type components = {
* @enum {string} * @enum {string}
*/ */
IPAdapterModelFormat: "invokeai"; IPAdapterModelFormat: "invokeai";
/**
* StableDiffusion1ModelFormat
* @description An enumeration.
* @enum {string}
*/
StableDiffusion1ModelFormat: "checkpoint" | "diffusers";
/**
* StableDiffusionOnnxModelFormat
* @description An enumeration.
* @enum {string}
*/
StableDiffusionOnnxModelFormat: "olive" | "onnx";
/**
* StableDiffusion2ModelFormat
* @description An enumeration.
* @enum {string}
*/
StableDiffusion2ModelFormat: "checkpoint" | "diffusers";
/** /**
* ControlNetModelFormat * ControlNetModelFormat
* @description An enumeration. * @description An enumeration.