@mcp-b/chrome-devtools-mcp 2.3.1 → 3.0.0-beta.20260529000441
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.
- package/package.json +1 -1
- package/build/src/DevToolsConnectionAdapter.js +0 -70
- package/build/src/DevtoolsUtils.js +0 -290
- package/build/src/McpContext.js +0 -687
- package/build/src/McpPage.js +0 -95
- package/build/src/McpResponse.js +0 -588
- package/build/src/Mutex.js +0 -37
- package/build/src/PageCollector.js +0 -308
- package/build/src/SlimMcpResponse.js +0 -18
- package/build/src/WaitForHelper.js +0 -135
- package/build/src/bin/chrome-devtools-cli-options.js +0 -651
- package/build/src/bin/chrome-devtools-mcp-cli-options.js +0 -317
- package/build/src/bin/chrome-devtools-mcp-main.js +0 -35
- package/build/src/bin/chrome-devtools-mcp.js +0 -21
- package/build/src/bin/chrome-devtools.js +0 -185
- package/build/src/bin/cliDefinitions.js +0 -615
- package/build/src/browser.js +0 -198
- package/build/src/daemon/client.js +0 -152
- package/build/src/daemon/daemon.js +0 -206
- package/build/src/daemon/types.js +0 -6
- package/build/src/daemon/utils.js +0 -108
- package/build/src/formatters/ConsoleFormatter.js +0 -234
- package/build/src/formatters/IssueFormatter.js +0 -192
- package/build/src/formatters/NetworkFormatter.js +0 -215
- package/build/src/formatters/SnapshotFormatter.js +0 -131
- package/build/src/index.js +0 -202
- package/build/src/issue-descriptions.js +0 -39
- package/build/src/logger.js +0 -36
- package/build/src/polyfill.js +0 -7
- package/build/src/telemetry/ClearcutLogger.js +0 -102
- package/build/src/telemetry/WatchdogClient.js +0 -60
- package/build/src/telemetry/flagUtils.js +0 -45
- package/build/src/telemetry/metricUtils.js +0 -14
- package/build/src/telemetry/persistence.js +0 -53
- package/build/src/telemetry/types.js +0 -33
- package/build/src/telemetry/watchdog/ClearcutSender.js +0 -203
- package/build/src/telemetry/watchdog/main.js +0 -127
- package/build/src/third_party/devtools-formatter-worker.js +0 -7
- package/build/src/third_party/index.js +0 -26
- package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +0 -54183
- package/build/src/tools/ToolDefinition.js +0 -72
- package/build/src/tools/categories.js +0 -24
- package/build/src/tools/console.js +0 -85
- package/build/src/tools/emulation.js +0 -55
- package/build/src/tools/extensions.js +0 -96
- package/build/src/tools/input.js +0 -368
- package/build/src/tools/lighthouse.js +0 -123
- package/build/src/tools/memory.js +0 -28
- package/build/src/tools/network.js +0 -120
- package/build/src/tools/pages.js +0 -319
- package/build/src/tools/performance.js +0 -190
- package/build/src/tools/screencast.js +0 -79
- package/build/src/tools/screenshot.js +0 -84
- package/build/src/tools/script.js +0 -119
- package/build/src/tools/slim/tools.js +0 -81
- package/build/src/tools/snapshot.js +0 -56
- package/build/src/tools/tools.js +0 -52
- package/build/src/tools/webmcp.js +0 -416
- package/build/src/trace-processing/parse.js +0 -84
- package/build/src/types.js +0 -6
- package/build/src/utils/ExtensionRegistry.js +0 -35
- package/build/src/utils/files.js +0 -19
- package/build/src/utils/keyboard.js +0 -296
- package/build/src/utils/pagination.js +0 -49
- package/build/src/utils/string.js +0 -36
- package/build/src/utils/types.js +0 -6
- package/build/src/version.js +0 -9
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2026 Google LLC
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
import fs from 'node:fs/promises';
|
|
7
|
-
import os from 'node:os';
|
|
8
|
-
import path from 'node:path';
|
|
9
|
-
import process from 'node:process';
|
|
10
|
-
import { logger } from '../logger.js';
|
|
11
|
-
const STATE_FILE_NAME = 'telemetry_state.json';
|
|
12
|
-
function getDataFolder() {
|
|
13
|
-
const homedir = os.homedir();
|
|
14
|
-
const { env } = process;
|
|
15
|
-
const name = 'chrome-devtools-mcp';
|
|
16
|
-
if (process.platform === 'darwin') {
|
|
17
|
-
return path.join(homedir, 'Library', 'Application Support', name);
|
|
18
|
-
}
|
|
19
|
-
if (process.platform === 'win32') {
|
|
20
|
-
const localAppData = env.LOCALAPPDATA || path.join(homedir, 'AppData', 'Local');
|
|
21
|
-
return path.join(localAppData, name, 'Data');
|
|
22
|
-
}
|
|
23
|
-
return path.join(env.XDG_DATA_HOME || path.join(homedir, '.local', 'share'), name);
|
|
24
|
-
}
|
|
25
|
-
export class FilePersistence {
|
|
26
|
-
#dataFolder;
|
|
27
|
-
constructor(dataFolderOverride) {
|
|
28
|
-
this.#dataFolder = dataFolderOverride ?? getDataFolder();
|
|
29
|
-
}
|
|
30
|
-
async loadState() {
|
|
31
|
-
try {
|
|
32
|
-
const filePath = path.join(this.#dataFolder, STATE_FILE_NAME);
|
|
33
|
-
const content = await fs.readFile(filePath, 'utf-8');
|
|
34
|
-
return JSON.parse(content);
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
return {
|
|
38
|
-
lastActive: '',
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
async saveState(state) {
|
|
43
|
-
const filePath = path.join(this.#dataFolder, STATE_FILE_NAME);
|
|
44
|
-
try {
|
|
45
|
-
await fs.mkdir(this.#dataFolder, { recursive: true });
|
|
46
|
-
await fs.writeFile(filePath, JSON.stringify(state, null, 2), 'utf-8');
|
|
47
|
-
}
|
|
48
|
-
catch (error) {
|
|
49
|
-
// Ignore errors during state saving to avoid crashing the server
|
|
50
|
-
logger(`Failed to save telemetry state to ${filePath}:`, error);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2026 Google LLC
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
// Enums
|
|
7
|
-
export var OsType;
|
|
8
|
-
(function (OsType) {
|
|
9
|
-
OsType[OsType["OS_TYPE_UNSPECIFIED"] = 0] = "OS_TYPE_UNSPECIFIED";
|
|
10
|
-
OsType[OsType["OS_TYPE_WINDOWS"] = 1] = "OS_TYPE_WINDOWS";
|
|
11
|
-
OsType[OsType["OS_TYPE_MACOS"] = 2] = "OS_TYPE_MACOS";
|
|
12
|
-
OsType[OsType["OS_TYPE_LINUX"] = 3] = "OS_TYPE_LINUX";
|
|
13
|
-
})(OsType || (OsType = {}));
|
|
14
|
-
export var ChromeChannel;
|
|
15
|
-
(function (ChromeChannel) {
|
|
16
|
-
ChromeChannel[ChromeChannel["CHROME_CHANNEL_UNSPECIFIED"] = 0] = "CHROME_CHANNEL_UNSPECIFIED";
|
|
17
|
-
ChromeChannel[ChromeChannel["CHROME_CHANNEL_CANARY"] = 1] = "CHROME_CHANNEL_CANARY";
|
|
18
|
-
ChromeChannel[ChromeChannel["CHROME_CHANNEL_DEV"] = 2] = "CHROME_CHANNEL_DEV";
|
|
19
|
-
ChromeChannel[ChromeChannel["CHROME_CHANNEL_BETA"] = 3] = "CHROME_CHANNEL_BETA";
|
|
20
|
-
ChromeChannel[ChromeChannel["CHROME_CHANNEL_STABLE"] = 4] = "CHROME_CHANNEL_STABLE";
|
|
21
|
-
})(ChromeChannel || (ChromeChannel = {}));
|
|
22
|
-
export var McpClient;
|
|
23
|
-
(function (McpClient) {
|
|
24
|
-
McpClient[McpClient["MCP_CLIENT_UNSPECIFIED"] = 0] = "MCP_CLIENT_UNSPECIFIED";
|
|
25
|
-
McpClient[McpClient["MCP_CLIENT_CLAUDE_CODE"] = 1] = "MCP_CLIENT_CLAUDE_CODE";
|
|
26
|
-
McpClient[McpClient["MCP_CLIENT_GEMINI_CLI"] = 2] = "MCP_CLIENT_GEMINI_CLI";
|
|
27
|
-
})(McpClient || (McpClient = {}));
|
|
28
|
-
// IPC types for messages between the main process and the
|
|
29
|
-
// telemetry watchdog process.
|
|
30
|
-
export var WatchdogMessageType;
|
|
31
|
-
(function (WatchdogMessageType) {
|
|
32
|
-
WatchdogMessageType["LOG_EVENT"] = "log-event";
|
|
33
|
-
})(WatchdogMessageType || (WatchdogMessageType = {}));
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2026 Google LLC
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
import crypto from 'node:crypto';
|
|
7
|
-
import { logger } from '../../logger.js';
|
|
8
|
-
const MAX_BUFFER_SIZE = 1000;
|
|
9
|
-
const DEFAULT_CLEARCUT_ENDPOINT = 'https://play.googleapis.com/log?format=json_proto';
|
|
10
|
-
const DEFAULT_FLUSH_INTERVAL_MS = 15 * 60 * 1000;
|
|
11
|
-
const LOG_SOURCE = 2839;
|
|
12
|
-
const CLIENT_TYPE = 47;
|
|
13
|
-
const MIN_RATE_LIMIT_WAIT_MS = 30_000;
|
|
14
|
-
const REQUEST_TIMEOUT_MS = 30_000;
|
|
15
|
-
const SHUTDOWN_TIMEOUT_MS = 5_000;
|
|
16
|
-
const SESSION_ROTATION_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
17
|
-
export class ClearcutSender {
|
|
18
|
-
#appVersion;
|
|
19
|
-
#osType;
|
|
20
|
-
#clearcutEndpoint;
|
|
21
|
-
#flushIntervalMs;
|
|
22
|
-
#includePidHeader;
|
|
23
|
-
#sessionId;
|
|
24
|
-
#sessionCreated;
|
|
25
|
-
#buffer = [];
|
|
26
|
-
#flushTimer = null;
|
|
27
|
-
#isFlushing = false;
|
|
28
|
-
#timerStarted = false;
|
|
29
|
-
constructor(config) {
|
|
30
|
-
this.#appVersion = config.appVersion;
|
|
31
|
-
this.#osType = config.osType;
|
|
32
|
-
this.#clearcutEndpoint =
|
|
33
|
-
config.clearcutEndpoint ?? DEFAULT_CLEARCUT_ENDPOINT;
|
|
34
|
-
this.#flushIntervalMs =
|
|
35
|
-
config.forceFlushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
|
|
36
|
-
this.#includePidHeader = config.includePidHeader ?? false;
|
|
37
|
-
this.#sessionId = crypto.randomUUID();
|
|
38
|
-
this.#sessionCreated = Date.now();
|
|
39
|
-
}
|
|
40
|
-
enqueueEvent(event) {
|
|
41
|
-
if (Date.now() - this.#sessionCreated > SESSION_ROTATION_INTERVAL_MS) {
|
|
42
|
-
this.#sessionId = crypto.randomUUID();
|
|
43
|
-
this.#sessionCreated = Date.now();
|
|
44
|
-
}
|
|
45
|
-
logger('Enqueing telemetry event', JSON.stringify(event, null, 2));
|
|
46
|
-
this.#addToBuffer({
|
|
47
|
-
...event,
|
|
48
|
-
session_id: this.#sessionId,
|
|
49
|
-
app_version: this.#appVersion,
|
|
50
|
-
os_type: this.#osType,
|
|
51
|
-
});
|
|
52
|
-
if (!this.#timerStarted) {
|
|
53
|
-
this.#timerStarted = true;
|
|
54
|
-
this.#scheduleFlush(this.#flushIntervalMs);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
async sendShutdownEvent() {
|
|
58
|
-
if (this.#flushTimer) {
|
|
59
|
-
clearTimeout(this.#flushTimer);
|
|
60
|
-
this.#flushTimer = null;
|
|
61
|
-
}
|
|
62
|
-
const shutdownEvent = {
|
|
63
|
-
server_shutdown: {},
|
|
64
|
-
};
|
|
65
|
-
this.enqueueEvent(shutdownEvent);
|
|
66
|
-
try {
|
|
67
|
-
await Promise.race([
|
|
68
|
-
this.#finalFlush(),
|
|
69
|
-
new Promise(resolve => setTimeout(resolve, SHUTDOWN_TIMEOUT_MS)),
|
|
70
|
-
]);
|
|
71
|
-
logger('Final flush completed');
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
logger('Final flush failed:', error);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
async #flush() {
|
|
78
|
-
if (this.#isFlushing) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
if (this.#buffer.length === 0) {
|
|
82
|
-
this.#scheduleFlush(this.#flushIntervalMs);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
this.#isFlushing = true;
|
|
86
|
-
let nextDelayMs = this.#flushIntervalMs;
|
|
87
|
-
// Optimistically remove events from buffer before sending.
|
|
88
|
-
// This prevents race conditions where a simultaneous #finalFlush would include these same events.
|
|
89
|
-
const eventsToSend = [...this.#buffer];
|
|
90
|
-
this.#buffer = [];
|
|
91
|
-
try {
|
|
92
|
-
const result = await this.#sendBatch(eventsToSend);
|
|
93
|
-
if (result.success) {
|
|
94
|
-
if (result.nextRequestWaitMs !== undefined) {
|
|
95
|
-
nextDelayMs = Math.max(result.nextRequestWaitMs, MIN_RATE_LIMIT_WAIT_MS);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
else if (result.isPermanentError) {
|
|
99
|
-
logger('Permanent error, dropped batch of', eventsToSend.length, 'events');
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
// Transient error: Requeue events at the front of the buffer
|
|
103
|
-
// to maintain order and retry them later.
|
|
104
|
-
this.#buffer = [...eventsToSend, ...this.#buffer];
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
catch (error) {
|
|
108
|
-
// Safety catch for unexpected errors, requeue events
|
|
109
|
-
this.#buffer = [...eventsToSend, ...this.#buffer];
|
|
110
|
-
logger('Flush failed unexpectedly:', error);
|
|
111
|
-
}
|
|
112
|
-
finally {
|
|
113
|
-
this.#isFlushing = false;
|
|
114
|
-
this.#scheduleFlush(nextDelayMs);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
#addToBuffer(event) {
|
|
118
|
-
if (this.#buffer.length >= MAX_BUFFER_SIZE) {
|
|
119
|
-
this.#buffer.shift();
|
|
120
|
-
logger('Telemetry buffer overflow: dropped oldest event');
|
|
121
|
-
}
|
|
122
|
-
this.#buffer.push({
|
|
123
|
-
event,
|
|
124
|
-
timestamp: Date.now(),
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
#scheduleFlush(delayMs) {
|
|
128
|
-
logger(`Scheduling flush in ${delayMs}`);
|
|
129
|
-
if (this.#flushTimer) {
|
|
130
|
-
clearTimeout(this.#flushTimer);
|
|
131
|
-
}
|
|
132
|
-
this.#flushTimer = setTimeout(() => {
|
|
133
|
-
this.#flush().catch(err => {
|
|
134
|
-
logger('Flush error:', err);
|
|
135
|
-
});
|
|
136
|
-
}, delayMs);
|
|
137
|
-
}
|
|
138
|
-
async #sendBatch(events) {
|
|
139
|
-
logger(`Sending batch of ${events.length}`);
|
|
140
|
-
const requestBody = {
|
|
141
|
-
log_source: LOG_SOURCE,
|
|
142
|
-
request_time_ms: Date.now().toString(),
|
|
143
|
-
client_info: {
|
|
144
|
-
client_type: CLIENT_TYPE,
|
|
145
|
-
},
|
|
146
|
-
log_event: events.map(({ event, timestamp }) => ({
|
|
147
|
-
event_time_ms: timestamp.toString(),
|
|
148
|
-
source_extension_json: JSON.stringify(event),
|
|
149
|
-
})),
|
|
150
|
-
};
|
|
151
|
-
const controller = new AbortController();
|
|
152
|
-
const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
153
|
-
try {
|
|
154
|
-
const response = await fetch(this.#clearcutEndpoint, {
|
|
155
|
-
method: 'POST',
|
|
156
|
-
headers: {
|
|
157
|
-
'Content-Type': 'application/json',
|
|
158
|
-
// Used in E2E tests to confirm that the watchdog process is killed
|
|
159
|
-
...(this.#includePidHeader
|
|
160
|
-
? { 'X-Watchdog-Pid': process.pid.toString() }
|
|
161
|
-
: {}),
|
|
162
|
-
},
|
|
163
|
-
body: JSON.stringify(requestBody),
|
|
164
|
-
signal: controller.signal,
|
|
165
|
-
});
|
|
166
|
-
clearTimeout(timeoutId);
|
|
167
|
-
if (response.ok) {
|
|
168
|
-
const data = (await response.json());
|
|
169
|
-
return {
|
|
170
|
-
success: true,
|
|
171
|
-
nextRequestWaitMs: data.next_request_wait_millis,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
const status = response.status;
|
|
175
|
-
if (status >= 500 || status === 429) {
|
|
176
|
-
return { success: false };
|
|
177
|
-
}
|
|
178
|
-
logger('Telemetry permanent error:', status);
|
|
179
|
-
return { success: false, isPermanentError: true };
|
|
180
|
-
}
|
|
181
|
-
catch {
|
|
182
|
-
clearTimeout(timeoutId);
|
|
183
|
-
return { success: false };
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
async #finalFlush() {
|
|
187
|
-
if (this.#buffer.length === 0) {
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
const eventsToSend = [...this.#buffer];
|
|
191
|
-
await this.#sendBatch(eventsToSend);
|
|
192
|
-
}
|
|
193
|
-
stopForTesting() {
|
|
194
|
-
if (this.#flushTimer) {
|
|
195
|
-
clearTimeout(this.#flushTimer);
|
|
196
|
-
this.#flushTimer = null;
|
|
197
|
-
}
|
|
198
|
-
this.#timerStarted = false;
|
|
199
|
-
}
|
|
200
|
-
get bufferSizeForTesting() {
|
|
201
|
-
return this.#buffer.length;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2026 Google LLC
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
import process from 'node:process';
|
|
7
|
-
import readline from 'node:readline';
|
|
8
|
-
import { parseArgs } from 'node:util';
|
|
9
|
-
import { logger, flushLogs, saveLogsToFile } from '../../logger.js';
|
|
10
|
-
import { WatchdogMessageType } from '../types.js';
|
|
11
|
-
import { ClearcutSender } from './ClearcutSender.js';
|
|
12
|
-
function parseWatchdogArgs() {
|
|
13
|
-
const { values } = parseArgs({
|
|
14
|
-
options: {
|
|
15
|
-
'parent-pid': { type: 'string' },
|
|
16
|
-
'app-version': { type: 'string' },
|
|
17
|
-
'os-type': { type: 'string' },
|
|
18
|
-
'log-file': { type: 'string' },
|
|
19
|
-
'clearcut-endpoint': { type: 'string' },
|
|
20
|
-
'clearcut-force-flush-interval-ms': { type: 'string' },
|
|
21
|
-
'clearcut-include-pid-header': { type: 'boolean' },
|
|
22
|
-
},
|
|
23
|
-
strict: true,
|
|
24
|
-
});
|
|
25
|
-
// Verify required arguments
|
|
26
|
-
const parentPid = parseInt(values['parent-pid'] ?? '', 10);
|
|
27
|
-
const appVersion = values['app-version'];
|
|
28
|
-
const osType = parseInt(values['os-type'] ?? '', 10);
|
|
29
|
-
if (isNaN(parentPid) || !appVersion || isNaN(osType)) {
|
|
30
|
-
console.error('Invalid arguments provided for watchdog process: ', JSON.stringify({ parentPid, appVersion, osType }));
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
// Parse Optional Arguments
|
|
34
|
-
const logFile = values['log-file'];
|
|
35
|
-
const clearcutEndpoint = values['clearcut-endpoint'];
|
|
36
|
-
const clearcutIncludePidHeader = values['clearcut-include-pid-header'];
|
|
37
|
-
let clearcutForceFlushIntervalMs;
|
|
38
|
-
if (values['clearcut-force-flush-interval-ms']) {
|
|
39
|
-
const parsed = parseInt(values['clearcut-force-flush-interval-ms'], 10);
|
|
40
|
-
if (!isNaN(parsed)) {
|
|
41
|
-
clearcutForceFlushIntervalMs = parsed;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return {
|
|
45
|
-
parentPid,
|
|
46
|
-
appVersion,
|
|
47
|
-
osType,
|
|
48
|
-
logFile,
|
|
49
|
-
clearcutEndpoint,
|
|
50
|
-
clearcutForceFlushIntervalMs,
|
|
51
|
-
clearcutIncludePidHeader,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
function main() {
|
|
55
|
-
const { parentPid, appVersion, osType, logFile, clearcutEndpoint, clearcutForceFlushIntervalMs, clearcutIncludePidHeader, } = parseWatchdogArgs();
|
|
56
|
-
let logStream;
|
|
57
|
-
if (logFile) {
|
|
58
|
-
logStream = saveLogsToFile(logFile);
|
|
59
|
-
}
|
|
60
|
-
const exit = (code) => {
|
|
61
|
-
if (!logStream) {
|
|
62
|
-
process.exit(code);
|
|
63
|
-
}
|
|
64
|
-
void flushLogs(logStream).finally(() => {
|
|
65
|
-
process.exit(code);
|
|
66
|
-
});
|
|
67
|
-
};
|
|
68
|
-
logger('Watchdog started', JSON.stringify({
|
|
69
|
-
pid: process.pid,
|
|
70
|
-
parentPid,
|
|
71
|
-
version: appVersion,
|
|
72
|
-
osType,
|
|
73
|
-
}, null, 2));
|
|
74
|
-
const sender = new ClearcutSender({
|
|
75
|
-
appVersion,
|
|
76
|
-
osType: osType,
|
|
77
|
-
clearcutEndpoint,
|
|
78
|
-
forceFlushIntervalMs: clearcutForceFlushIntervalMs,
|
|
79
|
-
includePidHeader: clearcutIncludePidHeader,
|
|
80
|
-
});
|
|
81
|
-
let isShuttingDown = false;
|
|
82
|
-
function onParentDeath(reason) {
|
|
83
|
-
if (isShuttingDown) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
isShuttingDown = true;
|
|
87
|
-
logger(`Parent death detected (${reason}). Sending shutdown event...`);
|
|
88
|
-
sender
|
|
89
|
-
.sendShutdownEvent()
|
|
90
|
-
.then(() => {
|
|
91
|
-
logger('Shutdown event sent. Exiting.');
|
|
92
|
-
exit(0);
|
|
93
|
-
})
|
|
94
|
-
.catch(err => {
|
|
95
|
-
logger('Failed to send shutdown event', err);
|
|
96
|
-
exit(1);
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
process.stdin.on('end', () => onParentDeath('stdin end'));
|
|
100
|
-
process.stdin.on('close', () => onParentDeath('stdin close'));
|
|
101
|
-
process.on('disconnect', () => onParentDeath('ipc disconnect'));
|
|
102
|
-
const rl = readline.createInterface({
|
|
103
|
-
input: process.stdin,
|
|
104
|
-
terminal: false,
|
|
105
|
-
});
|
|
106
|
-
rl.on('line', line => {
|
|
107
|
-
try {
|
|
108
|
-
if (!line.trim()) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
const msg = JSON.parse(line);
|
|
112
|
-
if (msg.type === WatchdogMessageType.LOG_EVENT && msg.payload) {
|
|
113
|
-
sender.enqueueEvent(msg.payload);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
catch (err) {
|
|
117
|
-
logger('Failed to parse IPC message', err);
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
try {
|
|
122
|
-
main();
|
|
123
|
-
}
|
|
124
|
-
catch (err) {
|
|
125
|
-
console.error('Watchdog fatal error:', err);
|
|
126
|
-
process.exit(1);
|
|
127
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2026 Google LLC
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
// eslint-disable-next-line no-restricted-imports
|
|
7
|
-
import '../../node_modules/chrome-devtools-frontend/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.js';
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2025 Google LLC
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
import 'core-js/modules/es.promise.with-resolvers.js';
|
|
7
|
-
import 'core-js/modules/es.set.union.v2.js';
|
|
8
|
-
import 'core-js/proposals/iterator-helpers.js';
|
|
9
|
-
export { default as yargs } from 'yargs';
|
|
10
|
-
export { hideBin } from 'yargs/helpers';
|
|
11
|
-
export { default as debug } from 'debug';
|
|
12
|
-
export { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
13
|
-
export { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
14
|
-
export { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
15
|
-
export { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
16
|
-
export { SetLevelRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
17
|
-
export { z as zod } from 'zod';
|
|
18
|
-
export { Locator, PredefinedNetworkConditions, KnownDevices, CDPSessionEvent, } from 'puppeteer-core';
|
|
19
|
-
export { default as puppeteer } from 'puppeteer-core';
|
|
20
|
-
export { PipeTransport } from 'puppeteer-core/internal/node/PipeTransport.js';
|
|
21
|
-
export { resolveDefaultUserDataDir, detectBrowserPlatform, Browser as BrowserEnum, } from '@puppeteer/browsers';
|
|
22
|
-
import { snapshot as snapshotImpl, navigation as navigationImpl, generateReport as generateReportImpl, } from './lighthouse-devtools-mcp-bundle.js';
|
|
23
|
-
export const snapshot = snapshotImpl;
|
|
24
|
-
export const navigation = navigationImpl;
|
|
25
|
-
export const generateReport = generateReportImpl;
|
|
26
|
-
export * as DevTools from '../../node_modules/chrome-devtools-frontend/mcp/mcp.js';
|