Skip to content

fix(runtime): emit camelCase OpenAI-compatible provider option keys - #3321

Merged
likun666661 merged 2 commits into
apache:mainfrom
yihanzhu:fix/openai-compatible-camelcase-provider-options
Aug 20, 2026
Merged

fix(runtime): emit camelCase OpenAI-compatible provider option keys#3321
likun666661 merged 2 commits into
apache:mainfrom
yihanzhu:fix/openai-compatible-camelcase-provider-options

Conversation

@yihanzhu

Copy link
Copy Markdown
Contributor

Summary

Every doGenerate through a built-in dashed OpenAI-compatible provider (zai-coding-plan, volcengine-ark, …) logs an AI SDK deprecation warning: options are keyed by the raw provider name, while the SDK's canonical key is its camelCase alias. This derives the key via the #2463 toCamelCase helper for all openai-compatible identities and fixes the three direct dashed emissions (volcengine-ark, cloudflare-workers-ai, the github-copilot chat lane). The open-responses path is unchanged — that SDK resolves only the raw name.

Fixes #1430

Verification

  • packages/runtime suite: 2977 tests pass; with the fix reverted, 8 fail (the updated namespace pins plus a new doGenerate capture test asserting reasoning_effort reaches the request body with zero deprecated warnings)
  • Root typecheck, lint, and format:check pass
  • Unrelated: node-pty-write-lifecycle times out on my machine (spawnSync ETIMEDOUT) — reproduced identically on unmodified main

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Claude Code (Fable 5) — implementation and tests, under my direction and review. The commit carries a Generated-by trailer.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

🤖 Generated with Claude Code

The AI SDK resolves openai-compatible providerOptions under the
camelCase alias of the provider name and flags raw dashed keys as
deprecated on every doGenerate. Derive the key via toCamelCase for all
openai-compatible identities (extends apache#2463, which only covered custom
relay slugs) and fix the three direct dashed emissions. The
open-responses path is unchanged: that SDK resolves only the raw name.

Closes apache#1430

Generated-by: Claude Code (Fable 5)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Astro-Han
Astro-Han previously approved these changes Aug 20, 2026

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. The change is correct, and it is correct for a reason worth stating: it draws the raw-versus-camelCase line exactly where the two SDKs actually differ, rather than applying one rule everywhere.

I verified the substance rather than taking the premise on trust:

  • The toCamelCase added here is semantically identical to the SDK's own (@ai-sdk/openai-compatible@3.0.30, dist/index.js:19-21) — same /[_-]([a-z])/g regex, same replacement. So the emitted key always matches the alias the SDK resolves, including the edge cases where they both decline to transform, such as a relay slug like relay-1 where the character after the dash is not a lowercase letter.
  • Both option paths resolve either spelling, so nothing is dropped. Schema options are parsed three times and merged — under "openaiCompatible", the raw name and the camelCase alias (dist/index.js:505-519). Passthrough fields are spread from both keys and then filtered against the chat-options shape (dist/index.js:569-577). That second one is what makes volcengine-ark's thinking and cloudflare-workers-ai's chat_template_kwargs safe to rekey, and it is the less obvious of the two.
  • The deprecation warning fires precisely when the raw key is present and differs from its alias (warnIfDeprecatedProviderOptionsKey, dist/index.js:29-40), so removing the dashed key removes the warning at its cause rather than suppressing it.
  • Leaving model-factory.ts:543 on the raw name is right, not an oversight. @ai-sdk/open-responses@2.0.28 sets providerOptionsName: providerName verbatim (dist/index.js:936) and never camelCases, so the Responses lane must stay raw. The comment already says so; I confirmed it against the pinned package.
  • The three providers whose namespaces change are all constructed through createOpenAICompatiblegithub-copilot explicitly at model-factory.ts:116-117, and volcengine-ark, zai-coding-plan and the rest via the generic path at :189 with name: openAiCompatibleProviderName(...), since their registry adapters are { kind: 'openai-compatible', name: 'provider' }. So every rekeyed identity is one the SDK aliases.

The new capture test is the right kind: it asserts reasoning_effort in the actual request body and that no deprecated warning comes back, which is the defect this PR closes rather than a proxy for it.

Two P3s below — a docstring note and a test gap. Neither blocks; both are about making the coupling to the SDK explicit rather than incidental.

One coordination note, not a finding. packages/runtime/src/model-factory.ts is contested right now: #3255 and #3300 both touch buildFamilyWire's openai-compatible case, and #3255 introduces a third provider-key resolver in model-runtime.ts that must stay raw for the Responses lane. Whichever of these lands last should re-check that the raw and camelCase resolvers are still distinguished on purpose — the refactor here makes openAiCompatibleProviderName the single raw source, which is the right base for that reconciliation.

AI disclosure: reviewed with Claude Code. I read the pinned @ai-sdk/openai-compatible@3.0.30 and @ai-sdk/open-responses@2.0.28 sources myself to confirm the alias resolution, the passthrough spread and the deprecation trigger, checked each rewritten provider's registry adapter, and grepped every providerMetadata reader in the runtime packages. The approval is mine and rests on those checks.

Comment thread packages/runtime/src/model-factory.ts
Comment thread packages/runtime/src/__tests__/model-factory-thinking.test.ts
Address review: note in the providerOptions-key docstring that the
camelCase alias also selects the SDK's response metadata namespace,
assert the capture test's providerMetadata comes back under the
camelCase key, and add a wire-level capture for volcengine-ark's
passthrough thinking object - the lane the existing reasoningEffort
captures do not exercise.

Generated-by: Claude Code (Fable 5)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@likun666661 likun666661 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the current head. The issue is correctly scoped to the deprecated OpenAI-compatible provider-options namespace; the Chat camelCase alias and Responses raw-name paths remain intentionally distinct. Wire-level coverage preserves both schema and passthrough fields, and the providerMetadata namespace change has no current raw-provider consumer. Approved.

@likun666661
likun666661 merged commit 77066f4 into apache:main Aug 20, 2026
1 check passed
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.

fix(runtime): use camelCase OpenAI-compatible provider option keys

3 participants