Skip to content

refactor: flatten provider settings across core and the AI package - #48429

Merged
rekram1-node merged 8 commits into
v2from
model-resolution
Sep 11, 2026
Merged

refactor: flatten provider settings across core and the AI package#48429
rekram1-node merged 8 commits into
v2from
model-resolution

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Problem

opencode settings are one flat bag everywhere (config, models.dev, catalog, variants). Native @opencode/ai packages read request options from a nested providerOptions object inside model(id, settings). Only the legacy aisdk: mapping path lifted flat keys into that object, with a hand-maintained whitelist per npm package.

So the same intent had multiple spellings and which one worked depended on the package prefix:

config aisdk:@ai-sdk/openai @opencode/ai/providers/openai
settings.reasoningEffort works silently dropped → route falls back to medium
settings.providerOptions.reasoningEffort double-nested, dropped works

The first failure also hit models.dev variants: overriding a provider's package to a native one in config made every generated reasoning variant a no-op.

Change

There is no providerOptions concept at any boundary opencode owns. Settings are flat in config, in the catalog, and at the AI package entrypoint.

@opencode/ai

model(modelID, settings) takes one flat object. Each of the 37 entrypoints destructures the connection keys it declares (apiKey, baseURL, region, resourceName, …) and passes the rest to the route as providerOptions. Settings types become ProviderPackage.Settings & <ProtocolOptionsInput> & { connection keys }, so autocomplete and type-checking are unchanged and the auth-exclusivity type tests still hold. Internal configure(...) / Config shapes are untouched; only the package entrypoint is flat. Package guide updated.

packages/core

  • Provider.nativeSettings drops opencode transport keys (timeout, chunkTimeout, fetch), which only the AI SDK runtime consumes. That is all; core knows no package key names.
  • AISDKNative.map is purely the legacy translator: package mapping plus the spellings that differ between AI SDK and native packages (Bedrock connection keys and Converse body fields, OpenRouter attribution headers, Azure/Mantle chat-vs-responses selection). The legacy AI SDK shape is decoded once with a lenient schema at the top of map, replacing 31 per-field isRecord/typeof checks. ~400 → ~200 lines.
  • ModelResolver applies nativeSettings once on the native path and loads whatever package the catalog names.

Tests

Existing tests updated to the flat shape (packages/ai/test/provider-package.test.ts, native-providers, meta, groq; core aisdk-native, model-resolver). One small nativeSettings case in provider.test.ts. packages/ai: 1300 pass. packages/core affected suites: 385 pass.

Behavior notes

  • A wrongly-typed request option (e.g. store: "yes") makes the OpenAI-family option schema decode return nothing for that request. The old aisdk: whitelists masked this; it was already native-path behavior. Making that decode lenient per field is a separate @opencode/ai change.
  • OpenRouter forwards unknown request options to its request body. Connection keys are destructured out before the rest becomes providerOptions, so apiKey/baseURL/headers/body never reach it.

Follow-up (not in this PR)

Register native packages and native-vocabulary variants at catalog ingest (models.dev, config) so the catalog itself is native and the legacy translator runs only at those entry points; add best-guess default variants for config-defined models with none.

Catalog settings are flat, but native @opencode/ai packages read request
options from a nested providerOptions object. Only the AI SDK mapping path
lifted flat keys, so a model on a native package silently dropped
reasoningEffort and every other request setting, including the variants
models.dev generates, while a config that already wrote providerOptions
was nested a second time on the aisdk: path.

Provider.nativeSettings now does the lift once for every native package:
connection keys stay on top, everything else moves into providerOptions,
and a nested providerOptions merges instead of wrapping. AISDKNative.map
uses it in place of its per-package whitelists and keeps only the real
vocabulary translations for Bedrock, OpenRouter, Azure, and Mantle.
Drop the connection-key list: core knows nothing about a package's shape.
The flat bag is offered to the package as-is and again as providerOptions,
excluding only the credentials core injects, the ProviderPackage.Settings
base keys, and opencode transport keys. Each side reads the names it
declares, so new package settings work without core changes. A legacy
nested providerOptions is flattened with flat keys taking precedence.

AISDKNative.map now emits flat settings and keeps only spelling
translations between AI SDK and native packages.
@rekram1-node rekram1-node changed the title fix(core): shape flat catalog settings for native provider packages fix(core): pass flat settings through to native provider packages Sep 11, 2026
Only OpenRouter forwards unknown request options to the wire, so the
constructor-only exclusion belongs with the other OpenRouter keys.
Type the AI SDK settings whose spelling differs from the native package
with a lenient schema decoded at the top of AISDKNative.map, replacing
the per-field isRecord and typeof checks. nativeSettings takes
Provider.Settings and its comment states the reason it exists.
model(modelID, settings) takes one flat object. Each entrypoint
destructures the connection keys it declares and passes everything else
to the route as providerOptions, so there is no nested providerOptions at
the package boundary and new package settings need no changes in core.

Core's nativeSettings shrinks to dropping opencode transport keys and
flattening a legacy nested providerOptions.
There is no providerOptions concept in opencode settings.
@rekram1-node rekram1-node changed the title fix(core): pass flat settings through to native provider packages refactor: flatten provider settings across core and the AI package Sep 11, 2026
@rekram1-node
rekram1-node merged commit a555f24 into v2 Sep 11, 2026
8 checks passed
@rekram1-node
rekram1-node deleted the model-resolution branch September 11, 2026 18:37
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