feat: add per-tier fallback field to model config schema

Each model tier (fast, default, complex, local) can now specify an
optional fallback provider config that the router will try before
falling through to the global fallback chain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
William Valentin
2026-02-07 12:08:17 -08:00
parent 42696566f6
commit c8c3c74fde
2 changed files with 56 additions and 1 deletions
+51
View File
@@ -89,6 +89,57 @@ describe('configSchema — routing', () => {
});
});
describe('configSchema — per-tier fallback', () => {
const minimalConfig = {
telegram: { bot_token: 'test', allowed_chat_ids: [1] },
models: { default: { provider: 'anthropic', model: 'claude-3' } },
};
it('accepts per-tier fallback config', () => {
const result = configSchema.parse({
...minimalConfig,
models: {
default: {
provider: 'anthropic',
model: 'claude-sonnet-4-5-20250929',
fallback: { provider: 'github', model: 'claude-sonnet-4-5-20250929' },
},
fast: {
provider: 'anthropic',
model: 'claude-haiku-4-5-20251001',
fallback: { provider: 'github', model: 'claude-haiku-4-5-20251001' },
},
},
});
expect(result.models.default.fallback?.provider).toBe('github');
expect(result.models.fast?.fallback?.provider).toBe('github');
});
it('works without fallback field (backward compat)', () => {
const result = configSchema.parse(minimalConfig);
expect(result.models.default.fallback).toBeUndefined();
});
it('fallback does not itself accept a nested fallback', () => {
const result = configSchema.parse({
...minimalConfig,
models: {
default: {
provider: 'anthropic',
model: 'claude-3',
fallback: {
provider: 'github',
model: 'claude-3',
fallback: { provider: 'ollama', model: 'llama' },
},
},
},
});
// Zod strips unknown keys from the base schema, so nested fallback is dropped
expect((result.models.default.fallback as Record<string, unknown>)?.fallback).toBeUndefined();
});
});
describe('configSchema automation', () => {
const baseConfig = {
telegram: { bot_token: 'test-token', allowed_chat_ids: [123] },