Files
OmniRoute/tests/unit/codex-capacity-limit-merge.test.ts
Xiangzhe e5b240479c fix(codex): preserve GPT-5.6 reasoning contract (#7012)
* fix(codex): preserve GPT-5.6 reasoning contract

* fix(vscode): expose Responses text models

* fix(codex): keep GPT-5.6 limits through discovery

* fix(ci): extract isUsableChatModel helpers to satisfy complexity ratchet

Splitting the supported_endpoints/output_modalities guard clauses into
excludesChatAndResponsesEndpoints() / excludesTextOutputModality() drops
isUsableChatModel's cyclomatic complexity from 16 to under the ratchet's
max of 15 (complexity-ratchets gate: 2057 -> 2056, back at baseline).
Behavior is unchanged; existing vscode/codex route tests cover it.

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>

* fix(codex): merge capacity limits conservatively (smaller of live vs pinned wins)

Resolve the #7012 catalog-merge policy collision: instead of the pinned
GPT-5.6 contract always winning for a fixed set of model ids, capacity
limits (inputTokenLimit/outputTokenLimit) now merge via
mergeCapacityLimitConservatively — Math.min(pinned, live) when both are
present, so OmniRoute never promises more context than the account can
actually serve. All other overlapping fields still take the live value
unconditionally.

Guard tests cover both directions (pinned smaller wins / pinned larger
loses) at the route level and via an isolated helper-level unit test.

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>

---------

Co-authored-by: Xiangzhe <xz-dev@users.noreply.github.com>
Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
2026-07-18 21:17:49 -03:00

76 lines
2.9 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
// Isolated unit coverage for the capacity-limit merge policy, independent of
// the /api/providers/[id]/models route. See
// src/app/api/providers/[id]/models/discovery/codex.ts::mergeCapacityLimitConservatively
// and the guard test in tests/unit/provider-models-route-codex.test.ts (#7012).
const codexDiscovery = await import(
"../../src/app/api/providers/[id]/models/discovery/codex.ts"
);
function liveModel(overrides: Record<string, unknown>) {
return {
id: "gpt-5.6-sol",
name: "GPT 5.6 Sol Live",
owned_by: "codex" as const,
apiFormat: "responses" as const,
supportedEndpoints: ["responses"] as ["responses"],
...overrides,
};
}
test("mergeCodexLiveModelsWithLocalCatalog: pinned (local) limit wins when it is SMALLER than live", () => {
const merged = codexDiscovery.mergeCodexLiveModelsWithLocalCatalog(
[liveModel({ inputTokenLimit: 999999, outputTokenLimit: 999999 })],
[
{
id: "gpt-5.6-sol",
name: "GPT 5.6 Sol",
maxInputTokens: 372000,
maxOutputTokens: 128000,
},
]
);
const model = merged.find((m) => m.id === "gpt-5.6-sol");
// Pinned (372000/128000) is smaller than live (999999/999999) — the smaller,
// safer value must win so requests never overrun the account's real budget.
assert.equal(model?.inputTokenLimit, 372000);
assert.equal(model?.outputTokenLimit, 128000);
// Non-capacity fields are unaffected — live still wins on those.
assert.equal(model?.name, "GPT 5.6 Sol Live");
});
test("mergeCodexLiveModelsWithLocalCatalog: live limit wins when the pinned (local) value is LARGER", () => {
const merged = codexDiscovery.mergeCodexLiveModelsWithLocalCatalog(
[liveModel({ inputTokenLimit: 100000, outputTokenLimit: 50000 })],
[
{
id: "gpt-5.6-sol",
name: "GPT 5.6 Sol",
maxInputTokens: 372000,
maxOutputTokens: 128000,
},
]
);
const model = merged.find((m) => m.id === "gpt-5.6-sol");
// Live (100000/50000) is smaller than pinned (372000/128000) here — the
// smaller live value must win, not the larger pinned contract.
assert.equal(model?.inputTokenLimit, 100000);
assert.equal(model?.outputTokenLimit, 50000);
});
test("mergeCodexLiveModelsWithLocalCatalog: uses whichever side has a value when only one side defines it", () => {
const liveOnly = codexDiscovery.mergeCodexLiveModelsWithLocalCatalog(
[liveModel({ inputTokenLimit: 200000 })],
[{ id: "gpt-5.6-sol", name: "GPT 5.6 Sol" }]
);
assert.equal(liveOnly.find((m) => m.id === "gpt-5.6-sol")?.inputTokenLimit, 200000);
const pinnedOnly = codexDiscovery.mergeCodexLiveModelsWithLocalCatalog(
[liveModel({ inputTokenLimit: undefined })],
[{ id: "gpt-5.6-sol", name: "GPT 5.6 Sol", maxInputTokens: 372000 }]
);
assert.equal(pinnedOnly.find((m) => m.id === "gpt-5.6-sol")?.inputTokenLimit, 372000);
});