From 944af4d4a91fcbaadea30d826164d5b24de20e4d Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 1 May 2025 19:07:15 +1000 Subject: [PATCH] feat(ui): show unsupported gen mode toasts as warnings intead of errors --- invokeai/frontend/web/public/locales/en.json | 4 ++-- .../listeners/enqueueRequestedLinear.ts | 12 ++++++++++-- .../util/graph/generation/buildChatGPT4oGraph.ts | 6 ++++-- .../nodes/util/graph/generation/buildFLUXGraph.ts | 10 ++++++++-- .../nodes/util/graph/generation/buildImagen3Graph.ts | 6 ++++-- .../web/src/features/nodes/util/graph/types.ts | 7 +++++++ 6 files changed, 35 insertions(+), 10 deletions(-) diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index 611775f593..6c52f2c005 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -1328,8 +1328,8 @@ "unableToCopyDesc": "Your browser does not support clipboard access. Firefox users may be able to fix this by following ", "unableToCopyDesc_theseSteps": "these steps", "fluxFillIncompatibleWithT2IAndI2I": "FLUX Fill is not compatible with Text to Image or Image to Image. Use other FLUX models for these tasks.", - "imagen3IncompatibleGenerationMode": "Google Imagen3 supports Text to Image only. Ensure the bounding box is empty, or use other models for Image to Image, Inpainting and Outpainting tasks.", - "chatGPT4oIncompatibleGenerationMode": "ChatGPT 4o supports Text to Image and Image to Image. Use other models Inpainting and Outpainting tasks.", + "imagen3IncompatibleGenerationMode": "Google Imagen3 supports Text to Image only. Use other models for Image to Image, Inpainting and Outpainting tasks.", + "chatGPT4oIncompatibleGenerationMode": "ChatGPT 4o supports Text to Image and Image to Image only. Use other models Inpainting and Outpainting tasks.", "problemUnpublishingWorkflow": "Problem Unpublishing Workflow", "problemUnpublishingWorkflowDescription": "There was a problem unpublishing the workflow. Please try again.", "workflowUnpublished": "Workflow Unpublished" diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/enqueueRequestedLinear.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/enqueueRequestedLinear.ts index bb36ea507f..f3d04533ba 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/enqueueRequestedLinear.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/enqueueRequestedLinear.ts @@ -1,3 +1,4 @@ +import type { AlertStatus } from '@invoke-ai/ui-library'; import { createAction } from '@reduxjs/toolkit'; import { logger } from 'app/logging/logger'; import type { AppStartListening } from 'app/store/middleware/listenerMiddleware'; @@ -13,6 +14,7 @@ import { buildImagen3Graph } from 'features/nodes/util/graph/generation/buildIma import { buildSD1Graph } from 'features/nodes/util/graph/generation/buildSD1Graph'; import { buildSD3Graph } from 'features/nodes/util/graph/generation/buildSD3Graph'; import { buildSDXLGraph } from 'features/nodes/util/graph/generation/buildSDXLGraph'; +import { UnsupportedGenerationModeError } from 'features/nodes/util/graph/types'; import { toast } from 'features/toast/toast'; import { serializeError } from 'serialize-error'; import { enqueueMutationFixedCacheKeyOptions, queueApi } from 'services/api/endpoints/queue'; @@ -60,15 +62,21 @@ export const addEnqueueRequestedLinear = (startAppListening: AppStartListening) }); if (buildGraphResult.isErr()) { + let title = 'Failed to build graph'; + let status: AlertStatus = 'error'; let description: string | null = null; if (buildGraphResult.error instanceof AssertionError) { description = extractMessageFromAssertionError(buildGraphResult.error); + } else if (buildGraphResult.error instanceof UnsupportedGenerationModeError) { + title = 'Unsupported generation mode'; + description = buildGraphResult.error.message; + status = 'warning'; } const error = serializeError(buildGraphResult.error); log.error({ error }, 'Failed to build graph'); toast({ - status: 'error', - title: 'Failed to build graph', + status, + title, description, }); return; diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildChatGPT4oGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildChatGPT4oGraph.ts index b50a8c642e..8aaec983af 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildChatGPT4oGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildChatGPT4oGraph.ts @@ -13,7 +13,7 @@ import { getBoardField, selectPresetModifiedPrompts, } from 'features/nodes/util/graph/graphBuilderUtils'; -import type { GraphBuilderReturn } from 'features/nodes/util/graph/types'; +import { type GraphBuilderReturn, UnsupportedGenerationModeError } from 'features/nodes/util/graph/types'; import { t } from 'i18next'; import { selectMainModelConfig } from 'services/api/endpoints/models'; import type { Equals } from 'tsafe'; @@ -24,7 +24,9 @@ const log = logger('system'); export const buildChatGPT4oGraph = async (state: RootState, manager: CanvasManager): Promise => { const generationMode = await manager.compositor.getGenerationMode(); - assert(generationMode === 'txt2img' || generationMode === 'img2img', t('toast.chatGPT4oIncompatibleGenerationMode')); + if (generationMode !== 'txt2img' && generationMode !== 'img2img') { + throw new UnsupportedGenerationModeError(t('toast.chatGPT4oIncompatibleGenerationMode')); + } log.debug({ generationMode }, 'Building GPT Image graph'); diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildFLUXGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildFLUXGraph.ts index c5b5a5ee30..5a88ca5aaa 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildFLUXGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildFLUXGraph.ts @@ -22,7 +22,11 @@ import { getSizes, selectPresetModifiedPrompts, } from 'features/nodes/util/graph/graphBuilderUtils'; -import type { GraphBuilderReturn, ImageOutputNodes } from 'features/nodes/util/graph/types'; +import { + type GraphBuilderReturn, + type ImageOutputNodes, + UnsupportedGenerationModeError, +} from 'features/nodes/util/graph/types'; import { t } from 'i18next'; import { selectMainModelConfig } from 'services/api/endpoints/models'; import type { Invocation } from 'services/api/types'; @@ -80,7 +84,9 @@ export const buildFLUXGraph = async (state: RootState, manager: CanvasManager): // // The other asserts above are just for sanity & type check and should never be hit, so they do not have // translations. - assert(generationMode === 'inpaint' || generationMode === 'outpaint', t('toast.fluxFillIncompatibleWithT2IAndI2I')); + if (generationMode === 'txt2img' || generationMode === 'img2img') { + throw new UnsupportedGenerationModeError(t('toast.fluxFillIncompatibleWithT2IAndI2I')); + } // FLUX Fill wants much higher guidance values than normal FLUX - silently "fix" the value for the user. // TODO(psyche): Figure out a way to alert the user that this is happening - maybe return warnings from the graph diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildImagen3Graph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildImagen3Graph.ts index cbd0d004f9..40903bfc98 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildImagen3Graph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/generation/buildImagen3Graph.ts @@ -11,7 +11,7 @@ import { getBoardField, selectPresetModifiedPrompts, } from 'features/nodes/util/graph/graphBuilderUtils'; -import type { GraphBuilderReturn } from 'features/nodes/util/graph/types'; +import { type GraphBuilderReturn, UnsupportedGenerationModeError } from 'features/nodes/util/graph/types'; import { t } from 'i18next'; import type { Equals } from 'tsafe'; import { assert } from 'tsafe'; @@ -21,7 +21,9 @@ const log = logger('system'); export const buildImagen3Graph = async (state: RootState, manager: CanvasManager): Promise => { const generationMode = await manager.compositor.getGenerationMode(); - assert(generationMode === 'txt2img', t('toast.imagen3IncompatibleGenerationMode')); + if (generationMode !== 'txt2img') { + throw new UnsupportedGenerationModeError(t('toast.imagen3IncompatibleGenerationMode')); + } log.debug({ generationMode }, 'Building Imagen3 graph'); diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/types.ts b/invokeai/frontend/web/src/features/nodes/util/graph/types.ts index 4fc22f8c5a..16c0c0341c 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/types.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/types.ts @@ -32,3 +32,10 @@ export type GraphBuilderReturn = { seedFieldIdentifier?: FieldIdentifier; positivePromptFieldIdentifier: FieldIdentifier; }; + +export class UnsupportedGenerationModeError extends Error { + constructor(message: string) { + super(message); + this.name = this.constructor.name; + } +}