Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/fixes/8866-auto-family-classification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **Auto routing**: `auto/<family>` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family
25 changes: 18 additions & 7 deletions src/sse/handlers/autoRouting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ import {
type AutoCategory,
type AutoTier,
} from "@omniroute/open-sse/services/autoCombo/suffixComposition.ts";
import {
isValidModelFamily,
type ModelFamily,
} from "@omniroute/open-sse/services/autoCombo/modelFamily.ts";
import { getCachedSettings } from "@/lib/localDb";
import * as log from "../utils/logger";

export type AutoRoutingState = {
model: string;
variant?: AutoVariant;
spec?: { category?: AutoCategory; tier?: AutoTier };
spec?: { category?: AutoCategory; tier?: AutoTier; family?: ModelFamily };
isAutoRouting: boolean;
recognizedBuiltInAuto: boolean;
response: Response | null;
Expand All @@ -37,12 +41,19 @@ function classifyAutoModel(
return { recognizedBuiltInAuto: true };
}
const parsedSuffix = parseAutoSuffix(suffix);
return parsedSuffix.valid
? {
recognizedBuiltInAuto: true,
spec: { category: parsedSuffix.category, tier: parsedSuffix.tier },
}
: { recognizedBuiltInAuto };
if (parsedSuffix.valid) {
return {
recognizedBuiltInAuto: true,
spec: { category: parsedSuffix.category, tier: parsedSuffix.tier },
};
}
if (isValidModelFamily(suffix)) {
return {
recognizedBuiltInAuto: true,
spec: { family: suffix as ModelFamily },
};
}
return { recognizedBuiltInAuto };
}

async function applyAutoPrefix(
Expand Down
50 changes: 50 additions & 0 deletions tests/unit/auto-family-classification-8866.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* #8866 — `auto/<family>` must be recognized as a built-in auto model.
*
* classifyAutoModel() is module-private, so this exercises it through the public
* resolveAutoRoutingState(). Before the fix, a family suffix failed parseAutoSuffix()
* and fell through to `recognizedBuiltInAuto: false` with no spec, so `auto/glm` was
* treated as an unknown model instead of a family-scoped auto combo.
*/
import test from "node:test";
import assert from "node:assert/strict";
import { MODEL_FAMILIES } from "@omniroute/open-sse/services/autoCombo/modelFamily.ts";
import { resolveAutoRoutingState } from "../../src/sse/handlers/autoRouting.ts";

test("#8866: every model family is recognized as auto/<family>", async () => {
assert.ok(MODEL_FAMILIES.length > 0, "expected a non-empty family list");
for (const family of MODEL_FAMILIES) {
const state = await resolveAutoRoutingState(`auto/${family}`);
assert.equal(
state.recognizedBuiltInAuto,
true,
`auto/${family} should be a recognized built-in auto model`
);
assert.equal(state.spec?.family, family, `auto/${family} should carry spec.family`);
assert.equal(state.isAutoRouting, true);
}
});

test("#8866: a family suffix does not hijack the category/tier spec", async () => {
// A valid category/tier suffix keeps its own shape — the family branch is only a
// fallback for suffixes parseAutoSuffix rejects.
const state = await resolveAutoRoutingState("auto/coding");
assert.equal(state.recognizedBuiltInAuto, true);
assert.equal(state.spec?.family, undefined, "auto/coding is a category, not a family");
});

test("#8866: an unknown suffix stays unrecognized", async () => {
const state = await resolveAutoRoutingState("auto/not-a-real-family-xyz");
assert.equal(
state.recognizedBuiltInAuto,
false,
"an unknown suffix must not be treated as a built-in auto model"
);
assert.equal(state.spec?.family, undefined);
});

test("#8866: a plain model is untouched by the family branch", async () => {
const state = await resolveAutoRoutingState("gpt-5.6-sol");
assert.equal(state.isAutoRouting, false);
assert.equal(state.spec?.family, undefined);
});