-
Notifications
You must be signed in to change notification settings - Fork 640
fix(image): stop advertising dall-e-3 and flux-1.1-pro in the OpenClaw image picker #254
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1609,6 +1609,17 @@ const IMAGE_PRICING: Record<string, { default: number; sizes?: Record<string, nu | |
| }, | ||
| }; | ||
|
|
||
| /** | ||
| * Image model ids the gateway can actually serve, in picker order. | ||
| * | ||
| * Derived from IMAGE_PRICING, which v0.12.227 re-synced against blockrun's | ||
| * IMAGE_MODELS — so an id missing here is an id the gateway will reject. | ||
| * Exported so the image picker advertised by buildImageGenerationProvider | ||
| * (index.ts) can be pinned against it: the picked id is forwarded to | ||
| * /v1/images/generations verbatim, with no alias resolution in between. | ||
| */ | ||
| export const IMAGE_MODEL_IDS: readonly string[] = Object.freeze(Object.keys(IMAGE_PRICING)); | ||
|
|
||
| // Video pricing (must match server's VIDEO_MODELS in blockrun/src/lib/models.ts). | ||
| // pricePerSecond is the BASE rate (no margin). estimateVideoCost applies the | ||
| // same 5% margin server-side uses, so values land on blockrun's quote. | ||
|
|
@@ -3869,7 +3880,7 @@ async function proxyRequest( | |
| if (imagegenMatch) { | ||
| const imageArgs = lastContent.slice(imagegenMatch.length).trim(); | ||
|
|
||
| // Parse optional flags: /cr-imagegen --model dall-e-3 --size 1792x1024 a cute cat | ||
| // Parse optional flags: /cr-imagegen --model gpt-image-2 --size 1536x1024 a cute cat | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win Add the The catalog advertises Add the alias and help entry, or document the full model ID. Proposed fix const IMAGE_MODEL_ALIASES: Record<string, string> = {
+ "nano-banana-2": "google/nano-banana-2",
"banana": "google/nano-banana",🤖 Prompt for AI Agents |
||
| let imageModel = "google/nano-banana"; | ||
| let imageSize = "1024x1024"; | ||
| let imagePrompt = imageArgs; | ||
|
|
@@ -4022,7 +4033,7 @@ async function proxyRequest( | |
| `[ClawRouter] /imagegen: failed to upload data URI: ${uploadErr instanceof Error ? uploadErr.message : String(uploadErr)}`, | ||
| ); | ||
| lines.push( | ||
| "Image generated but upload failed. Try again or use --model dall-e-3.", | ||
| "Image generated but upload failed. Try again or use --model gpt-image-2.", | ||
| ); | ||
| } | ||
| } else { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Prevent image-catalog drift.
The provider maintains a duplicate catalog, and the test checks only one-way inclusion. A future gateway model can therefore be omitted from the picker without a test failure.
src/index.ts#L1180-L1192: BuildmodelsfromIMAGE_MODEL_IDSor another shared canonical catalog.src/index.image-provider.test.ts#L28-L31: Assert equal model sets and equal lengths.📍 Affects 2 files
src/index.ts#L1180-L1192(this comment)src/index.image-provider.test.ts#L28-L31🤖 Prompt for AI Agents