fix(router): align fallback semantics and oauth provider behavior
This commit is contained in:
@@ -47,6 +47,57 @@ describe('ModelRouter', () => {
|
||||
expect(fallbackClient.chat).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('skips duplicate fallback clients that already failed as primary', async () => {
|
||||
const failingPrimary = createMockClient('primary', true);
|
||||
const fallbackClient = createMockClient('fallback');
|
||||
|
||||
const router = new ModelRouter({
|
||||
default: failingPrimary,
|
||||
fallbackChain: [failingPrimary, fallbackClient],
|
||||
});
|
||||
|
||||
const response = await router.chat({ messages: [{ role: 'user', content: 'Hi' }] });
|
||||
|
||||
expect(response.content).toBe('Response from fallback');
|
||||
expect(failingPrimary.chat).toHaveBeenCalledTimes(1);
|
||||
expect(fallbackClient.chat).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('applies retry policy to fallback clients', async () => {
|
||||
const failingPrimary = createMockClient('primary', true);
|
||||
let attempts = 0;
|
||||
const flakyFallback: ModelClient = {
|
||||
chat: vi.fn().mockImplementation(async () => {
|
||||
attempts += 1;
|
||||
if (attempts === 1) {
|
||||
throw new Error('transient');
|
||||
}
|
||||
return {
|
||||
content: 'Recovered fallback',
|
||||
stopReason: 'end_turn',
|
||||
usage: { inputTokens: 1, outputTokens: 1 },
|
||||
} satisfies ChatResponse;
|
||||
}),
|
||||
};
|
||||
|
||||
const router = new ModelRouter({
|
||||
default: failingPrimary,
|
||||
fallbackChain: [flakyFallback],
|
||||
retryConfig: {
|
||||
maxRetries: 1,
|
||||
initialDelayMs: 1,
|
||||
backoffMultiplier: 1,
|
||||
maxDelayMs: 1,
|
||||
nonRetryablePatterns: [],
|
||||
},
|
||||
});
|
||||
|
||||
const response = await router.chat({ messages: [{ role: 'user', content: 'retry fallback' }] });
|
||||
|
||||
expect(response.content).toBe('Recovered fallback');
|
||||
expect(flakyFallback.chat).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('throws when all providers fail', async () => {
|
||||
const failing1 = createMockClient('primary', true);
|
||||
const failing2 = createMockClient('fallback', true);
|
||||
|
||||
Reference in New Issue
Block a user