From cf31b8fe1d57684dc9eef28e1d8268b5a7ef0590 Mon Sep 17 00:00:00 2001 From: memosr Date: Thu, 20 Aug 2026 23:23:35 +0300 Subject: [PATCH] fix(image): stop advertising dall-e-3 and flux in the OpenClaw picker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The image UI sends the picked id from provider.models straight to /v1/images/generations, which forwards the body verbatim with no alias resolution. Two ids there have been dead since v0.12.227: - openai/dall-e-3 — gateway 400s (delisted upstream 2026-05-25) - black-forest/flux-1.1-pro — no gateway entry at all Both were dropped from IMAGE_PRICING and MODEL_ALIASES in that release, but buildImageGenerationProvider was missed, so picking either one is a guaranteed upstream failure. The three live models added since (gpt-image-2, nano-banana-2, seedream-5-pro) were never advertised. Same drift class the blockrun_image_generation tool description carried, which pointed agents at the same two dead ids. - picker list resynced to IMAGE_PRICING's 9 gateway-served ids - IMAGE_MODEL_IDS exported from proxy.ts as the pinning source of truth - partner tool description and model-param example refreshed - stale --model dall-e-3 hints in user-facing copy updated src/index.image-provider.test.ts pins the picker against IMAGE_PRICING so the two cannot drift apart again; it fails on the pre-fix list. --- src/index.image-provider.test.ts | 50 ++++++++++++++++++++++++++++++++ src/index.ts | 13 +++++++-- src/partners/registry.ts | 11 +++---- src/proxy.ts | 15 ++++++++-- 4 files changed, 79 insertions(+), 10 deletions(-) create mode 100644 src/index.image-provider.test.ts diff --git a/src/index.image-provider.test.ts b/src/index.image-provider.test.ts new file mode 100644 index 00000000..eba5b3d1 --- /dev/null +++ b/src/index.image-provider.test.ts @@ -0,0 +1,50 @@ +import { describe, expect, it } from "vitest"; + +import { buildImageGenerationProvider } from "./index.js"; +import { IMAGE_MODEL_IDS } from "./proxy.js"; + +/** + * The OpenClaw image UI sends the picked entry from `provider.models` straight + * through to `POST /v1/images/generations`, and that handler forwards the body + * to the gateway verbatim — no `resolveModelAlias()` pass. So every id we + * advertise here has to be a live gateway model id, not an alias and not a + * retired one, or the user's pick 400s upstream. + * + * `IMAGE_PRICING` in proxy.ts is the list that v0.12.227 kept in sync with + * blockrun's IMAGE_MODELS, so it is the local source of truth for "the gateway + * can serve this". Anything advertised but unpriced is drift. + */ +describe("image generation provider model list", () => { + const provider = buildImageGenerationProvider(); + + // `models` is optional on ImageGenerationProviderPlugin, so pin that we + // actually advertise something before asserting on its contents. + const models = provider.models ?? []; + + it("advertises a model list", () => { + expect(models.length).toBeGreaterThan(0); + }); + + it("only advertises models the gateway can still serve", () => { + const unservable = models.filter((id) => !IMAGE_MODEL_IDS.includes(id)); + expect(unservable).toEqual([]); + }); + + it("does not advertise models delisted upstream", () => { + // dall-e-3: gateway 400s ("Delisted 2026-05-25: OpenAI removed dall-e-3 + // from the API"). flux-1.1-pro: no gateway entry at all. Both were dropped + // from IMAGE_PRICING and MODEL_ALIASES in v0.12.227. + expect(models).not.toContain("openai/dall-e-3"); + expect(models).not.toContain("black-forest/flux-1.1-pro"); + }); + + it("advertises the live successors", () => { + expect(models).toContain("openai/gpt-image-2"); + expect(models).toContain("google/nano-banana-2"); + expect(models).toContain("bytedance/seedream-5-pro"); + }); + + it("advertises a default model that is itself advertised", () => { + expect(models).toContain(provider.defaultModel); + }); +}); diff --git a/src/index.ts b/src/index.ts index 2031fa1c..c9c9a51f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1172,17 +1172,24 @@ function parseGenArgs(raw: string): { * with OpenClaw's native image generation UI. * Delegates to the local proxy (which handles x402 payment). */ -function buildImageGenerationProvider(): ImageGenerationProviderPlugin { +export function buildImageGenerationProvider(): ImageGenerationProviderPlugin { return { id: "blockrun", label: "BlockRun", defaultModel: "google/nano-banana", + // Must stay in sync with IMAGE_PRICING (proxy.ts). OpenClaw sends the + // picked id straight to /v1/images/generations, which forwards the body + // verbatim with no alias resolution, so a retired id here is a guaranteed + // upstream 400. dall-e-3 (delisted 2026-05-25) and flux-1.1-pro (no + // gateway entry) were dropped in v0.12.227 and had lingered here. + // src/index.image-provider.test.ts pins the two lists together. models: [ "google/nano-banana", + "google/nano-banana-2", "google/nano-banana-pro", "openai/gpt-image-1", - "openai/dall-e-3", - "black-forest/flux-1.1-pro", + "openai/gpt-image-2", + "bytedance/seedream-5-pro", "xai/grok-imagine-image", "xai/grok-imagine-image-pro", "zai/cogview-4", diff --git a/src/partners/registry.ts b/src/partners/registry.ts index f43b3834..9d7d23de 100644 --- a/src/partners/registry.ts +++ b/src/partners/registry.ts @@ -636,12 +636,13 @@ export const PARTNER_SERVICES: PartnerServiceDefinition[] = [ name: "Image Generation", partner: "BlockRun", category: "Image & Video", - shortDescription: "8 image models (DALL-E, Flux, Grok, ...)", + shortDescription: "9 image models (Nano Banana, GPT Image, ...)", description: "Generate an image from a text prompt. Models available: google/nano-banana (default), " + - "google/nano-banana-pro (up to 4K), openai/gpt-image-1, openai/dall-e-3, " + - "black-forest/flux-1.1-pro, xai/grok-imagine-image, xai/grok-imagine-image-pro, " + - "zai/cogview-4. Returns a local http://localhost:8402/images/.png URL.", + "google/nano-banana-2, google/nano-banana-pro (up to 4K), openai/gpt-image-1, " + + "openai/gpt-image-2, bytedance/seedream-5-pro, xai/grok-imagine-image, " + + "xai/grok-imagine-image-pro, zai/cogview-4. " + + "Returns a local http://localhost:8402/images/.png URL.", proxyPath: "/images/generations", method: "POST", params: [ @@ -655,7 +656,7 @@ export const PARTNER_SERVICES: PartnerServiceDefinition[] = [ name: "model", type: "string", description: - "Full model ID (e.g. 'google/nano-banana', 'openai/dall-e-3'). Default: google/nano-banana.", + "Full model ID (e.g. 'google/nano-banana', 'openai/gpt-image-2'). Default: google/nano-banana.", required: false, }, { diff --git a/src/proxy.ts b/src/proxy.ts index 72f52f5c..0d8d9bea 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -1609,6 +1609,17 @@ const IMAGE_PRICING: Record