aboutsummaryrefslogtreecommitdiff
path: root/src/protocol.ts
diff options
context:
space:
mode:
authoramankumarsingh77 <amankumarsingh7702@gmal.com>2026-04-29 01:38:17 +0530
committeramankumarsingh77 <amankumarsingh7702@gmal.com>2026-04-29 01:38:17 +0530
commit63b16957587fe20566129ffc5191f66f24a70872 (patch)
tree8a40fa38e1ae5b4309b1e38d7a3779321f15db4e /src/protocol.ts
parent5317b32976edce3ab8e2f11d7fb4ff3f16dcac6f (diff)
Replace socket daemon with direct CDP WebSocket connection
Drops the Unix socket subprocess in favor of talking CDP directly over WebSocket from the extension. Removes the protocol's send/health helpers, simplifies setup to just verifying Chrome's remote debugging port, and tightens types in dynamic-tools. Bumps Node engine to >=22 and adds the ws dependency.
Diffstat (limited to 'src/protocol.ts')
-rw-r--r--src/protocol.ts134
1 files changed, 5 insertions, 129 deletions
diff --git a/src/protocol.ts b/src/protocol.ts
index 8edc79d..1b8bf40 100644
--- a/src/protocol.ts
+++ b/src/protocol.ts
@@ -1,36 +1,10 @@
/**
- * Protocol types and low-level socket communication for the browser-harness daemon.
+ * Protocol types for pi-browser-harness.
*
- * The daemon exposes a Unix socket at /tmp/bu-<NAME>.sock.
- * Protocol: one JSON-line request → one JSON-line response per connection.
+ * Defines the shape of CDP communication and browser state.
+ * No socket transport — the daemon talks CDP directly over WebSocket.
*/
-import { createConnection } from "node:net";
-
-// ── Request ──────────────────────────────────────────────────────────────────
-
-export interface DaemonRequest {
- /** CDP method (e.g. "Page.navigate") — absent for meta requests */
- method?: string;
- /** CDP parameters */
- params?: Record<string, unknown>;
- /** CDP session ID — null/absent for browser-level (Target.*) calls */
- session_id?: string | null;
- /** Meta command: "drain_events" | "set_session" | "pending_dialog" | "shutdown" */
- meta?: string;
-}
-
-// ── Response ─────────────────────────────────────────────────────────────────
-
-export interface DaemonResponse {
- result?: unknown;
- error?: string;
- events?: CDPEvent[];
- session_id?: string;
- dialog?: DialogInfo;
- ok?: boolean;
-}
-
// ── CDP Event ────────────────────────────────────────────────────────────────
export interface CDPEvent {
@@ -75,9 +49,9 @@ export type PageInfoResult = PageInfo | { dialog: DialogInfo };
export interface DaemonStatus {
alive: boolean;
sessionId: string | null;
- pid: number | null;
+ pid: number | null; // deprecated — always null (no subprocess)
namespace: string;
- socketPath: string;
+ socketPath: string; // deprecated — always "" (no socket)
remoteBrowserId?: string;
}
@@ -101,101 +75,3 @@ const INTERNAL_PREFIXES = [
export function isInternalUrl(url: string): boolean {
return INTERNAL_PREFIXES.some((p) => url.startsWith(p));
}
-
-// ── Low-level socket send ────────────────────────────────────────────────────
-
-/**
- * Send a single JSON-line request to the daemon socket and read one JSON-line response.
- * Opens a fresh connection per request (stateless, matches helpers.py _send pattern).
- */
-export function sendRequest(
- socketPath: string,
- request: DaemonRequest,
- timeoutMs = 15_000,
-): Promise<DaemonResponse> {
- return new Promise((resolve, reject) => {
- const socket = createConnection(socketPath);
-
- const timer = setTimeout(() => {
- socket.destroy();
- reject(new Error(`Daemon request timed out after ${timeoutMs}ms: ${JSON.stringify(request.method ?? request.meta)}`));
- }, timeoutMs);
-
- let buffer = "";
-
- socket.on("connect", () => {
- socket.write(JSON.stringify(request) + "\n");
- });
-
- socket.on("data", (chunk: Buffer) => {
- buffer += chunk.toString();
- // Response is one JSON line ending with \n
- if (buffer.includes("\n")) {
- clearTimeout(timer);
- const line = buffer.split("\n")[0];
- try {
- const response: DaemonResponse = JSON.parse(line);
- socket.end();
- resolve(response);
- } catch (e) {
- socket.end();
- reject(new Error(`Failed to parse daemon response: ${line.slice(0, 200)}`));
- }
- }
- });
-
- socket.on("error", (err: NodeJS.ErrnoException) => {
- clearTimeout(timer);
- socket.destroy();
- reject(new Error(`Daemon socket error (${socketPath}): ${err.message}`));
- });
-
- socket.on("close", () => {
- clearTimeout(timer);
- if (buffer.length === 0) {
- reject(new Error(`Daemon socket closed without response (${socketPath})`));
- }
- });
- });
-}
-
-/**
- * Quick check if the daemon socket accepts connections.
- */
-export function daemonAlive(socketPath: string, timeoutMs = 1000): Promise<boolean> {
- return new Promise((resolve) => {
- const socket = createConnection(socketPath);
- const timer = setTimeout(() => {
- socket.destroy();
- resolve(false);
- }, timeoutMs);
-
- socket.on("connect", () => {
- clearTimeout(timer);
- socket.end();
- resolve(true);
- });
-
- socket.on("error", () => {
- clearTimeout(timer);
- resolve(false);
- });
- });
-}
-
-/**
- * True health check: send Target.getTargets and verify "result" key in response.
- * A stale daemon can accept socket connections but have a dead CDP websocket.
- */
-export async function healthProbe(socketPath: string): Promise<boolean> {
- try {
- const response = await sendRequest(
- socketPath,
- { method: "Target.getTargets", params: {} },
- 3000,
- );
- return "result" in response && response.result !== undefined;
- } catch {
- return false;
- }
-}