feat(cloudflare): sync full Workers AI catalog + mirror into AI Gateway#3313
feat(cloudflare): sync full Workers AI catalog + mirror into AI Gateway#3313michaeldwan wants to merge 4 commits into
Conversation
The scripts/ + data/ pipeline hit gateway.ai.cloudflare.com/.../compat/models and hand-generated TOMLs under models/workers-ai/. It was never wired into the hourly model sync workflow, so its output drifted from providers/cloudflare-workers-ai/ by a year of merges. models/workers-ai/@cf still contains those stale, hand-generated TOMLs for now.
Delete the 43 hand-generated TOMLs under providers/cloudflare-ai-gateway/models/workers-ai/@cf and replace the subtree with a symlink to ../../../cloudflare-workers-ai/models/@cf so AIG's Workers AI catalog is the Cloudflare Workers AI catalog by construction. generate.ts, sync/index.ts, packages/web/src/render.tsx, and compare-model-migrations.ts all glob TOMLs with followSymlinks: true, so the symlink resolves at build/validate time and AIG's provider catalog materializes with WAI's contents. Merging a WAI sync PR now updates AIG's catalog on the next deploy too, through the same file. Net catalog change for AIG's workers-ai/: - 43 -> 22 models - drops 15 non-chat entries unique to AIG (BGE, Deepgram, MeloTTS, m2m100, distilbert, etc.) and 9 deprecated chat models - picks up 3 net-new WAI models (kimi-k2.7-code, glm-5.2, gemma-4-26b-a4b-it) Also rewrites providers/cloudflare-ai-gateway/README.md to describe the symlink and drop the (now-removed) shell pipeline docs.
Cloudflare's Workers AI models API returns two shapes: format=openrouter (rich, but chat-models only) and a native format that covers everything else it serves (embeddings, ASR, TTS, translation, classification, image gen, etc). The WAI sync only ever fetched the openrouter shape, so those other models were invisible to models.dev even though Cloudflare serves them live. This teaches the sync to also fetch the native format, and reshape each native record into the same OpenRouterModel shape the existing pipeline already builds from -- mapping task type to input/output modality, converting per-million-token pricing to the per-token format the schema expects, and reading capability flags (tool calling, reasoning) out of the native properties array. Native pagination has no page count to trust (total_count reflects Cloudflare's whole catalog, not this account's view), so it pages until an empty result instead. Two fields -- output token limit and open-weights status -- have no source in either API shape for any model, so they're faked (0 / false). Guessing these two fields when a provider's API doesn't report them is already normal in this codebase (e.g. digitalocean.ts, chutes.ts, and wandb.ts all fall back to 0 for a missing output limit; chutes defaults open_weights to true, digitalocean/pioneer/llmgateway/vercel default it to false) -- and the old hand-run AIG pipeline this branch replaces did exactly this too, hardcoding context=128000 and output=16384 as shell constants on every model it generated. Where both formats report the same model, the richer openrouter record wins, keeping fields native lacks -- max_completion_tokens, structured_output, hugging_face_id -- on the 22 existing chat models.
…ch surfaces These 39 TOMLs are the sync's output against the live Workers AI API: every model Cloudflare serves that only reports through the native shape, not format=openrouter -- 5 embedding models, 3 TTS voices, ASR (whisper), translation (m2m100), image classification, several text-to-image models, a couple of LoRA chat variants, and others. They existed on Cloudflare's side already; the sync had no path to them until now. The 22 existing chat models came out byte-identical.
Action items
|
1) Fix drift between Workers AI and AI Gateway
Cloudflare Workers AI models can be accessed directly, or through Cloudflare AI Gateway, but models.dev maintains them as two independent providers that have drifted apart for over a year.
Previously
cloudflare-workers-aikept Workers AI in sync each hour; AI Gateway had a hand-run shell pipeline underproviders/cloudflare-ai-gateway/scripts/that was never wired into the hourly workflow.cloudflare-ai-gateway/models/workers-ai/@cfis now a symlink tocloudflare-workers-ai/models/@cf, so AIG's Workers AI catalog is the WAI catalog. Thescripts/+data/pipeline is deleted, and the AIG README is rewritten to describe the symlink layout.2) Sync the complete Workers AI model catalog
The WAI sync now covers Cloudflare's complete Workers AI catalog -- 39 new TOMLs for embeddings, ASR, TTS, translation, classification, and image gen. Previously it was only fetching text generation models due to the
format=openrouterfilter. Now it also fetches and reshapes models from the nativeai/models/searchendpoint into the sameOpenRouterModelthe pipeline already builds from. Where both APIs report the same model, openrouter wins, so the 22 existing chat entries stay byte-identical.Any future WAI expansion (new task type, new model) lands in AIG on the next deploy through the same file.
Notes
The Cloudflare APIs don't provide all the data model TOMLs expose. I'll see if we can fix this on our (Cloudflare's) end:
0/false) -- same fallbackdigitalocean.ts,chutes.ts, andwandb.tsuse when a source doesn't report them. The old AIG shell pipeline this replaces incorrectly hardcodedcontext=128000/output=16384on every model.-1(OpenRouter's own sentinel) rather than a fake0, soprice()doesn't invent cost. Audio-priced models getinput_audio/output_audioapplied in a follow-up pass.Sources