fix(code): preflight Ollama host reachability before discovery probe (#4702)

Deep Agents Code no longer logs a misleading "discovery failed" error
when Ollama is not running; it now detects the daemon's absence and
skips discovery quietly.

---

When Ollama is not installed/running, model discovery probes
`http://localhost:11434/api/tags`, and the refused connection surfaces
as a misleading `Ollama model discovery failed ... Connection refused`
debug line. This adds a lightweight TCP presence preflight
(`_ollama_host_reachable`) that runs before the HTTP probe: if nothing
is listening, discovery is skipped quietly with an `Ollama daemon not
detected` debug line instead. The check is best-effort — any failure
(refused, DNS error, timeout, blocked sockets under `pytest-socket`) is
treated as absent, and an unparseable host defers to the existing HTTP
probe.

Made by [Open
SWE](https://openswe.vercel.app/agents/c3696bf2-ea9f-2932-0d07-4ce636b8f83e)

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
This commit is contained in:
Mason Daugherty
2026-07-13 16:39:35 -04:00
committed by GitHub
parent 3d499db8a6
commit 96fe71a381
2 changed files with 285 additions and 1 deletions
+68
View File
@@ -1435,6 +1435,63 @@ def _get_ollama_installed_models(endpoint: str | None) -> list[str]:
return list(models)
def _ollama_host_reachable(
base: str, *, timeout: float = OLLAMA_DISCOVERY_TIMEOUT_SECONDS
) -> bool:
"""Return whether a TCP listener appears to accept connections at `base`.
A lightweight presence preflight so Ollama discovery can skip the HTTP
probe entirely when no daemon is running (e.g. Ollama is not installed).
The check opens and immediately closes a TCP connection to the endpoint's
host and port. Any failure -- connection refused, DNS error, timeout, or
sockets blocked under `pytest-socket` -- is treated as "not reachable" so
discovery falls back gracefully; an unexpected (non-`OSError`) failure is
additionally logged at warning so a real bug isn't misreported as absence.
Args:
base: Base URL of the Ollama daemon, e.g. `http://localhost:11434`.
timeout: Socket connection timeout in seconds.
Returns:
`True` when a connection is established (a daemon appears present) or
when the target cannot be determined (deferring to the HTTP probe);
`False` when the connection cannot be made.
"""
import socket
parsed = urlparse(base)
host = parsed.hostname
if not host:
# Can't determine a target host; let the HTTP probe make the decision.
return True
try:
port = parsed.port
except ValueError:
# Malformed port (out of range / non-numeric); defer to the HTTP probe.
return True
if port is None:
port = 443 if parsed.scheme == "https" else 80
# Mirror the discovery probe below: expected transport failures (refused,
# DNS, timeout) just mean the daemon is absent and stay silent; anything
# else is surfaced at warning so a real bug isn't misreported as "not
# detected". `pytest-socket`'s `SocketBlockedError` inherits from
# `Exception` (not `OSError`), so the broad branch catches it. The socket
# is its own context manager, so `with` closes the probe connection.
try:
with socket.create_connection((host, port), timeout=timeout):
return True
except OSError:
return False
except Exception as exc: # noqa: BLE001 # see comment above
logger.warning(
"Ollama presence preflight raised unexpected %s for %s: %s",
type(exc).__name__,
base,
exc,
)
return False
def _fetch_ollama_installed_models(
endpoint: str | None,
*,
@@ -1472,6 +1529,17 @@ def _fetch_ollama_installed_models(
base,
)
return []
# Presence preflight (local endpoints only -- remote hosts may be reachable
# only through a proxy that the HTTP probe honors but a raw socket does
# not). A dead/absent daemon (the common case when Ollama is not installed)
# refuses the connection; detecting that here lets us skip the HTTP probe
# and log a quiet "not detected" line instead of a misleading
# "discovery failed ... Connection refused" debug line.
if _is_local_endpoint(base) and not _ollama_host_reachable(base, timeout=timeout):
logger.debug("Ollama daemon not detected at %s; skipping discovery", base)
return []
url = f"{base}/api/tags"
headers = _ollama_discovery_headers(base, content_type=False)
+217 -1
View File
@@ -6,7 +6,7 @@ from collections.abc import Iterator
from contextlib import AbstractContextManager
from pathlib import Path
from typing import Any, ClassVar, cast
from unittest.mock import patch
from unittest.mock import MagicMock, patch
import pytest
@@ -2764,6 +2764,82 @@ class _BytesContext:
class TestFetchOllamaInstalledModels:
"""Tests for the `_fetch_ollama_installed_models` HTTP probe."""
@pytest.fixture(autouse=True)
def _assume_host_reachable(self, monkeypatch: pytest.MonkeyPatch) -> None:
"""Bypass the TCP presence preflight so HTTP parsing paths are exercised."""
monkeypatch.setattr(
"deepagents_code.model_config._ollama_host_reachable",
lambda *_args, **_kwargs: True,
)
def test_skips_http_probe_when_host_unreachable(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
"""An unreachable daemon short-circuits before any HTTP request."""
monkeypatch.setattr(
"deepagents_code.model_config._ollama_host_reachable",
lambda *_args, **_kwargs: False,
)
with patch("urllib.request.urlopen") as fake:
assert (
model_config._fetch_ollama_installed_models("http://localhost:11434")
== []
)
fake.assert_not_called()
def test_hosted_endpoint_skips_tcp_preflight(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
"""Hosted endpoints proceed through the proxy-aware HTTP probe."""
import json
reachable = MagicMock(return_value=False)
monkeypatch.setattr(
"deepagents_code.model_config._ollama_host_reachable", reachable
)
with patch(
"urllib.request.urlopen",
return_value=_BytesContext(json.dumps({"models": []}).encode("utf-8")),
) as urlopen:
assert (
model_config._fetch_ollama_installed_models(
"https://ollama.example.com"
)
== []
)
reachable.assert_not_called()
urlopen.assert_called_once()
def test_forwards_normalized_base_and_timeout_to_preflight(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
"""The rstrip'd base and the caller's timeout reach the preflight."""
import json
reachable = MagicMock(return_value=True)
monkeypatch.setattr(
"deepagents_code.model_config._ollama_host_reachable", reachable
)
monkeypatch.delenv("OLLAMA_API_KEY", raising=False)
monkeypatch.delenv("DEEPAGENTS_CODE_OLLAMA_API_KEY", raising=False)
with patch(
"urllib.request.urlopen",
return_value=_BytesContext(json.dumps({"models": []}).encode("utf-8")),
):
assert (
model_config._fetch_ollama_installed_models(
"http://localhost:11434/", timeout=0.5
)
== []
)
reachable.assert_called_once_with("http://localhost:11434", timeout=0.5)
def test_returns_sorted_names_from_payload(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
@@ -2936,6 +3012,146 @@ class TestFetchOllamaInstalledModels:
fake.assert_not_called()
class TestOllamaHostReachable:
"""Tests for the `_ollama_host_reachable` TCP presence preflight."""
def test_true_when_connection_succeeds(self) -> None:
"""A successful TCP connection reports the daemon as present.
Also pins that the default timeout reaches `socket.create_connection`:
the preflight exists to fail *fast*, so a dropped timeout would let an
absent host stall on the OS connect timeout -- the hang this removes.
"""
captured: list[tuple[tuple[str, int], float]] = []
def fake_create_connection(
address: tuple[str, int], *, timeout: float
) -> MagicMock:
captured.append((address, timeout))
return MagicMock()
with patch("socket.create_connection", side_effect=fake_create_connection):
assert model_config._ollama_host_reachable("http://localhost:11434") is True
assert captured == [
(("localhost", 11434), model_config.OLLAMA_DISCOVERY_TIMEOUT_SECONDS)
]
def test_forwards_explicit_timeout(self) -> None:
"""A caller-supplied timeout is forwarded to the socket connect."""
captured: list[float] = []
def fake_create_connection(
address: tuple[str, int], # noqa: ARG001
*,
timeout: float,
) -> MagicMock:
captured.append(timeout)
return MagicMock()
with patch("socket.create_connection", side_effect=fake_create_connection):
assert (
model_config._ollama_host_reachable(
"http://localhost:11434", timeout=0.25
)
is True
)
assert captured == [0.25]
def test_false_and_silent_when_connection_refused(
self, caplog: pytest.LogCaptureFixture
) -> None:
"""Connection refused (an `OSError`) reports absent without warning."""
refused = ConnectionRefusedError(61, "Connection refused")
def boom(*_args: object, **_kwargs: object) -> None:
raise refused
with (
caplog.at_level(logging.WARNING, logger="deepagents_code.model_config"),
patch("socket.create_connection", side_effect=boom),
):
assert (
model_config._ollama_host_reachable("http://localhost:11434") is False
)
assert caplog.records == []
def test_false_and_warns_when_error_unexpected(
self, caplog: pytest.LogCaptureFixture
) -> None:
"""A non-`OSError` failure reports absent and surfaces a warning.
Covers `pytest-socket`'s `SocketBlockedError`, which inherits from
`Exception` (not `OSError`); an unexpected error here is a possible
real bug, so it is logged rather than silently swallowed.
"""
blocked = RuntimeError("sockets disabled")
def boom(*_args: object, **_kwargs: object) -> None:
raise blocked
with (
caplog.at_level(logging.WARNING, logger="deepagents_code.model_config"),
patch("socket.create_connection", side_effect=boom),
):
assert (
model_config._ollama_host_reachable("http://localhost:11434") is False
)
assert any("unexpected RuntimeError" in r.getMessage() for r in caplog.records)
def test_defers_to_probe_when_host_unparseable(self) -> None:
"""A URL without a host defers to the HTTP probe instead of blocking it."""
with patch("socket.create_connection") as fake:
assert model_config._ollama_host_reachable("http://") is True
fake.assert_not_called()
@pytest.mark.parametrize(
"endpoint",
["http://localhost:notaport", "http://localhost:99999"],
)
def test_defers_to_probe_when_port_invalid(self, endpoint: str) -> None:
"""An invalid port defers to the best-effort HTTP probe."""
with patch("socket.create_connection") as fake:
assert model_config._ollama_host_reachable(endpoint) is True
fake.assert_not_called()
@pytest.mark.parametrize(
("endpoint", "expected"),
[
("https://ollama.example.com", ("ollama.example.com", 443)),
("http://ollama.internal", ("ollama.internal", 80)),
],
)
def test_defaults_scheme_port_when_absent(
self, endpoint: str, expected: tuple[str, int]
) -> None:
"""A schemed URL without an explicit port falls back to the scheme default.
The preflight and the HTTP probe must agree on the target, so a portless
`http` host resolves to 80 and `https` to 443 -- matching what urllib
would connect to.
"""
captured: list[tuple[str, int]] = []
def fake_create_connection(
address: tuple[str, int],
*,
timeout: float, # noqa: ARG001
) -> MagicMock:
captured.append(address)
return MagicMock()
with patch("socket.create_connection", side_effect=fake_create_connection):
assert model_config._ollama_host_reachable(endpoint) is True
assert captured == [expected]
class TestFetchOllamaInstalledModelProfiles:
"""Tests for Ollama `/api/show` profile discovery."""