@cotestdev/mcp_playwright 0.0.34 → 0.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/lib/common/testType.js +1 -1
  2. package/lib/mcp/browser/browserContextFactory.js +12 -12
  3. package/lib/mcp/browser/browserServerBackend.js +24 -12
  4. package/lib/mcp/browser/config.js +37 -7
  5. package/lib/mcp/browser/context.js +17 -63
  6. package/lib/mcp/browser/response.js +183 -251
  7. package/lib/mcp/browser/sessionLog.js +19 -104
  8. package/lib/mcp/browser/tab.js +49 -28
  9. package/lib/mcp/browser/tools/common.js +4 -4
  10. package/lib/mcp/browser/tools/console.js +20 -3
  11. package/lib/mcp/browser/tools/dialogs.js +0 -1
  12. package/lib/mcp/browser/tools/evaluate.js +6 -4
  13. package/lib/mcp/browser/tools/install.js +4 -1
  14. package/lib/mcp/browser/tools/keyboard.js +75 -8
  15. package/lib/mcp/browser/tools/mouse.js +59 -7
  16. package/lib/mcp/browser/tools/navigate.js +48 -5
  17. package/lib/mcp/browser/tools/network.js +21 -3
  18. package/lib/mcp/browser/tools/pdf.js +4 -3
  19. package/lib/mcp/browser/tools/runCode.js +6 -10
  20. package/lib/mcp/browser/tools/screenshot.js +8 -26
  21. package/lib/mcp/browser/tools/snapshot.js +38 -22
  22. package/lib/mcp/browser/tools/tabs.js +8 -8
  23. package/lib/mcp/browser/tools/tool.js +3 -6
  24. package/lib/mcp/browser/tools/tracing.js +3 -3
  25. package/lib/mcp/browser/tools/utils.js +2 -2
  26. package/lib/mcp/browser/tools/verify.js +4 -4
  27. package/lib/mcp/browser/tools/wait.js +1 -1
  28. package/lib/mcp/browser/tools.js +2 -2
  29. package/lib/mcp/extension/extensionContextFactory.js +2 -2
  30. package/lib/mcp/program.js +3 -2
  31. package/lib/mcp/terminal/cli.js +4 -216
  32. package/lib/mcp/terminal/command.js +56 -0
  33. package/lib/mcp/terminal/commands.js +528 -0
  34. package/lib/mcp/terminal/daemon.js +42 -25
  35. package/lib/mcp/terminal/helpGenerator.js +152 -0
  36. package/lib/mcp/terminal/program.js +434 -0
  37. package/lib/mcp/terminal/socketConnection.js +2 -4
  38. package/lib/mcpBundleImpl/index.js +44 -44
  39. package/lib/util.js +3 -6
  40. package/package.json +3 -2
@@ -0,0 +1,152 @@
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 helpGenerator_exports = {};
20
+ __export(helpGenerator_exports, {
21
+ generateHelp: () => generateHelp,
22
+ generateHelpJSON: () => generateHelpJSON,
23
+ generateReadme: () => generateReadme
24
+ });
25
+ module.exports = __toCommonJS(helpGenerator_exports);
26
+ var import_commands = require("./commands");
27
+ function commandArgs(command) {
28
+ const args = [];
29
+ const shape = command.args ? command.args.shape : {};
30
+ for (const [name, schema] of Object.entries(shape)) {
31
+ const zodSchema = schema;
32
+ const description = zodSchema.description ?? "";
33
+ args.push({ name, description, optional: zodSchema.safeParse(void 0).success });
34
+ }
35
+ return args;
36
+ }
37
+ function commandArgsText(args) {
38
+ return args.map((a) => a.optional ? `[${a.name}]` : `<${a.name}>`).join(" ");
39
+ }
40
+ function generateCommandHelp(command) {
41
+ const args = commandArgs(command);
42
+ const lines = [
43
+ `playwright-cli ${command.name} ${commandArgsText(args)}`,
44
+ "",
45
+ command.description,
46
+ ""
47
+ ];
48
+ if (args.length) {
49
+ lines.push("Arguments:");
50
+ lines.push(...args.map((a) => formatWithGap(` ${a.optional ? `[${a.name}]` : `<${a.name}>`}`, a.description.toLowerCase())));
51
+ }
52
+ if (command.options) {
53
+ lines.push("Options:");
54
+ const optionsShape = command.options.shape;
55
+ for (const [name, schema] of Object.entries(optionsShape)) {
56
+ const zodSchema = schema;
57
+ const description = (zodSchema.description ?? "").toLowerCase();
58
+ lines.push(formatWithGap(` --${name}`, description));
59
+ }
60
+ }
61
+ return lines.join("\n");
62
+ }
63
+ const categories = [
64
+ { name: "core", title: "Core" },
65
+ { name: "navigation", title: "Navigation" },
66
+ { name: "keyboard", title: "Keyboard" },
67
+ { name: "mouse", title: "Mouse" },
68
+ { name: "export", title: "Save as" },
69
+ { name: "tabs", title: "Tabs" },
70
+ { name: "storage", title: "Storage" },
71
+ { name: "devtools", title: "DevTools" },
72
+ { name: "config", title: "Configuration" },
73
+ { name: "session", title: "Sessions" }
74
+ ];
75
+ function generateHelp() {
76
+ const lines = [];
77
+ lines.push("Usage: playwright-cli <command> [args] [options]");
78
+ const commandsByCategory = /* @__PURE__ */ new Map();
79
+ for (const c of categories)
80
+ commandsByCategory.set(c.name, []);
81
+ for (const command of Object.values(import_commands.commands))
82
+ commandsByCategory.get(command.category).push(command);
83
+ for (const c of categories) {
84
+ const cc = commandsByCategory.get(c.name);
85
+ if (!cc.length)
86
+ continue;
87
+ lines.push(`
88
+ ${c.title}:`);
89
+ for (const command of cc)
90
+ lines.push(generateHelpEntry(command));
91
+ }
92
+ lines.push("\nGlobal options:");
93
+ lines.push(formatWithGap(" --config <path>", "create a session with custom config, defaults to `playwright-cli.json`"));
94
+ lines.push(formatWithGap(" --headed", "create a headed session"));
95
+ lines.push(formatWithGap(" --help [command]", "print help"));
96
+ lines.push(formatWithGap(" --session", "run command in the scope of a specific session"));
97
+ lines.push(formatWithGap(" --version", "print version"));
98
+ return lines.join("\n");
99
+ }
100
+ function generateReadme() {
101
+ const lines = [];
102
+ lines.push("\n## Commands");
103
+ const commandsByCategory = /* @__PURE__ */ new Map();
104
+ for (const c of categories)
105
+ commandsByCategory.set(c.name, []);
106
+ for (const command of Object.values(import_commands.commands))
107
+ commandsByCategory.get(command.category).push(command);
108
+ for (const c of categories) {
109
+ const cc = commandsByCategory.get(c.name);
110
+ if (!cc.length)
111
+ continue;
112
+ lines.push(`
113
+ ### ${c.title}
114
+ `);
115
+ lines.push("```bash");
116
+ for (const command of cc)
117
+ lines.push(generateReadmeEntry(command));
118
+ lines.push("```");
119
+ }
120
+ return lines.join("\n");
121
+ }
122
+ function generateHelpEntry(command) {
123
+ const args = commandArgs(command);
124
+ const prefix = ` ${command.name} ${commandArgsText(args)}`;
125
+ const suffix = command.description.toLowerCase();
126
+ return formatWithGap(prefix, suffix);
127
+ }
128
+ function generateReadmeEntry(command) {
129
+ const args = commandArgs(command);
130
+ const prefix = `playwright-cli ${command.name} ${commandArgsText(args)}`;
131
+ const suffix = "# " + command.description.toLowerCase();
132
+ return formatWithGap(prefix, suffix, 40);
133
+ }
134
+ function generateHelpJSON() {
135
+ const help = {
136
+ global: generateHelp(),
137
+ commands: Object.fromEntries(
138
+ Object.entries(import_commands.commands).map(([name, command]) => [name, generateCommandHelp(command)])
139
+ )
140
+ };
141
+ return help;
142
+ }
143
+ function formatWithGap(prefix, text, threshold = 30) {
144
+ const indent = Math.max(1, threshold - prefix.length);
145
+ return prefix + " ".repeat(indent) + text;
146
+ }
147
+ // Annotate the CommonJS export names for ESM import in node:
148
+ 0 && (module.exports = {
149
+ generateHelp,
150
+ generateHelpJSON,
151
+ generateReadme
152
+ });
@@ -0,0 +1,434 @@
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
+ printResponse: () => printResponse,
32
+ program: () => program
33
+ });
34
+ module.exports = __toCommonJS(program_exports);
35
+ var import_child_process = require("child_process");
36
+ var import_crypto = __toESM(require("crypto"));
37
+ var import_fs = __toESM(require("fs"));
38
+ var import_net = __toESM(require("net"));
39
+ var import_os = __toESM(require("os"));
40
+ var import_path = __toESM(require("path"));
41
+ var import_socketConnection = require("./socketConnection");
42
+ class Session {
43
+ constructor(name, connection) {
44
+ this._nextMessageId = 1;
45
+ this._callbacks = /* @__PURE__ */ new Map();
46
+ this.name = name;
47
+ this._connection = connection;
48
+ this._connection.onmessage = (message) => this._onMessage(message);
49
+ this._connection.onclose = () => this.close();
50
+ }
51
+ async run(args) {
52
+ return await this._send("run", { args });
53
+ }
54
+ async stop() {
55
+ await this._send("stop");
56
+ this.close();
57
+ }
58
+ async _send(method, params = {}) {
59
+ const messageId = this._nextMessageId++;
60
+ const message = {
61
+ id: messageId,
62
+ method,
63
+ params
64
+ };
65
+ await this._connection.send(message);
66
+ return new Promise((resolve, reject) => {
67
+ this._callbacks.set(messageId, { resolve, reject });
68
+ });
69
+ }
70
+ close() {
71
+ for (const callback of this._callbacks.values())
72
+ callback.reject(new Error("Session closed"));
73
+ this._callbacks.clear();
74
+ this._connection.close();
75
+ }
76
+ _onMessage(object) {
77
+ if (object.id && this._callbacks.has(object.id)) {
78
+ const callback = this._callbacks.get(object.id);
79
+ this._callbacks.delete(object.id);
80
+ if (object.error)
81
+ callback.reject(new Error(object.error));
82
+ else
83
+ callback.resolve(object.result);
84
+ } else if (object.id) {
85
+ throw new Error(`Unexpected message id: ${object.id}`);
86
+ } else {
87
+ throw new Error(`Unexpected message without id: ${JSON.stringify(object)}`);
88
+ }
89
+ }
90
+ }
91
+ class SessionManager {
92
+ constructor(options) {
93
+ this._options = options;
94
+ }
95
+ async list() {
96
+ const dir = daemonProfilesDir;
97
+ try {
98
+ const files = await import_fs.default.promises.readdir(dir);
99
+ const sessions = /* @__PURE__ */ new Map();
100
+ for (const file of files) {
101
+ if (file.startsWith("ud-")) {
102
+ const sessionName = file.split("-")[1];
103
+ const live = await this._canConnect(sessionName);
104
+ sessions.set(sessionName, live);
105
+ }
106
+ }
107
+ return sessions;
108
+ } catch {
109
+ return /* @__PURE__ */ new Map();
110
+ }
111
+ }
112
+ async run(args) {
113
+ const sessionName = this._resolveSessionName(args.session);
114
+ const session = await this._connect(sessionName);
115
+ const result = await session.run(args);
116
+ await printResponse(result);
117
+ session.close();
118
+ }
119
+ async stop(sessionName) {
120
+ sessionName = this._resolveSessionName(sessionName);
121
+ if (!await this._canConnect(sessionName)) {
122
+ console.log(`Session '${sessionName}' is not running.`);
123
+ return;
124
+ }
125
+ const session = await this._connect(sessionName);
126
+ await session.stop();
127
+ console.log(`Session '${sessionName}' stopped.`);
128
+ }
129
+ async delete(sessionName) {
130
+ sessionName = this._resolveSessionName(sessionName);
131
+ if (await this._canConnect(sessionName)) {
132
+ const session = await this._connect(sessionName);
133
+ await session.stop();
134
+ }
135
+ const dataDirs = await import_fs.default.promises.readdir(daemonProfilesDir).catch(() => []);
136
+ const matchingDirs = dataDirs.filter((dir) => dir.startsWith(`ud-${sessionName}-`));
137
+ if (matchingDirs.length === 0) {
138
+ console.log(`No user data found for session '${sessionName}'.`);
139
+ return;
140
+ }
141
+ for (const dir of matchingDirs) {
142
+ const userDataDir = import_path.default.resolve(daemonProfilesDir, dir);
143
+ for (let i = 0; i < 5; i++) {
144
+ try {
145
+ await import_fs.default.promises.rm(userDataDir, { recursive: true });
146
+ console.log(`Deleted user data for session '${sessionName}'.`);
147
+ break;
148
+ } catch (e) {
149
+ if (e.code === "ENOENT") {
150
+ console.log(`No user data found for session '${sessionName}'.`);
151
+ break;
152
+ }
153
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
154
+ if (i === 4)
155
+ throw e;
156
+ }
157
+ }
158
+ }
159
+ if (import_os.default.platform() !== "win32") {
160
+ const socketPath = this._daemonSocketPath(sessionName);
161
+ await import_fs.default.promises.unlink(socketPath).catch(() => {
162
+ });
163
+ }
164
+ }
165
+ async configure(args) {
166
+ const sessionName = this._resolveSessionName(args.session);
167
+ if (await this._canConnect(sessionName)) {
168
+ const session2 = await this._connect(sessionName);
169
+ await session2.stop();
170
+ }
171
+ this._options.config = args._[1];
172
+ const session = await this._connect(sessionName);
173
+ session.close();
174
+ }
175
+ async _connect(sessionName) {
176
+ const socketPath = this._daemonSocketPath(sessionName);
177
+ if (await this._canConnect(sessionName)) {
178
+ try {
179
+ return await this._connectToSocket(sessionName, socketPath);
180
+ } catch (e) {
181
+ if (import_os.default.platform() !== "win32")
182
+ await import_fs.default.promises.unlink(socketPath).catch(() => {
183
+ });
184
+ }
185
+ }
186
+ await import_fs.default.promises.mkdir(daemonProfilesDir, { recursive: true });
187
+ const userDataDir = import_path.default.resolve(daemonProfilesDir, `ud-${sessionName}`);
188
+ const cliPath = import_path.default.join(__dirname, "../../../cli.js");
189
+ const configFile = resolveConfigFile(this._options.config);
190
+ const configArg = configFile !== void 0 ? [`--config=${configFile}`] : [];
191
+ const headedArg = this._options.headed ? [`--daemon-headed`] : [];
192
+ const outLog = import_path.default.join(daemonProfilesDir, "out.log");
193
+ const errLog = import_path.default.join(daemonProfilesDir, "err.log");
194
+ const out = import_fs.default.openSync(outLog, "w");
195
+ const err = import_fs.default.openSync(errLog, "w");
196
+ const child = (0, import_child_process.spawn)(process.execPath, [
197
+ cliPath,
198
+ "run-mcp-server",
199
+ `--daemon=${socketPath}`,
200
+ `--daemon-data-dir=${userDataDir}`,
201
+ ...configArg,
202
+ ...headedArg
203
+ ], {
204
+ detached: true,
205
+ stdio: ["ignore", out, err],
206
+ cwd: process.cwd()
207
+ // Will be used as root.
208
+ });
209
+ child.unref();
210
+ console.log(`<!-- Daemon for \`${sessionName}\` session started with pid ${child.pid}.`);
211
+ if (configFile)
212
+ console.log(`- Using config file at \`${import_path.default.relative(process.cwd(), configFile)}\`.`);
213
+ const sessionSuffix = sessionName !== "default" ? ` "${sessionName}"` : "";
214
+ console.log(`- You can stop the session daemon with \`playwright-cli session-stop${sessionSuffix}\` when done.`);
215
+ console.log(`- You can delete the session data with \`playwright-cli session-delete${sessionSuffix}\` when done.`);
216
+ console.log("-->");
217
+ const maxRetries = 50;
218
+ const retryDelay = 100;
219
+ for (let i = 0; i < maxRetries; i++) {
220
+ await new Promise((resolve) => setTimeout(resolve, 100));
221
+ try {
222
+ return await this._connectToSocket(sessionName, socketPath);
223
+ } catch (e) {
224
+ if (e.code !== "ENOENT")
225
+ throw e;
226
+ }
227
+ }
228
+ const outData = await import_fs.default.promises.readFile(outLog, "utf-8").catch(() => "");
229
+ const errData = await import_fs.default.promises.readFile(errLog, "utf-8").catch(() => "");
230
+ console.error(`Failed to connect to daemon at ${socketPath} after ${maxRetries * retryDelay}ms`);
231
+ if (outData.length)
232
+ console.log(outData);
233
+ if (errData.length)
234
+ console.error(errData);
235
+ process.exit(1);
236
+ }
237
+ async _connectToSocket(sessionName, socketPath) {
238
+ const socket = await new Promise((resolve, reject) => {
239
+ const socket2 = import_net.default.createConnection(socketPath, () => {
240
+ resolve(socket2);
241
+ });
242
+ socket2.on("error", reject);
243
+ });
244
+ return new Session(sessionName, new import_socketConnection.SocketConnection(socket));
245
+ }
246
+ async _canConnect(sessionName) {
247
+ const socketPath = this._daemonSocketPath(sessionName);
248
+ return new Promise((resolve) => {
249
+ const socket = import_net.default.createConnection(socketPath, () => {
250
+ socket.destroy();
251
+ resolve(true);
252
+ });
253
+ socket.on("error", () => {
254
+ resolve(false);
255
+ });
256
+ });
257
+ }
258
+ _resolveSessionName(sessionName) {
259
+ if (sessionName)
260
+ return sessionName;
261
+ if (process.env.PLAYWRIGHT_CLI_SESSION)
262
+ return process.env.PLAYWRIGHT_CLI_SESSION;
263
+ return "default";
264
+ }
265
+ _daemonSocketPath(sessionName) {
266
+ const socketName = `${sessionName}.sock`;
267
+ if (import_os.default.platform() === "win32")
268
+ return `\\\\.\\pipe\\${installationDirHash}-${socketName}`;
269
+ const socketsDir = process.env.PLAYWRIGHT_DAEMON_SOCKETS_DIR || import_path.default.join(import_os.default.tmpdir(), "playwright-cli");
270
+ return import_path.default.join(socketsDir, installationDirHash, socketName);
271
+ }
272
+ }
273
+ async function handleSessionCommand(sessionManager, subcommand, args) {
274
+ if (subcommand === "list") {
275
+ const sessions = await sessionManager.list();
276
+ console.log("Sessions:");
277
+ for (const [sessionName, live] of sessions.entries()) {
278
+ const liveMarker = live ? " (live)" : "";
279
+ console.log(` ${sessionName}${liveMarker}`);
280
+ }
281
+ if (sessions.size === 0)
282
+ console.log(" (no sessions)");
283
+ return;
284
+ }
285
+ if (subcommand === "stop") {
286
+ await sessionManager.stop(args._[1]);
287
+ return;
288
+ }
289
+ if (subcommand === "stop-all") {
290
+ const sessions = await sessionManager.list();
291
+ for (const sessionName of sessions.keys())
292
+ await sessionManager.stop(sessionName);
293
+ return;
294
+ }
295
+ if (subcommand === "delete") {
296
+ await sessionManager.delete(args._[1]);
297
+ return;
298
+ }
299
+ if (subcommand === "config") {
300
+ await sessionManager.configure(args);
301
+ return;
302
+ }
303
+ console.error(`Unknown session subcommand: ${subcommand}`);
304
+ process.exit(1);
305
+ }
306
+ const installationDirHash = (() => {
307
+ const hash = import_crypto.default.createHash("sha1");
308
+ hash.update(process.env.PLAYWRIGHT_DAEMON_INSTALL_DIR || require.resolve("../../../package.json"));
309
+ return hash.digest("hex").substring(0, 16);
310
+ })();
311
+ const daemonProfilesDir = (() => {
312
+ if (process.env.PLAYWRIGHT_DAEMON_SESSION_DIR)
313
+ return process.env.PLAYWRIGHT_DAEMON_SESSION_DIR;
314
+ let localCacheDir;
315
+ if (process.platform === "linux")
316
+ localCacheDir = process.env.XDG_CACHE_HOME || import_path.default.join(import_os.default.homedir(), ".cache");
317
+ if (process.platform === "darwin")
318
+ localCacheDir = import_path.default.join(import_os.default.homedir(), "Library", "Caches");
319
+ if (process.platform === "win32")
320
+ localCacheDir = process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local");
321
+ if (!localCacheDir)
322
+ throw new Error("Unsupported platform: " + process.platform);
323
+ return import_path.default.join(localCacheDir, "ms-playwright", "daemon", installationDirHash);
324
+ })();
325
+ async function program(options) {
326
+ const argv = process.argv.slice(2);
327
+ const args = require("minimist")(argv, {
328
+ boolean: ["help", "version", "headed"]
329
+ });
330
+ if (!argv.includes("--headed") && !argv.includes("--no-headed"))
331
+ delete args.headed;
332
+ const help = require("./help.json");
333
+ const commandName = args._[0];
334
+ if (args.version || args.v) {
335
+ console.log(options.version);
336
+ process.exit(0);
337
+ }
338
+ const command = help.commands[commandName];
339
+ if (args.help || args.h) {
340
+ if (command) {
341
+ console.log(command);
342
+ } else {
343
+ console.log("playwright-cli - run playwright mcp commands from terminal\n");
344
+ console.log(help.global);
345
+ }
346
+ process.exit(0);
347
+ }
348
+ if (!command) {
349
+ console.error(`Unknown command: ${commandName}
350
+ `);
351
+ console.log(help.global);
352
+ process.exit(1);
353
+ }
354
+ const sessionManager = new SessionManager(args);
355
+ if (commandName.startsWith("session")) {
356
+ const subcommand = args._[0].split("-").slice(1).join("-");
357
+ await handleSessionCommand(sessionManager, subcommand, args);
358
+ return;
359
+ }
360
+ if (commandName === "config") {
361
+ await handleSessionCommand(sessionManager, "config", args);
362
+ return;
363
+ }
364
+ await sessionManager.run(args);
365
+ }
366
+ async function printResponse(response) {
367
+ const { sections } = response;
368
+ if (!sections) {
369
+ console.log("### Error\n" + response.text);
370
+ return;
371
+ }
372
+ const text = [];
373
+ for (const section of sections) {
374
+ text.push(`### ${section.title}`);
375
+ for (const result of section.content) {
376
+ if (!result.file) {
377
+ if (result.text !== void 0)
378
+ text.push(result.text);
379
+ continue;
380
+ }
381
+ const generatedFileName = await outputFile(dateAsFileName(result.file.prefix, result.file.ext), { origin: "code" });
382
+ const fileName = result.file.suggestedFilename ? await outputFile(result.file.suggestedFilename, { origin: "llm" }) : generatedFileName;
383
+ text.push(`- [${result.title}](${import_path.default.relative(process.cwd(), fileName)})`);
384
+ if (result.data)
385
+ await import_fs.default.promises.writeFile(fileName, result.data);
386
+ else if (result.isBase64)
387
+ await import_fs.default.promises.writeFile(fileName, Buffer.from(result.text, "base64"));
388
+ else
389
+ await import_fs.default.promises.writeFile(fileName, result.text);
390
+ }
391
+ }
392
+ console.log(text.join("\n"));
393
+ }
394
+ function dateAsFileName(prefix, extension) {
395
+ const date = /* @__PURE__ */ new Date();
396
+ return `${prefix}-${date.toISOString().replace(/[:.]/g, "-")}.${extension}`;
397
+ }
398
+ const outputDir = import_path.default.join(process.cwd(), ".playwright-cli");
399
+ async function outputFile(fileName, options) {
400
+ await import_fs.default.promises.mkdir(outputDir, { recursive: true });
401
+ if (options.origin === "code")
402
+ return import_path.default.resolve(outputDir, fileName);
403
+ if (options.origin === "llm") {
404
+ fileName = fileName.split("\\").join("/");
405
+ const resolvedFile = import_path.default.resolve(outputDir, fileName);
406
+ if (!resolvedFile.startsWith(import_path.default.resolve(outputDir) + import_path.default.sep))
407
+ throw new Error(`Resolved file path ${resolvedFile} is outside of the output directory ${outputDir}. Use relative file names to stay within the output directory.`);
408
+ return resolvedFile;
409
+ }
410
+ return import_path.default.join(outputDir, sanitizeForFilePath(fileName));
411
+ }
412
+ function sanitizeForFilePath(s) {
413
+ const sanitize = (s2) => s2.replace(/[\x00-\x2C\x2E-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]+/g, "-");
414
+ const separator = s.lastIndexOf(".");
415
+ if (separator === -1)
416
+ return sanitize(s);
417
+ return sanitize(s.substring(0, separator)) + "." + sanitize(s.substring(separator + 1));
418
+ }
419
+ function resolveConfigFile(configParam) {
420
+ const configFile = configParam || process.env.PLAYWRIGHT_CLI_CONFIG;
421
+ if (configFile)
422
+ return import_path.default.resolve(process.cwd(), configFile);
423
+ try {
424
+ if (import_fs.default.existsSync(import_path.default.resolve(process.cwd(), "playwright-cli.json")))
425
+ return import_path.default.resolve(process.cwd(), "playwright-cli.json");
426
+ } catch {
427
+ }
428
+ return void 0;
429
+ }
430
+ // Annotate the CommonJS export names for ESM import in node:
431
+ 0 && (module.exports = {
432
+ printResponse,
433
+ program
434
+ });
@@ -21,8 +21,6 @@ __export(socketConnection_exports, {
21
21
  SocketConnection: () => SocketConnection
22
22
  });
23
23
  module.exports = __toCommonJS(socketConnection_exports);
24
- var import_utilsBundle = require("playwright-core/lib/utilsBundle");
25
- const daemonDebug = (0, import_utilsBundle.debug)("pw:daemon");
26
24
  class SocketConnection {
27
25
  constructor(socket) {
28
26
  this._pendingBuffers = [];
@@ -31,7 +29,7 @@ class SocketConnection {
31
29
  socket.on("close", () => {
32
30
  this.onclose?.();
33
31
  });
34
- socket.on("error", (e) => daemonDebug(`error: ${e.message}`));
32
+ socket.on("error", (e) => console.error(`error: ${e.message}`));
35
33
  }
36
34
  async send(message) {
37
35
  await new Promise((resolve, reject) => {
@@ -70,7 +68,7 @@ class SocketConnection {
70
68
  try {
71
69
  this.onmessage?.(JSON.parse(message));
72
70
  } catch (e) {
73
- daemonDebug("failed to dispatch message", e);
71
+ console.error("failed to dispatch message", e);
74
72
  }
75
73
  }
76
74
  }