Skip to content

Commit c32748b

Browse files
committed
docs: document browser cdp runtime
1 parent a3af426 commit c32748b

5 files changed

Lines changed: 91 additions & 0 deletions

File tree

extensions/browser/src/browser/bridge-server.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
/**
2+
* Loopback browser bridge server.
3+
*
4+
* Hosts the browser control routes on an authenticated local port for sandbox,
5+
* host, and node browser integrations that need HTTP access to browser control.
6+
*/
17
import type { Server } from "node:http";
28
import type { AddressInfo } from "node:net";
39
import express from "express";
@@ -13,6 +19,7 @@ import {
1319
installBrowserCommonMiddleware,
1420
} from "./server-middleware.js";
1521

22+
/** Running bridge server details returned to callers that manage its lifecycle. */
1623
export type BrowserBridge = {
1724
server: Server;
1825
port: number;
@@ -54,6 +61,7 @@ function buildNoVncBootstrapHtml(params: ResolvedNoVncObserver): string {
5461
</html>`;
5562
}
5663

64+
/** Start an authenticated loopback browser bridge and register browser routes. */
5765
export async function startBrowserBridgeServer(params: {
5866
resolved: ResolvedBrowserConfig;
5967
host?: string;
@@ -144,6 +152,7 @@ export async function startBrowserBridgeServer(params: {
144152
return { server, port: resolvedPort, baseUrl, state };
145153
}
146154

155+
/** Stop a browser bridge server and clear its ephemeral port auth. */
147156
export async function stopBrowserBridgeServer(server: Server): Promise<void> {
148157
try {
149158
const address = server.address() as AddressInfo | null;

extensions/browser/src/browser/cdp.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
/**
2+
* Chrome DevTools Protocol browser operations.
3+
*
4+
* Provides screenshots, target creation, JavaScript evaluation, ARIA/role
5+
* snapshots, DOM text, and selector lookup on top of the CDP socket helpers.
6+
*/
17
import { resolveIntegerOption } from "openclaw/plugin-sdk/number-runtime";
28
import type { SsrFPolicy } from "../infra/net/ssrf.js";
39
import {
@@ -22,6 +28,7 @@ export {
2228
isWebSocketUrl,
2329
} from "./cdp.helpers.js";
2430

31+
/** Normalize a reported CDP WebSocket URL against the configured CDP base URL. */
2532
export function normalizeCdpWsUrl(wsUrl: string, cdpUrl: string): string {
2633
const ws = new URL(wsUrl);
2734
const cdp = new URL(cdpUrl);
@@ -58,6 +65,7 @@ export function normalizeCdpWsUrl(wsUrl: string, cdpUrl: string): string {
5865
return ws.toString();
5966
}
6067

68+
/** Capture a PNG screenshot through CDP. */
6169
export async function captureScreenshotPng(opts: {
6270
wsUrl: string;
6371
fullPage?: boolean;
@@ -71,6 +79,7 @@ export async function captureScreenshotPng(opts: {
7179
});
7280
}
7381

82+
/** Capture a PNG or JPEG screenshot through CDP, optionally full-page. */
7483
export async function captureScreenshot(opts: {
7584
wsUrl: string;
7685
fullPage?: boolean;
@@ -183,11 +192,13 @@ export async function captureScreenshot(opts: {
183192
);
184193
}
185194

195+
/** HTTP and WebSocket timeout options for CDP actions that need discovery. */
186196
export type CdpActionTimeouts = {
187197
httpTimeoutMs?: number;
188198
handshakeTimeoutMs?: number;
189199
};
190200

201+
/** Create a new browser target after applying navigation and CDP SSRF policy. */
191202
export async function createTargetViaCdp(opts: {
192203
cdpUrl: string;
193204
url: string;
@@ -302,6 +313,7 @@ async function prepareCdpPageSession(send: CdpSendFn, sessionId?: string): Promi
302313
await send("Runtime.runIfWaitingForDebugger", undefined, sessionId).catch(() => {});
303314
}
304315

316+
/** Runtime.evaluate remote-object subset used by CDP helpers. */
305317
export type CdpRemoteObject = {
306318
type: string;
307319
subtype?: string;
@@ -311,6 +323,7 @@ export type CdpRemoteObject = {
311323
preview?: unknown;
312324
};
313325

326+
/** Exception details surfaced from CDP Runtime.evaluate. */
314327
export type CdpExceptionDetails = {
315328
text?: string;
316329
lineNumber?: number;
@@ -319,6 +332,7 @@ export type CdpExceptionDetails = {
319332
stackTrace?: unknown;
320333
};
321334

335+
/** Evaluate JavaScript in a CDP target and return by value when possible. */
322336
export async function evaluateJavaScript(opts: {
323337
wsUrl: string;
324338
expression: string;
@@ -349,6 +363,7 @@ export async function evaluateJavaScript(opts: {
349363
});
350364
}
351365

366+
/** Normalized accessibility tree node returned by ARIA snapshots. */
352367
export type AriaSnapshotNode = {
353368
ref: string;
354369
role: string;
@@ -359,9 +374,11 @@ export type AriaSnapshotNode = {
359374
depth: number;
360375
};
361376

377+
/** Prefix assigned to generated accessibility-node refs. */
362378
export const AX_REF_PREFIX = "ax";
363379
export const AX_REF_PATTERN = new RegExp(`^${AX_REF_PREFIX}\\d+$`);
364380

381+
/** Raw accessibility node subset read from CDP Accessibility.getFullAXTree. */
365382
export type RawAXNode = {
366383
nodeId?: string;
367384
role?: { value?: string };
@@ -386,6 +403,7 @@ function axValue(v: unknown): string {
386403
return "";
387404
}
388405

406+
/** Format raw AX nodes into bounded ARIA snapshot nodes. */
389407
export function formatAriaSnapshot(nodes: RawAXNode[], limit: number): AriaSnapshotNode[] {
390408
const byId = new Map<string, RawAXNode>();
391409
for (const n of nodes) {
@@ -454,6 +472,7 @@ export function formatAriaSnapshot(nodes: RawAXNode[], limit: number): AriaSnaps
454472
return out;
455473
}
456474

475+
/** Capture an accessibility-tree snapshot through CDP. */
457476
export async function snapshotAria(opts: {
458477
wsUrl: string;
459478
limit?: number;
@@ -474,6 +493,7 @@ export async function snapshotAria(opts: {
474493
);
475494
}
476495

496+
/** Role snapshot ref metadata used by agent-facing snapshots. */
477497
export type CdpRoleRef = {
478498
role: string;
479499
name?: string;
@@ -482,6 +502,7 @@ export type CdpRoleRef = {
482502
frameId?: string;
483503
};
484504

505+
/** Options for CDP role snapshot extraction and compaction. */
485506
export type CdpRoleSnapshotOptions = {
486507
interactive?: boolean;
487508
compact?: boolean;
@@ -919,6 +940,7 @@ async function buildCdpRoleSnapshot(params: {
919940
};
920941
}
921942

943+
/** Build a role/name text snapshot with stable refs from CDP DOM and AX data. */
922944
export async function snapshotRoleViaCdp(opts: {
923945
wsUrl: string;
924946
options?: CdpRoleSnapshotOptions;
@@ -958,6 +980,7 @@ export async function snapshotRoleViaCdp(opts: {
958980
);
959981
}
960982

983+
/** Capture a raw DOM snapshot through CDP. */
961984
export async function snapshotDom(opts: {
962985
wsUrl: string;
963986
limit?: number;
@@ -1028,6 +1051,7 @@ export async function snapshotDom(opts: {
10281051
return { nodes: Array.isArray(nodes) ? (nodes as DomSnapshotNode[]) : [] };
10291052
}
10301053

1054+
/** Simplified DOM node returned by DOM snapshot helpers. */
10311055
export type DomSnapshotNode = {
10321056
ref: string;
10331057
parentRef: string | null;
@@ -1043,6 +1067,7 @@ export type DomSnapshotNode = {
10431067
value?: string;
10441068
};
10451069

1070+
/** Extract visible DOM text from a CDP target. */
10461071
export async function getDomText(opts: {
10471072
wsUrl: string;
10481073
format: "html" | "text";
@@ -1084,6 +1109,7 @@ export async function getDomText(opts: {
10841109
return { text };
10851110
}
10861111

1112+
/** Query a selector in a CDP target and return matching node metadata. */
10871113
export async function querySelector(opts: {
10881114
wsUrl: string;
10891115
selector: string;
@@ -1139,6 +1165,7 @@ export async function querySelector(opts: {
11391165
return { matches: Array.isArray(matches) ? (matches as QueryMatch[]) : [] };
11401166
}
11411167

1168+
/** Selector match metadata returned by querySelector. */
11421169
export type QueryMatch = {
11431170
index: number;
11441171
tag: string;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
/**
2+
* Lazy Chrome MCP module loader.
3+
*
4+
* Keeps the heavy chrome-devtools-mcp adapter behind a runtime import boundary
5+
* for routes that only need it when existing-session profiles are selected.
6+
*/
17
type ChromeMcpModule = typeof import("./chrome-mcp.js");
28

9+
/** Import the Chrome MCP adapter module on demand. */
310
export async function getChromeMcpModule(): Promise<ChromeMcpModule> {
411
return await import("./chrome-mcp.js");
512
}

extensions/browser/src/browser/chrome-mcp.snapshot.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
/**
2+
* Chrome MCP snapshot conversion helpers.
3+
*
4+
* Converts chrome-devtools-mcp structured snapshots into OpenClaw ARIA nodes
5+
* and compact AI snapshots with stable refs and duplicate tracking.
6+
*/
17
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
28
import { normalizeString } from "../record-shared.js";
39
import type { SnapshotAriaNode } from "./client.types.js";
@@ -8,6 +14,7 @@ import {
814
} from "./pw-role-snapshot.js";
915
import { CONTENT_ROLES, INTERACTIVE_ROLES, STRUCTURAL_ROLES } from "./snapshot-roles.js";
1016

17+
/** Structured snapshot node shape returned by chrome-devtools-mcp. */
1118
export type ChromeMcpSnapshotNode = {
1219
id?: string;
1320
role?: string;
@@ -75,6 +82,7 @@ function registerRef(
7582
return undefined;
7683
}
7784

85+
/** Flatten a Chrome MCP snapshot tree into OpenClaw ARIA-style nodes. */
7886
export function flattenChromeMcpSnapshotToAriaNodes(
7987
root: ChromeMcpSnapshotNode,
8088
limit = 500,
@@ -109,6 +117,7 @@ export function flattenChromeMcpSnapshotToAriaNodes(
109117
return out;
110118
}
111119

120+
/** Build a compact text snapshot and ref map from a Chrome MCP snapshot tree. */
112121
export function buildAiSnapshotFromChromeMcpSnapshot(params: {
113122
root: ChromeMcpSnapshotNode;
114123
options?: RoleSnapshotOptions;

0 commit comments

Comments
 (0)