@szymonrybczak/playwright-mcp 0.0.16 → 0.0.18

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
4
4
 
5
- const version = "0.0.16";
5
+ const version = "0.0.18";
6
6
  const json = {
7
7
  version};
8
8
 
@@ -31,25 +31,14 @@ const playwright__namespace = /*#__PURE__*/_interopNamespaceDefault(playwright);
31
31
 
32
32
  const testDebug = debugStub.default("pw:mcp:test");
33
33
  function contextFactory(browserConfig) {
34
- console.log("[contextFactory] START");
35
- console.log("[contextFactory] browserConfig:", JSON.stringify(browserConfig, null, 2));
36
- if (browserConfig.remoteEndpoint) {
37
- console.log("[contextFactory] Using RemoteContextFactory");
34
+ if (browserConfig.remoteEndpoint)
38
35
  return new RemoteContextFactory(browserConfig);
39
- }
40
- if (browserConfig.cdpEndpoint) {
41
- console.log("[contextFactory] Using CdpContextFactory");
36
+ if (browserConfig.cdpEndpoint)
42
37
  return new CdpContextFactory(browserConfig);
43
- }
44
- if (browserConfig.isolated) {
45
- console.log("[contextFactory] Using IsolatedContextFactory");
38
+ if (browserConfig.isolated)
46
39
  return new IsolatedContextFactory(browserConfig);
47
- }
48
- if (browserConfig.browserAgent) {
49
- console.log("[contextFactory] Using BrowserServerContextFactory");
40
+ if (browserConfig.browserAgent)
50
41
  return new BrowserServerContextFactory(browserConfig);
51
- }
52
- console.log("[contextFactory] Using PersistentContextFactory");
53
42
  return new PersistentContextFactory(browserConfig);
54
43
  }
55
44
  class BaseContextFactory {
@@ -59,50 +48,66 @@ class BaseContextFactory {
59
48
  constructor(name, browserConfig) {
60
49
  this.name = name;
61
50
  this.browserConfig = browserConfig;
62
- console.log(`[BaseContextFactory] Created factory: ${name}`);
63
51
  }
64
52
  async _obtainBrowser() {
65
- console.log(`[BaseContextFactory._obtainBrowser] START (${this.name})`);
66
- console.log(`[BaseContextFactory._obtainBrowser] _browserPromise exists:`, !!this._browserPromise);
53
+ console.log(`[BaseContextFactory._obtainBrowser] --------- OBTAIN BROWSER START (${this.name}) ---------`);
54
+ console.log(`[BaseContextFactory._obtainBrowser] Browser promise exists: ${!!this._browserPromise}`);
67
55
  if (this._browserPromise) {
68
- console.log(`[BaseContextFactory._obtainBrowser] Returning existing promise`);
56
+ console.log(`[BaseContextFactory._obtainBrowser] Reusing existing browser promise`);
57
+ console.log(`[BaseContextFactory._obtainBrowser] --------- OBTAIN BROWSER END (${this.name}) ---------`);
69
58
  return this._browserPromise;
70
59
  }
71
60
  testDebug(`obtain browser (${this.name})`);
72
- console.log(`[BaseContextFactory._obtainBrowser] Calling _doObtainBrowser...`);
61
+ console.log(`[BaseContextFactory._obtainBrowser] No existing promise, calling _doObtainBrowser()...`);
73
62
  this._browserPromise = this._doObtainBrowser();
74
63
  void this._browserPromise.then((browser) => {
75
64
  console.log(`[BaseContextFactory._obtainBrowser] Browser obtained successfully`);
76
65
  browser.on("disconnected", () => {
77
- console.log(`[BaseContextFactory._obtainBrowser] Browser disconnected`);
66
+ console.log(`[BaseContextFactory._obtainBrowser] Browser disconnected event fired`);
78
67
  this._browserPromise = void 0;
79
68
  });
80
- }).catch((err) => {
81
- console.log(`[BaseContextFactory._obtainBrowser] Browser promise rejected:`, err.message);
69
+ }).catch((error) => {
70
+ console.error(`[BaseContextFactory._obtainBrowser] Browser promise rejected:`, error);
82
71
  this._browserPromise = void 0;
83
72
  });
73
+ console.log(`[BaseContextFactory._obtainBrowser] --------- OBTAIN BROWSER END (${this.name}) ---------`);
84
74
  return this._browserPromise;
85
75
  }
86
76
  async _doObtainBrowser() {
87
77
  throw new Error("Not implemented");
88
78
  }
89
79
  async createContext() {
90
- console.log(`[BaseContextFactory.createContext] START (${this.name})`);
80
+ console.log(`[BaseContextFactory.createContext] --------- CREATE CONTEXT START (${this.name}) ---------`);
91
81
  testDebug(`create browser context (${this.name})`);
92
- console.log(`[BaseContextFactory.createContext] Calling _obtainBrowser...`);
93
- const browser = await this._obtainBrowser();
94
- console.log(`[BaseContextFactory.createContext] Got browser`);
95
- console.log(`[BaseContextFactory.createContext] Calling _doCreateContext...`);
96
- const browserContext = await this._doCreateContext(browser);
97
- console.log(`[BaseContextFactory.createContext] Got browserContext`);
98
- console.log(`[BaseContextFactory.createContext] END`);
82
+ console.log(`[BaseContextFactory.createContext] Calling _obtainBrowser()...`);
83
+ const obtainStart = Date.now();
84
+ let browser;
85
+ try {
86
+ browser = await this._obtainBrowser();
87
+ console.log(`[BaseContextFactory.createContext] _obtainBrowser() completed in ${Date.now() - obtainStart}ms`);
88
+ } catch (error) {
89
+ console.error(`[BaseContextFactory.createContext] ERROR: _obtainBrowser() failed after ${Date.now() - obtainStart}ms`);
90
+ console.error(`[BaseContextFactory.createContext] Error:`, error);
91
+ throw error;
92
+ }
93
+ console.log(`[BaseContextFactory.createContext] Calling _doCreateContext()...`);
94
+ const createStart = Date.now();
95
+ let browserContext;
96
+ try {
97
+ browserContext = await this._doCreateContext(browser);
98
+ console.log(`[BaseContextFactory.createContext] _doCreateContext() completed in ${Date.now() - createStart}ms`);
99
+ } catch (error) {
100
+ console.error(`[BaseContextFactory.createContext] ERROR: _doCreateContext() failed after ${Date.now() - createStart}ms`);
101
+ console.error(`[BaseContextFactory.createContext] Error:`, error);
102
+ throw error;
103
+ }
104
+ console.log(`[BaseContextFactory.createContext] --------- CREATE CONTEXT END (${this.name}) ---------`);
99
105
  return { browserContext, close: () => this._closeBrowserContext(browserContext, browser) };
100
106
  }
101
107
  async _doCreateContext(browser) {
102
108
  throw new Error("Not implemented");
103
109
  }
104
110
  async _closeBrowserContext(browserContext, browser) {
105
- console.log(`[BaseContextFactory._closeBrowserContext] START (${this.name})`);
106
111
  testDebug(`close browser context (${this.name})`);
107
112
  if (browser.contexts().length === 1)
108
113
  this._browserPromise = void 0;
@@ -113,7 +118,6 @@ class BaseContextFactory {
113
118
  await browser.close().catch(() => {
114
119
  });
115
120
  }
116
- console.log(`[BaseContextFactory._closeBrowserContext] END`);
117
121
  }
118
122
  }
119
123
  class IsolatedContextFactory extends BaseContextFactory {
@@ -142,106 +146,43 @@ class CdpContextFactory extends BaseContextFactory {
142
146
  super("cdp", browserConfig);
143
147
  }
144
148
  async _doObtainBrowser() {
145
- console.log("[CdpContextFactory._doObtainBrowser] START");
146
- console.log("[CdpContextFactory._doObtainBrowser] cdpEndpoint:", this.browserConfig.cdpEndpoint);
147
- console.log("[CdpContextFactory._doObtainBrowser] cdpEndpoint type:", typeof this.browserConfig.cdpEndpoint);
148
- const endpoint = this.browserConfig.cdpEndpoint;
149
- const isCloudfareFetcher = typeof endpoint !== "string";
150
- console.log("[CdpContextFactory._doObtainBrowser] isCloudfareFetcher:", isCloudfareFetcher);
149
+ console.log(`[CdpContextFactory._doObtainBrowser] --------- CDP OBTAIN BROWSER START ---------`);
150
+ console.log(`[CdpContextFactory._doObtainBrowser] CDP endpoint: ${this.browserConfig.cdpEndpoint}`);
151
+ const connectStart = Date.now();
151
152
  try {
152
- let browser;
153
- if (isCloudfareFetcher) {
154
- const fetcher = endpoint;
155
- console.log("[CdpContextFactory._doObtainBrowser] Fetcher detected, using connect() method...");
156
- const connectUrls = [
157
- "https://cloudflare",
158
- "https://cloudflare/",
159
- "wss://cloudflare"
160
- ];
161
- let socket = null;
162
- let successUrl = "";
163
- for (const url of connectUrls) {
164
- try {
165
- console.log(`[CdpContextFactory._doObtainBrowser] Trying fetcher.connect("${url}")...`);
166
- const connection = await fetcher.connect(url);
167
- console.log("[CdpContextFactory._doObtainBrowser] connect() returned:", typeof connection);
168
- console.log("[CdpContextFactory._doObtainBrowser] connection keys:", Object.keys(connection || {}));
169
- console.log("[CdpContextFactory._doObtainBrowser] connection.socket:", typeof connection?.socket);
170
- if (connection && typeof connection === "object") {
171
- if ("accept" in connection && typeof connection.accept === "function") {
172
- console.log("[CdpContextFactory._doObtainBrowser] Connection has accept(), calling it...");
173
- connection.accept();
174
- }
175
- if ("send" in connection && "close" in connection) {
176
- socket = connection;
177
- successUrl = url;
178
- console.log("[CdpContextFactory._doObtainBrowser] Got WebSocket-like object directly");
179
- break;
180
- }
181
- if ("socket" in connection) {
182
- socket = connection.socket;
183
- successUrl = url;
184
- console.log("[CdpContextFactory._doObtainBrowser] Got socket from connection.socket");
185
- break;
186
- }
187
- if ("webSocket" in connection) {
188
- socket = connection.webSocket;
189
- if (socket && "accept" in socket) {
190
- socket.accept();
191
- }
192
- successUrl = url;
193
- console.log("[CdpContextFactory._doObtainBrowser] Got socket from connection.webSocket");
194
- break;
195
- }
196
- console.log("[CdpContextFactory._doObtainBrowser] Connection structure:", JSON.stringify(Object.getOwnPropertyNames(connection)));
197
- const proto = Object.getPrototypeOf(connection);
198
- if (proto) {
199
- console.log("[CdpContextFactory._doObtainBrowser] Connection prototype:", Object.getOwnPropertyNames(proto));
200
- }
201
- }
202
- } catch (e) {
203
- console.log(`[CdpContextFactory._doObtainBrowser] connect("${url}") error:`, e.message);
204
- }
205
- }
206
- if (!socket) {
207
- throw new Error("Could not establish WebSocket via Fetcher.connect(). Check logs above.");
208
- }
209
- console.log(`[CdpContextFactory._doObtainBrowser] WebSocket obtained from ${successUrl}`);
210
- console.log("[CdpContextFactory._doObtainBrowser] Socket type:", typeof socket);
211
- console.log("[CdpContextFactory._doObtainBrowser] Socket readyState:", socket.readyState);
212
- console.log("[CdpContextFactory._doObtainBrowser] Socket methods:", Object.getOwnPropertyNames(Object.getPrototypeOf(socket)));
213
- console.log("[CdpContextFactory._doObtainBrowser] playwright.chromium methods:", Object.keys(playwright__namespace.chromium));
214
- if (typeof playwright__namespace.chromium.connectOverCDPWithSocket === "function") {
215
- console.log("[CdpContextFactory._doObtainBrowser] Using connectOverCDPWithSocket...");
216
- browser = await playwright__namespace.chromium.connectOverCDPWithSocket(socket);
217
- } else if (typeof playwright__namespace.chromium.connectWithWebSocket === "function") {
218
- console.log("[CdpContextFactory._doObtainBrowser] Using connectWithWebSocket...");
219
- browser = await playwright__namespace.chromium.connectWithWebSocket(socket);
220
- } else {
221
- throw new Error(`WebSocket connection established but patchright needs a method to accept raw WebSocket for CDP. Available methods: ${Object.keys(playwright__namespace.chromium).join(", ")}`);
222
- }
223
- } else {
224
- console.log("[CdpContextFactory._doObtainBrowser] Using chromium.connectOverCDP() for CDP URL...");
225
- browser = await playwright__namespace.chromium.connectOverCDP(endpoint);
226
- }
227
- console.log("[CdpContextFactory._doObtainBrowser] Connection completed");
153
+ const browser = await playwright__namespace.chromium.connectOverCDP(this.browserConfig.cdpEndpoint);
154
+ console.log(`[CdpContextFactory._doObtainBrowser] connectOverCDP() completed in ${Date.now() - connectStart}ms`);
155
+ console.log(`[CdpContextFactory._doObtainBrowser] Browser connected: ${browser.isConnected()}`);
156
+ console.log(`[CdpContextFactory._doObtainBrowser] Browser version: ${browser.version()}`);
157
+ console.log(`[CdpContextFactory._doObtainBrowser] Existing contexts: ${browser.contexts().length}`);
158
+ console.log(`[CdpContextFactory._doObtainBrowser] --------- CDP OBTAIN BROWSER END ---------`);
228
159
  return browser;
229
- } catch (err) {
230
- console.log("[CdpContextFactory._doObtainBrowser] ERROR:", err.message, err.stack);
231
- throw err;
160
+ } catch (error) {
161
+ console.error(`[CdpContextFactory._doObtainBrowser] ERROR: connectOverCDP() failed after ${Date.now() - connectStart}ms`);
162
+ console.error(`[CdpContextFactory._doObtainBrowser] Error type: ${error.constructor.name}`);
163
+ console.error(`[CdpContextFactory._doObtainBrowser] Error message: ${error.message}`);
164
+ console.error(`[CdpContextFactory._doObtainBrowser] Error stack:`, error.stack);
165
+ throw error;
232
166
  }
233
167
  }
234
168
  async _doCreateContext(browser) {
235
- console.log("[CdpContextFactory._doCreateContext] START");
236
- console.log("[CdpContextFactory._doCreateContext] isolated:", this.browserConfig.isolated);
237
- try {
238
- const ctx = this.browserConfig.isolated ? await browser.newContext() : browser.contexts()[0];
239
- console.log("[CdpContextFactory._doCreateContext] Got context");
240
- return ctx;
241
- } catch (err) {
242
- console.log("[CdpContextFactory._doCreateContext] ERROR:", err.message, err.stack);
243
- throw err;
169
+ console.log(`[CdpContextFactory._doCreateContext] --------- CDP CREATE CONTEXT START ---------`);
170
+ console.log(`[CdpContextFactory._doCreateContext] Isolated mode: ${this.browserConfig.isolated}`);
171
+ console.log(`[CdpContextFactory._doCreateContext] Existing contexts: ${browser.contexts().length}`);
172
+ let context;
173
+ if (this.browserConfig.isolated) {
174
+ console.log(`[CdpContextFactory._doCreateContext] Creating new isolated context...`);
175
+ const newContextStart = Date.now();
176
+ context = await browser.newContext();
177
+ console.log(`[CdpContextFactory._doCreateContext] New context created in ${Date.now() - newContextStart}ms`);
178
+ } else {
179
+ console.log(`[CdpContextFactory._doCreateContext] Using existing context[0]...`);
180
+ context = browser.contexts()[0];
181
+ console.log(`[CdpContextFactory._doCreateContext] Existing context obtained`);
244
182
  }
183
+ console.log(`[CdpContextFactory._doCreateContext] Context pages: ${context.pages().length}`);
184
+ console.log(`[CdpContextFactory._doCreateContext] --------- CDP CREATE CONTEXT END ---------`);
185
+ return context;
245
186
  }
246
187
  }
247
188
  class RemoteContextFactory extends BaseContextFactory {
@@ -70,29 +70,42 @@ class Context {
70
70
  await this._currentTab.page.bringToFront();
71
71
  }
72
72
  async ensureTab() {
73
- console.log("[Context.ensureTab] START");
74
- console.log("[Context.ensureTab] _currentTab exists:", !!this._currentTab);
75
- console.log("[Context.ensureTab] Calling _ensureBrowserContext()...");
73
+ console.log(`[Context.ensureTab] --------- ENSURE TAB START ---------`);
74
+ console.log(`[Context.ensureTab] Current tab exists: ${!!this._currentTab}`);
75
+ console.log(`[Context.ensureTab] Number of tabs: ${this._tabs.length}`);
76
+ console.log(`[Context.ensureTab] Browser context promise exists: ${!!this._browserContextPromise}`);
77
+ console.log(`[Context.ensureTab] Calling _ensureBrowserContext()...`);
78
+ const ensureContextStart = Date.now();
76
79
  let browserContext;
77
80
  try {
78
81
  const result = await this._ensureBrowserContext();
79
82
  browserContext = result.browserContext;
80
- console.log("[Context.ensureTab] _ensureBrowserContext() completed");
81
- } catch (err) {
82
- console.log("[Context.ensureTab] ERROR in _ensureBrowserContext():", err.message, err.stack);
83
- throw err;
83
+ console.log(`[Context.ensureTab] _ensureBrowserContext() completed in ${Date.now() - ensureContextStart}ms`);
84
+ console.log(`[Context.ensureTab] Browser context obtained: ${!!browserContext}`);
85
+ } catch (error) {
86
+ console.error(`[Context.ensureTab] ERROR: _ensureBrowserContext() failed after ${Date.now() - ensureContextStart}ms`);
87
+ console.error(`[Context.ensureTab] Error type: ${error.constructor.name}`);
88
+ console.error(`[Context.ensureTab] Error message: ${error.message}`);
89
+ console.error(`[Context.ensureTab] Error stack:`, error.stack);
90
+ throw error;
84
91
  }
85
92
  if (!this._currentTab) {
86
- console.log("[Context.ensureTab] No current tab, creating new page...");
93
+ console.log(`[Context.ensureTab] No current tab, creating new page...`);
94
+ const newPageStart = Date.now();
87
95
  try {
88
96
  await browserContext.newPage();
89
- console.log("[Context.ensureTab] New page created");
90
- } catch (err) {
91
- console.log("[Context.ensureTab] ERROR creating new page:", err.message, err.stack);
92
- throw err;
97
+ console.log(`[Context.ensureTab] New page created in ${Date.now() - newPageStart}ms`);
98
+ console.log(`[Context.ensureTab] Current tab after newPage: ${!!this._currentTab}`);
99
+ } catch (error) {
100
+ console.error(`[Context.ensureTab] ERROR: newPage() failed after ${Date.now() - newPageStart}ms`);
101
+ console.error(`[Context.ensureTab] Error:`, error);
102
+ throw error;
93
103
  }
104
+ } else {
105
+ console.log(`[Context.ensureTab] Current tab already exists, skipping newPage()`);
94
106
  }
95
- console.log("[Context.ensureTab] END, returning tab");
107
+ console.log(`[Context.ensureTab] Returning tab. URL: ${this._currentTab?.page.url() ?? "N/A"}`);
108
+ console.log(`[Context.ensureTab] --------- ENSURE TAB END ---------`);
96
109
  return this._currentTab;
97
110
  }
98
111
  async listTabsMarkdown() {
@@ -269,51 +282,68 @@ ${code.join("\n")}
269
282
  }
270
283
  }
271
284
  _ensureBrowserContext() {
272
- console.log("[Context._ensureBrowserContext] START");
273
- console.log("[Context._ensureBrowserContext] _browserContextPromise exists:", !!this._browserContextPromise);
285
+ console.log(`[Context._ensureBrowserContext] --------- ENSURE BROWSER CONTEXT START ---------`);
286
+ console.log(`[Context._ensureBrowserContext] Browser context promise exists: ${!!this._browserContextPromise}`);
274
287
  if (!this._browserContextPromise) {
275
- console.log("[Context._ensureBrowserContext] Creating new browser context promise...");
288
+ console.log(`[Context._ensureBrowserContext] No existing promise, calling _setupBrowserContext()...`);
276
289
  this._browserContextPromise = this._setupBrowserContext();
277
- this._browserContextPromise.catch((err) => {
278
- console.log("[Context._ensureBrowserContext] Promise rejected:", err.message);
290
+ this._browserContextPromise.catch((error) => {
291
+ console.error(`[Context._ensureBrowserContext] _setupBrowserContext() promise rejected:`, error);
279
292
  this._browserContextPromise = void 0;
280
293
  });
294
+ } else {
295
+ console.log(`[Context._ensureBrowserContext] Reusing existing browser context promise`);
281
296
  }
282
- console.log("[Context._ensureBrowserContext] END, returning promise");
297
+ console.log(`[Context._ensureBrowserContext] --------- ENSURE BROWSER CONTEXT END ---------`);
283
298
  return this._browserContextPromise;
284
299
  }
285
300
  async _setupBrowserContext() {
286
- console.log("[Context._setupBrowserContext] START");
287
- console.log("[Context._setupBrowserContext] Calling _browserContextFactory.createContext()...");
301
+ console.log(`[Context._setupBrowserContext] --------- SETUP BROWSER CONTEXT START ---------`);
302
+ console.log(`[Context._setupBrowserContext] Calling browserContextFactory.createContext()...`);
303
+ const createContextStart = Date.now();
288
304
  let result;
289
305
  try {
290
306
  result = await this._browserContextFactory.createContext();
291
- console.log("[Context._setupBrowserContext] createContext() completed");
292
- } catch (err) {
293
- console.log("[Context._setupBrowserContext] ERROR in createContext():", err.message, err.stack);
294
- throw err;
307
+ console.log(`[Context._setupBrowserContext] createContext() completed in ${Date.now() - createContextStart}ms`);
308
+ } catch (error) {
309
+ console.error(`[Context._setupBrowserContext] ERROR: createContext() failed after ${Date.now() - createContextStart}ms`);
310
+ console.error(`[Context._setupBrowserContext] Error type: ${error.constructor.name}`);
311
+ console.error(`[Context._setupBrowserContext] Error message: ${error.message}`);
312
+ console.error(`[Context._setupBrowserContext] Error stack:`, error.stack);
313
+ throw error;
295
314
  }
296
315
  const { browserContext } = result;
297
- console.log("[Context._setupBrowserContext] Got browserContext");
298
- console.log("[Context._setupBrowserContext] Setting up request interception...");
316
+ console.log(`[Context._setupBrowserContext] Browser context obtained`);
317
+ console.log(`[Context._setupBrowserContext] Setting up request interception...`);
318
+ const interceptStart = Date.now();
299
319
  await this._setupRequestInterception(browserContext);
300
- console.log("[Context._setupBrowserContext] Request interception done");
301
- console.log("[Context._setupBrowserContext] Processing existing pages...");
302
- for (const page of browserContext.pages())
320
+ console.log(`[Context._setupBrowserContext] Request interception setup completed in ${Date.now() - interceptStart}ms`);
321
+ console.log(`[Context._setupBrowserContext] Processing existing pages...`);
322
+ const existingPages = browserContext.pages();
323
+ console.log(`[Context._setupBrowserContext] Found ${existingPages.length} existing pages`);
324
+ for (const page of existingPages) {
325
+ console.log(`[Context._setupBrowserContext] Processing existing page: ${page.url()}`);
303
326
  this._onPageCreated(page);
304
- browserContext.on("page", (page) => this._onPageCreated(page));
305
- console.log("[Context._setupBrowserContext] Pages processed");
327
+ }
328
+ console.log(`[Context._setupBrowserContext] Setting up 'page' event listener...`);
329
+ browserContext.on("page", (page) => {
330
+ console.log(`[Context._setupBrowserContext] 'page' event fired for: ${page.url()}`);
331
+ this._onPageCreated(page);
332
+ });
306
333
  if (this.config.saveTrace) {
307
- console.log("[Context._setupBrowserContext] Starting tracing...");
334
+ console.log(`[Context._setupBrowserContext] Starting tracing...`);
335
+ const traceStart = Date.now();
308
336
  await browserContext.tracing.start({
309
337
  name: "trace",
310
338
  screenshots: false,
311
339
  snapshots: true,
312
340
  sources: false
313
341
  });
314
- console.log("[Context._setupBrowserContext] Tracing started");
342
+ console.log(`[Context._setupBrowserContext] Tracing started in ${Date.now() - traceStart}ms`);
315
343
  }
316
- console.log("[Context._setupBrowserContext] END");
344
+ console.log(`[Context._setupBrowserContext] Total tabs after setup: ${this._tabs.length}`);
345
+ console.log(`[Context._setupBrowserContext] Current tab: ${this._currentTab ? "set" : "not set"}`);
346
+ console.log(`[Context._setupBrowserContext] --------- SETUP BROWSER CONTEXT END ---------`);
317
347
  return result;
318
348
  }
319
349
  }
@@ -50,40 +50,66 @@ class Tab {
50
50
  }));
51
51
  }
52
52
  async navigate(url) {
53
- console.log("[Tab.navigate] START, url:", url);
54
- console.log("[Tab.navigate] Clearing collected artifacts...");
53
+ const navStartTime = Date.now();
54
+ console.log(`[Tab.navigate] --------- TAB NAVIGATION START ---------`);
55
+ console.log(`[Tab.navigate] URL: ${url}`);
56
+ console.log(`[Tab.navigate] Current page URL: ${this.page.url()}`);
57
+ console.log(`[Tab.navigate] Page is closed: ${this.page.isClosed()}`);
58
+ console.log(`[Tab.navigate] Clearing collected artifacts...`);
55
59
  this._clearCollectedArtifacts();
56
- console.log("[Tab.navigate] Artifacts cleared");
57
- console.log("[Tab.navigate] Setting up download event listener...");
60
+ console.log(`[Tab.navigate] Artifacts cleared. Console messages: ${this._consoleMessages.length}, Requests: ${this._requests.size}`);
61
+ console.log(`[Tab.navigate] Setting up download event listener...`);
58
62
  const downloadEvent = utils.callOnPageNoTrace(this.page, (page) => page.waitForEvent("download").catch(() => {
59
63
  }));
60
- console.log("[Tab.navigate] Download event listener ready");
64
+ console.log(`[Tab.navigate] Download event listener set up`);
65
+ console.log(`[Tab.navigate] Calling page.goto() with waitUntil: 'domcontentloaded'`);
66
+ const gotoStartTime = Date.now();
61
67
  try {
62
- console.log("[Tab.navigate] Calling page.goto()...");
63
- await this.page.goto(url, { waitUntil: "domcontentloaded" });
64
- console.log("[Tab.navigate] page.goto() completed successfully");
68
+ const response = await this.page.goto(url, { waitUntil: "domcontentloaded" });
69
+ const gotoTime = Date.now() - gotoStartTime;
70
+ console.log(`[Tab.navigate] page.goto() completed in ${gotoTime}ms`);
71
+ if (response) {
72
+ console.log(`[Tab.navigate] Response status: ${response.status()}`);
73
+ console.log(`[Tab.navigate] Response URL: ${response.url()}`);
74
+ console.log(`[Tab.navigate] Response headers:`, JSON.stringify(response.headers(), null, 2));
75
+ } else {
76
+ console.log(`[Tab.navigate] Response is null (might be same-document navigation or cached)`);
77
+ }
65
78
  } catch (_e) {
66
79
  const e = _e;
67
- console.log("[Tab.navigate] page.goto() threw error:", e.message);
80
+ const gotoTime = Date.now() - gotoStartTime;
81
+ console.log(`[Tab.navigate] page.goto() threw after ${gotoTime}ms`);
82
+ console.log(`[Tab.navigate] Error name: ${e.name}`);
83
+ console.log(`[Tab.navigate] Error message: ${e.message}`);
68
84
  const mightBeDownload = e.message.includes("net::ERR_ABORTED") || e.message.includes("Download is starting");
85
+ console.log(`[Tab.navigate] Might be download: ${mightBeDownload}`);
69
86
  if (!mightBeDownload) {
70
- console.log("[Tab.navigate] Not a download, re-throwing error");
87
+ console.error(`[Tab.navigate] ERROR: Not a download, rethrowing error`);
88
+ console.error(`[Tab.navigate] Error stack:`, e.stack);
71
89
  throw e;
72
90
  }
73
- console.log("[Tab.navigate] Might be download, waiting for download event...");
91
+ console.log(`[Tab.navigate] Waiting for potential download event (up to 1000ms)...`);
92
+ const downloadWaitStart = Date.now();
74
93
  const download = await Promise.race([
75
94
  downloadEvent,
76
95
  new Promise((resolve) => setTimeout(resolve, 1e3))
77
96
  ]);
97
+ console.log(`[Tab.navigate] Download wait completed in ${Date.now() - downloadWaitStart}ms`);
98
+ console.log(`[Tab.navigate] Download detected: ${!!download}`);
78
99
  if (!download) {
79
- console.log("[Tab.navigate] No download received, re-throwing error");
100
+ console.error(`[Tab.navigate] ERROR: No download detected, rethrowing original error`);
80
101
  throw e;
81
102
  }
82
- console.log("[Tab.navigate] Download detected");
103
+ console.log(`[Tab.navigate] Download detected, continuing without error`);
83
104
  }
84
- console.log("[Tab.navigate] Waiting for load state...");
105
+ console.log(`[Tab.navigate] Waiting for 'load' state (timeout: 5000ms)...`);
106
+ const loadWaitStart = Date.now();
85
107
  await this.waitForLoadState("load", { timeout: 5e3 });
86
- console.log("[Tab.navigate] END");
108
+ console.log(`[Tab.navigate] 'load' state wait completed in ${Date.now() - loadWaitStart}ms`);
109
+ console.log(`[Tab.navigate] Final page URL: ${this.page.url()}`);
110
+ console.log(`[Tab.navigate] Final page title: ${await this.page.title().catch(() => "N/A")}`);
111
+ console.log(`[Tab.navigate] Total navigation time: ${Date.now() - navStartTime}ms`);
112
+ console.log(`[Tab.navigate] --------- TAB NAVIGATION END ---------`);
87
113
  }
88
114
  hasSnapshot() {
89
115
  return !!this._snapshot;
@@ -5,9 +5,6 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
5
5
  const zod = require('zod');
6
6
  const tool = require('./tool.js');
7
7
 
8
- const log = (msg, data) => {
9
- console.log(`[browser_navigate] ${msg}`, data !== void 0 ? JSON.stringify(data, null, 2) : "");
10
- };
11
8
  const navigate = (captureSnapshot) => tool.defineTool({
12
9
  capability: "core",
13
10
  schema: {
@@ -20,39 +17,49 @@ const navigate = (captureSnapshot) => tool.defineTool({
20
17
  type: "destructive"
21
18
  },
22
19
  handle: async (context, params) => {
23
- log("=== NAVIGATE HANDLER START ===");
24
- log("Params received:", params);
25
- log("captureSnapshot:", captureSnapshot);
26
- log("About to call context.ensureTab()...");
20
+ const startTime = Date.now();
21
+ console.log(`[browser_navigate] ========== NAVIGATION START ==========`);
22
+ console.log(`[browser_navigate] Target URL: ${params.url}`);
23
+ console.log(`[browser_navigate] Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}`);
24
+ console.log(`[browser_navigate] captureSnapshot setting: ${captureSnapshot}`);
25
+ console.log(`[browser_navigate] Ensuring tab is available...`);
26
+ const ensureTabStart = Date.now();
27
27
  let tab;
28
28
  try {
29
29
  tab = await context.ensureTab();
30
- log("context.ensureTab() completed successfully");
31
- log("Tab page URL:", tab.page?.url?.());
32
- } catch (err) {
33
- log("ERROR in context.ensureTab():", { message: err.message, stack: err.stack });
34
- throw err;
30
+ console.log(`[browser_navigate] Tab ensured successfully in ${Date.now() - ensureTabStart}ms`);
31
+ console.log(`[browser_navigate] Current page URL before navigation: ${tab.page.url()}`);
32
+ } catch (error) {
33
+ console.error(`[browser_navigate] ERROR: Failed to ensure tab after ${Date.now() - ensureTabStart}ms`);
34
+ console.error(`[browser_navigate] Error details:`, error);
35
+ throw error;
35
36
  }
36
- log(`About to call tab.navigate("${params.url}")...`);
37
+ console.log(`[browser_navigate] Starting navigation to: ${params.url}`);
38
+ const navigationStart = Date.now();
37
39
  try {
38
40
  await tab.navigate(params.url);
39
- log("tab.navigate() completed successfully");
40
- } catch (err) {
41
- log("ERROR in tab.navigate():", { message: err.message, stack: err.stack });
42
- throw err;
41
+ console.log(`[browser_navigate] Navigation completed successfully in ${Date.now() - navigationStart}ms`);
42
+ console.log(`[browser_navigate] Current page URL after navigation: ${tab.page.url()}`);
43
+ } catch (error) {
44
+ console.error(`[browser_navigate] ERROR: Navigation failed after ${Date.now() - navigationStart}ms`);
45
+ console.error(`[browser_navigate] Error type: ${error.constructor.name}`);
46
+ console.error(`[browser_navigate] Error message: ${error.message}`);
47
+ console.error(`[browser_navigate] Error stack:`, error.stack);
48
+ throw error;
43
49
  }
44
50
  const code = [
45
51
  `// Navigate to ${params.url}`,
46
52
  `await page.goto('${params.url}');`
47
53
  ];
48
- log("About to return result...");
49
- const result = {
54
+ const totalTime = Date.now() - startTime;
55
+ console.log(`[browser_navigate] Total execution time: ${totalTime}ms`);
56
+ console.log(`[browser_navigate] Returning with captureSnapshot: ${captureSnapshot}, waitForNetwork: false`);
57
+ console.log(`[browser_navigate] ========== NAVIGATION END ==========`);
58
+ return {
50
59
  code,
51
60
  captureSnapshot,
52
61
  waitForNetwork: false
53
62
  };
54
- log("=== NAVIGATE HANDLER END ===");
55
- return result;
56
63
  }
57
64
  });
58
65
  const goBack = (captureSnapshot) => tool.defineTool({
@@ -1,4 +1,4 @@
1
- const version = "0.0.16";
1
+ const version = "0.0.18";
2
2
  const json = {
3
3
  version};
4
4
 
@@ -8,25 +8,14 @@ import { userDataDir } from './fileUtils.js';
8
8
 
9
9
  const testDebug = createDebug("pw:mcp:test");
10
10
  function contextFactory(browserConfig) {
11
- console.log("[contextFactory] START");
12
- console.log("[contextFactory] browserConfig:", JSON.stringify(browserConfig, null, 2));
13
- if (browserConfig.remoteEndpoint) {
14
- console.log("[contextFactory] Using RemoteContextFactory");
11
+ if (browserConfig.remoteEndpoint)
15
12
  return new RemoteContextFactory(browserConfig);
16
- }
17
- if (browserConfig.cdpEndpoint) {
18
- console.log("[contextFactory] Using CdpContextFactory");
13
+ if (browserConfig.cdpEndpoint)
19
14
  return new CdpContextFactory(browserConfig);
20
- }
21
- if (browserConfig.isolated) {
22
- console.log("[contextFactory] Using IsolatedContextFactory");
15
+ if (browserConfig.isolated)
23
16
  return new IsolatedContextFactory(browserConfig);
24
- }
25
- if (browserConfig.browserAgent) {
26
- console.log("[contextFactory] Using BrowserServerContextFactory");
17
+ if (browserConfig.browserAgent)
27
18
  return new BrowserServerContextFactory(browserConfig);
28
- }
29
- console.log("[contextFactory] Using PersistentContextFactory");
30
19
  return new PersistentContextFactory(browserConfig);
31
20
  }
32
21
  class BaseContextFactory {
@@ -36,50 +25,66 @@ class BaseContextFactory {
36
25
  constructor(name, browserConfig) {
37
26
  this.name = name;
38
27
  this.browserConfig = browserConfig;
39
- console.log(`[BaseContextFactory] Created factory: ${name}`);
40
28
  }
41
29
  async _obtainBrowser() {
42
- console.log(`[BaseContextFactory._obtainBrowser] START (${this.name})`);
43
- console.log(`[BaseContextFactory._obtainBrowser] _browserPromise exists:`, !!this._browserPromise);
30
+ console.log(`[BaseContextFactory._obtainBrowser] --------- OBTAIN BROWSER START (${this.name}) ---------`);
31
+ console.log(`[BaseContextFactory._obtainBrowser] Browser promise exists: ${!!this._browserPromise}`);
44
32
  if (this._browserPromise) {
45
- console.log(`[BaseContextFactory._obtainBrowser] Returning existing promise`);
33
+ console.log(`[BaseContextFactory._obtainBrowser] Reusing existing browser promise`);
34
+ console.log(`[BaseContextFactory._obtainBrowser] --------- OBTAIN BROWSER END (${this.name}) ---------`);
46
35
  return this._browserPromise;
47
36
  }
48
37
  testDebug(`obtain browser (${this.name})`);
49
- console.log(`[BaseContextFactory._obtainBrowser] Calling _doObtainBrowser...`);
38
+ console.log(`[BaseContextFactory._obtainBrowser] No existing promise, calling _doObtainBrowser()...`);
50
39
  this._browserPromise = this._doObtainBrowser();
51
40
  void this._browserPromise.then((browser) => {
52
41
  console.log(`[BaseContextFactory._obtainBrowser] Browser obtained successfully`);
53
42
  browser.on("disconnected", () => {
54
- console.log(`[BaseContextFactory._obtainBrowser] Browser disconnected`);
43
+ console.log(`[BaseContextFactory._obtainBrowser] Browser disconnected event fired`);
55
44
  this._browserPromise = void 0;
56
45
  });
57
- }).catch((err) => {
58
- console.log(`[BaseContextFactory._obtainBrowser] Browser promise rejected:`, err.message);
46
+ }).catch((error) => {
47
+ console.error(`[BaseContextFactory._obtainBrowser] Browser promise rejected:`, error);
59
48
  this._browserPromise = void 0;
60
49
  });
50
+ console.log(`[BaseContextFactory._obtainBrowser] --------- OBTAIN BROWSER END (${this.name}) ---------`);
61
51
  return this._browserPromise;
62
52
  }
63
53
  async _doObtainBrowser() {
64
54
  throw new Error("Not implemented");
65
55
  }
66
56
  async createContext() {
67
- console.log(`[BaseContextFactory.createContext] START (${this.name})`);
57
+ console.log(`[BaseContextFactory.createContext] --------- CREATE CONTEXT START (${this.name}) ---------`);
68
58
  testDebug(`create browser context (${this.name})`);
69
- console.log(`[BaseContextFactory.createContext] Calling _obtainBrowser...`);
70
- const browser = await this._obtainBrowser();
71
- console.log(`[BaseContextFactory.createContext] Got browser`);
72
- console.log(`[BaseContextFactory.createContext] Calling _doCreateContext...`);
73
- const browserContext = await this._doCreateContext(browser);
74
- console.log(`[BaseContextFactory.createContext] Got browserContext`);
75
- console.log(`[BaseContextFactory.createContext] END`);
59
+ console.log(`[BaseContextFactory.createContext] Calling _obtainBrowser()...`);
60
+ const obtainStart = Date.now();
61
+ let browser;
62
+ try {
63
+ browser = await this._obtainBrowser();
64
+ console.log(`[BaseContextFactory.createContext] _obtainBrowser() completed in ${Date.now() - obtainStart}ms`);
65
+ } catch (error) {
66
+ console.error(`[BaseContextFactory.createContext] ERROR: _obtainBrowser() failed after ${Date.now() - obtainStart}ms`);
67
+ console.error(`[BaseContextFactory.createContext] Error:`, error);
68
+ throw error;
69
+ }
70
+ console.log(`[BaseContextFactory.createContext] Calling _doCreateContext()...`);
71
+ const createStart = Date.now();
72
+ let browserContext;
73
+ try {
74
+ browserContext = await this._doCreateContext(browser);
75
+ console.log(`[BaseContextFactory.createContext] _doCreateContext() completed in ${Date.now() - createStart}ms`);
76
+ } catch (error) {
77
+ console.error(`[BaseContextFactory.createContext] ERROR: _doCreateContext() failed after ${Date.now() - createStart}ms`);
78
+ console.error(`[BaseContextFactory.createContext] Error:`, error);
79
+ throw error;
80
+ }
81
+ console.log(`[BaseContextFactory.createContext] --------- CREATE CONTEXT END (${this.name}) ---------`);
76
82
  return { browserContext, close: () => this._closeBrowserContext(browserContext, browser) };
77
83
  }
78
84
  async _doCreateContext(browser) {
79
85
  throw new Error("Not implemented");
80
86
  }
81
87
  async _closeBrowserContext(browserContext, browser) {
82
- console.log(`[BaseContextFactory._closeBrowserContext] START (${this.name})`);
83
88
  testDebug(`close browser context (${this.name})`);
84
89
  if (browser.contexts().length === 1)
85
90
  this._browserPromise = void 0;
@@ -90,7 +95,6 @@ class BaseContextFactory {
90
95
  await browser.close().catch(() => {
91
96
  });
92
97
  }
93
- console.log(`[BaseContextFactory._closeBrowserContext] END`);
94
98
  }
95
99
  }
96
100
  class IsolatedContextFactory extends BaseContextFactory {
@@ -119,106 +123,43 @@ class CdpContextFactory extends BaseContextFactory {
119
123
  super("cdp", browserConfig);
120
124
  }
121
125
  async _doObtainBrowser() {
122
- console.log("[CdpContextFactory._doObtainBrowser] START");
123
- console.log("[CdpContextFactory._doObtainBrowser] cdpEndpoint:", this.browserConfig.cdpEndpoint);
124
- console.log("[CdpContextFactory._doObtainBrowser] cdpEndpoint type:", typeof this.browserConfig.cdpEndpoint);
125
- const endpoint = this.browserConfig.cdpEndpoint;
126
- const isCloudfareFetcher = typeof endpoint !== "string";
127
- console.log("[CdpContextFactory._doObtainBrowser] isCloudfareFetcher:", isCloudfareFetcher);
126
+ console.log(`[CdpContextFactory._doObtainBrowser] --------- CDP OBTAIN BROWSER START ---------`);
127
+ console.log(`[CdpContextFactory._doObtainBrowser] CDP endpoint: ${this.browserConfig.cdpEndpoint}`);
128
+ const connectStart = Date.now();
128
129
  try {
129
- let browser;
130
- if (isCloudfareFetcher) {
131
- const fetcher = endpoint;
132
- console.log("[CdpContextFactory._doObtainBrowser] Fetcher detected, using connect() method...");
133
- const connectUrls = [
134
- "https://cloudflare",
135
- "https://cloudflare/",
136
- "wss://cloudflare"
137
- ];
138
- let socket = null;
139
- let successUrl = "";
140
- for (const url of connectUrls) {
141
- try {
142
- console.log(`[CdpContextFactory._doObtainBrowser] Trying fetcher.connect("${url}")...`);
143
- const connection = await fetcher.connect(url);
144
- console.log("[CdpContextFactory._doObtainBrowser] connect() returned:", typeof connection);
145
- console.log("[CdpContextFactory._doObtainBrowser] connection keys:", Object.keys(connection || {}));
146
- console.log("[CdpContextFactory._doObtainBrowser] connection.socket:", typeof connection?.socket);
147
- if (connection && typeof connection === "object") {
148
- if ("accept" in connection && typeof connection.accept === "function") {
149
- console.log("[CdpContextFactory._doObtainBrowser] Connection has accept(), calling it...");
150
- connection.accept();
151
- }
152
- if ("send" in connection && "close" in connection) {
153
- socket = connection;
154
- successUrl = url;
155
- console.log("[CdpContextFactory._doObtainBrowser] Got WebSocket-like object directly");
156
- break;
157
- }
158
- if ("socket" in connection) {
159
- socket = connection.socket;
160
- successUrl = url;
161
- console.log("[CdpContextFactory._doObtainBrowser] Got socket from connection.socket");
162
- break;
163
- }
164
- if ("webSocket" in connection) {
165
- socket = connection.webSocket;
166
- if (socket && "accept" in socket) {
167
- socket.accept();
168
- }
169
- successUrl = url;
170
- console.log("[CdpContextFactory._doObtainBrowser] Got socket from connection.webSocket");
171
- break;
172
- }
173
- console.log("[CdpContextFactory._doObtainBrowser] Connection structure:", JSON.stringify(Object.getOwnPropertyNames(connection)));
174
- const proto = Object.getPrototypeOf(connection);
175
- if (proto) {
176
- console.log("[CdpContextFactory._doObtainBrowser] Connection prototype:", Object.getOwnPropertyNames(proto));
177
- }
178
- }
179
- } catch (e) {
180
- console.log(`[CdpContextFactory._doObtainBrowser] connect("${url}") error:`, e.message);
181
- }
182
- }
183
- if (!socket) {
184
- throw new Error("Could not establish WebSocket via Fetcher.connect(). Check logs above.");
185
- }
186
- console.log(`[CdpContextFactory._doObtainBrowser] WebSocket obtained from ${successUrl}`);
187
- console.log("[CdpContextFactory._doObtainBrowser] Socket type:", typeof socket);
188
- console.log("[CdpContextFactory._doObtainBrowser] Socket readyState:", socket.readyState);
189
- console.log("[CdpContextFactory._doObtainBrowser] Socket methods:", Object.getOwnPropertyNames(Object.getPrototypeOf(socket)));
190
- console.log("[CdpContextFactory._doObtainBrowser] playwright.chromium methods:", Object.keys(playwright.chromium));
191
- if (typeof playwright.chromium.connectOverCDPWithSocket === "function") {
192
- console.log("[CdpContextFactory._doObtainBrowser] Using connectOverCDPWithSocket...");
193
- browser = await playwright.chromium.connectOverCDPWithSocket(socket);
194
- } else if (typeof playwright.chromium.connectWithWebSocket === "function") {
195
- console.log("[CdpContextFactory._doObtainBrowser] Using connectWithWebSocket...");
196
- browser = await playwright.chromium.connectWithWebSocket(socket);
197
- } else {
198
- throw new Error(`WebSocket connection established but patchright needs a method to accept raw WebSocket for CDP. Available methods: ${Object.keys(playwright.chromium).join(", ")}`);
199
- }
200
- } else {
201
- console.log("[CdpContextFactory._doObtainBrowser] Using chromium.connectOverCDP() for CDP URL...");
202
- browser = await playwright.chromium.connectOverCDP(endpoint);
203
- }
204
- console.log("[CdpContextFactory._doObtainBrowser] Connection completed");
130
+ const browser = await playwright.chromium.connectOverCDP(this.browserConfig.cdpEndpoint);
131
+ console.log(`[CdpContextFactory._doObtainBrowser] connectOverCDP() completed in ${Date.now() - connectStart}ms`);
132
+ console.log(`[CdpContextFactory._doObtainBrowser] Browser connected: ${browser.isConnected()}`);
133
+ console.log(`[CdpContextFactory._doObtainBrowser] Browser version: ${browser.version()}`);
134
+ console.log(`[CdpContextFactory._doObtainBrowser] Existing contexts: ${browser.contexts().length}`);
135
+ console.log(`[CdpContextFactory._doObtainBrowser] --------- CDP OBTAIN BROWSER END ---------`);
205
136
  return browser;
206
- } catch (err) {
207
- console.log("[CdpContextFactory._doObtainBrowser] ERROR:", err.message, err.stack);
208
- throw err;
137
+ } catch (error) {
138
+ console.error(`[CdpContextFactory._doObtainBrowser] ERROR: connectOverCDP() failed after ${Date.now() - connectStart}ms`);
139
+ console.error(`[CdpContextFactory._doObtainBrowser] Error type: ${error.constructor.name}`);
140
+ console.error(`[CdpContextFactory._doObtainBrowser] Error message: ${error.message}`);
141
+ console.error(`[CdpContextFactory._doObtainBrowser] Error stack:`, error.stack);
142
+ throw error;
209
143
  }
210
144
  }
211
145
  async _doCreateContext(browser) {
212
- console.log("[CdpContextFactory._doCreateContext] START");
213
- console.log("[CdpContextFactory._doCreateContext] isolated:", this.browserConfig.isolated);
214
- try {
215
- const ctx = this.browserConfig.isolated ? await browser.newContext() : browser.contexts()[0];
216
- console.log("[CdpContextFactory._doCreateContext] Got context");
217
- return ctx;
218
- } catch (err) {
219
- console.log("[CdpContextFactory._doCreateContext] ERROR:", err.message, err.stack);
220
- throw err;
146
+ console.log(`[CdpContextFactory._doCreateContext] --------- CDP CREATE CONTEXT START ---------`);
147
+ console.log(`[CdpContextFactory._doCreateContext] Isolated mode: ${this.browserConfig.isolated}`);
148
+ console.log(`[CdpContextFactory._doCreateContext] Existing contexts: ${browser.contexts().length}`);
149
+ let context;
150
+ if (this.browserConfig.isolated) {
151
+ console.log(`[CdpContextFactory._doCreateContext] Creating new isolated context...`);
152
+ const newContextStart = Date.now();
153
+ context = await browser.newContext();
154
+ console.log(`[CdpContextFactory._doCreateContext] New context created in ${Date.now() - newContextStart}ms`);
155
+ } else {
156
+ console.log(`[CdpContextFactory._doCreateContext] Using existing context[0]...`);
157
+ context = browser.contexts()[0];
158
+ console.log(`[CdpContextFactory._doCreateContext] Existing context obtained`);
221
159
  }
160
+ console.log(`[CdpContextFactory._doCreateContext] Context pages: ${context.pages().length}`);
161
+ console.log(`[CdpContextFactory._doCreateContext] --------- CDP CREATE CONTEXT END ---------`);
162
+ return context;
222
163
  }
223
164
  }
224
165
  class RemoteContextFactory extends BaseContextFactory {
@@ -66,29 +66,42 @@ class Context {
66
66
  await this._currentTab.page.bringToFront();
67
67
  }
68
68
  async ensureTab() {
69
- console.log("[Context.ensureTab] START");
70
- console.log("[Context.ensureTab] _currentTab exists:", !!this._currentTab);
71
- console.log("[Context.ensureTab] Calling _ensureBrowserContext()...");
69
+ console.log(`[Context.ensureTab] --------- ENSURE TAB START ---------`);
70
+ console.log(`[Context.ensureTab] Current tab exists: ${!!this._currentTab}`);
71
+ console.log(`[Context.ensureTab] Number of tabs: ${this._tabs.length}`);
72
+ console.log(`[Context.ensureTab] Browser context promise exists: ${!!this._browserContextPromise}`);
73
+ console.log(`[Context.ensureTab] Calling _ensureBrowserContext()...`);
74
+ const ensureContextStart = Date.now();
72
75
  let browserContext;
73
76
  try {
74
77
  const result = await this._ensureBrowserContext();
75
78
  browserContext = result.browserContext;
76
- console.log("[Context.ensureTab] _ensureBrowserContext() completed");
77
- } catch (err) {
78
- console.log("[Context.ensureTab] ERROR in _ensureBrowserContext():", err.message, err.stack);
79
- throw err;
79
+ console.log(`[Context.ensureTab] _ensureBrowserContext() completed in ${Date.now() - ensureContextStart}ms`);
80
+ console.log(`[Context.ensureTab] Browser context obtained: ${!!browserContext}`);
81
+ } catch (error) {
82
+ console.error(`[Context.ensureTab] ERROR: _ensureBrowserContext() failed after ${Date.now() - ensureContextStart}ms`);
83
+ console.error(`[Context.ensureTab] Error type: ${error.constructor.name}`);
84
+ console.error(`[Context.ensureTab] Error message: ${error.message}`);
85
+ console.error(`[Context.ensureTab] Error stack:`, error.stack);
86
+ throw error;
80
87
  }
81
88
  if (!this._currentTab) {
82
- console.log("[Context.ensureTab] No current tab, creating new page...");
89
+ console.log(`[Context.ensureTab] No current tab, creating new page...`);
90
+ const newPageStart = Date.now();
83
91
  try {
84
92
  await browserContext.newPage();
85
- console.log("[Context.ensureTab] New page created");
86
- } catch (err) {
87
- console.log("[Context.ensureTab] ERROR creating new page:", err.message, err.stack);
88
- throw err;
93
+ console.log(`[Context.ensureTab] New page created in ${Date.now() - newPageStart}ms`);
94
+ console.log(`[Context.ensureTab] Current tab after newPage: ${!!this._currentTab}`);
95
+ } catch (error) {
96
+ console.error(`[Context.ensureTab] ERROR: newPage() failed after ${Date.now() - newPageStart}ms`);
97
+ console.error(`[Context.ensureTab] Error:`, error);
98
+ throw error;
89
99
  }
100
+ } else {
101
+ console.log(`[Context.ensureTab] Current tab already exists, skipping newPage()`);
90
102
  }
91
- console.log("[Context.ensureTab] END, returning tab");
103
+ console.log(`[Context.ensureTab] Returning tab. URL: ${this._currentTab?.page.url() ?? "N/A"}`);
104
+ console.log(`[Context.ensureTab] --------- ENSURE TAB END ---------`);
92
105
  return this._currentTab;
93
106
  }
94
107
  async listTabsMarkdown() {
@@ -265,51 +278,68 @@ ${code.join("\n")}
265
278
  }
266
279
  }
267
280
  _ensureBrowserContext() {
268
- console.log("[Context._ensureBrowserContext] START");
269
- console.log("[Context._ensureBrowserContext] _browserContextPromise exists:", !!this._browserContextPromise);
281
+ console.log(`[Context._ensureBrowserContext] --------- ENSURE BROWSER CONTEXT START ---------`);
282
+ console.log(`[Context._ensureBrowserContext] Browser context promise exists: ${!!this._browserContextPromise}`);
270
283
  if (!this._browserContextPromise) {
271
- console.log("[Context._ensureBrowserContext] Creating new browser context promise...");
284
+ console.log(`[Context._ensureBrowserContext] No existing promise, calling _setupBrowserContext()...`);
272
285
  this._browserContextPromise = this._setupBrowserContext();
273
- this._browserContextPromise.catch((err) => {
274
- console.log("[Context._ensureBrowserContext] Promise rejected:", err.message);
286
+ this._browserContextPromise.catch((error) => {
287
+ console.error(`[Context._ensureBrowserContext] _setupBrowserContext() promise rejected:`, error);
275
288
  this._browserContextPromise = void 0;
276
289
  });
290
+ } else {
291
+ console.log(`[Context._ensureBrowserContext] Reusing existing browser context promise`);
277
292
  }
278
- console.log("[Context._ensureBrowserContext] END, returning promise");
293
+ console.log(`[Context._ensureBrowserContext] --------- ENSURE BROWSER CONTEXT END ---------`);
279
294
  return this._browserContextPromise;
280
295
  }
281
296
  async _setupBrowserContext() {
282
- console.log("[Context._setupBrowserContext] START");
283
- console.log("[Context._setupBrowserContext] Calling _browserContextFactory.createContext()...");
297
+ console.log(`[Context._setupBrowserContext] --------- SETUP BROWSER CONTEXT START ---------`);
298
+ console.log(`[Context._setupBrowserContext] Calling browserContextFactory.createContext()...`);
299
+ const createContextStart = Date.now();
284
300
  let result;
285
301
  try {
286
302
  result = await this._browserContextFactory.createContext();
287
- console.log("[Context._setupBrowserContext] createContext() completed");
288
- } catch (err) {
289
- console.log("[Context._setupBrowserContext] ERROR in createContext():", err.message, err.stack);
290
- throw err;
303
+ console.log(`[Context._setupBrowserContext] createContext() completed in ${Date.now() - createContextStart}ms`);
304
+ } catch (error) {
305
+ console.error(`[Context._setupBrowserContext] ERROR: createContext() failed after ${Date.now() - createContextStart}ms`);
306
+ console.error(`[Context._setupBrowserContext] Error type: ${error.constructor.name}`);
307
+ console.error(`[Context._setupBrowserContext] Error message: ${error.message}`);
308
+ console.error(`[Context._setupBrowserContext] Error stack:`, error.stack);
309
+ throw error;
291
310
  }
292
311
  const { browserContext } = result;
293
- console.log("[Context._setupBrowserContext] Got browserContext");
294
- console.log("[Context._setupBrowserContext] Setting up request interception...");
312
+ console.log(`[Context._setupBrowserContext] Browser context obtained`);
313
+ console.log(`[Context._setupBrowserContext] Setting up request interception...`);
314
+ const interceptStart = Date.now();
295
315
  await this._setupRequestInterception(browserContext);
296
- console.log("[Context._setupBrowserContext] Request interception done");
297
- console.log("[Context._setupBrowserContext] Processing existing pages...");
298
- for (const page of browserContext.pages())
316
+ console.log(`[Context._setupBrowserContext] Request interception setup completed in ${Date.now() - interceptStart}ms`);
317
+ console.log(`[Context._setupBrowserContext] Processing existing pages...`);
318
+ const existingPages = browserContext.pages();
319
+ console.log(`[Context._setupBrowserContext] Found ${existingPages.length} existing pages`);
320
+ for (const page of existingPages) {
321
+ console.log(`[Context._setupBrowserContext] Processing existing page: ${page.url()}`);
299
322
  this._onPageCreated(page);
300
- browserContext.on("page", (page) => this._onPageCreated(page));
301
- console.log("[Context._setupBrowserContext] Pages processed");
323
+ }
324
+ console.log(`[Context._setupBrowserContext] Setting up 'page' event listener...`);
325
+ browserContext.on("page", (page) => {
326
+ console.log(`[Context._setupBrowserContext] 'page' event fired for: ${page.url()}`);
327
+ this._onPageCreated(page);
328
+ });
302
329
  if (this.config.saveTrace) {
303
- console.log("[Context._setupBrowserContext] Starting tracing...");
330
+ console.log(`[Context._setupBrowserContext] Starting tracing...`);
331
+ const traceStart = Date.now();
304
332
  await browserContext.tracing.start({
305
333
  name: "trace",
306
334
  screenshots: false,
307
335
  snapshots: true,
308
336
  sources: false
309
337
  });
310
- console.log("[Context._setupBrowserContext] Tracing started");
338
+ console.log(`[Context._setupBrowserContext] Tracing started in ${Date.now() - traceStart}ms`);
311
339
  }
312
- console.log("[Context._setupBrowserContext] END");
340
+ console.log(`[Context._setupBrowserContext] Total tabs after setup: ${this._tabs.length}`);
341
+ console.log(`[Context._setupBrowserContext] Current tab: ${this._currentTab ? "set" : "not set"}`);
342
+ console.log(`[Context._setupBrowserContext] --------- SETUP BROWSER CONTEXT END ---------`);
313
343
  return result;
314
344
  }
315
345
  }
@@ -46,40 +46,66 @@ class Tab {
46
46
  }));
47
47
  }
48
48
  async navigate(url) {
49
- console.log("[Tab.navigate] START, url:", url);
50
- console.log("[Tab.navigate] Clearing collected artifacts...");
49
+ const navStartTime = Date.now();
50
+ console.log(`[Tab.navigate] --------- TAB NAVIGATION START ---------`);
51
+ console.log(`[Tab.navigate] URL: ${url}`);
52
+ console.log(`[Tab.navigate] Current page URL: ${this.page.url()}`);
53
+ console.log(`[Tab.navigate] Page is closed: ${this.page.isClosed()}`);
54
+ console.log(`[Tab.navigate] Clearing collected artifacts...`);
51
55
  this._clearCollectedArtifacts();
52
- console.log("[Tab.navigate] Artifacts cleared");
53
- console.log("[Tab.navigate] Setting up download event listener...");
56
+ console.log(`[Tab.navigate] Artifacts cleared. Console messages: ${this._consoleMessages.length}, Requests: ${this._requests.size}`);
57
+ console.log(`[Tab.navigate] Setting up download event listener...`);
54
58
  const downloadEvent = callOnPageNoTrace(this.page, (page) => page.waitForEvent("download").catch(() => {
55
59
  }));
56
- console.log("[Tab.navigate] Download event listener ready");
60
+ console.log(`[Tab.navigate] Download event listener set up`);
61
+ console.log(`[Tab.navigate] Calling page.goto() with waitUntil: 'domcontentloaded'`);
62
+ const gotoStartTime = Date.now();
57
63
  try {
58
- console.log("[Tab.navigate] Calling page.goto()...");
59
- await this.page.goto(url, { waitUntil: "domcontentloaded" });
60
- console.log("[Tab.navigate] page.goto() completed successfully");
64
+ const response = await this.page.goto(url, { waitUntil: "domcontentloaded" });
65
+ const gotoTime = Date.now() - gotoStartTime;
66
+ console.log(`[Tab.navigate] page.goto() completed in ${gotoTime}ms`);
67
+ if (response) {
68
+ console.log(`[Tab.navigate] Response status: ${response.status()}`);
69
+ console.log(`[Tab.navigate] Response URL: ${response.url()}`);
70
+ console.log(`[Tab.navigate] Response headers:`, JSON.stringify(response.headers(), null, 2));
71
+ } else {
72
+ console.log(`[Tab.navigate] Response is null (might be same-document navigation or cached)`);
73
+ }
61
74
  } catch (_e) {
62
75
  const e = _e;
63
- console.log("[Tab.navigate] page.goto() threw error:", e.message);
76
+ const gotoTime = Date.now() - gotoStartTime;
77
+ console.log(`[Tab.navigate] page.goto() threw after ${gotoTime}ms`);
78
+ console.log(`[Tab.navigate] Error name: ${e.name}`);
79
+ console.log(`[Tab.navigate] Error message: ${e.message}`);
64
80
  const mightBeDownload = e.message.includes("net::ERR_ABORTED") || e.message.includes("Download is starting");
81
+ console.log(`[Tab.navigate] Might be download: ${mightBeDownload}`);
65
82
  if (!mightBeDownload) {
66
- console.log("[Tab.navigate] Not a download, re-throwing error");
83
+ console.error(`[Tab.navigate] ERROR: Not a download, rethrowing error`);
84
+ console.error(`[Tab.navigate] Error stack:`, e.stack);
67
85
  throw e;
68
86
  }
69
- console.log("[Tab.navigate] Might be download, waiting for download event...");
87
+ console.log(`[Tab.navigate] Waiting for potential download event (up to 1000ms)...`);
88
+ const downloadWaitStart = Date.now();
70
89
  const download = await Promise.race([
71
90
  downloadEvent,
72
91
  new Promise((resolve) => setTimeout(resolve, 1e3))
73
92
  ]);
93
+ console.log(`[Tab.navigate] Download wait completed in ${Date.now() - downloadWaitStart}ms`);
94
+ console.log(`[Tab.navigate] Download detected: ${!!download}`);
74
95
  if (!download) {
75
- console.log("[Tab.navigate] No download received, re-throwing error");
96
+ console.error(`[Tab.navigate] ERROR: No download detected, rethrowing original error`);
76
97
  throw e;
77
98
  }
78
- console.log("[Tab.navigate] Download detected");
99
+ console.log(`[Tab.navigate] Download detected, continuing without error`);
79
100
  }
80
- console.log("[Tab.navigate] Waiting for load state...");
101
+ console.log(`[Tab.navigate] Waiting for 'load' state (timeout: 5000ms)...`);
102
+ const loadWaitStart = Date.now();
81
103
  await this.waitForLoadState("load", { timeout: 5e3 });
82
- console.log("[Tab.navigate] END");
104
+ console.log(`[Tab.navigate] 'load' state wait completed in ${Date.now() - loadWaitStart}ms`);
105
+ console.log(`[Tab.navigate] Final page URL: ${this.page.url()}`);
106
+ console.log(`[Tab.navigate] Final page title: ${await this.page.title().catch(() => "N/A")}`);
107
+ console.log(`[Tab.navigate] Total navigation time: ${Date.now() - navStartTime}ms`);
108
+ console.log(`[Tab.navigate] --------- TAB NAVIGATION END ---------`);
83
109
  }
84
110
  hasSnapshot() {
85
111
  return !!this._snapshot;
@@ -1,9 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { defineTool } from './tool.js';
3
3
 
4
- const log = (msg, data) => {
5
- console.log(`[browser_navigate] ${msg}`, data !== void 0 ? JSON.stringify(data, null, 2) : "");
6
- };
7
4
  const navigate = (captureSnapshot) => defineTool({
8
5
  capability: "core",
9
6
  schema: {
@@ -16,39 +13,49 @@ const navigate = (captureSnapshot) => defineTool({
16
13
  type: "destructive"
17
14
  },
18
15
  handle: async (context, params) => {
19
- log("=== NAVIGATE HANDLER START ===");
20
- log("Params received:", params);
21
- log("captureSnapshot:", captureSnapshot);
22
- log("About to call context.ensureTab()...");
16
+ const startTime = Date.now();
17
+ console.log(`[browser_navigate] ========== NAVIGATION START ==========`);
18
+ console.log(`[browser_navigate] Target URL: ${params.url}`);
19
+ console.log(`[browser_navigate] Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}`);
20
+ console.log(`[browser_navigate] captureSnapshot setting: ${captureSnapshot}`);
21
+ console.log(`[browser_navigate] Ensuring tab is available...`);
22
+ const ensureTabStart = Date.now();
23
23
  let tab;
24
24
  try {
25
25
  tab = await context.ensureTab();
26
- log("context.ensureTab() completed successfully");
27
- log("Tab page URL:", tab.page?.url?.());
28
- } catch (err) {
29
- log("ERROR in context.ensureTab():", { message: err.message, stack: err.stack });
30
- throw err;
26
+ console.log(`[browser_navigate] Tab ensured successfully in ${Date.now() - ensureTabStart}ms`);
27
+ console.log(`[browser_navigate] Current page URL before navigation: ${tab.page.url()}`);
28
+ } catch (error) {
29
+ console.error(`[browser_navigate] ERROR: Failed to ensure tab after ${Date.now() - ensureTabStart}ms`);
30
+ console.error(`[browser_navigate] Error details:`, error);
31
+ throw error;
31
32
  }
32
- log(`About to call tab.navigate("${params.url}")...`);
33
+ console.log(`[browser_navigate] Starting navigation to: ${params.url}`);
34
+ const navigationStart = Date.now();
33
35
  try {
34
36
  await tab.navigate(params.url);
35
- log("tab.navigate() completed successfully");
36
- } catch (err) {
37
- log("ERROR in tab.navigate():", { message: err.message, stack: err.stack });
38
- throw err;
37
+ console.log(`[browser_navigate] Navigation completed successfully in ${Date.now() - navigationStart}ms`);
38
+ console.log(`[browser_navigate] Current page URL after navigation: ${tab.page.url()}`);
39
+ } catch (error) {
40
+ console.error(`[browser_navigate] ERROR: Navigation failed after ${Date.now() - navigationStart}ms`);
41
+ console.error(`[browser_navigate] Error type: ${error.constructor.name}`);
42
+ console.error(`[browser_navigate] Error message: ${error.message}`);
43
+ console.error(`[browser_navigate] Error stack:`, error.stack);
44
+ throw error;
39
45
  }
40
46
  const code = [
41
47
  `// Navigate to ${params.url}`,
42
48
  `await page.goto('${params.url}');`
43
49
  ];
44
- log("About to return result...");
45
- const result = {
50
+ const totalTime = Date.now() - startTime;
51
+ console.log(`[browser_navigate] Total execution time: ${totalTime}ms`);
52
+ console.log(`[browser_navigate] Returning with captureSnapshot: ${captureSnapshot}, waitForNetwork: false`);
53
+ console.log(`[browser_navigate] ========== NAVIGATION END ==========`);
54
+ return {
46
55
  code,
47
56
  captureSnapshot,
48
57
  waitForNetwork: false
49
58
  };
50
- log("=== NAVIGATE HANDLER END ===");
51
- return result;
52
59
  }
53
60
  });
54
61
  const goBack = (captureSnapshot) => defineTool({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@szymonrybczak/playwright-mcp",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "Cloudflare Playwright Tools for MCP",
5
5
  "type": "module",
6
6
  "repository": {