d3ro-voice/server/supabase/functions/_shared/llm-contract.test.ts
2026-08-29 18:33:45 +09:00

46 lines
1.6 KiB
TypeScript

import {
hasAssistantText,
LlmRequestError,
parseLlmRequest,
} from './llm-contract.ts'
function assert(condition: boolean, message: string): void {
if (!condition) throw new Error(message)
}
Deno.test('llm request normalization accepts a bounded conversation', () => {
const parsed = parseLlmRequest({
messages: [{ role: 'user', content: ' hello ' }],
max_tokens: 512,
stream: false,
})
assert(parsed.messages[0].content === 'hello', 'content should be trimmed')
assert(parsed.max_tokens === 512, 'max_tokens should be preserved')
})
Deno.test('llm request rejects empty, oversized, and malformed input', () => {
const invalid: unknown[] = [
{},
{ messages: [] },
{ messages: [{ role: 'system', content: 'x' }] },
{ messages: [{ role: 'user', content: '' }] },
{ messages: [{ role: 'user', content: 'x'.repeat(8_001) }] },
{ messages: [{ role: 'user', content: 'x' }], max_tokens: 0 },
{ messages: [{ role: 'user', content: 'x' }], stream: 'yes' },
]
for (const value of invalid) {
let rejected = false
try {
parseLlmRequest(value)
} catch (error) {
rejected = error instanceof LlmRequestError
}
assert(rejected, `expected rejection for ${JSON.stringify(value).slice(0, 80)}`)
}
})
Deno.test('assistant response must contain non-empty text', () => {
assert(hasAssistantText({ content: [{ type: 'text', text: 'answer' }] }), 'valid text missing')
assert(!hasAssistantText({ content: [{ type: 'tool_use', input: {} }] }), 'tool-only response accepted')
assert(!hasAssistantText({ content: [{ type: 'text', text: ' ' }] }), 'blank response accepted')
})