Repository navigation
feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) - #8363
Merged
diegosouzapw merged 1 commit intoJul 25, 2026
Conversation
…atible discovery (#8347)
10 tasks
HouMinXi
pushed a commit
to HouMinXi/OmniRoute
that referenced
this pull request
Aug 2, 2026
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
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.
What
Generic OpenAI-compatible / custom-node discovery had no metadata-mapping layer for
CLIProxyAPI-style reasoning-level metadata (nothing was ever captured — not "lost").
Owner-scoped this to two layers (not the report's original five):
src/lib/providerModels/modelDiscovery.ts):detectSupportedThinkingEffortsnow also parses
supported_reasoning_levels(entries as{effort}objects or plainstrings) and
thinking.levels, alongside the existingreasoning.supported_effortshandling (feat(providers): capture upstream reasoning.supported_efforts at sync so synced openai-compatible models become selectable with effort levels #7694). A shared
parseEffortListhelper normalizes/dedupes/canonicalizes(
max→xhigh, unknown native tiers likeultrapass through), and drops malformedentries per-record via Zod
safeParse— never throws, never fails a whole sync(Hard Rule chore(env): sync .env.example with current .env structure #7). Precedence is preserved and tested: flat
supportedThinkingEfforts(verbatim) >
reasoning.supported_efforts>supported_reasoning_levels>thinking.levels.src/app/api/providers/[id]/models/discoveryClientVersion.ts,wired into
route.ts): a default-OFF, per-connection opt-in(
providerSpecificData.discoveryClientVersionEnabled+discoveryClientVersion) appendsclient_versionto the model-list URL only.Unrelated generic OpenAI-compatible upstreams see byte-identical requests unless they
explicitly opt in; the param never touches any inference URL.
Out of scope per the owner's narrowing (documented follow-ups, not this PR):
persistence-schema, catalog-exposure, combo work (
appendSyncedEffortVariants/mergeComboCapabilitiesalready consumesupportedThinkingEffortsgenerically), and thetoken-budget range fields (
thinking.min/max/zero_allowed/dynamic_allowed).How tested
TDD (Hard Rule #18):
tests/unit/model-discovery-reasoning-levels.test.tswritten first,confirmed failing (missing
discoveryClientVersionmodule), then made to pass — 13/13green:
{effort}object entries, plain-string entries,thinking.levelsmax→xhighcanonicalization + unknown native tier retainedundefined, no throwclient_versionabsent by default / present only when opted in / never when disabledAlso re-ran the pre-existing #7694/#8072 suites
(
sync-reasoning-supported-efforts-7694.test.ts,combo-builder-effort-variants-8072.test.ts) — 24/24 still green, confirming noprecedence regression.
Gates run in-branch:
node --import tsx/esm --test tests/unit/model-discovery-reasoning-levels.test.ts— greennpm run typecheck:core— cleannpm run typecheck:noimplicit:core— pre-existing errors only, none in touched filesnpx eslinton touched files — cleannpm run check:cycles— cleannode scripts/check/check-test-discovery.mjs/check-file-size.mjs— OKcheck:complexity-ratchets— unchanged base-red (2167/956, matches documented baseline drift, not introduced by this PR)client_versiononly reaches the model-listuniqueEndpointsarray, never any inference/executor pathCloses #8347