Skip to content

Commit 0df8d33

Browse files
authored
Merge branch 'main' into orkon/lighthouse
2 parents edc5870 + c9691c6 commit 0df8d33

14 files changed

Lines changed: 228 additions & 179 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ Restart Claude Code to have the MCP server and skills load (check with `/skills`
150150

151151
<details>
152152
<summary>Codex</summary>
153-
Follow the <a href="https://github.com/openai/codex/blob/main/docs/advanced.md#model-context-protocol-mcp">configure MCP guide</a>
153+
Follow the <a href="https://developers.openai.com/codex/mcp/#configure-with-the-cli">configure MCP guide</a>
154154
using the standard config from above. You can also install the Chrome DevTools MCP server using the Codex CLI:
155155

156156
```bash

package-lock.json

Lines changed: 39 additions & 27 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"test:no-build": "node scripts/test.mjs",
2121
"test:only": "npm run build && node scripts/test.mjs --test-only",
2222
"test:update-snapshots": "npm run build && node scripts/test.mjs --test-update-snapshots",
23-
"prepare": "node --experimental-strip-types scripts/prepare.ts",
23+
"prepare": "npm run clean && node --experimental-strip-types scripts/prepare.ts",
2424
"verify-server-json-version": "node --experimental-strip-types scripts/verify-server-json-version.ts",
2525
"update-lighthouse": "node --experimental-strip-types scripts/update-lighthouse.ts",
2626
"eval": "npm run build && CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS=true node --experimental-strip-types scripts/eval_gemini.ts",
@@ -55,7 +55,7 @@
5555
"@types/yargs": "^17.0.33",
5656
"@typescript-eslint/eslint-plugin": "^8.43.0",
5757
"@typescript-eslint/parser": "^8.43.0",
58-
"chrome-devtools-frontend": "1.0.1585538",
58+
"chrome-devtools-frontend": "1.0.1583146",
5959
"core-js": "3.48.0",
6060
"debug": "4.4.3",
6161
"eslint": "^9.35.0",
@@ -64,7 +64,7 @@
6464
"globals": "^17.0.0",
6565
"lighthouse": "13.0.2",
6666
"prettier": "^3.6.2",
67-
"puppeteer": "24.37.3",
67+
"puppeteer": "24.37.4",
6868
"rollup": "4.57.1",
6969
"rollup-plugin-cleanup": "^3.2.1",
7070
"rollup-plugin-license": "^3.6.0",

src/formatters/NetworkFormatter.ts

Lines changed: 94 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,25 @@ export interface NetworkFormatterOptions {
2323
) => Promise<{filename: string}>;
2424
}
2525

26+
interface NetworkRequestConcise {
27+
requestId?: number | string;
28+
method: string;
29+
url: string;
30+
status: string;
31+
selectedInDevToolsUI?: boolean;
32+
}
33+
34+
interface NetworkRequestDetailed extends NetworkRequestConcise {
35+
requestHeaders: Record<string, string>;
36+
requestBody?: string;
37+
requestBodyFilePath?: string;
38+
responseHeaders?: Record<string, string>;
39+
responseBody?: string;
40+
responseBodyFilePath?: string;
41+
failure?: string;
42+
redirectChain?: NetworkRequestConcise[];
43+
}
44+
2645
export class NetworkFormatter {
2746
#request: HTTPRequest;
2847
#options: NetworkFormatterOptions;
@@ -114,72 +133,14 @@ export class NetworkFormatter {
114133
}
115134

116135
toString(): string {
117-
// TODO truncate the URL
118-
return `reqid=${this.#options.requestId} ${this.#request.method()} ${this.#request.url()} ${this.#getStatusFromRequest(this.#request)}${this.#options.selectedInDevToolsUI ? ` [selected in the DevTools Network panel]` : ''}`;
136+
return convertNetworkRequestConciseToString(this.toJSON());
119137
}
120138

121139
toStringDetailed(): string {
122-
const response: string[] = [];
123-
response.push(`## Request ${this.#request.url()}`);
124-
response.push(`Status: ${this.#getStatusFromRequest(this.#request)}`);
125-
response.push(`### Request Headers`);
126-
for (const line of this.#getFormattedHeaderValue(this.#request.headers())) {
127-
response.push(line);
128-
}
129-
130-
if (this.#requestBody) {
131-
response.push(`### Request Body`);
132-
response.push(this.#requestBody);
133-
} else if (this.#requestBodyFilePath) {
134-
response.push(`### Request Body`);
135-
response.push(`Saved to ${this.#requestBodyFilePath}.`);
136-
}
137-
138-
const httpResponse = this.#request.response();
139-
if (httpResponse) {
140-
response.push(`### Response Headers`);
141-
for (const line of this.#getFormattedHeaderValue(
142-
httpResponse.headers(),
143-
)) {
144-
response.push(line);
145-
}
146-
}
147-
148-
if (this.#responseBody) {
149-
response.push(`### Response Body`);
150-
response.push(this.#responseBody);
151-
} else if (this.#responseBodyFilePath) {
152-
response.push(`### Response Body`);
153-
response.push(`Saved to ${this.#responseBodyFilePath}.`);
154-
}
155-
156-
const httpFailure = this.#request.failure();
157-
if (httpFailure) {
158-
response.push(`### Request failed with`);
159-
response.push(httpFailure.errorText);
160-
}
161-
162-
const redirectChain = this.#request.redirectChain();
163-
if (redirectChain.length) {
164-
response.push(`### Redirect chain`);
165-
let indent = 0;
166-
for (const request of redirectChain.reverse()) {
167-
const id = this.#options.requestIdResolver
168-
? this.#options.requestIdResolver(request)
169-
: undefined;
170-
// We create a temporary synchronous instance just for toString
171-
const formatter = new NetworkFormatter(request, {
172-
requestId: id,
173-
saveFile: this.#options.saveFile,
174-
});
175-
response.push(`${' '.repeat(indent)}${formatter.toString()}`);
176-
indent++;
177-
}
178-
}
179-
return response.join('\n');
140+
return converNetworkRequestDetailedToStringDetailed(this.toJSONDetailed());
180141
}
181142

182-
toJSON(): object {
143+
toJSON(): NetworkRequestConcise {
183144
return {
184145
requestId: this.#options.requestId,
185146
method: this.#request.method(),
@@ -189,7 +150,7 @@ export class NetworkFormatter {
189150
};
190151
}
191152

192-
toJSONDetailed(): object {
153+
toJSONDetailed(): NetworkRequestDetailed {
193154
const redirectChain = this.#request.redirectChain();
194155
const formattedRedirectChain = redirectChain.reverse().map(request => {
195156
const id = this.#options.requestIdResolver
@@ -222,27 +183,15 @@ export class NetworkFormatter {
222183
const failure = request.failure();
223184
let status: string;
224185
if (httpResponse) {
225-
const responseStatus = httpResponse.status();
226-
status =
227-
responseStatus >= 200 && responseStatus <= 299
228-
? `[success - ${responseStatus}]`
229-
: `[failed - ${responseStatus}]`;
186+
status = httpResponse.status().toString();
230187
} else if (failure) {
231-
status = `[failed - ${failure.errorText}]`;
188+
status = failure.errorText;
232189
} else {
233-
status = '[pending]';
190+
status = 'pending';
234191
}
235192
return status;
236193
}
237194

238-
#getFormattedHeaderValue(headers: Record<string, string>): string[] {
239-
const response: string[] = [];
240-
for (const [name, value] of Object.entries(headers)) {
241-
response.push(`- ${name}:${value}`);
242-
}
243-
return response;
244-
}
245-
246195
async #getFormattedResponseBody(
247196
httpResponse: HTTPResponse,
248197
sizeLimit = BODY_CONTEXT_SIZE_LIMIT,
@@ -273,3 +222,71 @@ function getSizeLimitedString(text: string, sizeLimit: number) {
273222
}
274223
return text;
275224
}
225+
226+
function convertNetworkRequestConciseToString(
227+
data: NetworkRequestConcise,
228+
): string {
229+
// TODO truncate the URL
230+
return `reqid=${data.requestId} ${data.method} ${data.url} [${data.status}]${data.selectedInDevToolsUI ? ` [selected in the DevTools Network panel]` : ''}`;
231+
}
232+
233+
function formatHeadlers(headers: Record<string, string>): string[] {
234+
const response: string[] = [];
235+
for (const [name, value] of Object.entries(headers)) {
236+
response.push(`- ${name}:${value}`);
237+
}
238+
return response;
239+
}
240+
241+
function converNetworkRequestDetailedToStringDetailed(
242+
data: NetworkRequestDetailed,
243+
): string {
244+
const response: string[] = [];
245+
response.push(`## Request ${data.url}`);
246+
response.push(`Status: ${data.status}`);
247+
response.push(`### Request Headers`);
248+
for (const line of formatHeadlers(data.requestHeaders)) {
249+
response.push(line);
250+
}
251+
252+
if (data.requestBody) {
253+
response.push(`### Request Body`);
254+
response.push(data.requestBody);
255+
} else if (data.requestBodyFilePath) {
256+
response.push(`### Request Body`);
257+
response.push(`Saved to ${data.requestBodyFilePath}.`);
258+
}
259+
260+
if (data.responseHeaders) {
261+
response.push(`### Response Headers`);
262+
for (const line of formatHeadlers(data.responseHeaders)) {
263+
response.push(line);
264+
}
265+
}
266+
267+
if (data.responseBody) {
268+
response.push(`### Response Body`);
269+
response.push(data.responseBody);
270+
} else if (data.responseBodyFilePath) {
271+
response.push(`### Response Body`);
272+
response.push(`Saved to ${data.responseBodyFilePath}.`);
273+
}
274+
275+
if (data.failure) {
276+
response.push(`### Request failed with`);
277+
response.push(data.failure);
278+
}
279+
280+
const redirectChain = data.redirectChain;
281+
if (redirectChain?.length) {
282+
response.push(`### Redirect chain`);
283+
let indent = 0;
284+
for (const request of redirectChain.reverse()) {
285+
response.push(
286+
`${' '.repeat(indent)}${convertNetworkRequestConciseToString(request)})}`,
287+
);
288+
indent++;
289+
}
290+
}
291+
return response.join('\n');
292+
}

0 commit comments

Comments
 (0)