| 282 | } |
| 283 | |
| 284 | async function handleOllamaLogin() { |
| 285 | const check = await checkExistingConnection("ollama") |
| 286 | if (!check.proceed) { |
| 287 | prompts.outro("Cancelled") |
| 288 | return |
| 289 | } |
| 290 | |
| 291 | prompts.log.info("Connect to a local Ollama instance.") |
| 292 | |
| 293 | const host = await prompts.text({ |
| 294 | message: "Ollama host", |
| 295 | placeholder: "127.0.0.1", |
| 296 | defaultValue: "127.0.0.1", |
| 297 | }) |
| 298 | if (prompts.isCancel(host)) throw new UI.CancelledError() |
| 299 | |
| 300 | const portInput = await prompts.text({ |
| 301 | message: "Ollama port", |
| 302 | placeholder: "11434", |
| 303 | defaultValue: "11434", |
| 304 | validate: (x) => { |
| 305 | if (!x) return undefined |
| 306 | const port = parseInt(x, 10) |
| 307 | if (isNaN(port) || port < 1 || port > 65535) return "Invalid port number" |
| 308 | return undefined |
| 309 | }, |
| 310 | }) |
| 311 | if (prompts.isCancel(portInput)) throw new UI.CancelledError() |
| 312 | |
| 313 | const hostValue = host || "127.0.0.1" |
| 314 | const port = parseInt(portInput || "11434", 10) |
| 315 | const baseUrl = `http://${hostValue}:${port}` |
| 316 | |
| 317 | const spinner = prompts.spinner() |
| 318 | spinner.start("Connecting to Ollama...") |
| 319 | |
| 320 | try { |
| 321 | const response = await fetch(`${baseUrl}/v1/models`, { |
| 322 | signal: AbortSignal.timeout(10000), |
| 323 | }) |
| 324 | |
| 325 | if (!response.ok) { |
| 326 | spinner.stop("Failed to connect to Ollama", 1) |
| 327 | prompts.log.error(`HTTP ${response.status}: ${response.statusText}`) |
| 328 | return |
| 329 | } |
| 330 | |
| 331 | const data = (await response.json()) as OllamaModelsResponse |
| 332 | |
| 333 | if (!data.data || data.data.length === 0) { |
| 334 | spinner.stop("Connected but no models found", 1) |
| 335 | prompts.log.warn("No models available. Pull a model with: ollama pull <model>") |
| 336 | return |
| 337 | } |
| 338 | |
| 339 | spinner.stop("Connected to Ollama") |
| 340 | |
| 341 | prompts.log.info(`Found ${data.data.length} model${data.data.length === 1 ? "" : "s"}:`) |