fix(discovery): parse reasoning tiers nested under metadata.reasoning.supported_efforts (#10138)

neuralwatt's /v1/models wraps capabilities and reasoning under a metadata
object (metadata.reasoning.supported_efforts + metadata.capabilities
.reasoning_effort), one level deeper than the shapes detectSupported
ThinkingEfforts recognized. Synced openai-compatible rows therefore carried
no supportedThinkingEfforts and no effort aliases were advertised.

Recognize the metadata-nested shape with the same schema and validation as
the top-level #7694 reasoning.supported_efforts, placed right after it in
precedence so a top-level declaration still wins when both are present.
Covered by three regression tests (parse, precedence, malformed-degradation).
This commit is contained in:
Jonathan Bailey
2026-08-13 03:53:07 -07:00
committed by GitHub
parent 06f41cda63
commit f5629d2166
3 changed files with 59 additions and 0 deletions

View File

@@ -153,6 +153,27 @@ export function detectSupportedThinkingEfforts(record: JsonRecord): string[] | u
}
}
// neuralwatt-style upstreams wrap the same tier data one level deeper under
// `metadata.reasoning.supported_efforts` (their /v1/models nests capabilities
// and reasoning under a `metadata` object). Same semantics and validation as
// the top-level #7694 shape; placed right after it so a top-level declaration
// still wins when both are present.
const metadataRecord = asRecord(record.metadata);
const metadataParsed = reasoningSupportedEffortsSchema.safeParse(metadataRecord.reasoning);
if (metadataParsed.success && metadataParsed.data) {
const rawEfforts = metadataParsed.data.supported_efforts;
if (Array.isArray(rawEfforts)) {
const efforts = Array.from(
new Set(
rawEfforts
.filter((effort): effort is string => typeof effort === "string" && effort.length > 0)
.map(normalizeSupportedEffort)
)
);
if (efforts.length > 0) return efforts;
}
}
// #9160: fall back to `capabilities.effort_tiers` before the legacy fields.
// OmniRoute's own catalog surfaces effort tiers inside `capabilities.effort_tiers`,
// which the existing `parseEffortList` already handles (string arrays).