From 33d4e057ef93038fd0e04bf879279e30f4e823ef Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza Date: Tue, 14 Jul 2026 21:54:43 -0300 Subject: [PATCH] refactor(providers): split KIE image catalog out of imageRegistry to respect file-size cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit imageRegistry.ts hit 805 lines after adding the MiniMax image provider (cap is 800). Extract the KIE image-model catalog (largest single provider entry, ~35 models) into its own semantic-family module, providers/registry/kie/imageModels.ts, following the same pattern already used for LMARENA_DIRECT_IMAGE_MODELS. imageRegistry.ts now imports KIE_IMAGE_MODELS instead of inlining the list. Also update minimax-media-servicekinds.test.ts: getRegistryMediaKinds derives membership by design from every registry in MEDIA_KIND_REGISTRIES, including IMAGE_PROVIDERS. Now that minimax is a key in IMAGE_PROVIDERS, it correctly gains the "image" kind alongside tts/video/music — the same behavior already asserted for openai in this file. The exact-match assertion is updated to ["image","music","tts","video"]; the other assertions (which only check .includes for tts/video/music/llm) were already correct and untouched. --- open-sse/config/imageRegistry.ts | 40 +------------- .../providers/registry/kie/imageModels.ts | 55 +++++++++++++++++++ tests/unit/minimax-media-servicekinds.test.ts | 8 +-- 3 files changed, 61 insertions(+), 42 deletions(-) create mode 100644 open-sse/config/providers/registry/kie/imageModels.ts diff --git a/open-sse/config/imageRegistry.ts b/open-sse/config/imageRegistry.ts index cb28c09c34..8c61ef02c1 100644 --- a/open-sse/config/imageRegistry.ts +++ b/open-sse/config/imageRegistry.ts @@ -6,6 +6,7 @@ */ import { LMARENA_DIRECT_IMAGE_MODELS } from "./providers/registry/lmarena/directModels.ts"; +import { KIE_IMAGE_MODELS } from "./providers/registry/kie/imageModels.ts"; interface ImageModelEntry { id: string; @@ -311,44 +312,7 @@ export const IMAGE_PROVIDERS: Record = { authType: "apikey", authHeader: "bearer", format: "kie-image", - models: [ - { id: "gpt4o-image", name: "KIE 4o Image" }, - { id: "seedream/4.5-text-to-image", name: "Seedream 4.5", isMarket: true }, - { id: "seedream/4.5-edit", name: "Seedream 4.5 Edit", isMarket: true }, - { id: "seedream/5.0-lite-text-to-image", name: "Seedream 5.0 Lite", isMarket: true }, - { id: "seedream/5.0-lite-image-to-image", name: "Seedream 5.0 Lite I2I", isMarket: true }, - { id: "z-image/4.0-text-to-image", name: "Z-Image v4.0", isMarket: true }, - { id: "z-image/4.5-text-to-image", name: "Z-Image v4.5", isMarket: true }, - { id: "google-imagen/imagen4-fast", name: "Imagen 4 Fast", isMarket: true }, - { id: "google-imagen/imagen4-ultra", name: "Imagen 4 Ultra", isMarket: true }, - { id: "google-imagen/imagen4", name: "Imagen 4", isMarket: true }, - { id: "google-imagen/nano-banana-2", name: "Nano Banana 2", isMarket: true }, - { id: "google-imagen/nano-banana", name: "Nano Banana", isMarket: true }, - { id: "google-imagen/nano-banana-pro", name: "Nano Banana Pro", isMarket: true }, - { id: "google-imagen/nano-banana-edit", name: "Nano Banana Edit", isMarket: true }, - { id: "flux/2-pro-image-to-image", name: "Flux 2 Pro I2I", isMarket: true }, - { id: "flux/2-pro-text-to-image", name: "Flux 2 Pro T2I", isMarket: true }, - { id: "flux/2-image-to-image", name: "Flux 2 I2I", isMarket: true }, - { id: "flux/2-text-to-image", name: "Flux 2 T2I", isMarket: true }, - { id: "flux/kontext", name: "Flux Kontext", isMarket: true }, - { id: "grok-imagine/text-to-image", name: "Grok Imagine T2I", isMarket: true }, - { id: "grok-imagine/image-to-image", name: "Grok Imagine I2I", isMarket: true }, - { id: "gpt/gpt-image-1.5-text-to-image", name: "GPT Image 1.5 T2I", isMarket: true }, - { id: "gpt/gpt-image-1.5-image-to-image", name: "GPT Image 1.5 I2I", isMarket: true }, - { id: "gpt/gpt-image-2-text-to-image", name: "GPT Image 2 T2I", isMarket: true }, - { id: "gpt/gpt-image-2-image-to-image", name: "GPT Image 2 I2I", isMarket: true }, - { id: "ideogram/v3-text-to-image", name: "Ideogram v3", isMarket: true }, - { id: "ideogram/v3-edit", name: "Ideogram v3 Edit", isMarket: true }, - { id: "ideogram/v3-remix", name: "Ideogram v3 Remix", isMarket: true }, - { id: "ideogram/v3-reframe", name: "Ideogram v3 Reframe", isMarket: true }, - { id: "qwen/text-to-image", name: "Qwen T2I", isMarket: true }, - { id: "qwen/image-to-image", name: "Qwen I2I", isMarket: true }, - { id: "qwen/image-edit", name: "Qwen Edit", isMarket: true }, - { id: "qwen2/image-edit", name: "Qwen2 Edit", isMarket: true }, - { id: "qwen2/text-to-image", name: "Qwen2 T2I", isMarket: true }, - { id: "wan/2.7-image", name: "Wan 2.7 Image", isMarket: true }, - { id: "wan/2.7-image-pro", name: "Wan 2.7 Image Pro", isMarket: true }, - ], + models: KIE_IMAGE_MODELS, supportedSizes: ["1:1", "16:9", "9:16", "4:3", "3:4"], }, diff --git a/open-sse/config/providers/registry/kie/imageModels.ts b/open-sse/config/providers/registry/kie/imageModels.ts new file mode 100644 index 0000000000..5fbcd7b18d --- /dev/null +++ b/open-sse/config/providers/registry/kie/imageModels.ts @@ -0,0 +1,55 @@ +/** + * KIE image-generation model catalog. + * + * Extracted out of imageRegistry.ts (which hit the 800-line file-size cap) so the + * catalog lives in its own semantic family module, following the same pattern as + * `providers/registry/lmarena/directModels.ts`. KIE aggregates many third-party + * image models (Seedream, Z-Image, Imagen, Flux, Grok Imagine, GPT Image, Ideogram, + * Qwen, Wan) behind a single `kie-image` format/handler — see `imageRegistry.ts`'s + * `kie` entry for baseUrl/auth/format wiring. + */ + +export interface KieImageModelEntry { + id: string; + name: string; + isMarket?: boolean; +} + +export const KIE_IMAGE_MODELS: KieImageModelEntry[] = [ + { id: "gpt4o-image", name: "KIE 4o Image" }, + { id: "seedream/4.5-text-to-image", name: "Seedream 4.5", isMarket: true }, + { id: "seedream/4.5-edit", name: "Seedream 4.5 Edit", isMarket: true }, + { id: "seedream/5.0-lite-text-to-image", name: "Seedream 5.0 Lite", isMarket: true }, + { id: "seedream/5.0-lite-image-to-image", name: "Seedream 5.0 Lite I2I", isMarket: true }, + { id: "z-image/4.0-text-to-image", name: "Z-Image v4.0", isMarket: true }, + { id: "z-image/4.5-text-to-image", name: "Z-Image v4.5", isMarket: true }, + { id: "google-imagen/imagen4-fast", name: "Imagen 4 Fast", isMarket: true }, + { id: "google-imagen/imagen4-ultra", name: "Imagen 4 Ultra", isMarket: true }, + { id: "google-imagen/imagen4", name: "Imagen 4", isMarket: true }, + { id: "google-imagen/nano-banana-2", name: "Nano Banana 2", isMarket: true }, + { id: "google-imagen/nano-banana", name: "Nano Banana", isMarket: true }, + { id: "google-imagen/nano-banana-pro", name: "Nano Banana Pro", isMarket: true }, + { id: "google-imagen/nano-banana-edit", name: "Nano Banana Edit", isMarket: true }, + { id: "flux/2-pro-image-to-image", name: "Flux 2 Pro I2I", isMarket: true }, + { id: "flux/2-pro-text-to-image", name: "Flux 2 Pro T2I", isMarket: true }, + { id: "flux/2-image-to-image", name: "Flux 2 I2I", isMarket: true }, + { id: "flux/2-text-to-image", name: "Flux 2 T2I", isMarket: true }, + { id: "flux/kontext", name: "Flux Kontext", isMarket: true }, + { id: "grok-imagine/text-to-image", name: "Grok Imagine T2I", isMarket: true }, + { id: "grok-imagine/image-to-image", name: "Grok Imagine I2I", isMarket: true }, + { id: "gpt/gpt-image-1.5-text-to-image", name: "GPT Image 1.5 T2I", isMarket: true }, + { id: "gpt/gpt-image-1.5-image-to-image", name: "GPT Image 1.5 I2I", isMarket: true }, + { id: "gpt/gpt-image-2-text-to-image", name: "GPT Image 2 T2I", isMarket: true }, + { id: "gpt/gpt-image-2-image-to-image", name: "GPT Image 2 I2I", isMarket: true }, + { id: "ideogram/v3-text-to-image", name: "Ideogram v3", isMarket: true }, + { id: "ideogram/v3-edit", name: "Ideogram v3 Edit", isMarket: true }, + { id: "ideogram/v3-remix", name: "Ideogram v3 Remix", isMarket: true }, + { id: "ideogram/v3-reframe", name: "Ideogram v3 Reframe", isMarket: true }, + { id: "qwen/text-to-image", name: "Qwen T2I", isMarket: true }, + { id: "qwen/image-to-image", name: "Qwen I2I", isMarket: true }, + { id: "qwen/image-edit", name: "Qwen Edit", isMarket: true }, + { id: "qwen2/image-edit", name: "Qwen2 Edit", isMarket: true }, + { id: "qwen2/text-to-image", name: "Qwen2 T2I", isMarket: true }, + { id: "wan/2.7-image", name: "Wan 2.7 Image", isMarket: true }, + { id: "wan/2.7-image-pro", name: "Wan 2.7 Image Pro", isMarket: true }, +]; diff --git a/tests/unit/minimax-media-servicekinds.test.ts b/tests/unit/minimax-media-servicekinds.test.ts index 6eecb2a1c2..026e01d73f 100644 --- a/tests/unit/minimax-media-servicekinds.test.ts +++ b/tests/unit/minimax-media-servicekinds.test.ts @@ -10,16 +10,16 @@ import assert from "node:assert/strict"; // serviceKinds, so every media page was empty. The fix derives media membership from // the registries (single source of truth) and unions it with declared serviceKinds. // -// MiniMax was the flagged case: its international endpoint serves TTS/video/music, the -// China variant (minimax-cn) has no media registry entries. +// MiniMax was the flagged case: its international endpoint serves TTS/video/music/image, +// the China variant (minimax-cn) has no media registry entries. const { getRegistryMediaKinds, resolveProviderServiceKinds, REGISTRY_MEDIA_KINDS } = await import("../../open-sse/config/mediaServiceKinds.ts"); const { AI_PROVIDERS } = await import("../../src/shared/constants/providers.ts"); -test("minimax (international) derives tts/video/music from the registries", () => { +test("minimax (international) derives image/tts/video/music from the registries", () => { const kinds = getRegistryMediaKinds("minimax").sort(); - assert.deepEqual(kinds, ["music", "tts", "video"]); + assert.deepEqual(kinds, ["image", "music", "tts", "video"]); }); test("minimax-cn derives no media kinds (China endpoint has no media registry entries)", () => {