refactor(core): make the catalog native - #48562
Closed
rekram1-node wants to merge 1 commit into
Closed
Conversation
The catalog only holds native packages and native-vocabulary settings wherever a native package exists. models.dev registers native packages and variants directly; config and plugin writes are rewritten once by the new AISDKNativePlugin before variants are generated; V1 migration emits native packages. The resolver has two doors: native package or opaque aisdk: package. AISDKNative is now a catalog-record rewriter rather than a resolve-time mapper. openai-compatible always maps to its native package; a missing baseURL surfaces as a configuration error instead of falling back to the AI SDK.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
After #48429 settings are flat everywhere, but the catalog still lies about what runs. models.dev writes
aisdk:@ai-sdk/openaiwith variants spelled in AI SDK vocabulary, and the resolver translates on every resolve. Anything that reads the catalog (TUI, config surfaces, plugins) seesaisdk:packages that are never actually loaded, provider plugins branch on@ai-sdk/*names, and the resolver has three doors.Change
The catalog only ever holds native packages and native-vocabulary settings, headers, body and variants wherever a native package exists. Translation from AI SDK vocabulary happens once, at the point things enter the catalog.
Entry points
normalize()registers native packages and native-vocabulary variants directly. The variant table is keyed by native package (@opencode/ai/providers/openai,…/anthropic,…/amazon-bedrock, …). Bedrock variants arebody.additionalModelRequestFieldsoverlays, which is what Converse actually takes. Packages without a native equivalent (Vercel gateway, SAP, Cohere, Alibaba, …) keepaisdk:and AI SDK spellings; the Vercel gateway's upstream keys stay legacy because the gateway SDK is what reads them.AISDKNativePluginruns afterConfigProviderPluginand beforeVariantPlugin. It walks every catalog record and rewritesaisdk:packages, settings, headers, body and variants to native. Package choice uses the merged provider+model settings and the model ID (Azure chat vs responses, Mantle gpt-oss vs responses); a model gets an explicit package only when its native package differs from the provider's. Provider-level Converse request settings are pushed down onto each model first since their shape depends on the model.AISDKNativeNow a catalog-record rewriter:
rewrite(provider, models),translate(native, overlay, modelID),nativePackage(npm, modelID, settings). The legacy schema and all spelling rules (Bedrock connection and Converse body keys, OpenRouter attribution headers, AzureuseCompletionUrls, Mantle model selection) are unchanged; they just run at ingest instead of per resolve.ModelResolverTwo doors: native package → load it and hand it the flat settings;
aisdk:→ the AI SDK runtime. No translation, no@ai-sdk/*names. The one identity rule (openai-compatibletakes the catalog provider ID as itsprovider, which sets itsproviderMetadataKey) moved here from the translator so it cannot leak into models that override the provider's package.Plugins
azure,google-vertex,openrouter,zenmux,kilo,nvidia,llmgateway,cerebras,amazon-bedrock, and the GLM variant hack now match native package names. Copilot's Messages models and Modal's models are registered natively; Copilot's own SDK staysaisdk:.Behavior
Verified by resolving every models.dev provider (first model with variants plus each variant, first without) and every
aisdk:config spelling at both provider and model level, onv2and on this branch, and diffing what lands on the route: package, route id,provider,providerMetadataKey, baseURL, query,providerOptions, headers, body. 789 scenarios, 2 differences, both the agreed decision that@ai-sdk/openai-compatiblealways maps to native — without abaseURLit now fails with a configuration error instead of falling back to the AI SDK. Every models.dev provider has anapi, so no models.dev provider is affected.Tests
Existing tests updated to the native catalog shape.
aisdk-native.test.tsexercisesrewritewith the same expectations as before plus one test each for record-level rewriting and Converse pushdown.model-resolver.test.tsfixtures are rewritten the way the catalog does before reaching the resolver.packages/core: 5376 pass; the 8 failures are pre-existing shell-tool/env tests unrelated to this change.Docs
migrate-v1.mdxexample shows the native package the migration now produces.Follow-up (not in this PR)
aisdk.tsand thesdkhooks inopenai-compatible,cloudflare-workers-ai, andgoogle-vertexstill branch on@ai-sdk/openai-compatible; those paths are now unreachable from the catalog.nativeCredentialSettings,usesAPIKeyAuth).