cdp-mcp 0.1.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.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +240 -0
  3. package/dist/index.js +345 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/server.js +27 -0
  6. package/dist/server.js.map +1 -0
  7. package/dist/session/browser.js +394 -0
  8. package/dist/session/browser.js.map +1 -0
  9. package/dist/session/buffers.js +43 -0
  10. package/dist/session/buffers.js.map +1 -0
  11. package/dist/session/pause.js +99 -0
  12. package/dist/session/pause.js.map +1 -0
  13. package/dist/session/state.js +93 -0
  14. package/dist/session/state.js.map +1 -0
  15. package/dist/sourcemap/loader.js +138 -0
  16. package/dist/sourcemap/loader.js.map +1 -0
  17. package/dist/sourcemap/normalize.js +59 -0
  18. package/dist/sourcemap/normalize.js.map +1 -0
  19. package/dist/sourcemap/store.js +185 -0
  20. package/dist/sourcemap/store.js.map +1 -0
  21. package/dist/tools/_register.js +30 -0
  22. package/dist/tools/_register.js.map +1 -0
  23. package/dist/tools/breakpoints.js +164 -0
  24. package/dist/tools/breakpoints.js.map +1 -0
  25. package/dist/tools/console.js +48 -0
  26. package/dist/tools/console.js.map +1 -0
  27. package/dist/tools/dom.js +527 -0
  28. package/dist/tools/dom.js.map +1 -0
  29. package/dist/tools/execution.js +89 -0
  30. package/dist/tools/execution.js.map +1 -0
  31. package/dist/tools/inspect.js +178 -0
  32. package/dist/tools/inspect.js.map +1 -0
  33. package/dist/tools/nav.js +136 -0
  34. package/dist/tools/nav.js.map +1 -0
  35. package/dist/tools/network.js +137 -0
  36. package/dist/tools/network.js.map +1 -0
  37. package/dist/tools/session.js +76 -0
  38. package/dist/tools/session.js.map +1 -0
  39. package/dist/tools/source.js +63 -0
  40. package/dist/tools/source.js.map +1 -0
  41. package/dist/util/browser-resolve.js +263 -0
  42. package/dist/util/browser-resolve.js.map +1 -0
  43. package/dist/util/errors.js +12 -0
  44. package/dist/util/errors.js.map +1 -0
  45. package/dist/util/format.js +65 -0
  46. package/dist/util/format.js.map +1 -0
  47. package/dist/util/log.js +34 -0
  48. package/dist/util/log.js.map +1 -0
  49. package/package.json +74 -0
@@ -0,0 +1,89 @@
1
+ import { z } from "zod";
2
+ import { requireSession, requirePaused } from "../session/state.js";
3
+ import { mapCdpToOriginal } from "../sourcemap/store.js";
4
+ import { registerJsonTool } from "./_register.js";
5
+ export function registerExecutionTools(server) {
6
+ registerJsonTool(server, "resume", "Resume execution. Dispatched to the session that paused (root, worker, OOPIF, …).", undefined, async () => {
7
+ const s = requirePaused();
8
+ const sid = s.pause.current().sessionId;
9
+ await s.client.send("Debugger.resume", undefined, sid);
10
+ return "resumed";
11
+ });
12
+ registerJsonTool(server, "step_over", "Step over the current line. Awaits the next pause (or returns null if execution continues).", { timeout_ms: z.number().int().positive().optional() }, async (input) => stepThen((s, sid) => s.client.send("Debugger.stepOver", undefined, sid), input.timeout_ms));
13
+ registerJsonTool(server, "step_into", "Step into the next function call.", { timeout_ms: z.number().int().positive().optional() }, async (input) => stepThen((s, sid) => s.client.send("Debugger.stepInto", undefined, sid), input.timeout_ms));
14
+ registerJsonTool(server, "step_out", "Step out of the current function.", { timeout_ms: z.number().int().positive().optional() }, async (input) => stepThen((s, sid) => s.client.send("Debugger.stepOut", undefined, sid), input.timeout_ms));
15
+ registerJsonTool(server, "pause", "Pause execution manually at the next statement. By default targets the root page; pass `session_id` (from list_targets or a script's session_id) to pause a specific worker/iframe/service-worker.", {
16
+ session_id: z.string().nullable().optional().describe("null or omitted = root."),
17
+ }, async (input) => {
18
+ const s = requireSession();
19
+ const sid = input.session_id ?? undefined;
20
+ await s.client.send("Debugger.pause", undefined, sid);
21
+ return { paused_session: sid ?? null };
22
+ });
23
+ registerJsonTool(server, "wait_for_pause", "Block until the debugger pauses (or times out). Returns the pause reason and a TS-mapped call stack.", { timeout_ms: z.number().int().positive().optional().describe("Default 30000") }, async (input) => {
24
+ const s = requireSession();
25
+ const state = await s.pause.waitForPause(input.timeout_ms ?? 30000);
26
+ return summarizePause(s, state.reason, state.hitBreakpoints, state.data, state.callFrames, state.sessionId);
27
+ });
28
+ }
29
+ async function stepThen(send, timeoutMs) {
30
+ const s = requirePaused();
31
+ // Capture the paused session BEFORE marking resumed — pauseState is cleared
32
+ // by onResumed and we still need the sessionId to route the step command.
33
+ const sid = s.pause.current().sessionId;
34
+ s.pause.onResumed();
35
+ await send(s, sid);
36
+ const next = await s.pause.waitForPauseOrResume(timeoutMs ?? 30000);
37
+ if (!next)
38
+ return { paused: false, message: "execution did not pause within timeout" };
39
+ return {
40
+ paused: true,
41
+ ...summarizePause(s, next.reason, next.hitBreakpoints, next.data, next.callFrames, next.sessionId),
42
+ };
43
+ }
44
+ export function summarizePause(s, reason, hitBreakpoints, data, callFrames, sessionId) {
45
+ const userBreakpointIds = matchUserBreakpoints(s, hitBreakpoints ?? [], sessionId);
46
+ return {
47
+ reason,
48
+ hit_breakpoint_ids: userBreakpointIds,
49
+ session_id: sessionId ?? null,
50
+ data: data ?? null,
51
+ call_stack: callFrames.map((cf, i) => formatFrameForPause(s, cf, i, sessionId)),
52
+ };
53
+ }
54
+ function formatFrameForPause(s, cf, index, sessionId) {
55
+ const mapped = mapCdpToOriginal(s.scripts, cf.location, sessionId);
56
+ const script = s.scripts.get(cf.location.scriptId, sessionId);
57
+ return {
58
+ index,
59
+ frame_id: cf.callFrameId,
60
+ session_id: sessionId ?? null,
61
+ function_name: cf.functionName || "(anonymous)",
62
+ file: mapped?.file ?? script?.url ?? cf.url ?? "<unknown>",
63
+ line: mapped?.line ?? cf.location.lineNumber + 1,
64
+ column: mapped?.column ?? cf.location.columnNumber ?? 0,
65
+ js_url: script?.url,
66
+ js_line: cf.location.lineNumber + 1,
67
+ js_column: cf.location.columnNumber ?? 0,
68
+ scope_types: cf.scopeChain.map((sc) => sc.type),
69
+ this: cf.this ? { type: cf.this.subtype ?? cf.this.type, preview: cf.this.description ?? "" } : null,
70
+ };
71
+ }
72
+ /** @internal exported for unit tests; not part of the MCP tool surface. */
73
+ export function matchUserBreakpoints(s, hit, pauseSessionId) {
74
+ if (!hit.length)
75
+ return [];
76
+ const out = [];
77
+ for (const rec of s.breakpoints.values()) {
78
+ // Require BOTH cdpId AND sessionId match. setBreakpointByUrl derives
79
+ // the breakpoint ID from URL/line/column, so two sessions binding the
80
+ // same script can mint colliding cdpIds. Without the sessionId guard,
81
+ // a pause in one session would falsely be reported as a hit for
82
+ // another session's binding. undefined === undefined for root.
83
+ if (rec.bindings.some((b) => hit.includes(b.cdpId) && b.sessionId === pauseSessionId)) {
84
+ out.push(rec.id);
85
+ }
86
+ }
87
+ return out;
88
+ }
89
+ //# sourceMappingURL=execution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution.js","sourceRoot":"","sources":["../../src/tools/execution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,178 @@
1
+ import { z } from "zod";
2
+ import { requireSession, requirePaused } from "../session/state.js";
3
+ import { mapCdpToOriginal } from "../sourcemap/store.js";
4
+ import { describeRemote, previewRemoteObject } from "../util/format.js";
5
+ import { ToolError } from "../util/errors.js";
6
+ import { registerJsonTool } from "./_register.js";
7
+ // session_id provenance: objectIds, callFrameIds, and scriptIds returned by
8
+ // CDP are scoped per-session (per-target). The inspect tools attach
9
+ // `session_id` to every returned remote-object so the agent can pass it back
10
+ // to get_object_properties and route to the correct Runtime agent.
11
+ export function registerInspectTools(server) {
12
+ registerJsonTool(server, "get_call_stack", "Get the current call stack with TS-mapped frames. Only valid while paused. Each frame includes the session_id its Runtime/Debugger agent belongs to — pass it through to evaluate/get_object_properties for the right routing.", undefined, async () => {
13
+ const s = requirePaused();
14
+ const state = s.pause.current();
15
+ const sid = state.sessionId;
16
+ return state.callFrames.map((cf, i) => {
17
+ const mapped = mapCdpToOriginal(s.scripts, cf.location, sid);
18
+ const script = s.scripts.get(cf.location.scriptId, sid);
19
+ return {
20
+ index: i,
21
+ frame_id: cf.callFrameId,
22
+ session_id: sid ?? null,
23
+ function_name: cf.functionName || "(anonymous)",
24
+ file: mapped?.file ?? script?.url ?? cf.url ?? "<unknown>",
25
+ line: mapped?.line ?? cf.location.lineNumber + 1,
26
+ column: mapped?.column ?? cf.location.columnNumber ?? 0,
27
+ js_url: script?.url,
28
+ js_line: cf.location.lineNumber + 1,
29
+ scope_types: cf.scopeChain.map((sc) => sc.type),
30
+ };
31
+ });
32
+ });
33
+ registerJsonTool(server, "get_scope", "Return variables visible at a paused frame. Valid only while paused. Each item includes the session_id of the originating Runtime agent — required for follow-on get_object_properties calls when paused in a worker/iframe.", {
34
+ frame_index: z.number().int().nonnegative().optional().describe("Default 0 (topmost frame)"),
35
+ scope_type: z
36
+ .enum(["local", "closure", "global", "block", "catch", "with", "script", "eval", "module"])
37
+ .optional()
38
+ .describe("Default: local"),
39
+ max_props: z.number().int().positive().optional(),
40
+ }, async (input) => {
41
+ const s = requirePaused();
42
+ const state = s.pause.current();
43
+ const sid = state.sessionId;
44
+ const idx = input.frame_index ?? 0;
45
+ const frame = state.callFrames[idx];
46
+ if (!frame)
47
+ throw new ToolError("bad_frame", `Frame ${idx} out of range (${state.callFrames.length} frames)`);
48
+ const targetType = input.scope_type ?? "local";
49
+ const scope = frame.scopeChain.find((sc) => sc.type === targetType);
50
+ if (!scope?.object?.objectId) {
51
+ throw new ToolError("no_scope", `Frame ${idx} has no '${targetType}' scope. Available: ${frame.scopeChain.map((sc) => sc.type).join(", ")}`);
52
+ }
53
+ const max = input.max_props ?? 50;
54
+ const result = await s.client.send("Runtime.getProperties", {
55
+ objectId: scope.object.objectId,
56
+ ownProperties: false,
57
+ accessorPropertiesOnly: false,
58
+ generatePreview: true,
59
+ }, sid);
60
+ const items = (result.result ?? [])
61
+ .filter((p) => !p.symbol)
62
+ .slice(0, max)
63
+ .map((p) => ({
64
+ name: p.name,
65
+ ...(p.value ? describeRemote(p.value) : { type: "missing", preview: "(no value)" }),
66
+ session_id: sid ?? null,
67
+ writable: p.writable,
68
+ enumerable: p.enumerable,
69
+ }));
70
+ return {
71
+ frame_index: idx,
72
+ scope_type: targetType,
73
+ session_id: sid ?? null,
74
+ items,
75
+ truncated: (result.result?.length ?? 0) > max,
76
+ };
77
+ });
78
+ registerJsonTool(server, "evaluate", "Evaluate a JS expression. When the debugger is paused, the expression runs in the paused frame's context via Debugger.evaluateOnCallFrame (top frame by default; override with frame_index). When not paused, runs in the page's Runtime context via Runtime.evaluate. frame_index given while not paused is a not_paused error. Note: while paused the event loop is frozen, so async expressions return the unresolved Promise object rather than awaiting it.", {
79
+ expression: z.string(),
80
+ frame_index: z.number().int().nonnegative().optional(),
81
+ return_by_value: z.boolean().optional(),
82
+ timeout_ms: z.number().int().positive().optional(),
83
+ }, async (input) => {
84
+ const s = requireSession();
85
+ const paused = s.pause.isPaused();
86
+ if (input.frame_index !== undefined && !paused) {
87
+ throw new ToolError("not_paused", "frame_index requires paused state");
88
+ }
89
+ if (paused) {
90
+ const state = s.pause.current();
91
+ const sid = state.sessionId;
92
+ const idx = input.frame_index ?? 0;
93
+ const frame = state.callFrames[idx];
94
+ if (!frame)
95
+ throw new ToolError("bad_frame", `Frame ${idx} out of range (${state.callFrames.length} frames)`);
96
+ const res = await s.client.send("Debugger.evaluateOnCallFrame", {
97
+ callFrameId: frame.callFrameId,
98
+ expression: input.expression,
99
+ returnByValue: !!input.return_by_value,
100
+ generatePreview: true,
101
+ throwOnSideEffect: false,
102
+ ...(input.timeout_ms ? { timeout: input.timeout_ms } : {}),
103
+ }, sid);
104
+ return formatEvalResult(res.result, res.exceptionDetails, sid);
105
+ }
106
+ const res = await s.client.send("Runtime.evaluate", {
107
+ expression: input.expression,
108
+ returnByValue: !!input.return_by_value,
109
+ generatePreview: true,
110
+ awaitPromise: true,
111
+ ...(input.timeout_ms ? { timeout: input.timeout_ms } : {}),
112
+ });
113
+ return formatEvalResult(res.result, res.exceptionDetails, undefined);
114
+ });
115
+ registerJsonTool(server, "get_object_properties", "Inspect a RemoteObject by ID (from get_scope, evaluate, or a callstack frame). Pass `session_id` from the source response so the call routes to the right Runtime agent — null or omitted means root.", {
116
+ object_id: z.string(),
117
+ session_id: z.string().nullable().optional().describe("From get_scope/evaluate/get_call_stack response. null or omitted = root."),
118
+ own_only: z.boolean().optional().describe("Default true"),
119
+ max_props: z.number().int().positive().optional(),
120
+ }, async (input) => {
121
+ const s = requireSession();
122
+ // Strict provenance: omitted session_id means root. The previous
123
+ // "fall back to the paused session" behavior misrouted any
124
+ // root-minted objectId once a child session was paused — a root
125
+ // `evaluate` response carries no session_id (JSON drops undefined),
126
+ // so an agent could not pass it back, and the fallback then
127
+ // dispatched against the wrong target.
128
+ // null is the explicit "root" sentinel agents round-trip from responses;
129
+ // CDP wants undefined for root.
130
+ const sid = input.session_id ?? undefined;
131
+ const max = input.max_props ?? 50;
132
+ const ownProperties = input.own_only ?? true;
133
+ const result = await s.client.send("Runtime.getProperties", {
134
+ objectId: input.object_id,
135
+ ownProperties,
136
+ accessorPropertiesOnly: false,
137
+ generatePreview: true,
138
+ }, sid);
139
+ return {
140
+ session_id: sid ?? null,
141
+ items: (result.result ?? [])
142
+ .filter((p) => !p.symbol)
143
+ .slice(0, max)
144
+ .map((p) => ({
145
+ name: p.name,
146
+ ...(p.value ? describeRemote(p.value) : { type: "missing", preview: "(no value)" }),
147
+ session_id: sid ?? null,
148
+ writable: p.writable,
149
+ enumerable: p.enumerable,
150
+ })),
151
+ truncated: (result.result?.length ?? 0) > max,
152
+ };
153
+ });
154
+ }
155
+ function formatEvalResult(result, exceptionDetails, sessionId) {
156
+ // Emit session_id as `null` for root (not undefined) so it survives JSON
157
+ // serialization. Agents need a value to round-trip into
158
+ // get_object_properties — otherwise a root-evaluate response with no
159
+ // session_id field has nothing for the agent to pass back, and any
160
+ // omit-then-default fallback misroutes when a child session is paused.
161
+ const sid = sessionId ?? null;
162
+ if (exceptionDetails) {
163
+ return {
164
+ error: true,
165
+ message: exceptionDetails.exception?.description ?? exceptionDetails.text,
166
+ ...(exceptionDetails.exception?.objectId ? { object_id: exceptionDetails.exception.objectId } : {}),
167
+ session_id: sid,
168
+ };
169
+ }
170
+ return {
171
+ type: result.subtype ?? result.type,
172
+ preview: previewRemoteObject(result),
173
+ value: "value" in result ? result.value : undefined,
174
+ ...(result.objectId ? { object_id: result.objectId } : {}),
175
+ session_id: sid,
176
+ };
177
+ }
178
+ //# sourceMappingURL=inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../src/tools/inspect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ import { z } from "zod";
2
+ import { requireSession } from "../session/state.js";
3
+ import { registerJsonTool } from "./_register.js";
4
+ export function registerNavTools(server) {
5
+ registerJsonTool(server, "navigate", "Navigate the active page to a URL. Waits for the chosen load milestone.", {
6
+ url: z.string(),
7
+ wait: z.enum(["load", "domcontentloaded", "networkidle", "none"]).optional()
8
+ .describe("Default: load"),
9
+ timeout_ms: z.number().int().positive().optional(),
10
+ }, async (input) => {
11
+ const s = requireSession();
12
+ const wait = input.wait ?? "load";
13
+ const timeout = input.timeout_ms ?? 30000;
14
+ const loadPromise = waitForLoad(s.client, wait, timeout);
15
+ await s.client.send("Page.navigate", { url: input.url });
16
+ await loadPromise;
17
+ const { frameTree } = await s.client.send("Page.getFrameTree");
18
+ return { url: frameTree.frame.url, wait };
19
+ });
20
+ registerJsonTool(server, "reload", "Reload the active page.", { hard: z.boolean().optional().describe("Bypass cache") }, async (input) => {
21
+ const s = requireSession();
22
+ await s.client.send("Page.reload", { ignoreCache: !!input.hard });
23
+ return "reloaded";
24
+ });
25
+ registerJsonTool(server, "get_url", "Return the current top-frame URL.", undefined, async () => {
26
+ const s = requireSession();
27
+ const { frameTree } = await s.client.send("Page.getFrameTree");
28
+ return { url: frameTree.frame.url };
29
+ });
30
+ }
31
+ function waitForLoad(client, mode, timeoutMs) {
32
+ if (mode === "none")
33
+ return Promise.resolve();
34
+ // Gate to the root session: top-level navigation completion is only
35
+ // meaningful for the top frame. Now that the multi-target fix wires
36
+ // Page.enable + Network.enable for every child session (OOPIFs, workers,
37
+ // service workers), their events stream through the same root client
38
+ // tagged with their own eventSessionId. Without this gate, a cross-origin
39
+ // iframe firing Page.loadEventFired would prematurely settle navigate(),
40
+ // and an analytics iframe polling /beacon would starve `networkidle`
41
+ // forever.
42
+ const isRoot = (esid) => esid === undefined;
43
+ return new Promise((resolve, reject) => {
44
+ let settled = false;
45
+ const listeners = [];
46
+ const off = (api) => {
47
+ for (const { event, fn } of listeners) {
48
+ api.removeListener(event, fn);
49
+ }
50
+ listeners.length = 0;
51
+ };
52
+ const reg = (event, fn) => {
53
+ client.on(event, fn);
54
+ listeners.push({ event, fn });
55
+ };
56
+ const timer = setTimeout(() => {
57
+ if (settled)
58
+ return;
59
+ settled = true;
60
+ off(client);
61
+ reject(new Error(`navigate: ${mode} not reached within ${timeoutMs}ms`));
62
+ }, timeoutMs);
63
+ let idleTimer = null;
64
+ const done = () => {
65
+ if (settled)
66
+ return;
67
+ settled = true;
68
+ clearTimeout(timer);
69
+ if (idleTimer)
70
+ clearTimeout(idleTimer);
71
+ off(client);
72
+ resolve();
73
+ };
74
+ if (mode === "load") {
75
+ reg("Page.loadEventFired", (_p, esid) => {
76
+ if (isRoot(esid))
77
+ done();
78
+ });
79
+ }
80
+ else if (mode === "domcontentloaded") {
81
+ reg("Page.domContentEventFired", (_p, esid) => {
82
+ if (isRoot(esid))
83
+ done();
84
+ });
85
+ }
86
+ else if (mode === "networkidle") {
87
+ // Track in-flight root-session requests. The previous version reset
88
+ // the 500ms idle timer on both requestWillBeSent and loadingFinished
89
+ // — which meant a slow request that took 600ms to finish would emit
90
+ // the start event, then 500ms later `done()` fired while the
91
+ // request was still loading. networkidle resolved while a request
92
+ // was in flight.
93
+ //
94
+ // Correct semantics: idle timer starts ONLY when the in-flight set
95
+ // is empty, and resets whenever a new request joins.
96
+ const inFlight = new Set();
97
+ const armIdleIfEmpty = () => {
98
+ if (settled)
99
+ return;
100
+ if (idleTimer)
101
+ clearTimeout(idleTimer);
102
+ if (inFlight.size === 0)
103
+ idleTimer = setTimeout(done, 500);
104
+ };
105
+ reg("Network.requestWillBeSent", (p, esid) => {
106
+ if (settled || !isRoot(esid))
107
+ return;
108
+ // Skip persistent-connection types: WebSocket and EventSource stay
109
+ // open until the page navigates away, so they never emit
110
+ // Network.loadingFinished — tracking them would hold networkidle
111
+ // forever. Every Vite/Next/Astro dev server opens an HMR WebSocket,
112
+ // so this was the universal failure mode.
113
+ if (p.type === "WebSocket" || p.type === "EventSource")
114
+ return;
115
+ inFlight.add(p.requestId);
116
+ if (idleTimer)
117
+ clearTimeout(idleTimer);
118
+ });
119
+ reg("Network.loadingFinished", (p, esid) => {
120
+ if (settled || !isRoot(esid))
121
+ return;
122
+ inFlight.delete(p.requestId);
123
+ armIdleIfEmpty();
124
+ });
125
+ reg("Network.loadingFailed", (p, esid) => {
126
+ if (settled || !isRoot(esid))
127
+ return;
128
+ inFlight.delete(p.requestId);
129
+ armIdleIfEmpty();
130
+ });
131
+ // Initial arm — if nothing fires, we're already idle.
132
+ armIdleIfEmpty();
133
+ }
134
+ });
135
+ }
136
+ //# sourceMappingURL=nav.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nav.js","sourceRoot":"","sources":["../../src/tools/nav.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIlD,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,gBAAgB,CACd,MAAM,EACN,UAAU,EACV,yEAAyE,EACzE;QACE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;QACf,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE;aACzE,QAAQ,CAAC,eAAe,CAAC;QAC5B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;KACnD,EACD,KAAK,EAAE,KAA4D,EAAE,EAAE;QACrE,MAAM,CAAC,GAAG,cAAc,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC;QAClC,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC;QAC1C,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC,MAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,CAAC,CAAC,MAAO,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QAC1D,MAAM,WAAW,CAAC;QAClB,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,CAAC,MAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAChE,OAAO,EAAE,GAAG,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IAC5C,CAAC,CACF,CAAC;IAEF,gBAAgB,CACd,MAAM,EACN,QAAQ,EACR,yBAAyB,EACzB,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,EACzD,KAAK,EAAE,KAAyB,EAAE,EAAE;QAClC,MAAM,CAAC,GAAG,cAAc,EAAE,CAAC;QAC3B,MAAM,CAAC,CAAC,MAAO,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACnE,OAAO,UAAU,CAAC;IACpB,CAAC,CACF,CAAC;IAEF,gBAAgB,CACd,MAAM,EACN,SAAS,EACT,mCAAmC,EACnC,SAAS,EACT,KAAK,IAAI,EAAE;QACT,MAAM,CAAC,GAAG,cAAc,EAAE,CAAC;QAC3B,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,CAAC,MAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAChE,OAAO,EAAE,GAAG,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IACtC,CAAC,CACF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAClB,MAAgD,EAChD,IAAc,EACd,SAAiB;IAEjB,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC9C,oEAAoE;IACpE,oEAAoE;IACpE,yEAAyE;IACzE,qEAAqE;IACrE,0EAA0E;IAC1E,yEAAyE;IACzE,qEAAqE;IACrE,WAAW;IACX,MAAM,MAAM,GAAG,CAAC,IAAwB,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC;IAChE,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3C,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,MAAM,SAAS,GAAe,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,CAAC,GAAkB,EAAE,EAAE;YACjC,KAAK,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,SAAS,EAAE,CAAC;gBACrC,GAAuE,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACrG,CAAC;YACD,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;QACvB,CAAC,CAAC;QACF,MAAM,GAAG,GAAG,CAAC,KAAa,EAAE,EAA4B,EAAE,EAAE;YAC1D,MAAM,CAAC,EAAE,CAAC,KAAY,EAAE,EAAS,CAAC,CAAC;YACnC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAChC,CAAC,CAAC;QAEF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,GAAG,CAAC,MAAM,CAAC,CAAC;YACZ,MAAM,CAAC,IAAI,KAAK,CAAC,aAAa,IAAI,uBAAuB,SAAS,IAAI,CAAC,CAAC,CAAC;QAC3E,CAAC,EAAE,SAAS,CAAC,CAAC;QAEd,IAAI,SAAS,GAA0B,IAAI,CAAC;QAC5C,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,SAAS;gBAAE,YAAY,CAAC,SAAS,CAAC,CAAC;YACvC,GAAG,CAAC,MAAM,CAAC,CAAC;YACZ,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QAEF,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,GAAG,CAAC,qBAAqB,EAAE,CAAC,EAAW,EAAE,IAAa,EAAE,EAAE;gBACxD,IAAI,MAAM,CAAC,IAAI,CAAC;oBAAE,IAAI,EAAE,CAAC;YAC3B,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,IAAI,KAAK,kBAAkB,EAAE,CAAC;YACvC,GAAG,CAAC,2BAA2B,EAAE,CAAC,EAAW,EAAE,IAAa,EAAE,EAAE;gBAC9D,IAAI,MAAM,CAAC,IAAI,CAAC;oBAAE,IAAI,EAAE,CAAC;YAC3B,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;YAClC,oEAAoE;YACpE,qEAAqE;YACrE,oEAAoE;YACpE,6DAA6D;YAC7D,kEAAkE;YAClE,iBAAiB;YACjB,EAAE;YACF,mEAAmE;YACnE,qDAAqD;YACrD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;YACnC,MAAM,cAAc,GAAG,GAAG,EAAE;gBAC1B,IAAI,OAAO;oBAAE,OAAO;gBACpB,IAAI,SAAS;oBAAE,YAAY,CAAC,SAAS,CAAC,CAAC;gBACvC,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC;oBAAE,SAAS,GAAG,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC7D,CAAC,CAAC;YACF,GAAG,CAAC,2BAA2B,EAAE,CAAC,CAA0C,EAAE,IAAa,EAAE,EAAE;gBAC7F,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;oBAAE,OAAO;gBACrC,mEAAmE;gBACnE,yDAAyD;gBACzD,iEAAiE;gBACjE,oEAAoE;gBACpE,0CAA0C;gBAC1C,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,IAAI,KAAK,aAAa;oBAAE,OAAO;gBAC/D,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBAC1B,IAAI,SAAS;oBAAE,YAAY,CAAC,SAAS,CAAC,CAAC;YACzC,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,yBAAyB,EAAE,CAAC,CAAwC,EAAE,IAAa,EAAE,EAAE;gBACzF,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;oBAAE,OAAO;gBACrC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBAC7B,cAAc,EAAE,CAAC;YACnB,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,uBAAuB,EAAE,CAAC,CAAsC,EAAE,IAAa,EAAE,EAAE;gBACrF,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;oBAAE,OAAO;gBACrC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBAC7B,cAAc,EAAE,CAAC;YACnB,CAAC,CAAC,CAAC;YACH,sDAAsD;YACtD,cAAc,EAAE,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,137 @@
1
+ import { z } from "zod";
2
+ import { requireSession } from "../session/state.js";
3
+ import { truncate } from "../util/format.js";
4
+ import { registerJsonTool } from "./_register.js";
5
+ export function registerNetworkTools(server) {
6
+ registerJsonTool(server, "get_network_requests", "Query buffered network requests. Paginate with `since`. Bodies are NOT included — fetch via get_request_body/get_response_body.", {
7
+ since: z.number().int().nonnegative().optional(),
8
+ status: z.number().int().optional(),
9
+ type: z.string().optional().describe("e.g. Fetch, XHR, Document, Script"),
10
+ url_match: z.string().optional().describe("Substring filter"),
11
+ finished: z.boolean().optional().describe("If true, only return entries whose lifecycle has completed (loaded OR failed — also check the `failure` field before calling get_response_body)"),
12
+ limit: z.number().int().positive().optional(),
13
+ }, async (input) => {
14
+ const s = requireSession();
15
+ const match = input.url_match;
16
+ const items = s.network.query({
17
+ since: input.since ?? 0,
18
+ limit: input.limit ?? 50,
19
+ filter: (e) => {
20
+ if (input.status !== undefined && e.status !== input.status)
21
+ return false;
22
+ if (input.type && e.resourceType !== input.type)
23
+ return false;
24
+ if (match && !e.url.includes(match))
25
+ return false;
26
+ if (input.finished === true && !e.finished)
27
+ return false;
28
+ if (input.finished === false && e.finished)
29
+ return false;
30
+ return true;
31
+ },
32
+ });
33
+ return {
34
+ cursor: items.length ? items[items.length - 1].seq : input.since ?? 0,
35
+ items: items.map((e) => ({
36
+ seq: e.seq,
37
+ request_id: e.requestId,
38
+ // session_id is required to disambiguate when fetching the body —
39
+ // CDP requestIds are per-Network-agent, so two iframes can both
40
+ // emit requestId="123", and the root↔child case has the same
41
+ // collision risk. Emit `null` for root (rather than undefined) so
42
+ // the field survives JSON serialization and agents can round-trip
43
+ // it back to get_request_body / get_response_body.
44
+ session_id: e.sessionId ?? null,
45
+ ts: e.ts,
46
+ method: e.method,
47
+ url: e.url,
48
+ type: e.resourceType,
49
+ status: e.status,
50
+ status_text: e.statusText,
51
+ mime_type: e.mimeType,
52
+ from_cache: e.fromCache,
53
+ finished: !!e.finished,
54
+ duration_ms: e.durationMs,
55
+ failure: e.failureReason,
56
+ })),
57
+ };
58
+ });
59
+ registerJsonTool(server, "get_request_body", "Fetch the request body for a request ID. Often empty for GETs. Pass `session_id` from the get_network_requests item to disambiguate when child sessions have colliding request_ids. `null` = root.", {
60
+ request_id: z.string(),
61
+ session_id: z.string().nullable().optional().describe("From get_network_requests. null or omitted = root."),
62
+ max_chars: z.number().int().positive().optional(),
63
+ }, async (input) => {
64
+ const s = requireSession();
65
+ const max = input.max_chars ?? 4000;
66
+ // Normalize null→undefined for CDP. After normalization, sid is the
67
+ // session the agent intends (undefined = root, string = child).
68
+ const sid = input.session_id ?? undefined;
69
+ const entry = findEntry(s, input.request_id, sid);
70
+ try {
71
+ const r = await s.client.send("Network.getRequestPostData", { requestId: input.request_id }, sid ?? entry?.sessionId);
72
+ const body = r.postData ?? "";
73
+ return {
74
+ request_id: input.request_id,
75
+ body: truncate(body, max),
76
+ truncated_at: body.length > max ? max : null,
77
+ total_length: body.length,
78
+ };
79
+ }
80
+ catch (e) {
81
+ return { request_id: input.request_id, body: null, error: String(e) };
82
+ }
83
+ });
84
+ registerJsonTool(server, "get_response_body", "Fetch the response body for a request ID. Only safe when `finished: true` AND `failure` is absent in get_network_requests — failed requests are also `finished: true` but have no body. Pass `session_id` from the get_network_requests item to disambiguate cross-session request_id collisions. Binary payloads (base64_encoded=true) are returned as a clean base64 string — call Buffer.from(body, 'base64') to get raw bytes. Server does NOT decode binary to UTF-8 (which would corrupt PNGs/fonts/wasm/etc.) and does NOT truncate base64 bodies (truncation appended text characters that were inside the base64 alphabet, silently corrupting the tail bytes).", {
85
+ request_id: z.string(),
86
+ session_id: z.string().nullable().optional().describe("From get_network_requests. null or omitted = root."),
87
+ max_chars: z.number().int().positive().optional().describe("Only applied to TEXT responses; base64 payloads are returned in full"),
88
+ }, async (input) => {
89
+ const s = requireSession();
90
+ const max = input.max_chars ?? 4000;
91
+ const sid = input.session_id ?? undefined;
92
+ const entry = findEntry(s, input.request_id, sid);
93
+ try {
94
+ const r = await s.client.send("Network.getResponseBody", { requestId: input.request_id }, sid ?? entry?.sessionId);
95
+ const body = r.body;
96
+ // Text path: truncate freely. Base64 path: NEVER truncate — the old
97
+ // truncate() suffix "…(+N chars)" contains characters (digits, letters,
98
+ // `+`) that Node's lenient base64 decoder happily consumes as extra
99
+ // bytes, silently corrupting the tail of any binary response.
100
+ // Callers wanting more than the default should pass max_chars; for
101
+ // binary they get the whole thing.
102
+ if (r.base64Encoded) {
103
+ return {
104
+ request_id: input.request_id,
105
+ base64_encoded: true,
106
+ body,
107
+ truncated_at: null,
108
+ total_length: body.length,
109
+ };
110
+ }
111
+ return {
112
+ request_id: input.request_id,
113
+ base64_encoded: false,
114
+ body: truncate(body, max),
115
+ truncated_at: body.length > max ? max : null,
116
+ total_length: body.length,
117
+ };
118
+ }
119
+ catch (e) {
120
+ return { request_id: input.request_id, body: null, error: String(e) };
121
+ }
122
+ });
123
+ }
124
+ // Find the most-recent entry matching (requestId, sessionId). Strict match:
125
+ // omitted session_id means "root" (sessionId === undefined). The earlier
126
+ // permissive fallback (omitted matches any) created a root↔child collision
127
+ // hole — get_network_requests emits session_id:null for root entries
128
+ // (because JSON drops undefined), agents had no value to pass back, and the
129
+ // permissive filter then picked the most-recent matching requestId which
130
+ // could be a child entry, routing the body fetch to the wrong agent.
131
+ function findEntry(s, requestId, sessionId) {
132
+ return s.network.query({
133
+ filter: (e) => e.requestId === requestId && (e.sessionId ?? undefined) === sessionId,
134
+ limit: 1,
135
+ }).pop();
136
+ }
137
+ //# sourceMappingURL=network.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/tools/network.ts"],"names":[],"mappings":"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"}