@pedropaulovc/playwright 1.59.0-next → 1.59.0-next.3

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.
@@ -0,0 +1,310 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var program_exports = {};
30
+ __export(program_exports, {
31
+ program: () => program
32
+ });
33
+ module.exports = __toCommonJS(program_exports);
34
+ var import_child_process = require("child_process");
35
+ var import_crypto = __toESM(require("crypto"));
36
+ var import_fs = __toESM(require("fs"));
37
+ var import_net = __toESM(require("net"));
38
+ var import_os = __toESM(require("os"));
39
+ var import_path = __toESM(require("path"));
40
+ var import_utilsBundle = require("playwright-core/lib/utilsBundle");
41
+ var import_socketConnection = require("./socketConnection");
42
+ const debugCli = (0, import_utilsBundle.debug)("pw:cli");
43
+ class Session {
44
+ constructor(name, connection) {
45
+ this._nextMessageId = 1;
46
+ this._callbacks = /* @__PURE__ */ new Map();
47
+ this.name = name;
48
+ this._connection = connection;
49
+ this._connection.onmessage = (message) => this._onMessage(message);
50
+ this._connection.onclose = () => this.close();
51
+ }
52
+ async run(args) {
53
+ return await this._send("run", { args });
54
+ }
55
+ async stop() {
56
+ await this._send("stop");
57
+ this.close();
58
+ }
59
+ async _send(method, params = {}) {
60
+ const messageId = this._nextMessageId++;
61
+ const message = {
62
+ id: messageId,
63
+ method,
64
+ params
65
+ };
66
+ await this._connection.send(message);
67
+ return new Promise((resolve, reject) => {
68
+ this._callbacks.set(messageId, { resolve, reject });
69
+ });
70
+ }
71
+ close() {
72
+ for (const callback of this._callbacks.values())
73
+ callback.reject(new Error("Session closed"));
74
+ this._callbacks.clear();
75
+ this._connection.close();
76
+ }
77
+ _onMessage(object) {
78
+ if (object.id && this._callbacks.has(object.id)) {
79
+ const callback = this._callbacks.get(object.id);
80
+ this._callbacks.delete(object.id);
81
+ if (object.error)
82
+ callback.reject(new Error(object.error));
83
+ else
84
+ callback.resolve(object.result);
85
+ } else if (object.id) {
86
+ throw new Error(`Unexpected message id: ${object.id}`);
87
+ } else {
88
+ throw new Error(`Unexpected message without id: ${JSON.stringify(object)}`);
89
+ }
90
+ }
91
+ }
92
+ class SessionManager {
93
+ async list() {
94
+ const dir = daemonSocketDir;
95
+ try {
96
+ const files = await import_fs.default.promises.readdir(dir);
97
+ const sessions = [];
98
+ for (const file of files) {
99
+ if (file.endsWith("-user-data")) {
100
+ const sessionName = file.slice(0, -"-user-data".length);
101
+ const live = await this._canConnect(sessionName);
102
+ sessions.push({ name: sessionName, live });
103
+ }
104
+ }
105
+ return sessions;
106
+ } catch {
107
+ return [];
108
+ }
109
+ }
110
+ async run(args) {
111
+ const sessionName = this._resolveSessionName(args.session);
112
+ const session = await this._connect(sessionName);
113
+ const result = await session.run(args);
114
+ console.log(result);
115
+ session.close();
116
+ }
117
+ async stop(sessionName) {
118
+ sessionName = this._resolveSessionName(sessionName);
119
+ if (!await this._canConnect(sessionName)) {
120
+ console.log(`Session '${sessionName}' is not running.`);
121
+ return;
122
+ }
123
+ const session = await this._connect(sessionName);
124
+ await session.stop();
125
+ console.log(`Session '${sessionName}' stopped.`);
126
+ }
127
+ async delete(sessionName) {
128
+ sessionName = this._resolveSessionName(sessionName);
129
+ if (await this._canConnect(sessionName)) {
130
+ const session = await this._connect(sessionName);
131
+ await session.stop();
132
+ }
133
+ const userDataDir = import_path.default.resolve(daemonSocketDir, `${sessionName}-user-data`);
134
+ try {
135
+ await import_fs.default.promises.rm(userDataDir, { recursive: true });
136
+ console.log(`Deleted user data for session '${sessionName}'.`);
137
+ } catch (e) {
138
+ if (e.code === "ENOENT")
139
+ console.log(`No user data found for session '${sessionName}'.`);
140
+ else
141
+ throw e;
142
+ }
143
+ if (import_os.default.platform() !== "win32") {
144
+ const socketPath = this._daemonSocketPath(sessionName);
145
+ await import_fs.default.promises.unlink(socketPath).catch(() => {
146
+ });
147
+ }
148
+ }
149
+ async _connect(sessionName) {
150
+ const socketPath = process.env.PLAYWRIGHT_DAEMON_SOCKET_PATH || this._daemonSocketPath(sessionName);
151
+ debugCli(`Connecting to daemon at ${socketPath}`);
152
+ const socketExists = await import_fs.default.promises.stat(socketPath).then((stat) => stat?.isSocket() ?? false).catch(() => false);
153
+ if (socketExists) {
154
+ debugCli(`Socket file exists, attempting to connect...`);
155
+ try {
156
+ return await this._connectToSocket(sessionName, socketPath);
157
+ } catch (e) {
158
+ if (import_os.default.platform() !== "win32")
159
+ await import_fs.default.promises.unlink(socketPath).catch(() => {
160
+ });
161
+ }
162
+ }
163
+ if (process.env.PLAYWRIGHT_DAEMON_SOCKET_PATH)
164
+ throw new Error(`Socket path ${socketPath} does not exist`);
165
+ const userDataDir = import_path.default.resolve(daemonSocketDir, `${sessionName}-user-data`);
166
+ const child = spawnDaemon(socketPath, userDataDir, {
167
+ detached: true,
168
+ stdio: "ignore",
169
+ cwd: process.cwd()
170
+ // Will be used as root.
171
+ });
172
+ child.unref();
173
+ const maxRetries = 50;
174
+ const retryDelay = 100;
175
+ for (let i = 0; i < maxRetries; i++) {
176
+ await new Promise((resolve) => setTimeout(resolve, 100));
177
+ try {
178
+ return await this._connectToSocket(sessionName, socketPath);
179
+ } catch (e) {
180
+ if (e.code !== "ENOENT")
181
+ throw e;
182
+ debugCli(`Retrying to connect to daemon at ${socketPath} (${i + 1}/${maxRetries})`);
183
+ }
184
+ }
185
+ throw new Error(`Failed to connect to daemon at ${socketPath} after ${maxRetries * retryDelay}ms`);
186
+ }
187
+ async _connectToSocket(sessionName, socketPath) {
188
+ const socket = await new Promise((resolve, reject) => {
189
+ const socket2 = import_net.default.createConnection(socketPath, () => {
190
+ debugCli(`Connected to daemon at ${socketPath}`);
191
+ resolve(socket2);
192
+ });
193
+ socket2.on("error", reject);
194
+ });
195
+ return new Session(sessionName, new import_socketConnection.SocketConnection(socket));
196
+ }
197
+ async _canConnect(sessionName) {
198
+ const socketPath = this._daemonSocketPath(sessionName);
199
+ return new Promise((resolve) => {
200
+ const socket = import_net.default.createConnection(socketPath, () => {
201
+ socket.destroy();
202
+ resolve(true);
203
+ });
204
+ socket.on("error", () => {
205
+ resolve(false);
206
+ });
207
+ });
208
+ }
209
+ _resolveSessionName(sessionName) {
210
+ if (sessionName)
211
+ return sessionName;
212
+ if (process.env.PLAYWRIGHT_CLI_SESSION)
213
+ return process.env.PLAYWRIGHT_CLI_SESSION;
214
+ return "default";
215
+ }
216
+ _daemonSocketPath(sessionName) {
217
+ const socketName = `${sessionName}.sock`;
218
+ if (import_os.default.platform() === "win32")
219
+ return `\\\\.\\pipe\\${socketDirHash}-${socketName}`;
220
+ return import_path.default.join(daemonSocketDir, socketName);
221
+ }
222
+ }
223
+ async function handleSessionCommand(sessionManager, args) {
224
+ const subcommand = args._[0].split("-").slice(1).join("-");
225
+ if (subcommand === "list") {
226
+ const sessions = await sessionManager.list();
227
+ console.log("Sessions:");
228
+ for (const session of sessions) {
229
+ const liveMarker = session.live ? " (live)" : "";
230
+ console.log(` ${session.name}${liveMarker}`);
231
+ }
232
+ if (sessions.length === 0)
233
+ console.log(" (no sessions)");
234
+ return;
235
+ }
236
+ if (subcommand === "stop") {
237
+ await sessionManager.stop(args._[1]);
238
+ return;
239
+ }
240
+ if (subcommand === "stop-all") {
241
+ const sessions = await sessionManager.list();
242
+ for (const session of sessions)
243
+ await sessionManager.stop(session.name);
244
+ return;
245
+ }
246
+ if (subcommand === "delete") {
247
+ await sessionManager.delete(args._[1]);
248
+ return;
249
+ }
250
+ console.error(`Unknown session subcommand: ${subcommand}`);
251
+ process.exit(1);
252
+ }
253
+ const socketDirHash = (() => {
254
+ const hash = import_crypto.default.createHash("sha1");
255
+ hash.update(require.resolve("../../../package.json"));
256
+ return hash.digest("hex");
257
+ })();
258
+ const daemonSocketDir = (() => {
259
+ let localCacheDir;
260
+ if (process.platform === "linux")
261
+ localCacheDir = process.env.XDG_CACHE_HOME || import_path.default.join(import_os.default.homedir(), ".cache");
262
+ if (process.platform === "darwin")
263
+ localCacheDir = import_path.default.join(import_os.default.homedir(), "Library", "Caches");
264
+ if (process.platform === "win32")
265
+ localCacheDir = process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local");
266
+ if (!localCacheDir)
267
+ throw new Error("Unsupported platform: " + process.platform);
268
+ return import_path.default.join(localCacheDir, "ms-playwright", "daemon", "daemon", socketDirHash);
269
+ })();
270
+ function spawnDaemon(socketPath, userDataDir, options) {
271
+ const cliPath = import_path.default.join(__dirname, "../../../cli.js");
272
+ debugCli(`Will launch daemon process: ${cliPath}`);
273
+ return (0, import_child_process.spawn)(process.execPath, [cliPath, "run-mcp-server", `--daemon=${socketPath}`, `--user-data-dir=${userDataDir}`], options);
274
+ }
275
+ async function program(options) {
276
+ const argv = process.argv.slice(2);
277
+ const args = require("minimist")(argv);
278
+ const help = require("./help.json");
279
+ const commandName = args._[0];
280
+ if (args.version || args.v) {
281
+ console.log(options.version);
282
+ process.exit(0);
283
+ }
284
+ const command = help.commands[commandName];
285
+ if (args.help || args.h) {
286
+ if (command) {
287
+ console.log(command);
288
+ } else {
289
+ console.log("playwright-cli - run playwright mcp commands from terminal\n");
290
+ console.log(help.global);
291
+ }
292
+ process.exit(0);
293
+ }
294
+ if (!command) {
295
+ console.error(`Unknown command: ${commandName}
296
+ `);
297
+ console.log(help.global);
298
+ process.exit(1);
299
+ }
300
+ const sessionManager = new SessionManager();
301
+ if (commandName.startsWith("session")) {
302
+ await handleSessionCommand(sessionManager, args);
303
+ return;
304
+ }
305
+ await sessionManager.run(args);
306
+ }
307
+ // Annotate the CommonJS export names for ESM import in node:
308
+ 0 && (module.exports = {
309
+ program
310
+ });
package/lib/program.js CHANGED
@@ -388,6 +388,7 @@ const testOptions = [
388
388
  ["--repeat-each <N>", { description: `Run each test N times (default: 1)` }],
389
389
  ["--reporter <reporter>", { description: `Reporter to use, comma-separated, can be ${import_config.builtInReporters.map((name) => `"${name}"`).join(", ")} (default: "${import_config.defaultReporter}")` }],
390
390
  ["--retries <retries>", { description: `Maximum retry count for flaky tests, zero for no retries (default: no retries)` }],
391
+ ["--run-agents <mode>", { description: `Run agents to generate the code for page.perform`, choices: ["missing", "all", "none"], preset: "none" }],
391
392
  ["--shard <shard>", { description: `Shard tests and execute only the selected shard, specify in the form "current/all", 1-based, for example "3/5"` }],
392
393
  ["--test-list <file>", { description: `Path to a file containing a list of tests to run. See https://playwright.dev/docs/test-cli for more details.` }],
393
394
  ["--test-list-invert <file>", { description: `Path to a file containing a list of tests to skip. See https://playwright.dev/docs/test-cli for more details.` }],
@@ -368,10 +368,14 @@ function formatFailure(screen, config, test, index, options) {
368
368
  resultLines.push(screen.colors.dim(` ${relativePath}`));
369
369
  if (attachment.name === "trace") {
370
370
  const packageManagerCommand = (0, import_utils.getPackageManagerExecCommand)();
371
- resultLines.push(screen.colors.dim(` Usage:`));
371
+ resultLines.push(screen.colors.dim(` Usage (GUI):`));
372
372
  resultLines.push("");
373
373
  resultLines.push(screen.colors.dim(` ${packageManagerCommand} playwright show-trace ${quotePathIfNeeded(relativePath)}`));
374
374
  resultLines.push("");
375
+ resultLines.push(screen.colors.dim(` Usage (markdown, LLM friendly):`));
376
+ resultLines.push("");
377
+ resultLines.push(screen.colors.dim(` ${packageManagerCommand} playwright export-trace ${quotePathIfNeeded(relativePath)}`));
378
+ resultLines.push("");
375
379
  }
376
380
  } else {
377
381
  if (attachment.contentType.startsWith("text/") && attachment.body) {
@@ -187,8 +187,8 @@ function setTransformData(pluginName, value) {
187
187
  }
188
188
  function transformHook(originalCode, filename, moduleUrl) {
189
189
  let inputSourceMap;
190
- if (filename.endsWith(".md") && false) {
191
- const transformed = transformMDToTS(originalCode, filename);
190
+ if (filename.endsWith(".md")) {
191
+ const transformed = (0, import_md.transformMDToTS)(originalCode, filename);
192
192
  originalCode = transformed.code;
193
193
  inputSourceMap = transformed.map;
194
194
  }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@pedropaulovc/playwright",
3
- "version": "1.59.0-next",
3
+ "version": "1.59.0-next.3",
4
4
  "description": "A high-level API to automate web browsers",
5
5
  "repository": {
6
6
  "type": "git",
7
- "url": "git+https://github.com/microsoft/playwright.git"
7
+ "url": "git+https://github.com/pedropaulovc/playwright.git"
8
8
  },
9
9
  "homepage": "https://playwright.dev",
10
10
  "engines": {
@@ -26,6 +26,7 @@
26
26
  "./lib/mcp/program": "./lib/mcp/program.js",
27
27
  "./lib/mcp/sdk/bundle": "./lib/mcp/sdk/bundle.js",
28
28
  "./lib/mcp/sdk/exports": "./lib/mcp/sdk/exports.js",
29
+ "./lib/mcp/terminal/program": "./lib/mcp/terminal/program.js",
29
30
  "./lib/program": "./lib/program.js",
30
31
  "./lib/reporters/base": "./lib/reporters/base.js",
31
32
  "./lib/reporters/list": "./lib/reporters/list.js",
@@ -64,7 +65,7 @@
64
65
  },
65
66
  "license": "Apache-2.0",
66
67
  "dependencies": {
67
- "playwright-core": "1.59.0-next"
68
+ "@pedropaulovc/playwright-core": "1.59.0-next.3"
68
69
  },
69
70
  "optionalDependencies": {
70
71
  "fsevents": "2.3.2"
package/types/test.d.ts CHANGED
@@ -15,7 +15,7 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
- import type { APIRequestContext, Browser, BrowserContext, BrowserContextOptions, Page, LaunchOptions, ViewportSize, Geolocation, HTTPCredentials, Locator, APIResponse, PageScreenshotOptions } from 'playwright-core';
18
+ import type { APIRequestContext, Browser, BrowserContext, BrowserContextOptions, Page, PageAgent, LaunchOptions, ViewportSize, Geolocation, HTTPCredentials, Locator, APIResponse, PageScreenshotOptions } from 'playwright-core';
19
19
  export * from 'playwright-core';
20
20
 
21
21
  export type BlobReporterOptions = { outputDir?: string, fileName?: string };
@@ -1611,6 +1611,14 @@ interface TestConfig<TestArgs = {}, WorkerArgs = {}> {
1611
1611
  */
1612
1612
  retries?: number;
1613
1613
 
1614
+ /**
1615
+ * Whether to run LLM agent for [PageAgent](https://playwright.dev/docs/api/class-pageagent):
1616
+ * - "all" disregards existing cache and performs all actions via LLM
1617
+ * - "missing" only performs actions that don't have generated cache actions
1618
+ * - "none" does not talk to LLM at all, relies on the cached actions (default)
1619
+ */
1620
+ runAgents?: "all"|"missing"|"none";
1621
+
1614
1622
  /**
1615
1623
  * Shard tests and execute only the selected shard. Specify in the one-based form like `{ total: 5, current: 2 }`.
1616
1624
  *
@@ -2067,6 +2075,14 @@ export interface FullConfig<TestArgs = {}, WorkerArgs = {}> {
2067
2075
  */
2068
2076
  rootDir: string;
2069
2077
 
2078
+ /**
2079
+ * Whether to run LLM agent for [PageAgent](https://playwright.dev/docs/api/class-pageagent):
2080
+ * - "all" disregards existing cache and performs all actions via LLM
2081
+ * - "missing" only performs actions that don't have generated cache actions
2082
+ * - "none" does not talk to LLM at all, relies on the cached actions (default)
2083
+ */
2084
+ runAgents: "all"|"missing"|"none";
2085
+
2070
2086
  /**
2071
2087
  * See [testConfig.shard](https://playwright.dev/docs/api/class-testconfig#test-config-shard).
2072
2088
  */
@@ -6934,6 +6950,24 @@ export interface PlaywrightWorkerOptions {
6934
6950
  export type ScreenshotMode = 'off' | 'on' | 'only-on-failure' | 'on-first-failure';
6935
6951
  export type TraceMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry' | 'on-all-retries' | 'retain-on-first-failure';
6936
6952
  export type VideoMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry';
6953
+ export type AgentOptions = {
6954
+ provider?: {
6955
+ api: 'openai' | 'openai-compatible' | 'anthropic' | 'google';
6956
+ apiEndpoint?: string;
6957
+ apiKey: string;
6958
+ apiTimeout?: number;
6959
+ model: string;
6960
+ },
6961
+ limits?: {
6962
+ maxTokens?: number;
6963
+ maxActions?: number;
6964
+ maxActionRetries?: number;
6965
+ };
6966
+ cachePathTemplate?: string;
6967
+ runAgents?: 'all' | 'missing' | 'none';
6968
+ secrets?: { [key: string]: string };
6969
+ systemPrompt?: string;
6970
+ };
6937
6971
 
6938
6972
  /**
6939
6973
  * Playwright Test provides many options to configure test environment,
@@ -6974,6 +7008,7 @@ export type VideoMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry';
6974
7008
  *
6975
7009
  */
6976
7010
  export interface PlaywrightTestOptions {
7011
+ agentOptions: AgentOptions | undefined;
6977
7012
  /**
6978
7013
  * Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted.
6979
7014
  *
@@ -7683,6 +7718,7 @@ export interface PlaywrightTestArgs {
7683
7718
  *
7684
7719
  */
7685
7720
  request: APIRequestContext;
7721
+ agent: PageAgent;
7686
7722
  }
7687
7723
 
7688
7724
  type ExcludeProps<A, B> = {
@@ -1,16 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __copyProps = (to, from, except, desc) => {
7
- if (from && typeof from === "object" || typeof from === "function") {
8
- for (let key of __getOwnPropNames(from))
9
- if (!__hasOwnProp.call(to, key) && key !== except)
10
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
- }
12
- return to;
13
- };
14
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
- var actions_d_exports = {};
16
- module.exports = __toCommonJS(actions_d_exports);
@@ -1,66 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var navigateAndWait_exports = {};
20
- __export(navigateAndWait_exports, {
21
- default: () => navigateAndWait_default
22
- });
23
- module.exports = __toCommonJS(navigateAndWait_exports);
24
- var import_mcpBundle = require("playwright-core/lib/mcpBundle");
25
- var import_tool = require("./tool");
26
- const navigateThenWaitFor = (0, import_tool.defineTool)({
27
- capability: "core",
28
- schema: {
29
- name: "browser_navigate_then_wait_for",
30
- title: "Navigate to URL and wait",
31
- description: "Navigate to a URL and then wait for text to appear or disappear or a specified time to pass",
32
- inputSchema: import_mcpBundle.z.object({
33
- url: import_mcpBundle.z.string().describe("The URL to navigate to"),
34
- time: import_mcpBundle.z.number().optional().describe("The time to wait in seconds after navigation"),
35
- text: import_mcpBundle.z.string().optional().describe("The text to wait for after navigation"),
36
- textGone: import_mcpBundle.z.string().optional().describe("The text to wait for to disappear after navigation")
37
- }),
38
- type: "action"
39
- },
40
- handle: async (context, params, response) => {
41
- if (!params.text && !params.textGone && !params.time)
42
- throw new Error("Either time, text or textGone must be provided");
43
- const tab = await context.ensureTab();
44
- await tab.navigate(params.url);
45
- response.addCode(`await page.goto('${params.url}');`);
46
- if (params.time) {
47
- response.addCode(`await new Promise(f => setTimeout(f, ${params.time} * 1000));`);
48
- await new Promise((f) => setTimeout(f, Math.min(3e4, params.time * 1e3)));
49
- }
50
- const locator = params.text ? tab.page.getByText(params.text).first() : void 0;
51
- const goneLocator = params.textGone ? tab.page.getByText(params.textGone).first() : void 0;
52
- if (goneLocator) {
53
- response.addCode(`await page.getByText(${JSON.stringify(params.textGone)}).first().waitFor({ state: 'hidden' });`);
54
- await goneLocator.waitFor({ state: "hidden" });
55
- }
56
- if (locator) {
57
- response.addCode(`await page.getByText(${JSON.stringify(params.text)}).first().waitFor({ state: 'visible' });`);
58
- await locator.waitFor({ state: "visible" });
59
- }
60
- response.addResult(`Navigated to ${params.url} and waited for ${params.text || params.textGone || params.time}`);
61
- response.setIncludeSnapshot();
62
- }
63
- });
64
- var navigateAndWait_default = [
65
- navigateThenWaitFor
66
- ];
@@ -1,63 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var snapshotViewport_exports = {};
30
- __export(snapshotViewport_exports, {
31
- default: () => snapshotViewport_default
32
- });
33
- module.exports = __toCommonJS(snapshotViewport_exports);
34
- var import_fs = __toESM(require("fs"));
35
- var import_mcpBundle = require("playwright-core/lib/mcpBundle");
36
- var import_tool = require("./tool");
37
- const snapshotViewport = (0, import_tool.defineTool)({
38
- capability: "core",
39
- schema: {
40
- name: "browser_snapshot_viewport",
41
- title: "Viewport snapshot",
42
- description: "Capture accessibility snapshot of only what is visible in the current viewport",
43
- inputSchema: import_mcpBundle.z.object({
44
- filename: import_mcpBundle.z.string().optional().describe("Save snapshot to markdown file instead of returning it in the response.")
45
- }),
46
- type: "readOnly"
47
- },
48
- handle: async (context, params, response) => {
49
- const tab = await context.ensureTab();
50
- const snapshotResult = await tab.page._snapshotForAI({ track: "response", viewportOnly: true });
51
- const viewportSnapshot = snapshotResult.full;
52
- if (params.filename) {
53
- const fileName = await response.addFile(params.filename, { origin: "llm", reason: "Saved viewport snapshot" });
54
- await import_fs.default.promises.writeFile(fileName, viewportSnapshot);
55
- response.setIncludeMetaOnly();
56
- } else {
57
- response.addResult(viewportSnapshot);
58
- }
59
- }
60
- });
61
- var snapshotViewport_default = [
62
- snapshotViewport
63
- ];