diff --git a/changelog.d/fixes/11326-kie-market-google-imagen-ids.md b/changelog.d/fixes/11326-kie-market-google-imagen-ids.md new file mode 100644 index 0000000000..62dacb5d48 --- /dev/null +++ b/changelog.d/fixes/11326-kie-market-google-imagen-ids.md @@ -0,0 +1 @@ +- **fix(kie):** map the remaining `google-imagen/*` KIE Market catalog ids (`nano-banana`, `nano-banana-pro`, `nano-banana-edit`) to their real, KIE-documented upstream `model` values — `#11225`'s fix only covered `nano-banana-2` ([#11326](https://github.com/diegosouzapw/OmniRoute/pull/11326)). diff --git a/open-sse/handlers/imageGeneration.ts b/open-sse/handlers/imageGeneration.ts index fde2f4a403..db0745898e 100644 --- a/open-sse/handlers/imageGeneration.ts +++ b/open-sse/handlers/imageGeneration.ts @@ -91,8 +91,20 @@ interface KieImageOptions { } | null; } +// KIE Market catalog ids are namespaced for OmniRoute's catalog +// (`google-imagen/`), but the KIE Market createTask API expects +// vendor-specific upstream ids that do not follow a single consistent +// pattern (confirmed against docs.kie.ai/market/google/* — see #11225, +// #11296): nano-banana-2 and nano-banana-pro drop the vendor namespace +// entirely, while nano-banana and nano-banana-edit use a `google/` prefix +// instead of `google-imagen/`. Every other KIE Market namespace (seedream, +// flux, ideogram, qwen, wan, grok-imagine, gpt) already matches its real +// upstream id byte-for-byte, so this map stays scoped to google-imagen. export const KIE_MARKET_UPSTREAM_MODEL_IDS: ReadonlyMap = new Map([ + ["google-imagen/nano-banana", "google/nano-banana"], ["google-imagen/nano-banana-2", "nano-banana-2"], + ["google-imagen/nano-banana-pro", "nano-banana-pro"], + ["google-imagen/nano-banana-edit", "google/nano-banana-edit"], ]); export function resolveKieMarketUpstreamModelId(publicModelId: string): string { diff --git a/tests/unit/kie-market-upstream-model-id-11225.test.ts b/tests/unit/kie-market-upstream-model-id-11225.test.ts index bc9484494e..533d0d051f 100644 --- a/tests/unit/kie-market-upstream-model-id-11225.test.ts +++ b/tests/unit/kie-market-upstream-model-id-11225.test.ts @@ -103,7 +103,7 @@ function resolveLiveKieMarketCatalog() { })); } -test("KIE Market resolver changes exactly one id in the live market catalog", () => { +test("KIE Market resolver changes exactly the 4 google-imagen ids in the live market catalog", () => { const roundTrips = resolveLiveKieMarketCatalog(); const changed = roundTrips.filter(({ publicModelId, upstreamModelId }) => { return upstreamModelId !== publicModelId; @@ -114,12 +114,31 @@ test("KIE Market resolver changes exactly one id in the live market catalog", () publicModelId: "google-imagen/nano-banana-2", upstreamModelId: "nano-banana-2", }, + { + publicModelId: "google-imagen/nano-banana", + upstreamModelId: "google/nano-banana", + }, + { + publicModelId: "google-imagen/nano-banana-pro", + upstreamModelId: "nano-banana-pro", + }, + { + publicModelId: "google-imagen/nano-banana-edit", + upstreamModelId: "google/nano-banana-edit", + }, ]); }); +const REWRITTEN_GOOGLE_IMAGEN_MARKET_IDS = new Set([ + "google-imagen/nano-banana", + "google-imagen/nano-banana-2", + "google-imagen/nano-banana-pro", + "google-imagen/nano-banana-edit", +]); + test("KIE Market resolver preserves every other live market catalog id byte-identically", () => { for (const { publicModelId, upstreamModelId } of resolveLiveKieMarketCatalog()) { - if (publicModelId !== "google-imagen/nano-banana-2") { + if (!REWRITTEN_GOOGLE_IMAGEN_MARKET_IDS.has(publicModelId)) { assert.equal( upstreamModelId, publicModelId, @@ -129,8 +148,8 @@ test("KIE Market resolver preserves every other live market catalog id byte-iden } }); -test("KIE Market resolver keeps exactly one explicit upstream id mapping", () => { - assert.equal(KIE_MARKET_UPSTREAM_MODEL_IDS.size, 1); +test("KIE Market resolver keeps exactly the explicit google-imagen upstream id mappings (#11296)", () => { + assert.equal(KIE_MARKET_UPSTREAM_MODEL_IDS.size, 4); }); test("KIE Market resolver passes an unknown namespaced id through byte-identically", () => { @@ -160,6 +179,36 @@ test("KIE Market createTask sends the bare upstream model id for Nano Banana 2 ( assert.equal(captured.result.data.data[0].url, "https://example.com/kie-market-image.png"); }); +test("KIE Market createTask sends the KIE upstream id for Nano Banana (#11296)", async () => { + const captured = await runKieMarketGeneration("kie/google-imagen/nano-banana"); + + assert.equal( + captured.create.body.model, + "google/nano-banana", + "KIE Market createTask must send the KIE-documented google/nano-banana upstream id" + ); +}); + +test("KIE Market createTask sends the bare upstream model id for Nano Banana Pro (#11296)", async () => { + const captured = await runKieMarketGeneration("kie/google-imagen/nano-banana-pro"); + + assert.equal( + captured.create.body.model, + "nano-banana-pro", + "KIE Market createTask must send the KIE-documented nano-banana-pro upstream id" + ); +}); + +test("KIE Market createTask sends the KIE upstream id for Nano Banana Edit (#11296)", async () => { + const captured = await runKieMarketGeneration("kie/google-imagen/nano-banana-edit"); + + assert.equal( + captured.create.body.model, + "google/nano-banana-edit", + "KIE Market createTask must send the KIE-documented google/nano-banana-edit upstream id" + ); +}); + test("KIE Market createTask leaves genuinely namespaced upstream ids untouched (#11225 control)", async () => { const captured = await runKieMarketGeneration("kie/seedream/4.5-text-to-image");