all repos — sz-chrome-remote-cdp @ a9bdbd8590801cd9c2fa0cda6203948ac19a779c

pi-browser-harness, patched to drive a Chrome on another host over CDP, with castle_cdp_search web search

refactor: tidy the whitespace the comment removal left behind

Drops leading blank lines where a file header was removed, collapses
double blank lines, and closes the empty catch/handler blocks whose only
content had been a comment. Whitespace only.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Tue, 28 Jul 2026 20:34:49 +0530
commit

a9bdbd8590801cd9c2fa0cda6203948ac19a779c

parent

34e5cfdcbe29bbb5f2f46ba54eb67903abd9274d

M src/cdp/console-buffer.ts → src/cdp/console-buffer.ts

@@ -1,4 +1,3 @@

- import { decodeEvent } from "./events"; export type ConsoleLevel = "log" | "info" | "warn" | "error" | "debug";

@@ -43,8 +42,7 @@ if (pattern.length >= 2 && pattern.startsWith("/") && pattern.endsWith("/")) {

try { const re = new RegExp(pattern.slice(1, -1)); return (text) => re.test(text); - } catch { - } + } catch {} } return (text) => text.includes(pattern); };
M src/cdp/daemon-transport.ts → src/cdp/daemon-transport.ts

@@ -1,4 +1,3 @@

- import { createConnection, type Socket } from "node:net"; import { createInterface } from "node:readline"; import { type Result, err, ok } from "../util/result";

@@ -13,7 +12,6 @@ type WireControl,

deserialize, serialize, } from "../daemon/protocol"; - export const createDaemonTransport = (clientId: string): CdpTransport => { let socket: Socket | null = null;

@@ -35,7 +33,6 @@ if (socket) { try { socket.destroy(); } catch {} socket = null; }

for (const cb of closeListeners) cb(); }; - const connect = (_url: string, opts?: { timeoutMs?: number }): Promise<Result<void, CdpError>> => { const timeoutMs = opts?.timeoutMs ?? 10_000;

@@ -117,8 +114,7 @@ return;

} }); - sock.on("error", () => { - }); + sock.on("error", () => {}); sock.on("close", () => { clearTimeout(connectTimer);

@@ -140,7 +136,6 @@ });

}); }; - const close = async (): Promise<void> => { if (registered && socket && !socket.destroyed) { const dereg: WireControl = { type: "control", action: "deregister", clientId };

@@ -148,7 +143,6 @@ try { socket.write(serialize(dereg) + "\n"); } catch {}

} cleanup("close() called"); }; - const request = ( method: string,

@@ -175,9 +169,7 @@

return sendWithTimeout(pending, id, method, timeoutMs, "Daemon", () => sock.write(serialize(req) + "\n")); }; - const events = (): AsyncIterable<CdpEvent> => queue.iter; - const state = (): "open" | "closed" | "connecting" => { if (!socket) return "closed";
M src/cdp/discovery.ts → src/cdp/discovery.ts

@@ -114,8 +114,7 @@ try {

raw = await readFile(portFile, "utf8"); try { mtimeMs = (await stat(portFile)).mtimeMs; - } catch { - } + } catch {} } catch (e) { // EPERM/EACCES is common under sandboxes; remember it and fall back to network probing rather than failing the whole discovery. const code = errnoCode(e);
M src/cdp/event-queue.ts → src/cdp/event-queue.ts

@@ -1,4 +1,3 @@

- import { type Result, err } from "../util/result"; import { type CdpError, cdpError } from "./errors"; import type { CdpEvent } from "./types";
M src/cdp/network-buffer.ts → src/cdp/network-buffer.ts

@@ -1,4 +1,3 @@

- import { decodeEvent } from "./events"; export type NetworkRecord = {

@@ -47,8 +46,7 @@ if (pattern.length >= 2 && pattern.startsWith("/") && pattern.endsWith("/")) {

try { const re = new RegExp(pattern.slice(1, -1)); return (url) => re.test(url); - } catch { - } + } catch {} } return (url) => url.includes(pattern); };
M src/cdp/ownership.ts → src/cdp/ownership.ts

@@ -1,4 +1,3 @@

- export type OwnershipRegistry = { add(targetId: string): void; remove(targetId: string): void;
M src/daemon/bridge.ts → src/daemon/bridge.ts

@@ -1,4 +1,3 @@

- import WebSocket from "ws"; import { discoverWsUrl } from "../cdp/discovery"; import { isCdpRawMessage } from "../cdp/types";

@@ -6,7 +5,6 @@ import type { CdpRawMessage } from "../cdp/types";

import type { WireRequest, WireResponse, WireEvent } from "./protocol"; import { CDP_CONNECT_TIMEOUT_MS, CDP_COMMAND_TIMEOUT_MS } from "./protocol"; import { asString, isRecord } from "../util/guards"; - export type SendToClient = (clientId: string, msg: WireResponse | WireEvent) => void;

@@ -26,7 +24,6 @@ removeClient(clientId: string): void;

onEvent(handler: EventHandler): void; onClose(handler: CloseHandler): void; }; - interface PendingEntry { clientId: string;

@@ -62,7 +59,6 @@ if (m) { for (const [, did] of m) this.pending.delete(did); }

this.localToRemote.delete(clientId); } } - class EventRouter { private owners = new Map<string, string>();

@@ -108,7 +104,6 @@ return [...this.clientSessions.keys()];

} } - export const createCdpBridge = (): CdpBridge => { let ws: WebSocket | null = null; let wsUrl: string | null = null;

@@ -124,7 +119,6 @@ localId: number;

timer: ReturnType<typeof setTimeout>; isAttach: boolean; }>(); - const onChromeMessage = (raw: string): void => { let parsed: unknown;

@@ -183,8 +177,6 @@ eventHandler(wireEvent, targets);

} } }; - - let reconnectTimer: ReturnType<typeof setTimeout> | null = null; let reconnectAttempt = 0;
M src/daemon/index.ts → src/daemon/index.ts

@@ -1,4 +1,3 @@

- import { createIpcServer } from "./server"; import { createCdpBridge, type SendToClient } from "./bridge"; import { DAEMON_IDLE_TIMEOUT_MS } from "./protocol";

@@ -8,7 +7,6 @@ console.log("[pi-browser-daemon] Starting...");

const ipcServer = createIpcServer(); const cdpBridge = createCdpBridge(); - ipcServer.onMessage((msg, client) => { if (msg.type !== "request") return;

@@ -38,7 +36,6 @@ action: "shutdown",

reason: "chrome_disconnected", }); }); - let idleTimer: ReturnType<typeof setTimeout> | null = null;

@@ -60,7 +57,6 @@

ipcServer.onConnect(() => { cancelIdleTimer(); }); ipcServer.onDisconnect(() => { resetIdleTimer(); }); - try { await ipcServer.start(); console.log("[pi-browser-daemon] IPC server listening");

@@ -72,7 +68,6 @@

await cdpBridge.start(); resetIdleTimer(); - const shutdown = async () => { console.log("[pi-browser-daemon] Shutting down...");
M src/daemon/protocol.ts → src/daemon/protocol.ts

@@ -1,6 +1,4 @@

- import { isRecord } from "../util/guards"; - export type WireRequest = { readonly type: "request";

@@ -36,7 +34,6 @@ readonly reason?: string;

}; export type WireMessage = WireRequest | WireResponse | WireEvent | WireControl; - export const isWireMessage = (v: unknown): v is WireMessage => { if (!isRecord(v)) return false;

@@ -85,7 +82,6 @@ return false;

} }; - export const serialize = (msg: WireMessage): string => JSON.stringify(msg); export const deserialize = (line: string): WireMessage | null => {

@@ -98,7 +94,6 @@ }

if (!isWireMessage(parsed)) return null; return parsed; }; - // Windows requires a named pipe (`\\.\pipe\<name>`); a Unix path is not a valid `net` listen/connect target there. export const DAEMON_SOCKET_PATH =
M src/daemon/server.ts → src/daemon/server.ts

@@ -1,4 +1,3 @@

- import { createServer, type Server, type Socket } from "node:net"; import { createInterface, type Interface } from "node:readline"; import { unlinkSync } from "node:fs";

@@ -10,7 +9,6 @@ DAEMON_SOCKET_PATH,

DAEMON_MAX_CLIENTS, DAEMON_STALE_SOCKET_CLEANUP, } from "./protocol"; - export type ClientSocket = { id: string;

@@ -35,7 +33,6 @@ disconnectClient(clientId: string): void;

clients(): ReadonlyMap<string, ClientSocket>; clientCount(): number; }; - export const createIpcServer = (): IpcServer => { let server: Server | null = null;

@@ -51,8 +48,7 @@ new Promise((resolve, reject) => {

if (DAEMON_STALE_SOCKET_CLEANUP) { try { unlinkSync(DAEMON_SOCKET_PATH); - } catch { - } + } catch {} } server = createServer({ pauseOnConnect: false }, (socket: Socket) => {

@@ -113,8 +109,7 @@

messageHandler?.(msg, currentClient); }); - socket.on("error", () => { - }); + socket.on("error", () => {}); socket.on("close", () => { const found = clients.get(currentClient.id) ?? sockets.get(tempId);

@@ -176,8 +171,7 @@ const client = clients.get(clientId);

if (!client) return; try { client.socket.write(JSON.stringify(msg) + "\n"); - } catch { - } + } catch {} }, broadcast(msg) { for (const [clientId] of clients) {
M src/daemon/spawn.ts → src/daemon/spawn.ts

@@ -1,4 +1,3 @@

- import { spawn, type ChildProcess } from "node:child_process"; import { access, unlink } from "node:fs/promises"; import { existsSync } from "node:fs";
M src/deep-research.ts → src/deep-research.ts

@@ -1,6 +1,4 @@

- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; - export function buildDeepResearchPrompt(question: string): string { return (

@@ -10,7 +8,6 @@ `subagents to research each against the live web, then synthesize a source-cited report file.\n\n` +

`Question: ${question}` ); } - export function registerDeepResearchCommand(pi: ExtensionAPI): void { pi.registerCommand("deep-research", {
M src/domains/readpage/capture.ts → src/domains/readpage/capture.ts

@@ -1,4 +1,3 @@

- const BODY_TEXT_LIMIT = 20_000; export const buildPageCaptureExpr = (): string => `
M src/domains/readpage/readability.ts → src/domains/readpage/readability.ts

@@ -1,4 +1,3 @@

- export type ContentBlock = { readonly kind: "paragraph" | "heading" | "listitem" | "blockquote" | "other"; readonly text: string;
M src/domains/search/extract.ts → src/domains/search/extract.ts

@@ -1,4 +1,3 @@

- const PAGE_TEXT_LIMIT = 4000; export const buildSerpExtractionExpr = (): string => `
M src/domains/search/google-serp.ts → src/domains/search/google-serp.ts

@@ -1,4 +1,3 @@

- export type SerpAnchor = { readonly href: string; readonly heading: string;
M src/domains/setup.ts → src/domains/setup.ts

@@ -1,4 +1,3 @@

- import { Type } from "typebox"; import { Text } from "@mariozechner/pi-tui"; import type { Result } from "../util/result";
M src/index.ts → src/index.ts

@@ -1,4 +1,3 @@

- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; import { type BrowserClient, createBrowserClient } from "./client"; import { getBrowserSystemPrompt } from "./prompt";

@@ -118,7 +117,6 @@ });

} else { client.setProfilePin(profilePin); } - if (!toolsRegistered) { registerAllTools(pi, client);
M src/profile/bind.ts → src/profile/bind.ts

@@ -1,4 +1,3 @@

- import type { BrowserClient } from "../client"; import { attachTo } from "../cdp/attach"; import type { ResultOf } from "../cdp/commands";
M src/profile/browser-process.ts → src/profile/browser-process.ts

@@ -106,7 +106,6 @@ const value = match[1] ?? match[2] ?? match[3];

return value && value.length > 0 ? value : undefined; }; - const collectLinux = async (): Promise<ReadonlyArray<BrowserCandidate>> => { let pids: string[]; try {

@@ -135,8 +134,7 @@ if (!cmdline || hasChildProcessType(cmdline)) continue;

let link: string | undefined; try { link = await readlink(`/proc/${pid}/exe`); - } catch { - } + } catch {} // Chrome rewrites its argv to the bare executable path, so argv[0] is the live install location when /proc/<pid>/exe is unreadable or stale. const exePath = (link ? await spawnableExePath(link) : undefined) ??

@@ -149,7 +147,6 @@ });

} return candidates; }; - const collectDarwin = async (): Promise<ReadonlyArray<BrowserCandidate>> => { let lines: string[];

@@ -175,8 +172,7 @@ let args = "";

try { const { stdout } = await run("ps", ["-ww", "-o", "args=", "-p", pid], { timeout: EXEC_TIMEOUT_MS }); args = stdout.trim(); - } catch { - } + } catch {} if (args && hasChildProcessType(args)) continue; const explicit = args ? parseUserDataDirFlag(args) : undefined; candidates.push({

@@ -186,7 +182,6 @@ });

} return candidates; }; - const POWERSHELL_QUERY = [ "$ErrorActionPreference='SilentlyContinue';",

@@ -232,15 +227,13 @@ });

if (candidates.length > 0) return candidates; } } - } catch { - } + } catch {} try { const { stdout } = await run("tasklist.exe", [], { timeout: EXEC_TIMEOUT_MS, windowsHide: true }); const lower = stdout.toLowerCase(); if (WIN_IMAGE_NAMES.some((n) => lower.includes(n))) return [{}]; - } catch { - } + } catch {} return []; };

@@ -273,13 +266,11 @@ );

const match = /REG_[A-Z_]+\s+(.+)$/m.exec(stdout.trim()); const path = match?.[1]?.trim(); if (path) return path; - } catch { - } + } catch {} } } return undefined; }; - export const detectRunningBrowser = async (preferUserDataDir?: string): Promise<RunningBrowser> => { const candidates =

@@ -323,8 +314,7 @@ for (const candidate of winInstallCandidates()) {

try { await access(candidate); return candidate; - } catch { - } + } catch {} } return undefined; };
M src/profile/command.ts → src/profile/command.ts

@@ -1,4 +1,3 @@

- import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent"; import type { BrowserClient } from "../client"; import { discoverEndpoint } from "../cdp/discovery";
M src/profile/list.ts → src/profile/list.ts

@@ -1,4 +1,3 @@

- import { readdir, readFile } from "node:fs/promises"; import { join } from "node:path"; import { Type } from "typebox";
M src/profile/paths.ts → src/profile/paths.ts

@@ -3,7 +3,6 @@

import { homedir } from "node:os"; import { join } from "node:path"; - const ENV_AGENT_DIR = "PI_CODING_AGENT_DIR"; // Deliberately mirrors pi's expandTildePath (never `~\…`) rather than improving on it, or the pin lands somewhere pi does not look.

@@ -26,7 +25,6 @@ return join(homedir(), ".pi", "agent");

}; export const pinFilePath = (): string => join(agentDir(), "browser-harness.json"); - const localAppData = (): string => process.env["LOCALAPPDATA"] ?? join(homedir(), "AppData", "Local");
M src/setup.ts → src/setup.ts

@@ -1,11 +1,9 @@

- import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent"; import type { BrowserClient } from "./client"; import { ensureDaemon } from "./daemon/spawn"; import { DAEMON_SOCKET_PATH } from "./daemon/protocol"; import { isBrowserRunning } from "./profile/browser-process"; import { promptForProfileIfUnset } from "./profile/command"; - export function registerSetupCommand(pi: ExtensionAPI, client: BrowserClient): void { pi.registerCommand("browser-setup", {

@@ -21,9 +19,7 @@ },

}); } - export type SetupResult = { success: true; data: string } | { success: false; error: string }; - export async function performSetup(client: BrowserClient, ctx?: ExtensionContext): Promise<SetupResult> { const chromeRunning = await isBrowserRunning();
M src/state.ts → src/state.ts

@@ -1,4 +1,3 @@

- import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent"; import { asArrayOf, asNumber, asString, isRecord } from "./util/guards";
M test/manual/e2e-test.ts → test/manual/e2e-test.ts

@@ -34,14 +34,12 @@

await ipcServer.start(); console.log("Daemon started ✓"); - console.log("\nConnecting pi client (DaemonTransport)..."); const transport = createDaemonTransport("pi-e2e-test"); const connectResult = await transport.connect(""); check(connectResult.success, `Client connect: ${connectResult.success ? "ok" : connectResult.error.message}`); check(transport.state() === "open", "Transport state is open"); - let rawRequests: WireRequest[] = []; ipcServer.onMessage((msg, client) => {
M test/manual/profile-concurrency-test.ts → test/manual/profile-concurrency-test.ts

@@ -44,8 +44,7 @@ if (pid === undefined) return;

if (process.platform === "win32") { try { execFileSync("taskkill.exe", ["/pid", String(pid), "/T", "/F"], { stdio: "ignore" }); - } catch { - } + } catch {} return; } try {

@@ -53,8 +52,7 @@ process.kill(-pid, "SIGKILL");

} catch { try { process.kill(pid, "SIGKILL"); - } catch { - } + } catch {} } };

@@ -81,8 +79,7 @@ await sleep(500);

try { const res = await fetch(`http://127.0.0.1:${PORT}/json/version`); if (res.ok) endpoint = ((await res.json()) as { webSocketDebuggerUrl: string }).webSocketDebuggerUrl; - } catch { - } + } catch {} } if (!endpoint) { check(false, `${label}: browser exposed its DevTools endpoint`);

@@ -144,8 +141,7 @@ } finally {

killTree(browser.pid); try { rmSync(udd, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 }); - } catch { - } + } catch {} } }
M test/manual/profile-e2e-test.ts → test/manual/profile-e2e-test.ts

@@ -47,8 +47,7 @@ for (const name of ["google-chrome", "chromium", "chromium-browser"]) {

try { const resolved = execFileSync("which", [name], { encoding: "utf8" }).trim(); if (resolved) return resolved; - } catch { - } + } catch {} } } return undefined;

@@ -96,8 +95,7 @@ while (Date.now() < end) {

try { const res = await fetch(`http://127.0.0.1:${PORT}/json/version`); if (res.ok) return true; - } catch { - } + } catch {} await sleep(500); } return false;

@@ -132,8 +130,7 @@ // Any surviving child keeps the user-data-dir locked, which on Windows also blocks the directory removal.

if (process.platform === "win32") { try { execFileSync("taskkill.exe", ["/pid", String(browser.pid), "/T", "/F"], { stdio: "ignore" }); - } catch { - } + } catch {} } else { try { // detached:true put the browser in its own process group, so the negative pid signals the whole group.

@@ -141,14 +138,12 @@ process.kill(-browser.pid!, "SIGKILL");

} catch { try { browser.kill("SIGKILL"); - } catch { - } + } catch {} } } try { rmSync(udd, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 }); - } catch { - } + } catch {} }; try {
M test/manual/socket-guard-test.ts → test/manual/socket-guard-test.ts

@@ -1,4 +1,3 @@

- import { access } from "node:fs/promises"; import { setTimeout as sleep } from "node:timers/promises"; import { spawn } from "node:child_process";