diff options
| author | Igor Soarez <igor@soarez.me> | 2026-08-30 16:27:22 +0100 |
|---|---|---|
| committer | Igor Soarez <igor@soarez.org> | 2026-10-14 12:19:26 +0100 |
| commit | c8fd7b7078da841d5537aee9334291887445889f (patch) | |
| tree | 2ee3611d169dc872bde0af8be186e1356af17e7d /src/profile/command.ts | |
| parent | 3a0bfc3af446a947f8392aaa3e3b2605ea7ad2da (diff) | |
fix(profile): never prompt for a profile when driving a remote browser
Profile selection works by launching the browser with --profile-directory and
letting ProcessSingleton delegate to the running process, which only reaches a
browser on this machine. discoverEndpoint() already withholds userDataDir for a
remote target, but resolveUserDataDir() fell through to the local candidate
dirs, so the picker offered this disk's Chromium profiles for a browser on
another host - on castle, Brave's profiles for a Chrome on :9223. Pinning one
launched a local browser and polled the remote for a sentinel that could never
appear, failing after the seed deadline; seedProfileWindow()'s mismatch guard
missed it because connectedDir is undefined on the remote path.
Setup now returns early instead of prompting - the question had no actionable
answer, and since cancelling stores nothing it returned every session.
/browser-profile and seedProfileWindow() refuse with the reason, the latter
catching a pin left over from a local session.
Diffstat (limited to 'src/profile/command.ts')
| -rw-r--r-- | src/profile/command.ts | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/src/profile/command.ts b/src/profile/command.ts index 270b42f..ea0ddcc 100644 --- a/src/profile/command.ts +++ b/src/profile/command.ts @@ -1,6 +1,8 @@ import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent"; import type { BrowserClient } from "../client"; import { discoverEndpoint } from "../cdp/discovery"; +import { currentCdpTarget } from "../cdp/current-target"; +import { describeCdpTarget } from "../cdp/endpoint"; import { type Result, err, ok } from "../util/result"; import { type BrowserProfile, listProfiles } from "./list"; import { browserNameForUserDataDir, userDataDirCandidates } from "./paths"; @@ -60,6 +62,21 @@ const resolveUserDataDir = async (client: BrowserClient): Promise<Result<string, const endpoint = await discoverEndpoint(); if (endpoint.success && endpoint.data.userDataDir) return ok(endpoint.data.userDataDir); + // A remote browser has no user-data-dir on THIS disk. Falling through to the + // local candidates below would enumerate whatever Chromium browsers happen to + // be installed here and offer their profiles for a browser on another host — + // profiles the harness is not connected to and cannot open a window in. Worse, + // pinning one sends seedProfileWindow() off to launch a local browser whose + // sentinel page can never appear over this connection. + const target = await currentCdpTarget(); + if (target.kind === "remote") { + return err( + `Profile selection needs a browser on this machine, but the harness is driving ${describeCdpTarget(target)}. ` + + "Choosing a profile works by launching the browser with --profile-directory, which only reaches a local browser. " + + "Run /browser-target local to drive this machine's browser, then /browser-profile.", + ); + } + const withProfiles: string[] = []; for (const dir of userDataDirCandidates()) { if ((await listProfiles(dir)).length > 0) withProfiles.push(dir); @@ -164,6 +181,13 @@ export const promptForProfileIfUnset = async ( client.setProfilePin(stored); return undefined; } + // Never prompt for a remote browser. Profile selection cannot act on one (see + // resolveUserDataDir), so asking would be a blocking question with no useful + // answer — and every cancelled prompt stores nothing, so it would come back + // every session. Silence is correct here: the browser keeps its own default + // profile, and /browser-status already reports which browser is being driven. + if ((await currentCdpTarget()).kind === "remote") return undefined; + if (!ctx?.hasUI) { return "No browser profile selected — using whichever window is focused. Run /browser-profile to pin one."; } |
