(baseUrl = 'http://localhost:11434')
| 74 | |
| 75 | /** Probe Ollama daemon for installed models. */ |
| 76 | export async function detectOllamaModels(baseUrl = 'http://localhost:11434'): Promise<DetectedModel[]> { |
| 77 | const r = await fetchWithTimeout(`${baseUrl}/api/tags`); |
| 78 | if (!r || !r.ok) return []; |
| 79 | try { |
| 80 | const body = await r.json() as { models?: Array<{ name: string; size?: number; details?: any }> }; |
| 81 | if (!Array.isArray(body.models)) return []; |
| 82 | return body.models.map(m => { |
| 83 | const sizeGb = m.size ? m.size / (1024 ** 3) : undefined; |
| 84 | const paramsB = parseParamsFromId(m.name); |
| 85 | return { |
| 86 | provider: 'ollama' as const, |
| 87 | id: m.name, |
| 88 | label: m.name, |
| 89 | source: 'ollama' as const, |
| 90 | sizeGb: sizeGb ? Math.round(sizeGb * 10) / 10 : undefined, |
| 91 | paramsB, |
| 92 | // Ollama models support structured tool_calls IFF they were trained for it. |
| 93 | // Best-effort heuristic: Qwen 2.5+, Llama 3.1+, DeepSeek-V3/R1, Mistral support it natively. |
| 94 | // We err toward 'true' for known coder/instruct families since QodeX's recovery layer catches the rest. |
| 95 | toolCallsLikely: looksLikeToolCallCapable(m.name), |
| 96 | }; |
| 97 | }); |
| 98 | } catch (e: any) { |
| 99 | logger.debug('Ollama response parse failed', { err: e?.message }); |
| 100 | return []; |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | /** |
| 105 | * Probe LM Studio / llama.cpp server on common ports. |
no test coverage detected