From f2f9d729da5b953dc2410fb1cf85558995df95dd Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 3 Feb 2026 01:31:17 +0100 Subject: [PATCH] Add Ollama generation module for AI-powered maintenance Provides text generation via Ollama (llama3) for heartbeat operations like auto-dedupe, auto-tag, auto-summarize, auto-split, and auto-archive. --- src/core/search/ollamaGen.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/core/search/ollamaGen.ts diff --git a/src/core/search/ollamaGen.ts b/src/core/search/ollamaGen.ts new file mode 100644 index 0000000..76dc108 --- /dev/null +++ b/src/core/search/ollamaGen.ts @@ -0,0 +1,34 @@ +const OLLAMA_URL = process.env.OLLAMA_URL || 'http://localhost:11434'; +const GEN_MODEL = process.env.OLLAMA_GEN_MODEL || 'llama3'; + +let _available: boolean | null = null; + +export async function isGenAvailable(): Promise { + if (_available !== null) return _available; + try { + const res = await fetch(`${OLLAMA_URL}/api/tags`, { signal: AbortSignal.timeout(2000) }); + if (!res.ok) { _available = false; return false; } + const data = await res.json() as { models?: { name: string }[] }; + _available = !!data.models?.some(m => m.name.startsWith(GEN_MODEL)); + } catch { + _available = false; + } + return _available; +} + +export async function generate(prompt: string): Promise { + if (!(await isGenAvailable())) return null; + try { + const res = await fetch(`${OLLAMA_URL}/api/generate`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ model: GEN_MODEL, prompt, stream: false }), + signal: AbortSignal.timeout(60000), + }); + if (!res.ok) return null; + const data = await res.json() as { response?: string }; + return data.response?.trim() ?? null; + } catch { + return null; + } +}