77 lines
2.6 KiB
JavaScript
77 lines
2.6 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { LiteLLMProvider } from '../lib/llm/litellm.mjs';
|
|
import { createLLMProvider } from '../lib/llm/index.mjs';
|
|
|
|
test('factory creates a configured LiteLLM provider', () => {
|
|
const provider = createLLMProvider({
|
|
provider: 'litellm',
|
|
baseUrl: 'https://llm.example.test/v1/',
|
|
apiKey: 'proxy-key',
|
|
model: 'private-model',
|
|
});
|
|
|
|
assert.ok(provider instanceof LiteLLMProvider);
|
|
assert.equal(provider.baseUrl, 'https://llm.example.test/v1');
|
|
assert.equal(provider.isConfigured, true);
|
|
assert.deepEqual(provider.status, {
|
|
state: 'configured',
|
|
provider: 'litellm',
|
|
model: 'private-model',
|
|
baseUrl: 'https://llm.example.test/v1',
|
|
});
|
|
});
|
|
|
|
test('LiteLLM requires base URL, API key, and model', () => {
|
|
const missingBaseUrl = new LiteLLMProvider({ apiKey: 'key', model: 'model' });
|
|
assert.equal(missingBaseUrl.isConfigured, false);
|
|
assert.equal(missingBaseUrl.status.reason, 'LLM_BASE_URL is required for LiteLLM');
|
|
|
|
const missingKey = new LiteLLMProvider({ baseUrl: 'https://llm.example.test/v1', model: 'model' });
|
|
assert.equal(missingKey.status.reason, 'LLM_API_KEY is required for LiteLLM');
|
|
|
|
const missingModel = new LiteLLMProvider({ baseUrl: 'https://llm.example.test/v1', apiKey: 'key' });
|
|
assert.equal(missingModel.status.reason, 'LLM_MODEL is required for LiteLLM');
|
|
});
|
|
|
|
test('LiteLLM sends bearer-authenticated OpenAI-compatible requests', async () => {
|
|
const provider = new LiteLLMProvider({
|
|
baseUrl: 'https://llm.example.test/v1',
|
|
apiKey: 'proxy-key',
|
|
model: 'private-model',
|
|
temperature: 0.15,
|
|
maxTokens: 512,
|
|
});
|
|
const originalFetch = globalThis.fetch;
|
|
|
|
globalThis.fetch = async (url, options) => {
|
|
assert.equal(url, 'https://llm.example.test/v1/chat/completions');
|
|
assert.equal(options.headers.Authorization, 'Bearer proxy-key');
|
|
assert.deepEqual(JSON.parse(options.body), {
|
|
model: 'private-model',
|
|
temperature: 0.15,
|
|
messages: [
|
|
{ role: 'system', content: 'system' },
|
|
{ role: 'user', content: 'user' },
|
|
],
|
|
max_tokens: 512,
|
|
});
|
|
return {
|
|
ok: true,
|
|
json: async () => ({
|
|
choices: [{ message: { content: 'response' } }],
|
|
usage: { prompt_tokens: 7, completion_tokens: 11 },
|
|
model: 'private-model',
|
|
}),
|
|
};
|
|
};
|
|
|
|
try {
|
|
const result = await provider.complete('system', 'user');
|
|
assert.equal(result.text, 'response');
|
|
assert.deepEqual(result.usage, { inputTokens: 7, outputTokens: 11 });
|
|
} finally {
|
|
globalThis.fetch = originalFetch;
|
|
}
|
|
});
|