@dyyz1993/agent-browser 0.13.2 → 0.24.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/README.md +108 -0
- package/bin/agent-browser-darwin-arm64 +0 -0
- package/bin/agent-browser-darwin-x64 +0 -0
- package/bin/agent-browser-linux-arm64 +0 -0
- package/bin/agent-browser-linux-x64 +0 -0
- package/bin/agent-browser-win32-x64.exe +0 -0
- package/dist/__tests__/e2e/utils/test-helpers.d.ts +1 -0
- package/dist/__tests__/e2e/utils/test-helpers.d.ts.map +1 -1
- package/dist/__tests__/e2e/utils/test-helpers.js +14 -1
- package/dist/__tests__/e2e/utils/test-helpers.js.map +1 -1
- package/dist/__tests__/utils/free-port.d.ts +2 -0
- package/dist/__tests__/utils/free-port.d.ts.map +1 -0
- package/dist/__tests__/utils/free-port.js +18 -0
- package/dist/__tests__/utils/free-port.js.map +1 -0
- package/dist/__tests__/utils/parseCli.d.ts.map +1 -1
- package/dist/__tests__/utils/parseCli.js +83 -9
- package/dist/__tests__/utils/parseCli.js.map +1 -1
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +298 -9
- package/dist/actions.js.map +1 -1
- package/dist/browser.d.ts +11 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +75 -19
- package/dist/browser.js.map +1 -1
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +172 -15
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/connection.d.ts +13 -0
- package/dist/cli/connection.d.ts.map +1 -1
- package/dist/cli/connection.js +137 -48
- package/dist/cli/connection.js.map +1 -1
- package/dist/cli/flags.d.ts.map +1 -1
- package/dist/cli/flags.js +0 -1
- package/dist/cli/flags.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +63 -22
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +0 -32
- package/dist/cli/output.js.map +1 -1
- package/dist/cli.js +20 -2
- package/dist/cli.js.map +1 -1
- package/dist/daemon.d.ts +1 -0
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +291 -264
- package/dist/daemon.js.map +1 -1
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +1 -1
- package/dist/diff.js.map +1 -1
- package/dist/flow/exporters/cypress.d.ts +9 -0
- package/dist/flow/exporters/cypress.d.ts.map +1 -0
- package/dist/flow/exporters/cypress.js +256 -0
- package/dist/flow/exporters/cypress.js.map +1 -0
- package/dist/flow/exporters/index.d.ts +6 -0
- package/dist/flow/exporters/index.d.ts.map +1 -0
- package/dist/flow/exporters/index.js +5 -0
- package/dist/flow/exporters/index.js.map +1 -0
- package/dist/flow/exporters/playwright.d.ts +20 -0
- package/dist/flow/exporters/playwright.d.ts.map +1 -0
- package/dist/flow/exporters/playwright.js +175 -0
- package/dist/flow/exporters/playwright.js.map +1 -0
- package/dist/flow/exporters/python.d.ts +20 -0
- package/dist/flow/exporters/python.d.ts.map +1 -0
- package/dist/flow/exporters/python.js +163 -0
- package/dist/flow/exporters/python.js.map +1 -0
- package/dist/flow/exporters/selenium.d.ts +9 -0
- package/dist/flow/exporters/selenium.d.ts.map +1 -0
- package/dist/flow/exporters/selenium.js +298 -0
- package/dist/flow/exporters/selenium.js.map +1 -0
- package/dist/flow/exporters/types.d.ts +13 -0
- package/dist/flow/exporters/types.d.ts.map +1 -0
- package/dist/flow/exporters/types.js +2 -0
- package/dist/flow/exporters/types.js.map +1 -0
- package/dist/flow/flow-executor.d.ts +57 -0
- package/dist/flow/flow-executor.d.ts.map +1 -0
- package/dist/flow/flow-executor.js +1263 -0
- package/dist/flow/flow-executor.js.map +1 -0
- package/dist/flow/index.d.ts +15 -0
- package/dist/flow/index.d.ts.map +1 -0
- package/dist/flow/index.js +10 -0
- package/dist/flow/index.js.map +1 -0
- package/dist/flow/output.d.ts +11 -0
- package/dist/flow/output.d.ts.map +1 -0
- package/dist/flow/output.js +84 -0
- package/dist/flow/output.js.map +1 -0
- package/dist/flow/plugin-system.d.ts +48 -0
- package/dist/flow/plugin-system.d.ts.map +1 -0
- package/dist/flow/plugin-system.js +132 -0
- package/dist/flow/plugin-system.js.map +1 -0
- package/dist/flow/plugins/file-output-plugin.d.ts +8 -0
- package/dist/flow/plugins/file-output-plugin.d.ts.map +1 -0
- package/dist/flow/plugins/file-output-plugin.js +31 -0
- package/dist/flow/plugins/file-output-plugin.js.map +1 -0
- package/dist/flow/plugins/index.d.ts +4 -0
- package/dist/flow/plugins/index.d.ts.map +1 -0
- package/dist/flow/plugins/index.js +4 -0
- package/dist/flow/plugins/index.js.map +1 -0
- package/dist/flow/plugins/logging-plugin.d.ts +7 -0
- package/dist/flow/plugins/logging-plugin.d.ts.map +1 -0
- package/dist/flow/plugins/logging-plugin.js +40 -0
- package/dist/flow/plugins/logging-plugin.js.map +1 -0
- package/dist/flow/plugins/webhook-plugin.d.ts +7 -0
- package/dist/flow/plugins/webhook-plugin.d.ts.map +1 -0
- package/dist/flow/plugins/webhook-plugin.js +24 -0
- package/dist/flow/plugins/webhook-plugin.js.map +1 -0
- package/dist/flow/presets/index.d.ts +10 -0
- package/dist/flow/presets/index.d.ts.map +1 -0
- package/dist/flow/presets/index.js +29 -0
- package/dist/flow/presets/index.js.map +1 -0
- package/dist/flow/recorder-to-flow.d.ts +70 -0
- package/dist/flow/recorder-to-flow.d.ts.map +1 -0
- package/dist/flow/recorder-to-flow.js +392 -0
- package/dist/flow/recorder-to-flow.js.map +1 -0
- package/dist/flow/site-manager.d.ts +24 -0
- package/dist/flow/site-manager.d.ts.map +1 -0
- package/dist/flow/site-manager.js +125 -0
- package/dist/flow/site-manager.js.map +1 -0
- package/dist/flow/types.d.ts +196 -0
- package/dist/flow/types.d.ts.map +1 -0
- package/dist/flow/types.js +2 -0
- package/dist/flow/types.js.map +1 -0
- package/dist/flow/yaml-parser.d.ts +15 -0
- package/dist/flow/yaml-parser.d.ts.map +1 -0
- package/dist/flow/yaml-parser.js +216 -0
- package/dist/flow/yaml-parser.js.map +1 -0
- package/dist/human-mouse.d.ts.map +1 -1
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +15 -11
- package/dist/protocol.js.map +1 -1
- package/dist/rc-config.d.ts.map +1 -1
- package/dist/rc-config.js +1 -2
- package/dist/rc-config.js.map +1 -1
- package/dist/recorder/inject.js +730 -332
- package/dist/snapshot-store.d.ts +83 -0
- package/dist/snapshot-store.d.ts.map +1 -0
- package/dist/snapshot-store.js +112 -0
- package/dist/snapshot-store.js.map +1 -0
- package/dist/snapshot.d.ts +6 -7
- package/dist/snapshot.d.ts.map +1 -1
- package/dist/snapshot.js +471 -17
- package/dist/snapshot.js.map +1 -1
- package/dist/stream-server-standalone.d.ts.map +1 -1
- package/dist/stream-server-standalone.js.map +1 -1
- package/dist/stream-server.d.ts.map +1 -1
- package/dist/stream-server.js +38 -13
- package/dist/stream-server.js.map +1 -1
- package/dist/test-live.js +5 -5
- package/dist/test-live.js.map +1 -1
- package/dist/types.d.ts +13 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/viewer-script.d.ts.map +1 -1
- package/dist/viewer-script.js +12 -6
- package/dist/viewer-script.js.map +1 -1
- package/package.json +18 -5
- package/skills/agent-browser/SKILL.md +151 -3
- package/dist/ios-actions.d.ts +0 -11
- package/dist/ios-actions.d.ts.map +0 -1
- package/dist/ios-actions.js +0 -228
- package/dist/ios-actions.js.map +0 -1
- package/dist/ios-manager.d.ts +0 -266
- package/dist/ios-manager.d.ts.map +0 -1
- package/dist/ios-manager.js +0 -1076
- package/dist/ios-manager.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dyyz1993/agent-browser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"description": "Headless browser automation CLI for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/daemon.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"skills"
|
|
12
12
|
],
|
|
13
13
|
"bin": {
|
|
14
|
-
"agent-browser": "./
|
|
14
|
+
"agent-browser": "./bin/agent-browser.js"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
17
|
"prepare": "husky",
|
|
@@ -27,10 +27,14 @@
|
|
|
27
27
|
"release": "npm run version:sync && npm run build && npm run build:all-platforms && npm publish",
|
|
28
28
|
"start": "node dist/daemon.js",
|
|
29
29
|
"dev": "tsx src/daemon.ts",
|
|
30
|
+
"lint": "eslint src/ --ext .ts",
|
|
31
|
+
"lint:fix": "eslint src/ --ext .ts --fix",
|
|
30
32
|
"typecheck": "tsc --noEmit",
|
|
31
33
|
"format": "prettier --write 'src/**/*.ts'",
|
|
32
34
|
"format:check": "prettier --check 'src/**/*.ts'",
|
|
33
35
|
"test": "vitest run",
|
|
36
|
+
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
37
|
+
"test:e2e": "vitest run --config vitest.integration.config.ts src/__tests__/e2e/snapshot-selector-store.e2e.test.ts",
|
|
34
38
|
"test:watch": "vitest",
|
|
35
39
|
"postinstall": "node scripts/postinstall.js",
|
|
36
40
|
"changeset": "changeset",
|
|
@@ -55,18 +59,21 @@
|
|
|
55
59
|
},
|
|
56
60
|
"homepage": "https://github.com/xuyingzhou/agent-browser#readme",
|
|
57
61
|
"dependencies": {
|
|
58
|
-
"
|
|
62
|
+
"js-yaml": "^4.1.1",
|
|
59
63
|
"playwright-core": "^1.57.0",
|
|
60
64
|
"sharp": "^0.34.5",
|
|
61
|
-
"undici": "^
|
|
62
|
-
"webdriverio": "^9.15.0",
|
|
65
|
+
"undici": "^7.25.0",
|
|
63
66
|
"ws": "^8.19.0",
|
|
64
67
|
"zod": "^3.22.4"
|
|
65
68
|
},
|
|
66
69
|
"devDependencies": {
|
|
67
70
|
"@changesets/cli": "^2.29.8",
|
|
71
|
+
"@types/js-yaml": "^4.0.9",
|
|
68
72
|
"@types/node": "^20.10.0",
|
|
69
73
|
"@types/ws": "^8.18.1",
|
|
74
|
+
"@typescript-eslint/eslint-plugin": "^8.59.2",
|
|
75
|
+
"@typescript-eslint/parser": "^8.59.2",
|
|
76
|
+
"eslint": "^10.3.0",
|
|
70
77
|
"happy-dom": "^20.7.0",
|
|
71
78
|
"husky": "^9.1.7",
|
|
72
79
|
"lint-staged": "^15.2.11",
|
|
@@ -74,6 +81,7 @@
|
|
|
74
81
|
"prettier": "^3.7.4",
|
|
75
82
|
"tsx": "^4.6.0",
|
|
76
83
|
"typescript": "^5.3.0",
|
|
84
|
+
"typescript-eslint": "^8.59.2",
|
|
77
85
|
"vitest": "^4.0.16"
|
|
78
86
|
},
|
|
79
87
|
"lint-staged": {
|
|
@@ -83,5 +91,10 @@
|
|
|
83
91
|
"doc": "docs",
|
|
84
92
|
"test": "test"
|
|
85
93
|
},
|
|
94
|
+
"pnpm": {
|
|
95
|
+
"overrides": {
|
|
96
|
+
"lodash": "^4.18.0"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
86
99
|
"author": "xuyingzhou"
|
|
87
100
|
}
|
|
@@ -83,6 +83,150 @@ agent-browser reload # Trigger requests
|
|
|
83
83
|
agent-browser network requests # Now shows captured requests
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
+
### WebSocket Monitoring
|
|
87
|
+
|
|
88
|
+
WebSocket tracking activates on first use and captures all WS connections at the CDP level (no JS injection needed, survives page navigation):
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
agent-browser network websockets # Activate tracking + show connections
|
|
92
|
+
agent-browser network websockets --json # Structured JSON output
|
|
93
|
+
agent-browser network websockets --filter "ws://" # Filter by URL
|
|
94
|
+
agent-browser network websockets --clear # Clear captured data
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Snapshot ID System
|
|
98
|
+
|
|
99
|
+
Every `snapshot -i` now returns a unique snapshot ID (snap_1, snap_2, ...) in the output. This ID is used to query stable CSS selectors for any element captured in that snapshot.
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
agent-browser snapshot -i
|
|
103
|
+
# Output includes:
|
|
104
|
+
# ## Snapshot: snap_3
|
|
105
|
+
# - searchbox "Search" [ref=e1]
|
|
106
|
+
# - button "Submit" [ref=e2]
|
|
107
|
+
# Tip: Use --selector-for snap_3:@e1 to get a stable selector
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Stable Selectors & Command History
|
|
111
|
+
|
|
112
|
+
After taking a snapshot, use the snapshot ID to query stable CSS selectors that survive across page changes (unlike refs, which are invalidated by DOM mutations). Selectors are generated using an 8-strategy algorithm that always produces the shortest, most semantically meaningful unique selector.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Get selector for a specific element (by ref)
|
|
116
|
+
agent-browser snapshot --selector-for snap_3:@e1
|
|
117
|
+
# Output: snap_3 e1 (button "Submit")
|
|
118
|
+
# CSS: #submit-btn
|
|
119
|
+
# XPath: //*[@id="submit-btn"]
|
|
120
|
+
|
|
121
|
+
# Get selector by index
|
|
122
|
+
agent-browser snapshot --selector-for snap_3:1
|
|
123
|
+
|
|
124
|
+
# List all selectors for a snapshot
|
|
125
|
+
agent-browser snapshot --selectors-of snap_3
|
|
126
|
+
# Output:
|
|
127
|
+
# [1] e1 searchbox "Search" -> #search-input
|
|
128
|
+
# [2] e2 button "Submit" -> #submit-btn
|
|
129
|
+
|
|
130
|
+
# Validate selectors still match after page changes
|
|
131
|
+
agent-browser snapshot --validate snap_3
|
|
132
|
+
# Output:
|
|
133
|
+
# [1] e1 #search-input -> valid
|
|
134
|
+
# [2] e2 #submit-btn -> not found (element removed)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Selector strategies (tried in order, first unique match wins):
|
|
138
|
+
|
|
139
|
+
1. `#id`
|
|
140
|
+
2. `[data-testid="..."]`
|
|
141
|
+
3. `tag[name="..."]`
|
|
142
|
+
4. `tag[aria-label="..."]`
|
|
143
|
+
5. `tag.semantic-class`
|
|
144
|
+
6. `tag.class[attr="..."]`
|
|
145
|
+
7. Composed path (`ancestor > tag`)
|
|
146
|
+
8. `tag:nth-child(n)` fallback
|
|
147
|
+
|
|
148
|
+
Each strategy validates uniqueness via `querySelectorAll`, ensuring the selector matches exactly one element.
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# Get recorded interaction history (auto-captured)
|
|
152
|
+
agent-browser history # Show all recorded interactions
|
|
153
|
+
agent-browser history --filter "fill" # Filter by action type
|
|
154
|
+
agent-browser history --clear # Clear history
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Note:** `history` records `fill`, `click`, `select`, `check`, `uncheck`, and `eval` commands. `eval` entries have `action: "eval"`, `selector: "javascript"`, and `value` containing the script (truncated at 200 chars). Failed eval commands are also recorded with `success: false`.
|
|
158
|
+
|
|
159
|
+
### Strict Mode Auto-Fallback
|
|
160
|
+
|
|
161
|
+
When `find text`, `find role`, or `find label` matches multiple elements, Playwright throws a "strict mode violation" error. agent-browser now automatically falls back to the first matching element instead of failing.
|
|
162
|
+
|
|
163
|
+
The command succeeds with a yellow warning in the output:
|
|
164
|
+
```
|
|
165
|
+
⚠ Matched 3 elements, used first match. Use 'find nth <index> text "X" --click' for a specific match.
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
To target a specific element, use `find nth <index> text "X" --click` or a more specific CSS selector (`#id`, `[data-testid]`).
|
|
169
|
+
|
|
170
|
+
### Self-Healing Replay
|
|
171
|
+
|
|
172
|
+
When replaying recorded flows, the engine automatically tries fallback selectors and element identity matching when the primary selector fails. This makes replays resilient to DOM changes, class renames, and structural reorganizations.
|
|
173
|
+
|
|
174
|
+
Healing strategies (tried in order):
|
|
175
|
+
|
|
176
|
+
1. **fallback** — Try the top-3 alternative selectors captured during recording
|
|
177
|
+
2. **identity_text** — Match by tagName + visible text content
|
|
178
|
+
3. **identity_attr** — Match by tagName + stable attribute combination
|
|
179
|
+
4. **identity_parent** — Match by parent signature + position
|
|
180
|
+
|
|
181
|
+
The healing log is included in flow results when `--output json` is used:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
agent-browser flow run my-site.my-flow --output json
|
|
185
|
+
# healingLog entries show which strategy succeeded and the original vs healed selector
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Script Export
|
|
189
|
+
|
|
190
|
+
Flows and recordings can be exported as standalone scripts that run without agent-browser:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# Export as Playwright TypeScript
|
|
194
|
+
agent-browser flow export recording.yaml --format playwright
|
|
195
|
+
|
|
196
|
+
# Export as Python Playwright
|
|
197
|
+
agent-browser flow export recording.yaml --format python
|
|
198
|
+
|
|
199
|
+
# With options
|
|
200
|
+
agent-browser flow export recording.yaml --format playwright --headless
|
|
201
|
+
agent-browser flow export recording.yaml --format python --base-url https://staging.example.com
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Options:
|
|
205
|
+
|
|
206
|
+
- `--format <playwright|python>` — Export format (required)
|
|
207
|
+
- `--headless` — Include headless mode in the exported script
|
|
208
|
+
- `--base-url <url>` — Override base URL in the exported script
|
|
209
|
+
|
|
210
|
+
### Enhanced Recording
|
|
211
|
+
|
|
212
|
+
The recorder captures additional metadata beyond basic selectors, enabling self-healing replay and robust script export:
|
|
213
|
+
|
|
214
|
+
- **Fallback selectors** — Top-3 alternative CSS selectors per element, so replay can recover when the primary selector breaks
|
|
215
|
+
- **Element identity** — tagName, visible text, key attributes, and parent signature for fuzzy matching
|
|
216
|
+
- **SPA URL change detection** — Tracks `pushState` and `replaceState` calls to accurately record navigation in single-page applications
|
|
217
|
+
- **DOM stability signals** — Uses MutationObserver to wait for DOM settling before capturing selectors, avoiding stale captures during dynamic rendering
|
|
218
|
+
|
|
219
|
+
### Snapshot --all (Include Visually Hidden Elements)
|
|
220
|
+
|
|
221
|
+
By default, `snapshot -i --selectors` only includes elements that are visually visible. Elements with `opacity: 0`, zero dimensions, or positioned off-screen are filtered out.
|
|
222
|
+
|
|
223
|
+
Use `--all` to include all elements present in the accessibility tree:
|
|
224
|
+
```bash
|
|
225
|
+
agent-browser snapshot -i --selectors --all
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Limitation:** Elements with `display: none` or `visibility: hidden` are excluded by Playwright's accessibility tree generator and cannot be included, even with `--all`. For such elements, use `eval` to discover them via DOM queries.
|
|
229
|
+
|
|
86
230
|
## Capabilities
|
|
87
231
|
|
|
88
232
|
| Area | Key Commands | Deep Dive |
|
|
@@ -91,7 +235,7 @@ agent-browser network requests # Now shows captured requests
|
|
|
91
235
|
| Snapshot & Element Inspection | `snapshot` | [snapshot-refs](references/snapshot-refs.md) |
|
|
92
236
|
| Finding Elements | `find by role`, `text`, `label` | [commands](references/commands.md) |
|
|
93
237
|
| Data Extraction | `eval` | [data-extraction](references/data-extraction.md) |
|
|
94
|
-
| Network Control | `request monitoring`, `API mocking`, `URL blocking` | [network-monitoring](references/network-monitoring.md) |
|
|
238
|
+
| Network Control | `request monitoring`, `WebSocket monitoring`, `API mocking`, `URL blocking` | [network-monitoring](references/network-monitoring.md) |
|
|
95
239
|
| Session & State | `connect`, `close`, `cookies`, `storage`, `tab` | [session-management](references/session-management.md) |
|
|
96
240
|
| Authentication | `login flows`, `OAuth`, `2FA` | [authentication](references/authentication.md) |
|
|
97
241
|
| Recording & Replay | `record`, `recorder` | [recorder](references/recorder.md) |
|
|
@@ -104,9 +248,11 @@ agent-browser network requests # Now shows captured requests
|
|
|
104
248
|
### Core Workflow Pattern
|
|
105
249
|
|
|
106
250
|
1. `open <url>` → navigate
|
|
107
|
-
2. `snapshot -i` → get element refs (`@e1`, `@e2`, ...)
|
|
251
|
+
2. `snapshot -i` → get element refs (`@e1`, `@e2`, ...) and a snapshot ID (`snap_N`)
|
|
108
252
|
3. `fill` / `click` / `select` → interact using refs
|
|
109
|
-
4.
|
|
253
|
+
4. After page changes, `snapshot --validate snap_N` to check which selectors still work
|
|
254
|
+
5. Use `snapshot --selectors-of snap_N` to collect stable selectors for later use
|
|
255
|
+
6. Re-`snapshot -i` after significant page changes (refs are invalidated)
|
|
110
256
|
|
|
111
257
|
### Session Isolation
|
|
112
258
|
|
|
@@ -125,6 +271,8 @@ If ref errors occur unexpectedly, check whether another process is operating on
|
|
|
125
271
|
|
|
126
272
|
Refs (`@e1`, `@e2`) are **session-scoped** — valid across Bash processes within the same session, but invalidated by any page change (navigation, form submit, dynamic load). Always re-snapshot after DOM mutations. See [snapshot-refs.md](references/snapshot-refs.md).
|
|
127
273
|
|
|
274
|
+
For selectors that survive page changes, use the stable selector system (`--selector-for`, `--selectors-of`, `--validate`) with snapshot IDs. Stable selectors are CSS selectors computed once per snapshot and can be validated later even after the DOM mutates.
|
|
275
|
+
|
|
128
276
|
When multiple elements share the same role+name, each gets a unique ref with a `[nth=N]` annotation. Just use the ref — the nth index is built in:
|
|
129
277
|
|
|
130
278
|
```
|
package/dist/ios-actions.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* iOS command execution - mirrors actions.ts but for iOS Safari via Appium.
|
|
3
|
-
* Provides 1:1 command parity where possible.
|
|
4
|
-
*/
|
|
5
|
-
import type { IOSManager } from './ios-manager.js';
|
|
6
|
-
import type { Command, Response } from './types.js';
|
|
7
|
-
/**
|
|
8
|
-
* Execute a command on the iOS manager
|
|
9
|
-
*/
|
|
10
|
-
export declare function executeIOSCommand(command: Command, manager: IOSManager): Promise<Response>;
|
|
11
|
-
//# sourceMappingURL=ios-actions.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ios-actions.d.ts","sourceRoot":"","sources":["../src/ios-actions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAUpD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,CA6PhG"}
|
package/dist/ios-actions.js
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* iOS command execution - mirrors actions.ts but for iOS Safari via Appium.
|
|
3
|
-
* Provides 1:1 command parity where possible.
|
|
4
|
-
*/
|
|
5
|
-
function successResponse(id, data) {
|
|
6
|
-
return { id, success: true, data };
|
|
7
|
-
}
|
|
8
|
-
function errorResponse(id, error) {
|
|
9
|
-
return { id, success: false, error };
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Execute a command on the iOS manager
|
|
13
|
-
*/
|
|
14
|
-
export async function executeIOSCommand(command, manager) {
|
|
15
|
-
const { id, action } = command;
|
|
16
|
-
try {
|
|
17
|
-
switch (action) {
|
|
18
|
-
case 'launch': {
|
|
19
|
-
const cmd = command;
|
|
20
|
-
await manager.launch({
|
|
21
|
-
device: cmd.device,
|
|
22
|
-
udid: cmd.udid,
|
|
23
|
-
});
|
|
24
|
-
const info = manager.getDeviceInfo();
|
|
25
|
-
return successResponse(id, {
|
|
26
|
-
launched: true,
|
|
27
|
-
device: info?.name ?? 'iOS Simulator',
|
|
28
|
-
udid: info?.udid,
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
case 'navigate': {
|
|
32
|
-
const cmd = command;
|
|
33
|
-
const result = await manager.navigate(cmd.url);
|
|
34
|
-
return successResponse(id, result);
|
|
35
|
-
}
|
|
36
|
-
case 'click': {
|
|
37
|
-
const cmd = command;
|
|
38
|
-
await manager.click(cmd.selector);
|
|
39
|
-
return successResponse(id, { clicked: true });
|
|
40
|
-
}
|
|
41
|
-
case 'tap': {
|
|
42
|
-
const cmd = command;
|
|
43
|
-
await manager.tap(cmd.selector);
|
|
44
|
-
return successResponse(id, { tapped: true });
|
|
45
|
-
}
|
|
46
|
-
case 'type': {
|
|
47
|
-
const cmd = command;
|
|
48
|
-
await manager.type(cmd.selector, cmd.text, {
|
|
49
|
-
delay: cmd.delay,
|
|
50
|
-
clear: cmd.clear,
|
|
51
|
-
});
|
|
52
|
-
return successResponse(id, { typed: true });
|
|
53
|
-
}
|
|
54
|
-
case 'fill': {
|
|
55
|
-
const cmd = command;
|
|
56
|
-
await manager.fill(cmd.selector, cmd.value);
|
|
57
|
-
return successResponse(id, { filled: true });
|
|
58
|
-
}
|
|
59
|
-
case 'screenshot': {
|
|
60
|
-
const cmd = command;
|
|
61
|
-
const result = await manager.screenshot({
|
|
62
|
-
path: cmd.path,
|
|
63
|
-
fullPage: cmd.fullPage,
|
|
64
|
-
});
|
|
65
|
-
return successResponse(id, result);
|
|
66
|
-
}
|
|
67
|
-
case 'snapshot': {
|
|
68
|
-
const cmd = command;
|
|
69
|
-
const result = await manager.getSnapshot({
|
|
70
|
-
interactive: cmd.interactive,
|
|
71
|
-
});
|
|
72
|
-
return successResponse(id, { snapshot: result.tree, refs: result.refs });
|
|
73
|
-
}
|
|
74
|
-
case 'scroll': {
|
|
75
|
-
const cmd = command;
|
|
76
|
-
await manager.scroll({
|
|
77
|
-
selector: cmd.selector,
|
|
78
|
-
x: cmd.x,
|
|
79
|
-
y: cmd.y,
|
|
80
|
-
direction: cmd.direction,
|
|
81
|
-
amount: cmd.amount,
|
|
82
|
-
});
|
|
83
|
-
return successResponse(id, { scrolled: true });
|
|
84
|
-
}
|
|
85
|
-
case 'swipe': {
|
|
86
|
-
const cmd = command;
|
|
87
|
-
await manager.swipe(cmd.direction, { distance: cmd.distance });
|
|
88
|
-
return successResponse(id, { swiped: true });
|
|
89
|
-
}
|
|
90
|
-
case 'evaluate': {
|
|
91
|
-
const cmd = command;
|
|
92
|
-
const result = await manager.evaluate(cmd.script, ...(cmd.args ?? []));
|
|
93
|
-
return successResponse(id, { result });
|
|
94
|
-
}
|
|
95
|
-
case 'wait': {
|
|
96
|
-
const cmd = command;
|
|
97
|
-
await manager.wait({
|
|
98
|
-
selector: cmd.selector,
|
|
99
|
-
timeout: cmd.timeout,
|
|
100
|
-
state: cmd.state,
|
|
101
|
-
});
|
|
102
|
-
return successResponse(id, { waited: true });
|
|
103
|
-
}
|
|
104
|
-
case 'press': {
|
|
105
|
-
const cmd = command;
|
|
106
|
-
await manager.press(cmd.key);
|
|
107
|
-
return successResponse(id, { pressed: true });
|
|
108
|
-
}
|
|
109
|
-
case 'hover': {
|
|
110
|
-
const cmd = command;
|
|
111
|
-
await manager.hover(cmd.selector);
|
|
112
|
-
return successResponse(id, { hovered: true });
|
|
113
|
-
}
|
|
114
|
-
case 'content': {
|
|
115
|
-
const cmd = command;
|
|
116
|
-
const html = await manager.getContent(cmd.selector);
|
|
117
|
-
return successResponse(id, { html });
|
|
118
|
-
}
|
|
119
|
-
case 'gettext': {
|
|
120
|
-
const cmd = command;
|
|
121
|
-
const text = await manager.getText(cmd.selector);
|
|
122
|
-
return successResponse(id, { text });
|
|
123
|
-
}
|
|
124
|
-
case 'getattribute': {
|
|
125
|
-
const cmd = command;
|
|
126
|
-
const value = await manager.getAttribute(cmd.selector, cmd.attribute);
|
|
127
|
-
return successResponse(id, { value });
|
|
128
|
-
}
|
|
129
|
-
case 'isvisible': {
|
|
130
|
-
const cmd = command;
|
|
131
|
-
const visible = await manager.isVisible(cmd.selector);
|
|
132
|
-
return successResponse(id, { visible });
|
|
133
|
-
}
|
|
134
|
-
case 'isenabled': {
|
|
135
|
-
const cmd = command;
|
|
136
|
-
const enabled = await manager.isEnabled(cmd.selector);
|
|
137
|
-
return successResponse(id, { enabled });
|
|
138
|
-
}
|
|
139
|
-
case 'url': {
|
|
140
|
-
const url = await manager.getUrl();
|
|
141
|
-
return successResponse(id, { url });
|
|
142
|
-
}
|
|
143
|
-
case 'title': {
|
|
144
|
-
const title = await manager.getTitle();
|
|
145
|
-
return successResponse(id, { title });
|
|
146
|
-
}
|
|
147
|
-
case 'back': {
|
|
148
|
-
await manager.goBack();
|
|
149
|
-
return successResponse(id, { navigated: 'back' });
|
|
150
|
-
}
|
|
151
|
-
case 'forward': {
|
|
152
|
-
await manager.goForward();
|
|
153
|
-
return successResponse(id, { navigated: 'forward' });
|
|
154
|
-
}
|
|
155
|
-
case 'reload': {
|
|
156
|
-
await manager.reload();
|
|
157
|
-
return successResponse(id, { reloaded: true });
|
|
158
|
-
}
|
|
159
|
-
case 'select': {
|
|
160
|
-
const cmd = command;
|
|
161
|
-
await manager.select(cmd.selector, cmd.values);
|
|
162
|
-
return successResponse(id, { selected: true });
|
|
163
|
-
}
|
|
164
|
-
case 'check': {
|
|
165
|
-
const cmd = command;
|
|
166
|
-
await manager.check(cmd.selector);
|
|
167
|
-
return successResponse(id, { checked: true });
|
|
168
|
-
}
|
|
169
|
-
case 'uncheck': {
|
|
170
|
-
const cmd = command;
|
|
171
|
-
await manager.uncheck(cmd.selector);
|
|
172
|
-
return successResponse(id, { unchecked: true });
|
|
173
|
-
}
|
|
174
|
-
case 'focus': {
|
|
175
|
-
const cmd = command;
|
|
176
|
-
await manager.focus(cmd.selector);
|
|
177
|
-
return successResponse(id, { focused: true });
|
|
178
|
-
}
|
|
179
|
-
case 'clear': {
|
|
180
|
-
const cmd = command;
|
|
181
|
-
await manager.clear(cmd.selector);
|
|
182
|
-
return successResponse(id, { cleared: true });
|
|
183
|
-
}
|
|
184
|
-
case 'count': {
|
|
185
|
-
const cmd = command;
|
|
186
|
-
const count = await manager.count(cmd.selector);
|
|
187
|
-
return successResponse(id, { count });
|
|
188
|
-
}
|
|
189
|
-
case 'boundingbox': {
|
|
190
|
-
const cmd = command;
|
|
191
|
-
const box = await manager.getBoundingBox(cmd.selector);
|
|
192
|
-
return successResponse(id, { box });
|
|
193
|
-
}
|
|
194
|
-
case 'close': {
|
|
195
|
-
await manager.close();
|
|
196
|
-
return successResponse(id, { closed: true });
|
|
197
|
-
}
|
|
198
|
-
// iOS-specific: device list
|
|
199
|
-
case 'device_list': {
|
|
200
|
-
const devices = await manager.listDevices();
|
|
201
|
-
return successResponse(id, { devices });
|
|
202
|
-
}
|
|
203
|
-
// Commands that don't apply to iOS Safari
|
|
204
|
-
case 'tab_new':
|
|
205
|
-
case 'tab_list':
|
|
206
|
-
case 'tab_switch':
|
|
207
|
-
case 'tab_close':
|
|
208
|
-
case 'window_new':
|
|
209
|
-
return errorResponse(id, `Command '${action}' is not supported on iOS Safari. Mobile Safari does not support programmatic tab management.`);
|
|
210
|
-
case 'pdf':
|
|
211
|
-
return errorResponse(id, 'PDF generation is not supported on iOS Safari.');
|
|
212
|
-
case 'screencast_start':
|
|
213
|
-
case 'screencast_stop':
|
|
214
|
-
return errorResponse(id, 'Screencast is not supported on iOS (requires CDP).');
|
|
215
|
-
case 'recording_start':
|
|
216
|
-
case 'recording_stop':
|
|
217
|
-
case 'recording_restart':
|
|
218
|
-
return errorResponse(id, 'Video recording is not yet supported on iOS.');
|
|
219
|
-
default:
|
|
220
|
-
return errorResponse(id, `Unknown or unsupported iOS command: ${action}`);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
catch (error) {
|
|
224
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
225
|
-
return errorResponse(id, message);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
//# sourceMappingURL=ios-actions.js.map
|
package/dist/ios-actions.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ios-actions.js","sourceRoot":"","sources":["../src/ios-actions.ts"],"names":[],"mappings":"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"}
|