fix(js/plugins/compat-oai): keep provider baseURL on request-scoped clients; expose DeepSeek reasoning config - #6056
Open
AnasMK9 wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
Code Review
This pull request adds support for reasoningEffort and thinking configurations in the DeepSeek plugin, and ensures that request-scoped clients with per-call API keys retain their provider-specific base URLs (DeepSeek and xAI) instead of falling back to OpenAI. A new test suite has been added to verify this behavior. Feedback highlights a potential TypeScript compilation error when assigning reasoning_effort directly to params and suggests casting params to any to support DeepSeek's custom enum values.
AnasMK9
force-pushed
the
fix/compat-oai-request-scoped-baseurl
branch
from
August 14, 2026 03:02
d854d5a to
9a9fadf
Compare
…lients; expose DeepSeek reasoning config Request-scoped clients (created when a call supplies config.apiKey) are rebuilt from pluginOptions, which the DeepSeek and xAI plugins passed without baseURL — so those requests, carrying the caller's provider API key, were sent to the OpenAI SDK default, api.openai.com. Fix the two plugins to derive plugin arguments and pluginOptions from one object that always carries the provider baseURL, and harden maybeCreateRequestScopedOpenAIClient so a request-scoped client can never point at a different host than the default client it derives from. Also add reasoningEffort and thinking to the DeepSeek config schema and request builder (the response side already surfaces reasoning_content). Enum values verified against the DeepSeek API's request validation: reasoning_effort is a top-level field accepting none|minimal|low|medium|high|xhigh|max; thinking.type accepts adaptive|enabled|disabled. The extra fields are typed via a schema-inferred interface and applied with a satisfies-checked Object.assign — no any casts. Tested: new regression tests drive the real plugins with a recording fetch (without the fix the request URL is api.openai.com), plus unit tests on the client rebuild; validated live against the DeepSeek and OpenAI APIs.
AnasMK9
force-pushed
the
fix/compat-oai-request-scoped-baseurl
branch
from
August 14, 2026 03:05
9a9fadf to
df9053d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug 1: per-call
config.apiKeysends DeepSeek/xAI requests (and the key) to api.openai.comRequest-scoped clients — created when a call supplies
config.apiKey— are rebuilt from thepluginOptionsobject, whichdeepSeekPluginandxAIPlugin(identical code pattern) passed withoutbaseURL:The rebuilt client therefore fell back to the OpenAI SDK default, so the request — carrying the caller's DeepSeek/xAI API key — was sent to
https://api.openai.com. Besides failing, this leaks the provider key to a third party.Fix, two layers:
openAICompatiblearguments andpluginOptionsfrom one object that always carries the providerbaseURL, so the two can't drift.DEEPSEEK_BASE_URL/XAI_BASE_URLare exported and used by the regression test.maybeCreateRequestScopedOpenAIClientis hardened to inherit the default client'sbaseURLwhenpluginOptionsomit it — a request-scoped client can never silently point at a different host than the client it derives from, closing this bug class for future plugins too.Tests:
request_scoped_client_test.tsdrives the real plugins with a recordingfetch(without the fix:https://api.openai.com/v1/chat/completions; with it: the provider host), andutils_test.tscovers the client-rebuild guard directly. Also verified live against the real DeepSeek API: plugin constructed with a bogus key, real key onconfig.apiKey, request succeeds againstapi.deepseek.com.Bug 2: DeepSeek config schema has no reasoning controls
The response side already surfaces
reasoning_content, butDeepSeekChatCompletionConfigSchemaexposed no way to control it. This addsreasoningEffortandthinkingto the schema and request builder, with.describe()docs surfaced in the Dev UI.DeepSeek's own docs contradict each other on where
reasoning_effortlives (API reference says nested underthinking, reasoning guide says top-level), so the enums were verified against the API's request validation, empirically:reasoning_effort(top-level):none | minimal | low | medium | high | xhigh | max— nested insidethinkingit is silently ignoredthinking.type:adaptive | enabled | disabledThe extra fields are typed via a schema-inferred interface and applied with a
satisfies-checkedObject.assign— noanycasts (per review feedback). Validated live:reasoningEffortscales reasoning token usage;thinking: { type: 'disabled' }yields no reasoning content.Checklist
.describe()documentation (Dev UI); the genkit.dev DeepSeek integration page lives outside this repo and can be updated once this merges