diff --git a/management/ncp.py b/management/ncp.py index 07d60fe..701a273 100644 --- a/management/ncp.py +++ b/management/ncp.py @@ -64,6 +64,19 @@ def http_ok(url: str, timeout: float = 1.0) -> bool: return False +def ollama_bin() -> str | None: + """The bundled binary if we have one, else whatever is on PATH. + + Only Linux ships a copy in the repo (bin/fetch-ollama.sh); on Windows the + installer gets Ollama from winget, which puts it in %LOCALAPPDATA%\\Programs + and on PATH. Checking only the bundled path made `ncp doctor` report a red + "Ollama binary missing" on every Windows box, and made `ncp models install` + refuse to run there at all. Mirrors _ollama_bin() in ollama_manager.py.""" + if OLLAMA_BIN.exists(): + return str(OLLAMA_BIN) + return shutil.which("ollama") + + def npm() -> str | None: """npm, resolving through nvm. The bash version sourced ~/.nvm/nvm.sh; a non-login shell has neither, so fall back to globbing the nvm install.""" @@ -191,7 +204,11 @@ def check(svc: Service) -> bool: def wait_for_port(svc: Service, timeout: int = 30) -> bool: if http_ok(svc.url): - print(f" {svc.label} already running (:{svc.port})") + # "READY", not "already running": `ncp start` launches memory and backend + # together and only then waits on each, so by the time the backend's turn + # comes it is normally up - and reporting "already running" for a service + # this same command started two seconds ago reads like a stale process. + print(f" {svc.label} READY (:{svc.port})") return True for _ in range(timeout): time.sleep(1) @@ -477,8 +494,9 @@ def cmd_doctor() -> None: "Memory database directory writable", "Memory database directory not writable") print("\nChecking Ollama...") - mark(OLLAMA_BIN.exists(), f"Ollama binary found ({OLLAMA_BIN})", - f"Ollama binary missing at {OLLAMA_BIN}") + _obin = ollama_bin() + mark(bool(_obin), f"Ollama binary found ({_obin})", + f"Ollama binary missing (not at {OLLAMA_BIN}, not on PATH)") mark(OLLAMA_MODELS_DIR.is_dir(), f"Ollama models directory found ({OLLAMA_MODELS_DIR})", f"Ollama models directory missing at {OLLAMA_MODELS_DIR}") print() @@ -575,11 +593,12 @@ def cmd_models(action, name) -> None: print("Usage: ncp models install ") print("Run 'ncp models available' to see options.") return - if not OLLAMA_BIN.exists(): - print(f"Ollama binary not found at {OLLAMA_BIN}") + obin = ollama_bin() + if not obin: + print(f"Ollama binary not found at {OLLAMA_BIN}, and no 'ollama' on PATH") return print(f"Pulling '{name}' into {OLLAMA_MODELS_DIR} ...\n") - subprocess.run([str(OLLAMA_BIN), "pull", name], + subprocess.run([obin, "pull", name], env={**os.environ, "OLLAMA_MODELS": str(OLLAMA_MODELS_DIR)}) print("\nDone. Run 'ncp models list' to verify.") else: