pw-repl 0.12.8 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +19 -37
- package/README.md +9 -4
- package/bin/pw-repl.js +12 -10
- package/lib/background.js +2 -2
- package/lib/capture.js +11 -12
- package/lib/cli-names.js +1 -1
- package/lib/commands.js +3 -0
- package/lib/elements.js +21 -6
- package/lib/help.js +75 -33
- package/lib/inspect.js +95 -38
- package/lib/output.js +10 -3
- package/lib/profile.js +16 -14
- package/lib/record.js +17 -13
- package/lib/routes.js +8 -9
- package/lib/runner.js +28 -9
- package/lib/send.js +19 -8
- package/lib/server.js +4 -1
- package/lib/state.js +26 -9
- package/lib/syntax.js +4 -1
- package/lib/tabs.js +6 -0
- package/lib/toast.js +1 -6
- package/lib/util.js +25 -1
- package/lib/watch.js +4 -2
- package/lib/written.js +67 -0
- package/package.json +1 -1
- package/skill/SKILL.md +12 -4
package/lib/written.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// The files the REPL wrote this session, and for whom, so close and stop can say which are still
|
|
2
|
+
// there to clean up. Kept in memory only, and nothing is removed.
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { state, onShutdownEnd } = require('./state');
|
|
6
|
+
const out = require('./output');
|
|
7
|
+
const { FILES_LEFT } = require('./util');
|
|
8
|
+
|
|
9
|
+
const written = new Map();
|
|
10
|
+
|
|
11
|
+
// kind: what it is, as the summary counts it (screenshot, video, steps file, profile, watch file).
|
|
12
|
+
function noteWritten(file, kind, client = state.client) {
|
|
13
|
+
written.set(path.resolve(file), { kind, client: client ?? null });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// A file renamed (record off <file>) is still the same one.
|
|
17
|
+
function noteMoved(from, to) {
|
|
18
|
+
const entry = written.get(path.resolve(from));
|
|
19
|
+
if (!entry) return;
|
|
20
|
+
written.delete(path.resolve(from));
|
|
21
|
+
written.set(path.resolve(to), entry);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function remaining(client) {
|
|
25
|
+
const files = [];
|
|
26
|
+
for (const [file, entry] of written) {
|
|
27
|
+
if (entry.client !== (client ?? null)) continue;
|
|
28
|
+
try { files.push({ file, kind: entry.kind, size: fs.statSync(file).size }); } catch {}
|
|
29
|
+
}
|
|
30
|
+
return files;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function sizeText(bytes) {
|
|
34
|
+
if (bytes < 1024 * 1024) return `${Math.max(1, Math.round(bytes / 1024))} KB`;
|
|
35
|
+
return `${Number((bytes / 1024 / 1024).toFixed(1))} MB`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// For close: the client's own files, in full.
|
|
39
|
+
function ownFilesText(client) {
|
|
40
|
+
const files = remaining(client);
|
|
41
|
+
if (!files.length) return null;
|
|
42
|
+
return [`Files you wrote that are still there; remove what is no longer needed:`, ...files.map(f => ` ${f.file} (${sizeText(f.size)})`)].join('\n');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const plural = (n, kind) => `${n} ${kind}${n === 1 ? '' : 's'}`;
|
|
46
|
+
|
|
47
|
+
// For stop: one line for each client that left files, each with what and where.
|
|
48
|
+
function summaryLines() {
|
|
49
|
+
const clients = [...new Set([...written.values()].map(e => e.client))];
|
|
50
|
+
const lines = [];
|
|
51
|
+
for (const client of clients) {
|
|
52
|
+
const files = remaining(client);
|
|
53
|
+
if (!files.length) continue;
|
|
54
|
+
const kinds = new Map();
|
|
55
|
+
for (const f of files) kinds.set(f.kind, (kinds.get(f.kind) || 0) + 1);
|
|
56
|
+
const folders = [...new Set(files.map(f => `${path.dirname(f.file)}/`))];
|
|
57
|
+
const bytes = files.reduce((sum, f) => sum + f.size, 0);
|
|
58
|
+
const who = client ? `by ${client}` : 'without a client name';
|
|
59
|
+
lines.push(`${FILES_LEFT} ${who}: ${plural(files.length, 'file')}, ${sizeText(bytes)} (${[...kinds].map(([k, n]) => plural(n, k)).join(', ')}) in ${folders.join(' and ')}`);
|
|
60
|
+
}
|
|
61
|
+
return lines;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// After every recording has been saved, so its file is whole.
|
|
65
|
+
onShutdownEnd(() => { for (const line of summaryLines()) out.log(line); });
|
|
66
|
+
|
|
67
|
+
module.exports = { noteWritten, noteMoved, ownFilesText, summaryLines };
|
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pw-repl
|
|
3
|
-
description: Inspect and drive a Chromium browser, possibly one the user is using, through the pw-repl REPL - tabs, page snapshots, clicks and typing, the mouse at a point (moves, buttons, wheel), requests and their bodies, console messages, waiting for pages and elements, choosing files, faking, patching or delaying responses, cutting or slowing the network, emulating a phone, dark mode, a locale or a timezone, recording what the user does, profiling what makes a page slow (long tasks, forced layouts, input delay, dropped frames), and recording a video of a tab, with a pointer and on-screen captions. Use when asked to look at, debug or test something in a web page, in an existing Chromium with remote debugging or in one it starts itself.
|
|
3
|
+
description: Inspect and drive a Chromium browser, possibly one the user is using, through the pw-repl REPL - tabs, page snapshots, clicks and typing, the mouse at a point (moves, buttons, wheel), requests and their bodies, console messages, what a page copied to the clipboard, waiting for pages and elements, choosing files, faking, patching or delaying responses, cutting or slowing the network, emulating a phone, dark mode, a locale or a timezone, recording what the user does, profiling what makes a page slow (long tasks, forced layouts, input delay, dropped frames), and recording a video of a tab, with a pointer and on-screen captions. Use when asked to look at, debug or test something in a web page, in an existing Chromium with remote debugging or in one it starts itself.
|
|
4
4
|
allowed-tools: Bash(pw-repl:*) Bash(npx pw-repl@latest:*)
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -93,7 +93,7 @@ client of your own: `PW_CLIENT=<name>` (or `send -c <name>`), with a name that s
|
|
|
93
93
|
as `[server:<name>]` lines.
|
|
94
94
|
- `modes` and `tab` say which client turned each mode on and opened each tab. `modes off --mine` turns
|
|
95
95
|
off only what you turned on; `tab close <url-part>` closes a tab you opened.
|
|
96
|
-
- Commands run one at a time, from every client: a long one (`capture on
|
|
96
|
+
- Commands run one at a time, from every client: a long one (`capture on 60s`, `sleep`) holds the rest.
|
|
97
97
|
|
|
98
98
|
A REPL of your own, on a socket of its own, is for a browser of your own (`--launch`), or when you are
|
|
99
99
|
asked for one. Several REPLs on one browser each see every tab but list only their own modes, and can
|
|
@@ -105,16 +105,19 @@ A REPL in a terminal stops at its prompt (`quit`, or Ctrl-C); `send quit` is ref
|
|
|
105
105
|
|
|
106
106
|
```bash
|
|
107
107
|
pw-repl send tab
|
|
108
|
-
pw-repl send -t
|
|
108
|
+
pw-repl send -t 90s 'screenshot -d 60s' # wait longer than the 20s default
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
+
Times, in send's `-t` and in every command, are in milliseconds, as in Playwright, or in seconds with an
|
|
112
|
+
`s`: `-t 90000` or `-t 90s`.
|
|
113
|
+
|
|
111
114
|
Always send commands with `pw-repl send`; don't type into the pane yourself, except `quit` at the prompt
|
|
112
115
|
of a REPL of your own, which `send` refuses. The words after `send` are the command. For `fill`, `type`,
|
|
113
116
|
`select`, `press`, `upload` and `wait`, a word quoted in your shell stays one word
|
|
114
117
|
(`pw-repl send fill "text=Your name" Ada`, `pw-repl send wait text "Showing 1"`); other commands get the words as they are, joined by
|
|
115
118
|
spaces (`pw-repl send eval "document.title + ' x'"`). A command that takes only a selector takes the
|
|
116
119
|
whole line, spaces and all: `pw-repl send click "text=Your name"`. `send`'s own options (`-t`, `-c`, `-e`,
|
|
117
|
-
`-s`, `--no-vars`) go before the command or after it (`pw-repl send open <url> -t
|
|
120
|
+
`-s`, `--no-vars`) go before the command or after it (`pw-repl send open <url> -t 30s`); after `--`, every
|
|
118
121
|
word is the command's. It works however the REPL was started:
|
|
119
122
|
|
|
120
123
|
- `run` (in tmux): `send` types the command into the tmux pane and reads the result back off the screen.
|
|
@@ -227,6 +230,9 @@ pw-repl send -c <name> close # your modes off; tab close
|
|
|
227
230
|
lists what is on in every tab (the prompt shows the selected tab's, e.g. `(watch routes:1) pw>`);
|
|
228
231
|
`modes off` turns off every mode in every tab.
|
|
229
232
|
- Someone may be attached to the REPL's tmux session; killing the session ends it for them too.
|
|
233
|
+
- What a page copied (a Copy button): click it, then `clipboard` prints it. In a headless browser
|
|
234
|
+
(`--launch`) that is the browser's own clipboard. In one with a window it is the user's, which may
|
|
235
|
+
hold a password, so `clipboard` refuses there without `--shared-clipboard`: ask the user first.
|
|
230
236
|
- To point something out, to the user or in a screenshot, `highlight <ref|selector>` draws a box over it
|
|
231
237
|
without changing the page (`--style=<css>` restyles it; `highlight off` hides them), without
|
|
232
238
|
Playwright's locator label unless `highlight --labels on`.
|
|
@@ -249,6 +255,8 @@ pw-repl send -c <name> close # your modes off; tab close
|
|
|
249
255
|
not by `send`. Without it, a REPL on a socket of its own saves them next to its socket, and any other
|
|
250
256
|
in `/tmp`. `screenshot` prints each file's path; other REPLs may save theirs in the same place. Remove
|
|
251
257
|
only your own, and keep those too if they are needed, e.g. as evidence or as something to hand over.
|
|
258
|
+
`close` (as a client, `-c <name>`) lists every file you wrote that is still there: screenshots,
|
|
259
|
+
videos, saved profiles and watches.
|
|
252
260
|
- `PW_ENDPOINT` / `PW_TMUX_SESSION` — defaults for `send -e` / `-s`. `PW_SOCKET` — the socket `serve`
|
|
253
261
|
serves on and `send` looks for when neither is given (default `/tmp/pw-repl.sock`).
|
|
254
262
|
|