Skip to content

fix(core): forward unrecognized OpenAI-compatible model settings as body fields - #53975

Closed
opencode-agent[bot] wants to merge 2 commits into
devfrom
compatible-options-passthrough
Closed

opencode-agent[bot] wants to merge 2 commits into
devfrom
compatible-options-passthrough

Conversation

@opencode-agent

@opencode-agent opencode-agent Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Issue for this PR

Closes #53677

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

@ai-sdk/openai-compatible is swapped for the native @opencode/ai/providers/openai-compatible package. The AI SDK package sent any model provider option it didn't recognize straight into the request body. The native package reads only its typed OpenAI options and drops everything else without a warning. As a result, a v1 config like models.x.options.allowed_openai_params (LiteLLM's dynamic allowlist) never reached the wire, so the request failed with a 400 from the proxy.

AISDKNative.options() now moves model and variant settings that the generic OpenAI-compatible package doesn't read into the body overlay. Settings it does read stay in settings: apiKey, baseURL, body, provider, the OpenAI option fields, and Core settings such as timeouts. So do the two AI SDK chat options it never forwarded (user and strictJsonSchema).

The rewrite runs on every model update, once per config layer, and each run moves only the settings that were just merged in. Forwarded fields are therefore applied on top of the existing body, so a later layer overrides an earlier one: a project config can override a global allowed_openai_params. A side effect is that when one config entry sets the same key in both settings and body/extraBody, the setting wins.

v1 variants marked disabled: true are now dropped during migration, which matches v1. Before, the flag was copied into settings, where it would have been forwarded as a body field. v2 has no way to disable a built-in variant, so a disabled built-in still shows up exactly as it does on v2 today; it just no longer leaks the flag.

Provider-level settings aren't forwarded, because in v1 those were constructor options (includeUsage and similar), not request options. The rewrite tells the two apart by whether it has a model ID. That's the same signal the Bedrock Converse mapping already uses.

One behavior change for v2-shaped configs: unknown model or variant settings on the generic package are now sent as body fields instead of being dropped. Two existing fixtures relied on the old drop (models-dev and provider-opencode), and their expectations are updated. The documented way to add body fields in v2 config is still body.

How did you verify your code works?

  • New unit tests cover the model and variant forwarding, a later update overriding an earlier forwarded value, provider-level settings not being forwarded, and disabled v1 variants being dropped. The last two tests fail without the fix. A resolver test checks that the route's HTTP body overlay carries allowed_openai_params while reasoning_effort is still lowered by the protocol.
  • End-to-end run with the issue's v1 config (provider.litellm.npm = @ai-sdk/openai-compatible, model options: { reasoningEffort: "high", allowed_openai_params: ["reasoning_effort"] }) against a local echo server, using opencode run --standalone. Before the change, the captured body had reasoning_effort: "high" and no allowed_openai_params. After the change, it had both. With a second layer (OPENCODE_CONFIG_CONTENT) setting reasoningEffort: "medium" and foo: "from-content", both overrides reached the wire. A custom variant's enable_thinking was sent, and selecting the disabled variant returned "Variant unavailable".
  • bun typecheck in packages/core passes. The full packages/core test run has the same pre-existing failures as v2 (shell/XDG environment and flock contention tests), and they're unrelated to this change.

Screenshots / recordings

N/A

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Requested by: @neriousy (Filip via Slack)

@github-actions

github-actions Bot commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

Automated PR Cleanup

Thank you for contributing to opencode.

Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions.

This PR was closed because it matched the following cleanup criteria:

  • The PR was created more than 1 month ago
  • The PR had fewer than 2 positive reactions
  • Positive reactions are counted as thumbs-up, heart, celebration, or rocket reactions on the PR

PRs created within the last month are not affected by this cleanup.

If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate.

Thanks again for taking the time to contribute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] openai-compatible: unknown provider options no longer forwarded, breaks LiteLLM allowed_openai_params passthrough (worked in v1)

1 participant