const fs = require('fs'); const path = require('path'); const guideStructure = fs.readFileSync(path.join(__dirname, 'GUIDE-STRUCTURE.md'), 'utf-8'); const explainStructure = fs.readFileSync(path.join(__dirname, 'EXPLAIN-STRUCTURE.md'), 'utf-8'); // --- 1. OPENAI FORMAT (OpenAI, Groq, DeepSeek) --- async function fetchOpenAIFormat(prompt, system, apiKey, endpoint, modelName, jsonMode) { let systemPrompt = system; let userPrompt = prompt; if (jsonMode) { if (!systemPrompt.toLowerCase().includes("json")) systemPrompt += "\n\nYou must respond strictly with a valid JSON object."; if (!userPrompt.toLowerCase().includes("json")) userPrompt += " (Respond strictly in JSON format)"; } const payload = { model: modelName, messages: [{ role: "system", content: systemPrompt }, { role: "user", content: userPrompt }], temperature: 0.2 }; if (jsonMode) payload.response_format = { type: "json_object" }; const res = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}` }, body: JSON.stringify(payload) }); if (!res.ok) throw new Error(`OpenAI format error: ${await res.text()}`); const data = await res.json(); return data.choices[0].message.content; } // --- 2. CLAUDE FORMAT --- async function fetchClaude(prompt, system, apiKey, modelName, jsonMode) { let finalPrompt = prompt; if (jsonMode) finalPrompt += "\n\nRespond ONLY with valid JSON."; const res = await fetch("https://api.anthropic.com/v1/messages", { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey, 'anthropic-version': '2023-06-01' }, body: JSON.stringify({ model: modelName, system: system, messages: [{ role: "user", content: finalPrompt }], max_tokens: 1024, temperature: 0.1 }) }); if (!res.ok) throw new Error(`Claude error: ${await res.text()}`); const data = await res.json(); return data.content[0].text; } // --- 3. GEMINI FORMAT --- async function fetchGemini(prompt, system, apiKey, modelName, jsonMode) { const url = `https://generativelanguage.googleapis.com/v1beta/models/${modelName}:generateContent?key=${apiKey}`; const payload = { systemInstruction: { parts: [{ text: system }] }, contents: [{ parts: [{ text: prompt }] }], generationConfig: { temperature: 0.1 } }; if (jsonMode) payload.generationConfig.responseMimeType = "application/json"; const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!res.ok) throw new Error(`Gemini error: ${await res.text()}`); const data = await res.json(); return data.candidates[0].content.parts[0].text; } // --- MAIN ROUTERS --- async function callLLM(prompt, provider, apiKey, modelName, isExplain) { const system = isExplain ? explainStructure : guideStructure; const jsonMode = !isExplain; if (provider === 'zerogpu') { const endpoint = isExplain ? '/explain' : '/generate'; const res = await fetch(`http://127.0.0.1:8000${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: prompt }) }); if (!res.ok) throw new Error("Local Python AI Server is down"); const data = await res.json(); return isExplain ? data.explanation : JSON.stringify(data); } if (!apiKey) throw new Error(`API key required for ${provider}`); switch (provider.toLowerCase()) { case 'openai': return await fetchOpenAIFormat(prompt, system, apiKey, "https://api.openai.com/v1/chat/completions", modelName, jsonMode); case 'groq': return await fetchOpenAIFormat(prompt, system, apiKey, "https://api.groq.com/openai/v1/chat/completions", modelName, jsonMode); case 'claude': return await fetchClaude(prompt, system, apiKey, modelName, jsonMode); case 'gemini': return await fetchGemini(prompt, system, apiKey, modelName, jsonMode); default: throw new Error("Unsupported LLM Provider"); } } async function routeCommand(query, provider, apiKey, modelName) { const text = await callLLM(query, provider, apiKey, modelName, false); try { return JSON.parse(text); } catch (e) { throw new Error(`LLM did not return valid JSON: ${text}`); } } async function explainResult(context, provider, apiKey, modelName) { return await callLLM(context, provider, apiKey, modelName, true); } module.exports = { routeCommand, explainResult };