feat(models): add streaming and tier switching to ModelRouter
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { ModelRouter } from './router.js';
|
||||
import type { ModelClient, ChatResponse } from './types.js';
|
||||
import type { ModelClient, ChatResponse, ChatStreamEvent } from './types.js';
|
||||
|
||||
describe('ModelRouter', () => {
|
||||
const createMockClient = (name: string, shouldFail = false): ModelClient => ({
|
||||
@@ -78,3 +78,66 @@ describe('ModelRouter', () => {
|
||||
expect(defaultClient.chat).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ModelRouter streaming', () => {
|
||||
it('streams from primary client', async () => {
|
||||
const mockStream = async function* (): AsyncIterable<ChatStreamEvent> {
|
||||
yield { type: 'content', content: 'Hello' };
|
||||
yield { type: 'done', usage: { inputTokens: 5, outputTokens: 3 } };
|
||||
};
|
||||
|
||||
const mockClient = {
|
||||
chat: vi.fn(),
|
||||
chatStream: vi.fn().mockReturnValue(mockStream()),
|
||||
};
|
||||
|
||||
const router = new ModelRouter({
|
||||
default: mockClient,
|
||||
fallbackChain: [],
|
||||
});
|
||||
|
||||
const chunks: string[] = [];
|
||||
for await (const event of router.chatStream({ messages: [] })) {
|
||||
if (event.type === 'content' && event.content) {
|
||||
chunks.push(event.content);
|
||||
}
|
||||
}
|
||||
|
||||
expect(chunks).toEqual(['Hello']);
|
||||
});
|
||||
|
||||
it('falls back when primary stream fails', async () => {
|
||||
const failingStream = async function* (): AsyncIterable<ChatStreamEvent> {
|
||||
yield { type: 'error', error: new Error('Primary failed') };
|
||||
};
|
||||
|
||||
const fallbackStream = async function* (): AsyncIterable<ChatStreamEvent> {
|
||||
yield { type: 'content', content: 'Fallback' };
|
||||
yield { type: 'done', usage: { inputTokens: 5, outputTokens: 3 } };
|
||||
};
|
||||
|
||||
const primaryClient = {
|
||||
chat: vi.fn(),
|
||||
chatStream: vi.fn().mockReturnValue(failingStream()),
|
||||
};
|
||||
|
||||
const fallbackClient = {
|
||||
chat: vi.fn(),
|
||||
chatStream: vi.fn().mockReturnValue(fallbackStream()),
|
||||
};
|
||||
|
||||
const router = new ModelRouter({
|
||||
default: primaryClient,
|
||||
fallbackChain: [fallbackClient],
|
||||
});
|
||||
|
||||
const chunks: string[] = [];
|
||||
for await (const event of router.chatStream({ messages: [] })) {
|
||||
if (event.type === 'content' && event.content) {
|
||||
chunks.push(event.content);
|
||||
}
|
||||
}
|
||||
|
||||
expect(chunks).toEqual(['Fallback']);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user