* Check if the model endpoint is reachable. * Returns true if connected, false otherwise.
(config)
| 274 | * Returns true if connected, false otherwise. |
| 275 | */ |
| 276 | async function checkEndpoint(config) { |
| 277 | const baseUrl = config.model.baseUrl || process.env.OLLAMA_HOST || 'http://localhost:11434'; |
| 278 | |
| 279 | // Plugin-registered providers handle their own connectivity |
| 280 | const { providerRegistry } = require('../src/compiled/providers/registry'); |
| 281 | if (providerRegistry.has(config.model.provider)) { |
| 282 | console.log(` Using plugin provider: ${config.model.provider}`); |
| 283 | return true; |
| 284 | } |
| 285 | |
| 286 | // OpenAI-compatible endpoint (LM Studio, vLLM, OpenRouter, etc.) |
| 287 | if (config.model.provider === 'openai' || baseUrl.includes('/v1')) { |
| 288 | try { |
| 289 | const headers = buildAuthHeaders(config); |
| 290 | const response = await fetch(`${baseUrl}/models`, { headers }); |
| 291 | if (!response.ok) { |
| 292 | console.log(` ⚠ Cannot reach endpoint at ${baseUrl}`); |
| 293 | console.log(` Got HTTP ${response.status} from ${baseUrl}/models`); |
| 294 | if (response.status === 404 && !/\/v1(\/|$)/.test(baseUrl)) { |
| 295 | // The most common cause: user gave a base URL without /v1. |
| 296 | console.log(` Tip: this URL has no /v1 path. Try SMALLCODE_BASE_URL=${baseUrl}/v1 in your .env.`); |
| 297 | } else { |
| 298 | console.log(` Check that your model server is running and accessible.`); |
| 299 | } |
| 300 | if (response.status === 401 || response.status === 403) { |
| 301 | console.log(` Got ${response.status} — set OPENAI_API_KEY in .env if your server requires auth.`); |
| 302 | } |
| 303 | return false; |
| 304 | } |
| 305 | const data = await response.json(); |
| 306 | const models = data.data || []; |
| 307 | if (models.length > 0) { |
| 308 | console.log(` Connected: ${baseUrl}`); |
| 309 | console.log(` Model: ${config.model.name}`); |
| 310 | const activeModel = models.find(m => (m.id || m.name || '').includes(config.model.name)) || models[0]; |
| 311 | if (activeModel && activeModel.context_length) { |
| 312 | config.context.detected_window = activeModel.context_length; |
| 313 | console.log(` Context: ${activeModel.context_length} tokens`); |
| 314 | } |
| 315 | } |
| 316 | return true; |
| 317 | } catch (e) { |
| 318 | console.log(` ⚠ Cannot reach endpoint at ${baseUrl}`); |
| 319 | console.log(` Check that your model server is running and the URL is correct.`); |
| 320 | return false; |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | // Ollama endpoint. |
| 325 | // Prefer the user-supplied base URL (SMALLCODE_BASE_URL) over OLLAMA_HOST / |
| 326 | // localhost so a remote Ollama server is actually probed. Previously this |
| 327 | // branch always hit localhost and reported "Ollama not running" even when |
| 328 | // the user pointed SMALLCODE_BASE_URL at a remote host (issue #59). |
| 329 | // Ollama's native API lives at the host root (/api/tags), so strip any |
| 330 | // trailing OpenAI-style /v1 and normalise the trailing slash. |
| 331 | let host = config.model.baseUrl || process.env.OLLAMA_HOST || 'http://localhost:11434'; |
| 332 | host = host.replace(/\/v1\/?$/, '').replace(/\/+$/, ''); |
| 333 | const tagsUrl = `${host}/api/tags`; |
no test coverage detected