cdp-toolkit 1.1.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,13 @@
1
1
  /**
2
- * network_mock.ts — a per-target FAKE BACKEND for the page: intercept matching
2
+ * network_mock.ts: a per-target FAKE BACKEND for the page: intercept matching
3
3
  * requests via the CDP Fetch domain and fulfill them with a canned response,
4
4
  * fail (abort) them, or let them continue (optionally with fault injection).
5
5
  * The rod `HijackRequests` capability the read-only console/network tools lack.
6
6
  *
7
7
  * This file is split into two layers:
8
8
  * 1. PURE logic (urlMatches / selectRule / buildFulfillParams / effectiveAction)
9
- * — no browser, unit-tested in test/network_mock.test.ts.
10
- * 2. STATEFUL tools (mockRequest / listMocks / clearMocks) — hold a persistent
9
+ * No browser needed, unit-tested in test/network_mock.test.ts.
10
+ * 2. STATEFUL tools (mockRequest / listMocks / clearMocks): hold a persistent
11
11
  * CDP connection per target; integration-tested in test/mock-smoke.ts.
12
12
  */
13
13
  import { CdpError, openPage, resolveTarget } from "../client.ts";
@@ -15,7 +15,7 @@ import type { CdpConnection } from "../client.ts";
15
15
  import type { Target, TargetSelector } from "../types.ts";
16
16
 
17
17
  /* ============================================================================
18
- * LAYER 1 — pure logic (no I/O)
18
+ * LAYER 1: pure logic (no I/O)
19
19
  * ========================================================================== */
20
20
 
21
21
  export type MockAction = "fulfill" | "fail" | "continue";
@@ -111,7 +111,7 @@ export function effectiveAction(rule: { action: MockAction; failRate?: number },
111
111
  }
112
112
 
113
113
  /* ============================================================================
114
- * LAYER 2 — stateful tools (persistent per-target CDP connection)
114
+ * LAYER 2: stateful tools (persistent per-target CDP connection)
115
115
  *
116
116
  * A "fake backend" is a per-target SESSION holding ONE persistent CDP connection
117
117
  * with the Fetch domain enabled. Each session carries a list of rules; an
@@ -122,7 +122,7 @@ export function effectiveAction(rule: { action: MockAction; failRate?: number },
122
122
  * Persistence works because the MCP server process is long-lived across tool
123
123
  * calls, so this module-level `sessions` map and its open connections outlive a
124
124
  * single call. (The stateless CLI process exits after one command, so persistent
125
- * mocking is an MCP-server capability — like the recorder's background mode.)
125
+ * mocking is an MCP-server capability, like the recorder's background mode.)
126
126
  *
127
127
  * SAFETY: every paused request MUST be answered or the renderer hangs. A request
128
128
  * that pauses but matches no rule is continued untouched.
@@ -182,7 +182,7 @@ function registerHandler(session: MockSession): void {
182
182
  session.intercepted.push({ url: p.request.url, method: p.request.method, action: act });
183
183
  })
184
184
  .catch((e) => {
185
- // Tab navigated away mid-flight or the connection dropped — best-effort.
185
+ // Tab navigated away mid-flight or the connection dropped, best-effort.
186
186
  if (/closed|connection|Target|Inspected/i.test(String(e))) session.dead = true;
187
187
  });
188
188
  });
@@ -359,7 +359,7 @@ export async function clearMocks(args: ClearMocksArgs = {}): Promise<{ cleared:
359
359
  * Page.enable + Page.reload (reload:true), Runtime.evaluate (liveness probe).
360
360
  * Model: persistent per-target session (like recorder.ts), MCP-server-scoped state.
361
361
  * Parity gaps vs rod HijackRequests / chrome-devtools-mcp:
362
- * - Request-stage only — no live Response-body rewriting (add requestStage:"Response"
362
+ * - Request-stage only, no live Response-body rewriting (add requestStage:"Response"
363
363
  * + Fetch.getResponseBody/continueResponse for that).
364
364
  * - Persistence is in-process: works via the long-lived MCP server, not the
365
365
  * one-shot CLI (mirrors the recorder's background mode).
@@ -1,19 +1,19 @@
1
1
  /**
2
- * performance.ts — performance tracing + insight analysis over raw CDP.
2
+ * performance.ts: performance tracing + insight analysis over raw CDP.
3
3
  *
4
4
  * NOTE ON THE INSIGHT ANALYZER: `performanceAnalyzeInsight` is a CDP-native
5
5
  * APPROXIMATION of chrome-devtools-mcp's insight analyzer. The MCP tool runs the
6
6
  * DevTools/Lighthouse "Trace Engine" insight pipeline (a large TS engine that
7
7
  * models the full RAIL/Core-Web-Vitals heuristics). We do NOT vendor that
8
8
  * engine (zero-runtime-deps rule). Instead we parse the raw Chrome trace event
9
- * stream ourselves and derive the headline metrics — navigationStart, FCP, LCP,
10
- * long tasks (>50ms), layout shifts / CLS, and total blocking time — directly
9
+ * stream ourselves and derive the headline metrics (navigationStart, FCP, LCP,
10
+ * long tasks (>50ms), layout shifts / CLS, and total blocking time) directly
11
11
  * from the trace events. Numbers will be close to but not byte-identical with
12
12
  * the MCP/DevTools panel, which applies extra normalization (e.g. main-thread
13
13
  * attribution, frame-scoped LCP, soft-navigation handling).
14
14
  *
15
15
  * NOTE ON TRACING STATE: CDP `Tracing.start`/`Tracing.end` are bound to a single
16
- * live session — the recording lives on the WebSocket connection, and
16
+ * live session: the recording lives on the WebSocket connection, and
17
17
  * `Tracing.dataCollected` events stream back on that same connection. There is
18
18
  * no way to "re-attach" to an in-flight trace from a fresh process, because the
19
19
  * buffer is owned by the connection that started it. Cross-process persistence
@@ -213,7 +213,7 @@ export async function performanceStopTrace(
213
213
  ): Promise<{ path: string; bytes: number; events: number; metrics: TraceMetrics }> {
214
214
  // CDP tracing is browser-GLOBAL: a second Tracing.start throws "Tracing has
215
215
  // already been started", so at most one trace is ever live in this process.
216
- // There is therefore nothing to disambiguate by target — take the single live
216
+ // There is therefore nothing to disambiguate by target; take the single live
217
217
  // trace if present. (`args.target` is accepted for API symmetry with start.)
218
218
  void args.target;
219
219
  const entry: LiveTrace | undefined = liveTraces.size === 1 ? [...liveTraces.values()][0] : undefined;
@@ -250,7 +250,7 @@ export async function performanceStopTrace(
250
250
  }
251
251
 
252
252
  /* ------------------------------------------------------------------ */
253
- /* performanceTrace (PRIMARY one-shot — the smoke path) */
253
+ /* performanceTrace (PRIMARY one-shot, the smoke path) */
254
254
  /* ------------------------------------------------------------------ */
255
255
 
256
256
  export interface PerformanceTraceArgs {
@@ -366,7 +366,7 @@ export function analyzeEvents(events: TraceEvent[]): TraceMetrics {
366
366
  continue;
367
367
  }
368
368
 
369
- // LCP candidate — the LAST candidate before user input is the real LCP.
369
+ // LCP candidate: the LAST candidate before user input is the real LCP.
370
370
  if (name === "largestContentfulPaint::Candidate" && typeof e.ts === "number") {
371
371
  // candidates are monotonic; keep the latest timestamp seen.
372
372
  if (lcpUs === undefined || e.ts > lcpUs) lcpUs = e.ts;
@@ -383,7 +383,7 @@ export function analyzeEvents(events: TraceEvent[]): TraceMetrics {
383
383
  continue;
384
384
  }
385
385
 
386
- // Layout shifts — sum scores that did NOT follow recent user input.
386
+ // Layout shifts: sum scores that did NOT follow recent user input.
387
387
  if (name === "LayoutShift") {
388
388
  const data = e.args?.data;
389
389
  const hadRecentInput = data?.had_recent_input === true;
@@ -438,7 +438,7 @@ export interface PerformanceAnalyzeInsightArgs {
438
438
  /**
439
439
  * CDP-native approximation of the MCP insight analyzer. Reads a trace JSON file
440
440
  * (bare array OR { traceEvents: [...] }) and returns structured headline
441
- * metrics. If `tracePath` is omitted, throws — there is no implicit "latest
441
+ * metrics. If `tracePath` is omitted, throws; there is no implicit "latest
442
442
  * trace" magic; callers pass the path returned by a trace tool.
443
443
  */
444
444
  export async function performanceAnalyzeInsight(
@@ -473,9 +473,9 @@ export async function performanceAnalyzeInsight(
473
473
  /*
474
474
  * CDP methods/domains used:
475
475
  * - Tracing.start (traceConfig.includedCategories, transferMode:ReportEvents)
476
- * - Tracing.dataCollected (event — buffered into the event array)
476
+ * - Tracing.dataCollected (event, buffered into the event array)
477
477
  * - Tracing.end
478
- * - Tracing.tracingComplete (event — awaited to know recording is flushed)
478
+ * - Tracing.tracingComplete (event, awaited to know recording is flushed)
479
479
  * - Page.enable / Page.navigate / Page.reload / Page.loadEventFired (one-shot reload path)
480
480
  *
481
481
  * Parity gaps vs chrome-devtools-mcp performance tools:
@@ -1,5 +1,5 @@
1
1
  /**
2
- * recorder.ts — the stateful console+network capture engine.
2
+ * recorder.ts: the stateful console+network capture engine.
3
3
  *
4
4
  * RECORDER MODEL
5
5
  * ==============
@@ -22,7 +22,7 @@
22
22
  *
23
23
  * CAPTURE MODEL (what the tool surface actually uses)
24
24
  * ---------------------------------------------------
25
- * The console/network tools drive `captureWindow()` — a one-shot reload capture
25
+ * The console/network tools drive `captureWindow()`, a one-shot reload capture
26
26
  * that records BOTH domains into a UNIQUE per-capture file
27
27
  * (`rec-<targetId>-<captureId>.jsonl`) and, on stop, publishes that capture as
28
28
  * the target's shared "latest" buffer (`rec-<targetId>.jsonl`). Capturing both
@@ -154,7 +154,7 @@ export async function startRecorder(target: TargetSelector, opts: RecorderOption
154
154
  try {
155
155
  await conn.send("Log.enable");
156
156
  } catch {
157
- /* Log not supported on this target type — Runtime events still flow */
157
+ /* Log not supported on this target type; Runtime events still flow */
158
158
  }
159
159
  for (const ev of CONSOLE_EVENTS) {
160
160
  unsubs.push(conn.on(ev, (params) => persist("console", ev, params)));
@@ -165,7 +165,7 @@ export async function startRecorder(target: TargetSelector, opts: RecorderOption
165
165
  throw err;
166
166
  }
167
167
 
168
- // Stop accepting new events, then let queued appends settle — without closing
168
+ // Stop accepting new events, then let queued appends settle, without closing
169
169
  // the connection (response bodies stay fetchable on `conn`).
170
170
  const flush = async (): Promise<void> => {
171
171
  for (const off of unsubs) off();
@@ -195,7 +195,7 @@ export async function startRecorder(target: TargetSelector, opts: RecorderOption
195
195
  export interface CaptureWindow {
196
196
  /** The unique per-capture buffer file (read this for isolated results). */
197
197
  file: string;
198
- /** Live connection (open until stop) — for Network.getResponseBody etc. */
198
+ /** Live connection (open until stop), for Network.getResponseBody etc. */
199
199
  conn: CdpConnection;
200
200
  /** Resolved target identity. */
201
201
  resolved: { id: string; url: string; title: string };
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * The reference scheme (CONTRACT.md "The element-reference scheme"):
5
5
  * A `Uid` IS a CDP `backendDOMNodeId` (a number). Refs are therefore
6
- * stateless — `take_snapshot` emits them straight from the a11y tree, and
6
+ * stateless: `take_snapshot` emits them straight from the a11y tree, and
7
7
  * every interaction tool resolves them back to a live DOM node via
8
8
  * `DOM.resolveNode({ backendNodeId: uid })`. There is no server-side ref
9
9
  * table to drift or expire.
@@ -124,7 +124,7 @@ export interface TakeSnapshotResult {
124
124
  }
125
125
 
126
126
  /**
127
- * take_snapshot — Accessibility.getFullAXTree walked into a compact indented
127
+ * take_snapshot: Accessibility.getFullAXTree walked into a compact indented
128
128
  * text tree. Each emitted line carries the node's backendDOMNodeId as [uid],
129
129
  * which interaction tools feed straight back to resolveUid.
130
130
  */