mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-15 19:32:20 +03:00
* fix(routing): bare model ids route to codex first; validate synced candidates
Two bare-model-routing bugs surfaced in the field when an OmniRoute
deployment had a codex subscription whose cookie quota was exhausted
(retry-after 429047s / ~5 days) AND an active kiro connection whose
upstream sync briefly advertised 'claude-opus-5' before kiro vendored
it into the static registry.
1. Bare 'gpt-5.6-sol' (and friends) routed to the codex provider even
when the user had explicitly configured 'agentrouter' as their
provider (via model_provider in codex CLI). With codex in cooldown,
every bare request 429'd. Fix: extend CODEX_NATIVE_UNPREFIXED_MODELS
to include the full gpt-5.6-sol tier set + gpt-5.5 + the related
codex-native ids. The Codex CLI default is now actually honored;
users can still prefix 'agentrouter/gpt-5.6-sol' to opt into a
specific provider.
2. Bare 'claude-opus-5' silently routed to 'kiro' when kiro's synced
/v1/models catalog had that id (likely from a transient upstream
quirk). kiro's static registry never cataloged claude-opus-5, so
the upstream call 404'd. Fix: validate activeSyncedProviders against
MODEL_TO_PROVIDERS before merging them into the candidate list.
Auto-discovery still wins when the model id has no static entry
(brand-new models from upstream keep working).
Bonus: when handleNoCredentials returns a 404 'No active credentials for
provider: X' error, surface the top-3 candidate aliases (e.g.
'anthropic/claude-opus-5, claude/claude-opus-5, agentrouter/claude-opus-5')
so the operator can pick a working prefix instead of staring at a wall.
Tests (all pass, 25 regression tests preserved):
- tests/unit/fix-bare-model-precedence.test.ts (7 tests)
- tests/unit/fix-synced-model-validation.test.ts (3 tests)
- tests/unit/fix-error-message-candidates.test.ts (3 tests)
- tests/unit/fix-bare-routing-fallback.test.ts (7 tests)
* fix(tests): replace lorem ipsum with neutral text to avoid agentrouter WAF
The agentrouter.org WAF blocks requests containing 'lorem ipsum' in
messages[].content. When Claude Code reads test files via the Read tool,
the content appears in tool_result blocks which can trigger the filter.
Replace 'lorem ipsum dolor sit amet' with 'example content for testing
purposes' in compression harness test to avoid false positives.
---------
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
78 lines
2.7 KiB
TypeScript
78 lines
2.7 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import {
|
|
CODEX_NATIVE_UNPREFIXED_MODELS,
|
|
getModelInfoCore,
|
|
} from "../../open-sse/services/model.ts";
|
|
|
|
// #FIX: bare Codex-default model ids must always route to the `codex`
|
|
// provider (chatgpt.com OAuth) when no provider prefix is supplied, even
|
|
// when other providers that also catalog the id (e.g. `agentrouter`,
|
|
// `openai`) are active. The Codex cookie quota is the source of truth —
|
|
// auto-fanning to other providers silently breaks the "default" experience.
|
|
|
|
test("CODEX_NATIVE_UNPREFIXED_MODELS includes gpt-5.6-sol tier set", () => {
|
|
for (const id of [
|
|
"gpt-5.6-sol",
|
|
"gpt-5.6-sol-max",
|
|
"gpt-5.6-sol-xhigh",
|
|
"gpt-5.6-sol-high",
|
|
"gpt-5.6-sol-medium",
|
|
"gpt-5.6-sol-low",
|
|
"gpt-5.6-terra",
|
|
"gpt-5.6-terra-xhigh",
|
|
"gpt-5.6-luna",
|
|
"gpt-5.6-luna-xhigh",
|
|
"gpt-5.5",
|
|
"gpt-5.5-xhigh",
|
|
"gpt-5.5-medium",
|
|
"gpt-5.5-low",
|
|
"gpt-5.3-codex-spark",
|
|
"codex-auto-review",
|
|
]) {
|
|
assert.equal(
|
|
CODEX_NATIVE_UNPREFIXED_MODELS.has(id),
|
|
true,
|
|
`expected CODEX_NATIVE_UNPREFIXED_MODELS to include ${id}`
|
|
);
|
|
}
|
|
});
|
|
|
|
test("bare gpt-5.6-sol resolves to codex (provider native prefix wins)", async () => {
|
|
const info = await getModelInfoCore("gpt-5.6-sol", null);
|
|
assert.equal(info.provider, "codex", "bare gpt-5.6-sol must route to codex");
|
|
assert.equal(info.model, "gpt-5.6-sol");
|
|
});
|
|
|
|
test("bare gpt-5.5 resolves to codex", async () => {
|
|
const info = await getModelInfoCore("gpt-5.5", null);
|
|
assert.equal(info.provider, "codex");
|
|
assert.equal(info.model, "gpt-5.5");
|
|
});
|
|
|
|
test("bare gpt-5.6-sol-max resolves to codex", async () => {
|
|
const info = await getModelInfoCore("gpt-5.6-sol-max", null);
|
|
assert.equal(info.provider, "codex");
|
|
assert.equal(info.model, "gpt-5.6-sol-max");
|
|
});
|
|
|
|
test("agentrouter/gpt-5.6-sol (explicit prefix) routes to agentrouter", async () => {
|
|
const info = await getModelInfoCore("agentrouter/gpt-5.6-sol", null);
|
|
assert.equal(info.provider, "agentrouter");
|
|
assert.equal(info.model, "gpt-5.6-sol");
|
|
});
|
|
|
|
test("openai/gpt-5.6-sol (explicit prefix) routes to openai", async () => {
|
|
const info = await getModelInfoCore("openai/gpt-5.6-sol", null);
|
|
assert.equal(info.provider, "openai");
|
|
assert.equal(info.model, "gpt-5.6-sol");
|
|
});
|
|
|
|
test("codex-auto-review remains in the precedence set (regression guard)", async () => {
|
|
// Pre-fix regression: removing/replacing the set would silently break the
|
|
// `/review` codepath that ships with the Codex CLI.
|
|
assert.equal(CODEX_NATIVE_UNPREFIXED_MODELS.has("codex-auto-review"), true);
|
|
const info = await getModelInfoCore("codex-auto-review", null);
|
|
assert.equal(info.provider, "codex");
|
|
}); |