Skip to content

fix: merge provider routing options in chat and completion models - #628

Open
mattapperson wants to merge 3 commits into
mainfrom
claude/merge-provider-routing
Open

mattapperson wants to merge 3 commits into
mainfrom
claude/merge-provider-routing

Conversation

@mattapperson

@mattapperson mattapperson commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Fixes #587

The chat model built the request body as { ...this.getArgs(options), ...restOpenrouterOptions }, so a call-time providerOptions.openrouter.provider replaced the configured settings.provider / extraBody.provider outright. Configured keys such as allow_fallbacks and sort were dropped. The completion model had the same problem with extraBody.provider.

Changes:

  • Shared helper src/utils/merge-provider-routing.ts, mergeProviderRouting(configured, runtime):
    • shallow merges plain-object sources (prototype Object.prototype or null), later sources winning; nested arrays/objects (order, only, ignore, max_price) are replaced, not merged
    • ignores non-plain-object configured values (undefined, null, arrays, primitives, class instances)
    • an explicit runtime provider: null clears routing entirely (returns undefined), keeping the escape hatch that existed on main for chat/completion
    • returns undefined when nothing applies
  • Chat doGenerate / doStream: settings.provider < factory extraBody.provider < model extraBody.provider < providerOptions.openrouter.provider.
  • Completion doGenerate / doStream: factory extraBody.provider < model extraBody.provider < runtime. Completion settings have no provider field.
  • Chat, completion, image and embedding always assign provider to the helper result, so a non-object provider coming from extraBody (e.g. extraBody: { provider: null }) never leaks into the body. undefined is dropped by JSON serialization.
  • Image (fix(image): merge runtime provider options with configured routing preferences #551) and embedding (fix(embedding): forward providerOptions.openrouter in embed/embedMany #632) now use the shared helper; the local copy in src/embedding/index.ts is removed.
  • README gets a Provider Routing section documenting precedence, shallow-merge semantics, and how to drop configured keys (null clears everything).

Behavior changes (see changeset, minor):

  • Chat/completion: a runtime provider object now merges with configured routing instead of replacing it. Runtime null still clears routing.
  • Image/embedding: runtime provider: null previously was ignored (configured routing kept); it now clears routing, consistent with chat/completion. Image no longer forwards non-object extraBody.provider values.

Checklist

  • I have run pnpm stylecheck and pnpm typecheck
  • I have run pnpm test and all tests pass
  • I have added tests for my changes (if applicable)
  • I have updated documentation (if applicable)

Changeset

  • I have run pnpm changeset to create a changeset file

Devin Review

devin-ai-integration[bot]

This comment was marked as resolved.

Runtime providerOptions.openrouter.provider now shallow merges with
settings.provider and extraBody.provider instead of replacing them,
matching the image model (#551). Extracts a shared mergeProviderRouting
helper used by chat, completion and image models.

Fixes #587
…models

- mergeProviderRouting(configured, runtime): runtime null clears routing,
  plain-object check via prototype, nested values documented as replaced
- chat/completion/image always set provider to the merged result so
  non-object extraBody/settings provider values never leak
- embedding uses the shared helper instead of its local copy
- tests for null-clears and no-leak in chat, completion, embedding, image;
  drop 'as never' casts in favor of SharedV4ProviderOptions
- changeset and README document shallow-merge semantics and the image/
  embedding null behavior change
@mattapperson
mattapperson force-pushed the claude/merge-provider-routing branch from d492ff7 to 3452d33 Compare November 4, 2026 14:40
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.

Chat model replaces configured provider routing instead of merging (consistency with image model, #551)

2 participants