import { describe, it, expect, vi, beforeEach } from 'vitest'; import { getModelFactory, providers } from '../../../src/core/providers.js'; // Mock AI SDK providers vi.mock('@ai-sdk/anthropic', () => ({ createAnthropic: vi.fn(() => { const modelFn = (model: string) => ({ modelId: `anthropic:${model}` }); return modelFn; }), })); vi.mock('@ai-sdk/deepseek', () => ({ createDeepSeek: vi.fn(() => { const modelFn = (model: string) => ({ modelId: `deepseek:${model}` }); return modelFn; }), })); vi.mock('@ai-sdk/openai', () => ({ createOpenAI: vi.fn(() => { const modelFn = (model: string) => ({ modelId: `openai:${model}` }); return modelFn; }), })); vi.mock('qwen-ai-provider-v5', () => ({ createQwen: vi.fn(() => { const modelFn = (model: string) => ({ modelId: `qwen:${model}` }); return modelFn; }), })); import { createAnthropic } from '@ai-sdk/anthropic'; import { createDeepSeek } from '@ai-sdk/deepseek'; import { createOpenAI } from '@ai-sdk/openai'; import { createQwen } from 'qwen-ai-provider-v5'; describe('providers', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('providers 注册表', () => { it('包含所有支持的 provider 类型', () => { expect(providers).toHaveProperty('anthropic'); expect(providers).toHaveProperty('deepseek'); expect(providers).toHaveProperty('openai'); }); it('每个 provider 是一个工厂函数', () => { expect(typeof providers.anthropic).toBe('function'); expect(typeof providers.deepseek).toBe('function'); expect(typeof providers.openai).toBe('function'); }); }); describe('Anthropic provider', () => { it('创建 Anthropic 客户端', () => { const factory = providers.anthropic({ apiKey: 'test-api-key', }); expect(createAnthropic).toHaveBeenCalledWith({ apiKey: 'test-api-key', baseURL: undefined, }); expect(typeof factory).toBe('function'); }); it('支持自定义 baseUrl', () => { providers.anthropic({ apiKey: 'test-api-key', baseUrl: 'https://custom.anthropic.com', }); expect(createAnthropic).toHaveBeenCalledWith({ apiKey: 'test-api-key', baseURL: 'https://custom.anthropic.com', }); }); it('返回的工厂函数可以创建模型', () => { const factory = providers.anthropic({ apiKey: 'test-api-key', }); const model = factory('claude-3-opus'); expect(model).toEqual({ modelId: 'anthropic:claude-3-opus' }); }); }); describe('DeepSeek provider', () => { it('创建 DeepSeek 客户端', () => { const factory = providers.deepseek({ apiKey: 'test-deepseek-key', }); expect(createDeepSeek).toHaveBeenCalledWith({ apiKey: 'test-deepseek-key', baseURL: undefined, }); expect(typeof factory).toBe('function'); }); it('支持自定义 baseUrl', () => { providers.deepseek({ apiKey: 'test-deepseek-key', baseUrl: 'https://custom.deepseek.com', }); expect(createDeepSeek).toHaveBeenCalledWith({ apiKey: 'test-deepseek-key', baseURL: 'https://custom.deepseek.com', }); }); it('返回的工厂函数可以创建模型', () => { const factory = providers.deepseek({ apiKey: 'test-deepseek-key', }); const model = factory('deepseek-chat'); expect(model).toEqual({ modelId: 'deepseek:deepseek-chat' }); }); }); describe('OpenAI provider', () => { it('创建 OpenAI 客户端(标准 URL)', () => { const factory = providers.openai({ apiKey: 'test-openai-key', }); expect(createOpenAI).toHaveBeenCalledWith({ apiKey: 'test-openai-key', baseURL: undefined, }); expect(createQwen).not.toHaveBeenCalled(); expect(typeof factory).toBe('function'); }); it('支持自定义 baseUrl(非 DashScope)', () => { providers.openai({ apiKey: 'test-openai-key', baseUrl: 'https://custom.openai.com/v1', }); expect(createOpenAI).toHaveBeenCalledWith({ apiKey: 'test-openai-key', baseURL: 'https://custom.openai.com/v1', }); expect(createQwen).not.toHaveBeenCalled(); }); it('返回的工厂函数可以创建模型', () => { const factory = providers.openai({ apiKey: 'test-openai-key', }); const model = factory('gpt-4'); expect(model).toEqual({ modelId: 'openai:gpt-4' }); }); }); describe('DashScope (Qwen) 检测', () => { beforeEach(() => { vi.clearAllMocks(); }); it('检测 dashscope URL 并使用 Qwen provider', () => { providers.openai({ apiKey: 'test-qwen-key', baseUrl: 'https://dashscope.aliyuncs.com/compatible-mode/v1', }); expect(createQwen).toHaveBeenCalledWith({ apiKey: 'test-qwen-key', baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1', }); expect(createOpenAI).not.toHaveBeenCalled(); }); it('检测包含 dashscope 的任意 URL', () => { providers.openai({ apiKey: 'test-qwen-key', baseUrl: 'https://api.dashscope.example.com/v1', }); expect(createQwen).toHaveBeenCalled(); expect(createOpenAI).not.toHaveBeenCalled(); }); it('Qwen 工厂函数可以创建模型', () => { const factory = providers.openai({ apiKey: 'test-qwen-key', baseUrl: 'https://dashscope.aliyuncs.com/v1', }); const model = factory('qwen-turbo'); expect(model).toEqual({ modelId: 'qwen:qwen-turbo' }); }); }); }); describe('getModelFactory', () => { beforeEach(() => { vi.clearAllMocks(); }); it('获取 Anthropic 模型工厂', () => { const factory = getModelFactory('anthropic', { apiKey: 'test-key', }); expect(typeof factory).toBe('function'); expect(createAnthropic).toHaveBeenCalled(); }); it('获取 DeepSeek 模型工厂', () => { const factory = getModelFactory('deepseek', { apiKey: 'test-key', }); expect(typeof factory).toBe('function'); expect(createDeepSeek).toHaveBeenCalled(); }); it('获取 OpenAI 模型工厂', () => { const factory = getModelFactory('openai', { apiKey: 'test-key', }); expect(typeof factory).toBe('function'); expect(createOpenAI).toHaveBeenCalled(); }); it('传递正确的选项给 provider', () => { getModelFactory('anthropic', { apiKey: 'my-api-key', baseUrl: 'https://my-proxy.com', }); expect(createAnthropic).toHaveBeenCalledWith({ apiKey: 'my-api-key', baseURL: 'https://my-proxy.com', }); }); it('不支持的 provider 抛出错误', () => { expect(() => { getModelFactory('unsupported' as any, { apiKey: 'test-key', }); }).toThrow('不支持的 provider: unsupported'); }); it('返回的工厂函数可以创建模型实例', () => { const factory = getModelFactory('anthropic', { apiKey: 'test-key', }); const model = factory('claude-3-sonnet'); expect(model).toEqual({ modelId: 'anthropic:claude-3-sonnet' }); }); });