const OLLAMA_API_URL = process.env.OLLAMA_API_URL; const OLLAMA_API_KEY = process.env.OLLAMA_API_KEY; async function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // Utility: strip markdown artifacts function cleanText(str) { return str .replace(/^#+\s*/gm, "") // remove headers .replace(/\*\*(.*?)\*\*/g, "$1") // remove bold .replace(/[*_`]/g, "") // remove stray formatting .replace(/\s+/g, " ") // normalize whitespace .trim(); } export async function callOllama(prompt, model = "gemma3n:e4b", retries = 5, stepName = "unknown") { const isUsingOpenWebUI = !!OLLAMA_API_KEY; for (let attempt = 1; attempt <= retries; attempt++) { try { const promptCharCount = prompt.length; const promptWordCount = prompt.split(/\s+/).length; console.log(`\n[${stepName}] Sending prompt (attempt ${attempt}/${retries})`); console.log(`Prompt: ${promptCharCount} chars, ~${promptWordCount} words`); const headers = { "Content-Type": "application/json" }; if (isUsingOpenWebUI) { headers["Authorization"] = `Bearer ${OLLAMA_API_KEY}`; } const body = isUsingOpenWebUI ? { model, messages: [{ role: "user", content: prompt }], } : { model, messages: [{ role: "user", content: prompt }], stream: false, }; const response = await fetch(OLLAMA_API_URL, { method: "POST", headers, body: JSON.stringify(body), }); if (!response.ok) throw new Error(`Ollama request failed: ${response.status} ${response.statusText}`); const data = await response.json(); const rawText = isUsingOpenWebUI ? data.choices?.[0]?.message?.content : data.message?.content; if (!rawText) throw new Error("No response from Ollama"); const cleaned = cleanText(rawText); console.log(`[${stepName}] Received: ${rawText.length} chars, ~${rawText.split(/\s+/).length} words`); // console.log(`Raw output:\n${rawText}\n`); // console.log(`Cleaned output:\n${cleaned}\n`); return cleaned; } catch (err) { console.warn(`[${stepName}] Attempt ${attempt} failed: ${err.message}`); if (attempt === retries) throw err; const delay = 1000 * Math.pow(2, attempt) + Math.random() * 500; console.log(`Retrying in ${Math.round(delay / 1000)}s...`); await sleep(delay); } } }