feat(cliproxy): add model-specific reasoning effort caps

Add maxLevel field to ThinkingSupport interface to cap reasoning
effort at model's maximum supported level. This fixes Issue #344
where gpt-5-mini fails with xhigh reasoning (only supports high).

- Add Codex provider to model catalog with gpt-5.2-codex and gpt-5-mini
- Add capLevelAtMax() and capEffortAtModelMax() for runtime capping
- Update UI presets with new Codex models and tier mappings
This commit is contained in:
kaitranntt
2026-01-21 14:27:46 -05:00
parent 2f584802bd
commit eec44d54e2
4 changed files with 152 additions and 19 deletions
+26 -1
View File
@@ -1,6 +1,7 @@
import * as http from 'http';
import * as https from 'https';
import { URL } from 'url';
import { getModelMaxLevel } from './model-catalog';
export type CodexReasoningEffort = 'medium' | 'high' | 'xhigh';
@@ -51,10 +52,32 @@ const EFFORT_RANK: Record<CodexReasoningEffort, number> = {
xhigh: 3,
};
/** All valid codex effort levels in rank order */
const EFFORT_BY_RANK: CodexReasoningEffort[] = ['medium', 'high', 'xhigh'];
function minEffort(a: CodexReasoningEffort, b: CodexReasoningEffort): CodexReasoningEffort {
return EFFORT_RANK[a] <= EFFORT_RANK[b] ? a : b;
}
/**
* Cap effort at model's max level from catalog.
* Returns the capped effort (or original if no cap applies).
*/
function capEffortAtModelMax(model: string, effort: CodexReasoningEffort): CodexReasoningEffort {
const maxLevel = getModelMaxLevel('codex', model);
if (!maxLevel) return effort;
// Map maxLevel to CodexReasoningEffort (only medium/high/xhigh are valid)
const maxEffort = EFFORT_BY_RANK.find((e) => e === maxLevel);
if (!maxEffort) return effort;
// Cap if effort exceeds max
if (EFFORT_RANK[effort] > EFFORT_RANK[maxEffort]) {
return maxEffort;
}
return effort;
}
export function buildCodexModelEffortMap(
models: CodexReasoningModelMap,
defaultEffort: CodexReasoningEffort = 'medium'
@@ -85,7 +108,9 @@ export function getEffortForModel(
defaultEffort: CodexReasoningEffort
): CodexReasoningEffort {
if (!model) return defaultEffort;
return modelEffort.get(model) ?? defaultEffort;
const effort = modelEffort.get(model) ?? defaultEffort;
// Apply model-specific cap from catalog
return capEffortAtModelMax(model, effort);
}
export function injectReasoningEffortIntoBody(