Skip to content

fix(provider): split providerOptions key on dot for openai-compatible, openai, and anthropic providers#25145

Merged
rekram1-node merged 1 commit intoanomalyco:devfrom
Sewer56:fix/openai-compatible-provideroptions-dot-key
Apr 30, 2026
Merged

fix(provider): split providerOptions key on dot for openai-compatible, openai, and anthropic providers#25145
rekram1-node merged 1 commit intoanomalyco:devfrom
Sewer56:fix/openai-compatible-provideroptions-dot-key

Conversation

@Sewer56
Copy link
Copy Markdown
Contributor

@Sewer56 Sewer56 commented Apr 30, 2026

Issue for this PR

Closes #23622

Type of change

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

What does this PR do?

Providers with dots in their ID (e.g. wafer.ai) that use @ai-sdk/openai-compatible, @ai-sdk/openai, or @ai-sdk/anthropic never have their providerOptions sent to the API. This silently breaks features like reasoningEffort - reasoning models return no thinking content.

Three AI SDK packages resolve the providerOptions key by splitting the provider name on .:

// @ai-sdk/openai-compatible, @ai-sdk/openai, @ai-sdk/anthropic
get providerOptionsName() {
    return this.config.provider.split(".")[0].trim();
}

So "wafer.ai" reads providerOptions["wafer"], but opencode writes providerOptions["wafer.ai"] - key mismatch, options silently dropped.

@ai-sdk/openai and @ai-sdk/anthropic have the same dot-split but are currently protected by sdkKey() mappings. Those mappings aren't guaranteed to stay in sync, so the fix covers all three.

Other AI SDK packages (xai, mistral, groq, cohere, togetherai, etc.) use hardcoded keys like "xai" - not derived from the provider name. Applying .split(".")[0] would break those, so they are excluded.

Fix: apply the same dot-split for the three packages that use the providerOptionsName pattern:

const usesDotSplitOptions =
  model.api.npm === "@ai-sdk/openai-compatible" ||
  model.api.npm === "@ai-sdk/openai" ||
  model.api.npm === "@ai-sdk/anthropic"
const key =
  sdkKey(model.api.npm) ??
  (usesDotSplitOptions
    ? model.providerID.split(".")[0]
    : model.providerID)

Regression analysis:

  • Only wafer.ai has a dot among all models.dev openai-compatible providers - all others unaffected
  • @ai-sdk/openai and @ai-sdk/anthropic are covered but currently protected by sdkKey() mappings anyway
  • Other AI SDK packages (xai, mistral, groq, etc.) use hardcoded keys and are excluded from the dot-split
  • User-defined providers in opencode.json with dots also benefit

How did you verify your code works?

Manually tested the change on a fork of OpenCode.

Screenshots / recordings

N/A

Checklist

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

… providers

The AI SDK's @ai-sdk/openai-compatible, @ai-sdk/openai, and
@ai-sdk/anthropic modules all resolve the providerOptions key by
splitting the provider name on '.' and taking the first segment:

    get providerOptionsName() {
        return this.config.provider.split('.')[0].trim();
    }

This means a provider named 'wafer.ai' will look for options under
providerOptions['wafer'], NOT providerOptions['wafer.ai'].

However, opencode's providerOptions() in transform.ts uses the raw
providerID as the key when sdkKey() returns undefined (which it does
for @ai-sdk/openai-compatible):

    const key = sdkKey(model.api.npm) ?? model.providerID
    return { [key]: options }

For provider 'wafer.ai', this puts options under
providerOptions['wafer.ai'] - a key the SDK never reads. The result
is that provider options like { reasoningEffort: 'medium' } are
silently dropped. No reasoning_effort is sent in the API request,
so models like DeepSeek-V4-Pro return no reasoning_content.

@sdk/openai and @sdk/anthropic are also affected in principle, but
currently protected by their sdkKey() mappings (returning 'openai'
and 'anthropic' respectively). Those mappings are not guaranteed to
stay in sync, so the dot-split is applied to all three packages.

Other AI SDK packages (xai, mistral, groq, cohere, togetherai, etc.)
use hardcoded providerOptions keys like 'xai' or 'cohere' rather than
deriving them from the provider name - applying .split('.')[0] would
break those, so they are excluded.

Fix: for SDKs that use the providerOptionsName dot-split pattern,
apply the same logic here so the key we write matches the key they
read.
@github-actions github-actions Bot added contributor needs:compliance This means the issue will auto-close after 2 hours. needs:issue labels Apr 30, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions
Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Potential Duplicate Found:

Current PR #25145 is the one being checked (not a duplicate of itself).

@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Apr 30, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@Sewer56
Copy link
Copy Markdown
Contributor Author

Sewer56 commented Apr 30, 2026

This also closes

Aforementioned PR only solves for openai-compatible. This solves for all affected ai-sdk providers; I did a further search/investigation.

@rekram1-node rekram1-node merged commit a123333 into anomalyco:dev Apr 30, 2026
18 of 19 checks passed
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.

openai-compatible provider options silently dropped if provider name contains dot

2 participants