From 93291247e83b5b79558eae6d90f8455eae533820 Mon Sep 17 00:00:00 2001 From: Thabhelo <50872400+Thabhelo@users.noreply.github.com> Date: Fri, 22 May 2026 13:12:43 -0700 Subject: [PATCH 1/2] fix(onboard): detect installed Windows Ollama when daemon is stopped Probe known install paths even when Ollama is not on PATH and not running, so WSL onboarding offers Start instead of Install. Fixes #4066. --- src/lib/onboard/windows-host-ollama.test.ts | 43 +++++++++++++++++++++ src/lib/onboard/windows-host-ollama.ts | 9 ++--- 2 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 src/lib/onboard/windows-host-ollama.test.ts diff --git a/src/lib/onboard/windows-host-ollama.test.ts b/src/lib/onboard/windows-host-ollama.test.ts new file mode 100644 index 0000000000..b29bd6cdd9 --- /dev/null +++ b/src/lib/onboard/windows-host-ollama.test.ts @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { afterEach, describe, expect, it, vi } from "vitest"; + +const runCapture = vi.fn<(command: string | string[]) => string>(() => ""); + +vi.mock("../runner", () => ({ + runCapture: (command: string | string[]) => runCapture(command), +})); + +vi.mock("../platform", () => ({ + isWsl: vi.fn(() => true), +})); + +import { isWsl } from "../platform"; +import { detectWindowsHostOllama } from "./windows-host-ollama"; + +describe("detectWindowsHostOllama", () => { + afterEach(() => { + vi.clearAllMocks(); + vi.mocked(isWsl).mockReturnValue(true); + }); + + it("detects installed-but-not-running Ollama via known install path (#4066)", () => { + const knownPath = "C:\\Users\\tester\\AppData\\Local\\Programs\\Ollama\\ollama.exe"; + runCapture.mockImplementation((command) => { + const cmd = Array.isArray(command) ? command.join(" ") : command; + if (cmd.includes("Get-Command ollama.exe")) return ""; + if (cmd.includes("Get-Process ollama") && cmd.includes("Path")) return ""; + if (cmd.includes("Get-Process ollama") && cmd.includes("Id")) return ""; + if (cmd.includes("Test-Path -LiteralPath")) return knownPath; + if (cmd.includes("Get-NetTCPConnection")) return ""; + return ""; + }); + + expect(detectWindowsHostOllama()).toEqual({ + installed: true, + installedPath: knownPath, + loopbackOnly: false, + }); + }); +}); diff --git a/src/lib/onboard/windows-host-ollama.ts b/src/lib/onboard/windows-host-ollama.ts index e131c4d5ee..a496d34887 100644 --- a/src/lib/onboard/windows-host-ollama.ts +++ b/src/lib/onboard/windows-host-ollama.ts @@ -55,12 +55,9 @@ function probeInstalledPath(): string { // lookup (#3949). const processPath = powershell(GET_PROCESS_OLLAMA_PATH); if (processPath.length > 0) return processPath; - // Some WSL-launched PowerShell sessions can see the Windows ollama PID - // but cannot read the Path property. Only after observing the live - // daemon, fall back to fixed installer locations so the restart path - // still has an explicit executable to launch. - const pid = powershell(GET_PROCESS_OLLAMA_ID); - if (!pid) return ""; + // Silent installs often land in fixed locations without updating PATH or + // leaving a running daemon to probe. Check those paths even when no PID is + // visible so WSL onboarding offers Start instead of Install (#4066). return powershell(GET_KNOWN_OLLAMA_INSTALL_PATH); } From cc0e54faf071efae20ecb37c29dfae83ce0db53f Mon Sep 17 00:00:00 2001 From: Thabhelo <50872400+Thabhelo@users.noreply.github.com> Date: Wed, 3 Jun 2026 14:00:47 -0400 Subject: [PATCH 2/2] test(onboard): align runCapture mock with runner signature Address review feedback on #4089. --- src/lib/onboard/windows-host-ollama.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/onboard/windows-host-ollama.test.ts b/src/lib/onboard/windows-host-ollama.test.ts index b29bd6cdd9..da12abcef8 100644 --- a/src/lib/onboard/windows-host-ollama.test.ts +++ b/src/lib/onboard/windows-host-ollama.test.ts @@ -3,10 +3,10 @@ import { afterEach, describe, expect, it, vi } from "vitest"; -const runCapture = vi.fn<(command: string | string[]) => string>(() => ""); +const runCapture = vi.fn<(cmd: readonly string[]) => string>(() => ""); vi.mock("../runner", () => ({ - runCapture: (command: string | string[]) => runCapture(command), + runCapture: (cmd: readonly string[]) => runCapture(cmd), })); vi.mock("../platform", () => ({ @@ -24,8 +24,8 @@ describe("detectWindowsHostOllama", () => { it("detects installed-but-not-running Ollama via known install path (#4066)", () => { const knownPath = "C:\\Users\\tester\\AppData\\Local\\Programs\\Ollama\\ollama.exe"; - runCapture.mockImplementation((command) => { - const cmd = Array.isArray(command) ? command.join(" ") : command; + runCapture.mockImplementation((command: readonly string[]) => { + const cmd = command.join(" "); if (cmd.includes("Get-Command ollama.exe")) return ""; if (cmd.includes("Get-Process ollama") && cmd.includes("Path")) return ""; if (cmd.includes("Get-Process ollama") && cmd.includes("Id")) return "";