@petukhovart/agent-view 0.15.0 → 0.17.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.
Files changed (89) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +34 -11
  3. package/dist/cdp/png.d.ts +15 -0
  4. package/dist/cdp/png.d.ts.map +1 -0
  5. package/dist/cdp/png.js +147 -0
  6. package/dist/cdp/png.js.map +1 -0
  7. package/dist/cdp/transport.d.ts +2 -0
  8. package/dist/cdp/transport.d.ts.map +1 -1
  9. package/dist/cdp/transport.js +233 -50
  10. package/dist/cdp/transport.js.map +1 -1
  11. package/dist/cdp/types.d.ts +72 -6
  12. package/dist/cdp/types.d.ts.map +1 -1
  13. package/dist/cdp/types.js.map +1 -1
  14. package/dist/cli/client.d.ts.map +1 -1
  15. package/dist/cli/client.js +1 -3
  16. package/dist/cli/client.js.map +1 -1
  17. package/dist/cli/commands/act.d.ts +3 -0
  18. package/dist/cli/commands/act.d.ts.map +1 -0
  19. package/dist/cli/commands/act.js +19 -0
  20. package/dist/cli/commands/act.js.map +1 -0
  21. package/dist/cli/commands/click.d.ts +2 -0
  22. package/dist/cli/commands/click.d.ts.map +1 -1
  23. package/dist/cli/commands/click.js +9 -4
  24. package/dist/cli/commands/click.js.map +1 -1
  25. package/dist/cli/commands/dom.d.ts.map +1 -1
  26. package/dist/cli/commands/dom.js +1 -0
  27. package/dist/cli/commands/dom.js.map +1 -1
  28. package/dist/cli/commands/drag.d.ts +4 -0
  29. package/dist/cli/commands/drag.d.ts.map +1 -1
  30. package/dist/cli/commands/drag.js +18 -0
  31. package/dist/cli/commands/drag.js.map +1 -1
  32. package/dist/cli/commands/fill.d.ts +2 -0
  33. package/dist/cli/commands/fill.d.ts.map +1 -1
  34. package/dist/cli/commands/fill.js +11 -4
  35. package/dist/cli/commands/fill.js.map +1 -1
  36. package/dist/cli/commands/screenshot.d.ts +2 -0
  37. package/dist/cli/commands/screenshot.d.ts.map +1 -1
  38. package/dist/cli/commands/screenshot.js +10 -1
  39. package/dist/cli/commands/screenshot.js.map +1 -1
  40. package/dist/cli/commands/wait.d.ts +3 -1
  41. package/dist/cli/commands/wait.d.ts.map +1 -1
  42. package/dist/cli/commands/wait.js +6 -2
  43. package/dist/cli/commands/wait.js.map +1 -1
  44. package/dist/cli/commands/watch.js +1 -1
  45. package/dist/cli/commands/watch.js.map +1 -1
  46. package/dist/cli/index.js +51 -5
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/config/manager.d.ts.map +1 -1
  49. package/dist/config/manager.js +4 -0
  50. package/dist/config/manager.js.map +1 -1
  51. package/dist/config/types.d.ts +5 -0
  52. package/dist/config/types.d.ts.map +1 -1
  53. package/dist/inspectors/controls/index.d.ts +39 -0
  54. package/dist/inspectors/controls/index.d.ts.map +1 -0
  55. package/dist/inspectors/controls/index.js +140 -0
  56. package/dist/inspectors/controls/index.js.map +1 -0
  57. package/dist/inspectors/dom/index.d.ts +2 -0
  58. package/dist/inspectors/dom/index.d.ts.map +1 -1
  59. package/dist/inspectors/dom/index.js +21 -14
  60. package/dist/inspectors/dom/index.js.map +1 -1
  61. package/dist/server/act-replay.d.ts +23 -0
  62. package/dist/server/act-replay.d.ts.map +1 -0
  63. package/dist/server/act-replay.js +143 -0
  64. package/dist/server/act-replay.js.map +1 -0
  65. package/dist/server/act-script.d.ts +46 -0
  66. package/dist/server/act-script.d.ts.map +1 -0
  67. package/dist/server/act-script.js +46 -0
  68. package/dist/server/act-script.js.map +1 -0
  69. package/dist/server/act-session.d.ts +23 -0
  70. package/dist/server/act-session.d.ts.map +1 -0
  71. package/dist/server/act-session.js +304 -0
  72. package/dist/server/act-session.js.map +1 -0
  73. package/dist/server/locator.d.ts +19 -0
  74. package/dist/server/locator.d.ts.map +1 -0
  75. package/dist/server/locator.js +33 -0
  76. package/dist/server/locator.js.map +1 -0
  77. package/dist/server/port.d.ts +7 -0
  78. package/dist/server/port.d.ts.map +1 -0
  79. package/dist/server/port.js +19 -0
  80. package/dist/server/port.js.map +1 -0
  81. package/dist/server/server.d.ts +1 -0
  82. package/dist/server/server.d.ts.map +1 -1
  83. package/dist/server/server.js +89 -25
  84. package/dist/server/server.js.map +1 -1
  85. package/dist/types.d.ts +2 -0
  86. package/dist/types.d.ts.map +1 -1
  87. package/package.json +1 -1
  88. package/skills/verify/SKILL.md +12 -20
  89. package/skills/verify/references/commands.md +127 -6
@@ -11,6 +11,7 @@ listing call — always expand from the most recent one.
11
11
  - [Interaction](#interaction) — `click`, `fill`, `drag`
12
12
  - [Modals & file pickers](#modals--file-pickers-dialog-upload) — `dialog`, `upload`
13
13
  - [Waiting](#waiting-wait) — `wait`
14
+ - [Step protocol](#step-protocol-act) — `act`
14
15
  - [Screenshots](#screenshots) — `screenshot`
15
16
  - [Runtime state](#runtime-state-eval) — `eval`
16
17
  - [Reactive state](#reactive-state-watch) — `watch`
@@ -48,6 +49,15 @@ agent-view dom --diff # Lines changed since last dom call (+ a
48
49
 
49
50
  `--count` skips tree output and ref mutations — cheapest way to assert "element exists N times" without loading the full tree into context.
50
51
 
52
+ **Test ids.** A node carrying a test id prints it: `button "Save" [testid=save-btn] [ref=12]`. An
53
+ unnamed wrapper that carries one is printed too (`generic [testid=email] [ref=6]`), because
54
+ component libraries put the id on the wrapper. The attribute is `testIdAttribute` from
55
+ `agent-view.config.json`; without it `data-testid`, `data-test-id`, `data-test`, `data-qa` and
56
+ `data-cy` are all read. A test id survives HMR, navigation and text changes; a ref does not. Once
57
+ `dom` has shown a test id, address the element with `--testid` (below). Limit: an element absent
58
+ from the AX tree prints no line. An inline `<span data-testid>` holding only text prints as its
59
+ `StaticText`, without the id. `--testid` still finds it.
60
+
51
61
  ### Interaction
52
62
  ```bash
53
63
  agent-view click <ref> # Click element by ref from dom output
@@ -55,21 +65,40 @@ agent-view click --filter "Save" # Find element by text and click
55
65
  agent-view click --pos 100,200 # Click by coordinates — CANVAS ONLY, see below
56
66
  agent-view click <ref> --double # Double-click (fires dblclick handlers); works with --filter / --pos too
57
67
  agent-view click <ref> --right # Right-click (fires contextmenu); works with --filter / --pos too
68
+ agent-view click --testid save-btn # By test id (see "Test ids" above)
69
+ agent-view click --selector "tr:nth-child(3) button" # By CSS selector
58
70
  agent-view fill <ref> "text" # Type into input field
71
+ agent-view fill --testid email "a@b.c" # A test id on a wrapper resolves to the input/textarea inside
59
72
  agent-view drag --from <ref> --to <ref> # Drag element to another element by ref
60
73
  agent-view drag --from-pos 50,80 --to-pos 200,300 # Drag by coordinates (for canvas / Pixi)
61
74
  agent-view drag --from <ref> --to <ref> --steps 25 --hold-ms 60 # Smoother movement, longer hold
75
+ agent-view drag --from-pos 385,303 --to-pos 1250,589 --cancel # HTML5: dragCancel instead of drop
76
+ agent-view drag --from-pos 385,303 --to-pos 1250,589 --html5 # Fail unless an HTML5 drag started
62
77
  ```
63
78
 
64
- `drag` dispatches `mousePressed` → N × `mouseMoved` → `mouseReleased` via CDP. Endpoints can mix
79
+ `drag` presses and moves via CDP; if Chromium starts an HTML5 drag (`draggable=true`) it takes it
80
+ over with `Input.dispatchDragEvent` and drops with the app's real `dataTransfer`, otherwise it is a
81
+ plain pointer drag. The first output line says which: `via html5 drop` followed by one line per
82
+ MIME type (`application/json: "..."`) — check the payload is the app's, not a text selection — or
83
+ `via pointer` with a warning when no HTML5 drag started. Start HTML5 drags on a cell without a
84
+ control: an input/select/button under the cursor swallows `dragstart`. Endpoints can mix
65
85
  ref and coordinate (e.g. `--from <ref> --to-pos 400,300`). For canvas/Pixi targets always use
66
86
  `--from-pos`/`--to-pos` — derive the centroid via `agent-view eval` from the scene graph.
67
87
  Refs are resolved fresh on each call, so window resizes between snapshots are tolerated.
68
88
  Increase `--steps` for handlers using `globalpointermove` so intermediate frames are not skipped.
69
89
 
90
+ `--testid` / `--selector` act on the **first visible** match; hidden copies (`v-show`, a closed
91
+ popover) are skipped. When several match, the output says so — `Clicked testid "row" (first visible
92
+ of 3)` — and the address is too broad: narrow it, e.g. a `--selector` with `:nth-child`. Exit 1 with
93
+ `No element matches testid "x"` when nothing matches, and with `None of 2 element(s) matching
94
+ testid "x" is visible` when every match is hidden. Pass exactly one of `<ref>`, `--filter`,
95
+ `--testid`, `--selector`, `--pos`. `fill` exits 1 with `No input or textarea at or inside the
96
+ element` when the element holds no field.
97
+
70
98
  **Coordinates are a last resort.** `--pos` / `--from-pos` / `--to-pos` exist for canvas and WebGL,
71
- where no ref exists. On DOM the correct order is `dom --filter "<text>"` → take the `[ref=N]` →
72
- `click <ref>`, or `click --filter "<text>"` in one step. A coordinate pair breaks on any layout
99
+ where no ref exists. On DOM, use `--testid` when `dom` shows one. Otherwise run
100
+ `dom --filter "<text>"` → take the `[ref=N]` → `click <ref>`, or `click --filter "<text>"` in one
101
+ step. A coordinate pair breaks on any layout
73
102
  shift, scroll, zoom, or window resize, and it clicks whatever now sits at that point — silently.
74
103
  If you reach for `--pos` on a DOM element, first say why the ref was not usable.
75
104
 
@@ -141,25 +170,117 @@ an IPC channel) are out of reach — CDP does not see the main process.
141
170
  agent-view wait --filter "Saved" # until the text appears in the AX tree
142
171
  agent-view wait --filter "Saved" --timeout 20 # max wait in seconds (default 10)
143
172
  agent-view wait --filter "Row 5" --window "Main" # specific window
173
+ agent-view wait --testid order-saved # until an element with this test id is visible
174
+ agent-view wait --selector ".toast.success" # until a selector match is visible
144
175
  ```
145
176
 
146
- Exits as soon as the element appears; exits non-zero on timeout — so `&&` after it is a real gate.
177
+ Exactly one of `--filter`, `--testid`, `--selector`. Exits as soon as the element appears; exits
178
+ non-zero on timeout — so `&&` after it is a real gate.
179
+ A mounted but hidden match (`v-show`, `display:none`, `visibility:hidden`) does not end a
180
+ `--testid` / `--selector` wait. On timeout the error says whether nothing matched or every match
181
+ was hidden.
147
182
 
148
183
  **Never sleep for a fixed time** — see the waiting-signal table in `SKILL.md`. If no condition-based
149
184
  wait fits, poll `dom --filter X --count` with an explicit attempt cap and report the attempt count.
150
185
 
151
186
 
187
+ ### Step protocol (`act`)
188
+
189
+ For a driver that only ever answers `op n [text]`. Each call acts, waits for the UI to settle,
190
+ checks the done condition, and prints a fresh numbered control table. The done condition is
191
+ agent-view's to check, never the driver's: `act start` needs exactly one of `--until-testid`,
192
+ `--until-selector`.
193
+
194
+ ```bash
195
+ agent-view act start --until-testid workspace-root # new session for this CDP port; prints the table
196
+ agent-view act start --until-selector ".dashboard" --max-steps 20 # budget, default 30
197
+ agent-view act table # re-snapshot, print the table
198
+ agent-view act click 3 # row numbers refer to the LAST printed table
199
+ agent-view act type 1 "admin" # fill
200
+ agent-view act select 4 "Monthly" # native <select> only
201
+ agent-view act scroll down # wheel ~0.8 viewport at its centre; also `up`
202
+ agent-view act do "type 2 root" "type 3 secret" "click 1" # several ops, all numbered from ONE table; stops at the first BLOCKED/DONE/error
203
+ agent-view act drag 5 # pointer-drag row 5 onto the viewport centre
204
+ agent-view act drag 5 2 # … onto the centre of row 2
205
+ agent-view act drag 7 testid=video-panel right # … onto any visible element by test id, 20 px inside its right edge
206
+ agent-view act drag 7 center left # … near the viewport's left edge; edge: left|right|top|bottom|center (default)
207
+ agent-view act wait # no action: settle up to 3 s, print the table (not a step)
208
+ agent-view act save login # writes ~/.agent-view/scratch/login.json, prints the path
209
+ agent-view act start --until-testid x --save login # same, written automatically on DONE (one turn fewer)
210
+ AGENT_VIEW_SECRET=… agent-view act replay login # re-run it with no model; exit 0 DONE, 1 FAIL, 3 STALE, 2 error
211
+ ```
212
+
213
+ Table — interactive controls visible in the viewport, renumbered from 1 on every print, capped at
214
+ 150 rows (`… N more below — act scroll down`). Named `alert` / `status` nodes (a snackbar) are listed
215
+ too, so the driver sees why a form came back. A field wrapper that boxes a field of its own role
216
+ (Vuetify `v-field` around its input) is folded into the inner one. After the AX rows come `item`
217
+ rows: elements with no interactive role but a test id and computed `cursor: pointer` (a
218
+ `<div @pointerdown>` widget-bar entry), so they can be clicked or dragged; one inside a control is
219
+ that control. Password values print as `••••`, or `empty`:
220
+
221
+ ```
222
+ act step 2/30 · 14 controls · until testid "workspace-root"
223
+ [1] textbox "Логин" testid=login-input · "admin"
224
+ [2] textbox "Пароль" testid=password · ••••
225
+ [3] button "Войти" testid=login-btn
226
+ [4] checkbox "Запомнить" · checked
227
+ ```
228
+
229
+ First line of an op's output:
230
+
231
+ | Line | Meaning |
232
+ |---|---|
233
+ | `✓ click [3] button "Войти" · 240ms` | acted and settled; the new table follows |
234
+ | `✓ click [3] button "Войти" · window reloaded · 900ms` | the window reloaded under the action (login); settled on the new document |
235
+ | `✓ drag [7] item "ГИС" testid=nav__widgetbar__item-GisWidget → testid=video-panel right · 310ms` | dragged: `→` names the target and edge |
236
+ | `DONE: until testid "workspace-root" · 3 steps · 4.1s` | until condition visible; nothing follows |
237
+ | `BLOCKED: [3] button "Войти" is gone` | row no longer on screen, no unique match; fresh table follows, nothing was done |
238
+ | `BLOCKED: [3] covered by div.overlay testid=spinner` | something else receives the click; fresh table follows, nothing was done |
239
+ | `BLOCKED: step budget 30 exhausted` | `--max-steps` reached |
240
+
241
+ `act wait` runs even after the budget is spent. Errors (non-zero exit):
242
+
243
+ - `` run `agent-view act start` first ``, `act start --until-testid <id> | --until-selector <css> — exactly one`
244
+ - `` this act run is DONE — `agent-view act start` for a new one `` (any step after DONE; `table` / `wait` still work)
245
+ - `No row [n] in the last table (1-N)`
246
+ - `[n] is a <role>, not a text field — pick a textbox/combobox row` (`type` on a non-text row);
247
+ `No input or textarea at or inside the element` (`type` on a native `<select>` — use `select`)
248
+ - `not a native select — click it`, `No option "x" in [n]`
249
+ - `act do: "…" — each step is click|type|select <n> [text]` (checked before any step runs; a
250
+ failing step prints the `✓` lines of the ones before it)
251
+ - `act scroll <up|down>`, `act drag <n> [to] [edge] — edge is one of left|right|top|bottom|center`
252
+
253
+ The saved script names each control by test id, else role + name — never by row number — and
254
+ stores no password. `act replay` runs it inside the server: each step waits (50 ms polls, 10 s cap)
255
+ only for its own control to be on screen, enabled and uncovered, then acts; a window reload
256
+ mid-run is ridden over. Its one line, ending in the total time:
257
+
258
+ | Line | Exit | Meaning |
259
+ |---|---|---|
260
+ | `DONE: replay login · 2 steps in 0.1s, then testid "x" · 1.8s` | 0 | until met; the steps took 0.1 s, the app the rest |
261
+ | `FAIL: replay login — steps ran, testid "x" not visible after 15s · 16.2s` | 1 | the app did not answer — likely a bug |
262
+ | `FAIL: step 2/2 click button "Войти" testid=login-btn — still disabled after 10s · 10.4s` | 1 | the control is there but stayed `disabled` / `covered by …` — likely a bug |
263
+ | `STALE: step 2/2 click button "Войти" — not on screen within 10s · 10.3s` | 3 | the script no longer fits the app — re-record it |
264
+ | `STALE: step 3/3 drag target testid=video-panel not found · 10.5s` | 3 | same, for a drop target |
265
+ | `STALE: step 1/2 select combobox "Период" — no option "Monthly" · 0.2s` | 3 | same, for an option (or `not a native select`) |
266
+ | `STALE: step 2/3 click button "Закрыть" — <CDP error> · 0.4s` | 3 | the control vanished between finding and acting |
267
+
268
+ Exit 2, message on stderr: the replay could not run — `No saved script "x"`, `"x" types a password —
269
+ set AGENT_VIEW_SECRET`, `"x" has no done condition`.
270
+
152
271
  ### Screenshots
153
272
  ```bash
154
- agent-view screenshot --scale 0.5 # Recommended: JPEG at half-res (~3× fewer vision tokens)
273
+ agent-view screenshot --scale 0.5 # Recommended: half-res PNG (~3× fewer vision tokens)
155
274
  agent-view screenshot --scale 0.5 --window <id> # Specific window
156
275
  agent-view screenshot --crop "Sidebar" # Crop to element bounding box (~1.6k tokens — 12× win)
157
276
  agent-view screenshot --crop "Chart" --scale 0.5 # Crop + scale (stacks)
158
277
  agent-view screenshot --crop "Active bookings" --crop-up 1 # Crop the card, not just its heading
278
+ agent-view screenshot --testid order-card # Crop to the element with this test id
279
+ agent-view screenshot --selector ".chart" # Crop to the first visible selector match
159
280
  agent-view screenshot # Full-res PNG (expensive: ~19k tokens at 1920×1080)
160
281
  ```
161
282
 
162
- `--crop <filter>` resolves the element with the same filter syntax as `dom --filter`, then crops the screenshot to its bounding box. Prefer `--crop` over full-window screenshots whenever you only need to inspect a specific section. Falls back to full-window with a stderr warning if the filter matches nothing.
283
+ `--crop <filter>` resolves the element with the same filter syntax as `dom --filter`, then crops the screenshot to its bounding box. Prefer `--crop` over full-window screenshots whenever you only need to inspect a specific section. Falls back to full-window with a stderr warning if the filter matches nothing. `--testid` / `--selector` crop the same way and take `--crop-up`, but a miss exits 1 instead: an exact address that misses is a wrong address, and a full-window capture would spend ~19k tokens on it. Pass at most one of `--crop`, `--testid`, `--selector`.
163
284
 
164
285
  A text filter usually matches the text-bearing node, so cropping on a section title returns a thin strip of that title. `--crop-up <n>` climbs `n` element ancestors before cropping — use `1` (sometimes `2`) to get the surrounding card/section. When a crop comes back text-sized, the command says so on stderr.
165
286