From ca3ccf92bc5cc5aad2dcecbc5477f442fc567225 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 18 Sep 2025 22:04:56 +1000 Subject: [PATCH] tidy(ui): prefer types from zod schemas for model attrs --- .../frontend/web/src/features/metadata/parsing.tsx | 4 ++-- .../subpanels/ModelManagerPanel/ModelBaseBadge.tsx | 2 +- .../web/src/features/nodes/types/common.test-d.ts | 11 ++++++----- .../frontend/web/src/features/nodes/types/common.ts | 2 +- .../nodes/util/graph/buildLinearBatchConfig.ts | 3 ++- .../features/parameters/components/ModelPicker.tsx | 3 ++- .../web/src/features/parameters/types/constants.ts | 2 +- .../src/features/parameters/util/optimalDimension.ts | 2 +- invokeai/frontend/web/src/services/api/types.ts | 7 ------- 9 files changed, 16 insertions(+), 20 deletions(-) diff --git a/invokeai/frontend/web/src/features/metadata/parsing.tsx b/invokeai/frontend/web/src/features/metadata/parsing.tsx index 10cd0e32f7..a2363004ef 100644 --- a/invokeai/frontend/web/src/features/metadata/parsing.tsx +++ b/invokeai/frontend/web/src/features/metadata/parsing.tsx @@ -49,7 +49,7 @@ import { zVideoDuration, zVideoResolution, } from 'features/controlLayers/store/types'; -import type { ModelIdentifierField } from 'features/nodes/types/common'; +import type { ModelIdentifierField, ModelType } from 'features/nodes/types/common'; import { zModelIdentifierField } from 'features/nodes/types/common'; import { zModelIdentifier } from 'features/nodes/types/v2/common'; import { modelSelected } from 'features/parameters/store/actions'; @@ -108,7 +108,7 @@ import { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { imagesApi } from 'services/api/endpoints/images'; import { modelsApi } from 'services/api/endpoints/models'; -import type { AnyModelConfig, ModelType } from 'services/api/types'; +import type { AnyModelConfig } from 'services/api/types'; import { assert } from 'tsafe'; import z from 'zod'; diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelManagerPanel/ModelBaseBadge.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelManagerPanel/ModelBaseBadge.tsx index c5ace46ac5..a1be6b208e 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelManagerPanel/ModelBaseBadge.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelManagerPanel/ModelBaseBadge.tsx @@ -1,7 +1,7 @@ import { Badge } from '@invoke-ai/ui-library'; import { MODEL_BASE_TO_COLOR, MODEL_BASE_TO_SHORT_NAME } from 'features/modelManagerV2/models'; +import type { BaseModelType } from 'features/nodes/types/common'; import { memo } from 'react'; -import type { BaseModelType } from 'services/api/types'; type Props = { base: BaseModelType; diff --git a/invokeai/frontend/web/src/features/nodes/types/common.test-d.ts b/invokeai/frontend/web/src/features/nodes/types/common.test-d.ts index ff137c6281..e3fa3772bb 100644 --- a/invokeai/frontend/web/src/features/nodes/types/common.test-d.ts +++ b/invokeai/frontend/web/src/features/nodes/types/common.test-d.ts @@ -1,5 +1,4 @@ import type { - BaseModelType, BoardField, Classification, ColorField, @@ -10,11 +9,12 @@ import type { ModelIdentifierField, ProgressImage, SchedulerField, - SubModelType, T2IAdapterField, + zBaseModelType, zClipVariantType, zModelFormat, zModelVariantType, + zSubModelType, } from 'features/nodes/types/common'; import type { Invocation, S } from 'services/api/types'; import type { Equals, Extends } from 'tsafe'; @@ -24,7 +24,8 @@ import type z from 'zod'; /** * These types originate from the server and are recreated as zod schemas manually, for use at runtime. - * The tests ensure that the types are correctly recreated. + * The tests ensure that the types are correctly recreated. If one of these tests fails, it means the zod + * schema and the type have diverged and need to be reconciled - update the zod schema. */ describe('Common types', () => { @@ -40,8 +41,8 @@ describe('Common types', () => { // Model component types test('ModelIdentifier', () => assert>()); - test('ModelIdentifier', () => assert>()); - test('ModelIdentifier', () => assert>()); + test('ModelIdentifier', () => assert, S['BaseModelType']>>()); + test('ModelIdentifier', () => assert, S['SubModelType']>>()); test('ClipVariantType', () => assert, S['ClipVariantType']>>()); test('ModelVariantType', () => assert, S['ModelVariantType']>>()); test('ModelFormat', () => assert, S['ModelFormat']>>()); diff --git a/invokeai/frontend/web/src/features/nodes/types/common.ts b/invokeai/frontend/web/src/features/nodes/types/common.ts index 2be17026d0..f7c706687e 100644 --- a/invokeai/frontend/web/src/features/nodes/types/common.ts +++ b/invokeai/frontend/web/src/features/nodes/types/common.ts @@ -130,7 +130,7 @@ export const zModelType = z.enum([ 'unknown', ]); export type ModelType = z.infer; -const zSubModelType = z.enum([ +export const zSubModelType = z.enum([ 'unet', 'transformer', 'text_encoder', diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearBatchConfig.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearBatchConfig.ts index 5e89cd1242..3792b22206 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearBatchConfig.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearBatchConfig.ts @@ -3,9 +3,10 @@ import { generateSeeds } from 'common/util/generateSeeds'; import { range } from 'es-toolkit/compat'; import type { SeedBehaviour } from 'features/dynamicPrompts/store/dynamicPromptsSlice'; import { API_BASE_MODELS, VIDEO_BASE_MODELS } from 'features/modelManagerV2/models'; +import type { BaseModelType } from 'features/nodes/types/common'; import type { Graph } from 'features/nodes/util/graph/generation/Graph'; import type { components } from 'services/api/schema'; -import type { BaseModelType, Batch, EnqueueBatchArg, Invocation } from 'services/api/types'; +import type { Batch, EnqueueBatchArg, Invocation } from 'services/api/types'; const getExtendedPrompts = (arg: { seedBehaviour: SeedBehaviour; diff --git a/invokeai/frontend/web/src/features/parameters/components/ModelPicker.tsx b/invokeai/frontend/web/src/features/parameters/components/ModelPicker.tsx index 871c00182e..14d1993451 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ModelPicker.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ModelPicker.tsx @@ -32,6 +32,7 @@ import { } from 'features/modelManagerV2/models'; import { setInstallModelsTabByName } from 'features/modelManagerV2/store/installModelsStore'; import ModelImage from 'features/modelManagerV2/subpanels/ModelManagerPanel/ModelImage'; +import type { BaseModelType } from 'features/nodes/types/common'; import { NavigateToModelManagerButton } from 'features/parameters/components/MainModel/NavigateToModelManagerButton'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { selectIsModelsTabDisabled } from 'features/system/store/configSlice'; @@ -41,7 +42,7 @@ import { memo, useCallback, useMemo, useRef } from 'react'; import { Trans, useTranslation } from 'react-i18next'; import { PiCaretDownBold, PiLinkSimple } from 'react-icons/pi'; import { useGetRelatedModelIdsBatchQuery } from 'services/api/endpoints/modelRelationships'; -import type { AnyModelConfig, BaseModelType } from 'services/api/types'; +import type { AnyModelConfig } from 'services/api/types'; const selectSelectedModelKeys = createMemoizedSelector(selectParamsSlice, selectLoRAsSlice, (params, loras) => { const keys: string[] = []; diff --git a/invokeai/frontend/web/src/features/parameters/types/constants.ts b/invokeai/frontend/web/src/features/parameters/types/constants.ts index 0b3b81cf27..3f879db257 100644 --- a/invokeai/frontend/web/src/features/parameters/types/constants.ts +++ b/invokeai/frontend/web/src/features/parameters/types/constants.ts @@ -1,5 +1,5 @@ import type { ComboboxOption } from '@invoke-ai/ui-library'; -import type { BaseModelType } from 'services/api/types'; +import type { BaseModelType } from 'features/nodes/types/common'; /** * Mapping of base model to CLIP skip parameter constraints diff --git a/invokeai/frontend/web/src/features/parameters/util/optimalDimension.ts b/invokeai/frontend/web/src/features/parameters/util/optimalDimension.ts index 0ff43f72c8..4318c65144 100644 --- a/invokeai/frontend/web/src/features/parameters/util/optimalDimension.ts +++ b/invokeai/frontend/web/src/features/parameters/util/optimalDimension.ts @@ -1,4 +1,4 @@ -import type { BaseModelType } from 'services/api/types'; +import type { BaseModelType } from 'features/nodes/types/common'; /** * Gets the optimal dimension for a given base model: diff --git a/invokeai/frontend/web/src/services/api/types.ts b/invokeai/frontend/web/src/services/api/types.ts index 1b91fcf6a5..b9798c04d9 100644 --- a/invokeai/frontend/web/src/services/api/types.ts +++ b/invokeai/frontend/web/src/services/api/types.ts @@ -105,16 +105,9 @@ export const isVideoDTO = (dto: ImageDTO | VideoDTO): dto is VideoDTO => { return 'video_id' in dto; }; -// Models -export type ModelType = S['ModelType']; -export type BaseModelType = S['BaseModelType']; - // Model Configs - export type ControlLoRAModelConfig = S['ControlLoRALyCORISConfig'] | S['ControlLoRADiffusersConfig']; -// TODO(MM2): Can we make key required in the pydantic model? export type LoRAModelConfig = S['LoRADiffusersConfig'] | S['LoRALyCORISConfig'] | S['LoRAOmiConfig']; -// TODO(MM2): Can we rename this from Vae -> VAE export type VAEModelConfig = S['VAECheckpointConfig'] | S['VAEDiffusersConfig']; export type ControlNetModelConfig = S['ControlNetDiffusersConfig'] | S['ControlNetCheckpointConfig']; export type IPAdapterModelConfig = S['IPAdapterInvokeAIConfig'] | S['IPAdapterCheckpointConfig'];