33 lines
1.8 KiB
TypeScript
33 lines
1.8 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { buildJsonCompletion, parseAiUsage, parseJsonCompletion, resolveAiProvider } from './ai-provider'
|
|
|
|
const request = { system: 'Return JSON.', messages: [{ role: 'user' as const, content: 'Create a world' }], schemaName: 'world', jsonSchema: { type: 'object' } }
|
|
|
|
describe('AI provider adapter', () => {
|
|
it('keeps OpenRouter structured outputs', () => {
|
|
const completion = buildJsonCompletion({ aiProvider: 'openrouter', openrouterApiKey: 'key', openrouterModel: 'model' }, request)
|
|
expect(completion.endpoint).toBe('https://openrouter.ai/api/v1/chat/completions')
|
|
expect(completion.body.response_format).toEqual({ type: 'json_schema', json_schema: { name: 'world', strict: true, schema: { type: 'object' } } })
|
|
})
|
|
|
|
it('uses official DeepSeek JSON mode', () => {
|
|
const completion = buildJsonCompletion({ aiProvider: 'deepseek', deepseekApiKey: 'key', deepseekModel: 'deepseek-v4-flash' }, request)
|
|
expect(completion.endpoint).toBe('https://api.deepseek.com/chat/completions')
|
|
expect(completion.body.response_format).toEqual({ type: 'json_object' })
|
|
expect(completion.body['thinking']).toEqual({ type: 'disabled' })
|
|
})
|
|
|
|
it('rejects missing credentials and malformed responses', () => {
|
|
expect(() => resolveAiProvider({ aiProvider: 'deepseek' })).toThrow('DEEPSEEK_API_KEY')
|
|
expect(() => parseJsonCompletion({ choices: [] })).toThrow()
|
|
expect(parseJsonCompletion({ choices: [{ message: { content: '{"ok":true}' } }] })).toEqual({ ok: true })
|
|
})
|
|
|
|
it('normalizes provider usage telemetry', () => {
|
|
expect(parseAiUsage({
|
|
choices: [{ message: { content: '{}' } }],
|
|
usage: { prompt_tokens: 120, completion_tokens: 30, cost: 0.0042 },
|
|
})).toEqual({ inputTokens: 120, outputTokens: 30, costUsd: 0.0042 })
|
|
})
|
|
})
|