import { describe, it, beforeEach, afterEach } from 'node:test'; import assert from 'node:assert/strict'; import { getLLMConfig } from './config.js'; const ENV_KEYS = [ 'OPENAI_API_KEY', 'OPENAI_BASE_URL', 'OPENAI_MODEL', 'CLAUDE_API_KEY', 'CLAUDE_BASE_URL', 'CLAUDE_MODEL', 'GEMINI_API_KEY', 'GEMINI_BASE_URL', 'GEMINI_MODEL', 'OLLAMA_BASE_URL', 'OLLAMA_MODEL', 'AMAZONQ_API_KEY', 'AMAZONQ_BASE_URL', 'AMAZONQ_MODEL', ]; let saved = {}; beforeEach(() => { saved = {}; for (const k of ENV_KEYS) { saved[k] = process.env[k]; delete process.env[k]; } }); afterEach(() => { for (const k of ENV_KEYS) { if (saved[k] === undefined) delete process.env[k]; else process.env[k] = saved[k]; } }); describe('getLLMConfig', () => { it('returns null provider when no env vars set', () => { const cfg = getLLMConfig(); assert.equal(cfg.provider, null); assert.deepEqual(cfg.apiKeys, []); }); it('detects openai with defaults', () => { process.env.OPENAI_API_KEY = 'sk-test'; const cfg = getLLMConfig(); assert.equal(cfg.provider, 'openai'); assert.deepEqual(cfg.apiKeys, ['sk-test']); assert.equal(cfg.baseURL, 'https://api.openai.com/v1'); assert.equal(cfg.model, 'gpt-4o-mini'); }); it('detects openai with custom base url and model', () => { process.env.OPENAI_API_KEY = 'sk-test'; process.env.OPENAI_BASE_URL = 'https://openrouter.ai/api/v1'; process.env.OPENAI_MODEL = 'gpt-4o'; const cfg = getLLMConfig(); assert.equal(cfg.provider, 'openai'); assert.equal(cfg.baseURL, 'https://openrouter.ai/api/v1'); assert.equal(cfg.model, 'gpt-4o'); }); it('detects gemini with comma-separated keys, picks one', () => { process.env.GEMINI_API_KEY = 'key1,key2,key3'; const cfg = getLLMConfig(); assert.equal(cfg.provider, 'gemini'); assert.deepEqual(cfg.apiKeys, ['key1', 'key2', 'key3']); }); it('detects gemini with single key (no comma)', () => { process.env.GEMINI_API_KEY = 'gemini-key'; const cfg = getLLMConfig(); assert.equal(cfg.provider, 'gemini'); assert.equal(cfg.model, 'gemini-2.5-flash'); }); it('detects gemini with custom model', () => { process.env.GEMINI_API_KEY = 'gemini-key'; process.env.GEMINI_MODEL = 'gemini-2.0-flash'; const cfg = getLLMConfig(); assert.equal(cfg.model, 'gemini-2.0-flash'); }); it('detects claude with defaults', () => { process.env.CLAUDE_API_KEY = 'claude-key'; const cfg = getLLMConfig(); assert.equal(cfg.provider, 'claude'); assert.equal(cfg.model, 'claude-3-haiku-20240307'); }); it('detects amazonq with its own model env', () => { process.env.AMAZONQ_API_KEY = 'aq-key'; process.env.AMAZONQ_MODEL = 'my-amazon-model'; const cfg = getLLMConfig(); assert.equal(cfg.provider, 'amazonq'); assert.equal(cfg.model, 'my-amazon-model'); }); it('openai takes priority over gemini when both set', () => { process.env.OPENAI_API_KEY = 'sk-test'; process.env.GEMINI_API_KEY = 'gemini-key'; const cfg = getLLMConfig(); assert.equal(cfg.provider, 'openai'); }); it('empty string api key is treated as not set', () => { process.env.OPENAI_API_KEY = ''; process.env.GEMINI_API_KEY = 'gemini-key'; const cfg = getLLMConfig(); assert.equal(cfg.provider, 'gemini'); }); it('detects ollama without api key', () => { process.env.OLLAMA_BASE_URL = 'http://localhost:11434'; process.env.OLLAMA_MODEL = 'llama3'; const cfg = getLLMConfig(); assert.equal(cfg.provider, 'ollama'); assert.equal(cfg.model, 'llama3'); }); it('comma-only api key is treated as not set', () => { process.env.OPENAI_API_KEY = ',,,'; const cfg = getLLMConfig(); assert.equal(cfg.provider, null); assert.deepEqual(cfg.apiKeys, []); }); });