fix: address gemini native and route coverage regressions
This commit is contained in:
@@ -154,4 +154,31 @@ describe('TokenRouter patterns and model mapping', () => {
|
||||
expect(decision.actualModel).toBe('claude-opus-4-5');
|
||||
expect(exposedModels).toContain('claude-opus-4-6');
|
||||
});
|
||||
|
||||
it('prefers an exact route over a colliding group display-name alias', async () => {
|
||||
await createRouteWithSingleChannel(
|
||||
're:^claude-(opus|sonnet)-4-5$',
|
||||
undefined,
|
||||
{
|
||||
displayName: 'claude-opus-4-6',
|
||||
sourceModel: 'claude-opus-4-5',
|
||||
},
|
||||
);
|
||||
const exact = await createRouteWithSingleChannel(
|
||||
'claude-opus-4-6',
|
||||
undefined,
|
||||
{
|
||||
sourceModel: 'claude-opus-4-6',
|
||||
},
|
||||
);
|
||||
const router = new TokenRouter();
|
||||
|
||||
const selected = await router.selectChannel('claude-opus-4-6');
|
||||
const decision = await router.explainSelection('claude-opus-4-6');
|
||||
|
||||
expect(selected).toBeTruthy();
|
||||
expect(selected?.channel.id).toBe(exact.channel.id);
|
||||
expect(selected?.actualModel).toBe('claude-opus-4-6');
|
||||
expect(decision.actualModel).toBe('claude-opus-4-6');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -257,9 +257,9 @@ export function parseRegexModelPattern(pattern: string): RegExp | null {
|
||||
}
|
||||
}
|
||||
|
||||
export function matchesModelPattern(model: string, pattern: string): boolean {
|
||||
const normalizedPattern = (pattern || '').trim();
|
||||
if (!normalizedPattern) return false;
|
||||
export function matchesModelPattern(model: string, pattern: string): boolean {
|
||||
const normalizedPattern = (pattern || '').trim();
|
||||
if (!normalizedPattern) return false;
|
||||
|
||||
if (normalizedPattern === model) return true;
|
||||
|
||||
@@ -268,8 +268,15 @@ export function matchesModelPattern(model: string, pattern: string): boolean {
|
||||
return !!re && re.test(model);
|
||||
}
|
||||
|
||||
return minimatch(model, normalizedPattern);
|
||||
}
|
||||
return minimatch(model, normalizedPattern);
|
||||
}
|
||||
|
||||
function isExactRouteModelPattern(pattern: string): boolean {
|
||||
const normalizedPattern = (pattern || '').trim();
|
||||
if (!normalizedPattern) return false;
|
||||
if (isRegexModelPattern(normalizedPattern)) return false;
|
||||
return !/[\*\?\[]/.test(normalizedPattern);
|
||||
}
|
||||
|
||||
function normalizeRouteDisplayName(displayName: string | null | undefined): string {
|
||||
return (displayName || '').trim();
|
||||
@@ -993,12 +1000,14 @@ export class TokenRouter {
|
||||
routes = routes.filter((route) => allowSet.has(route.id));
|
||||
}
|
||||
|
||||
// Find matching route by model pattern or display alias.
|
||||
const matchedRoute = routes.find((r) => {
|
||||
return matchesRouteRequestModel(model, r);
|
||||
});
|
||||
|
||||
if (!matchedRoute) return null;
|
||||
const matchedRoute = routes.find((route) => (
|
||||
isExactRouteModelPattern(route.modelPattern)
|
||||
&& (route.modelPattern || '').trim() === model
|
||||
))
|
||||
|| routes.find((route) => isRouteDisplayNameMatch(model, route.displayName))
|
||||
|| routes.find((route) => matchesModelPattern(model, route.modelPattern));
|
||||
|
||||
if (!matchedRoute) return null;
|
||||
|
||||
return await this.loadRouteMatch(matchedRoute);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user