Skip to content

refactor(core): make the catalog native - #48562

Closed
rekram1-node wants to merge 1 commit into
v2from
catalog-native
Closed

refactor(core): make the catalog native#48562
rekram1-node wants to merge 1 commit into
v2from
catalog-native

Conversation

@rekram1-node

Copy link
Copy Markdown
Collaborator

Problem

After #48429 settings are flat everywhere, but the catalog still lies about what runs. models.dev writes aisdk:@ai-sdk/openai with variants spelled in AI SDK vocabulary, and the resolver translates on every resolve. Anything that reads the catalog (TUI, config surfaces, plugins) sees aisdk: 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

  • models.devnormalize() 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 are body.additionalModelRequestFields overlays, which is what Converse actually takes. Packages without a native equivalent (Vercel gateway, SAP, Cohere, Alibaba, …) keep aisdk: and AI SDK spellings; the Vercel gateway's upstream keys stay legacy because the gateway SDK is what reads them.
  • Config and plugins — new AISDKNativePlugin runs after ConfigProviderPlugin and before VariantPlugin. It walks every catalog record and rewrites aisdk: 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.
  • V1 migrate — the migrated document names native packages and native settings.

AISDKNative

Now 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, Azure useCompletionUrls, Mantle model selection) are unchanged; they just run at ingest instead of per resolve.

ModelResolver

Two 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-compatible takes the catalog provider ID as its provider, which sets its providerMetadataKey) 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 stays aisdk:.

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, on v2 and 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-compatible always maps to native — without a baseURL it now fails with a configuration error instead of falling back to the AI SDK. Every models.dev provider has an api, so no models.dev provider is affected.

Tests

Existing tests updated to the native catalog shape. aisdk-native.test.ts exercises rewrite with the same expectations as before plus one test each for record-level rewriting and Converse pushdown. model-resolver.test.ts fixtures 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.mdx example shows the native package the migration now produces.

Follow-up (not in this PR)

  • Best-guess default variants for config-defined models with none.
  • aisdk.ts and the sdk hooks in openai-compatible, cloudflare-workers-ai, and google-vertex still branch on @ai-sdk/openai-compatible; those paths are now unreachable from the catalog.
  • Resolver credential handling still names package specifiers (nativeCredentialSettings, usesAPIKeyAuth).

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant