appium-session-recorder 0.0.1
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/LICENSE +21 -0
- package/README.md +362 -0
- package/bun.lock +731 -0
- package/package.json +62 -0
- package/skills/appium-cli-selector-navigator/SKILL.md +349 -0
- package/src/cli/arg-parser.ts +311 -0
- package/src/cli/commands/drive.ts +147 -0
- package/src/cli/commands/index.ts +54 -0
- package/src/cli/commands/proxy.ts +41 -0
- package/src/cli/commands/screen.ts +73 -0
- package/src/cli/commands/selectors.ts +42 -0
- package/src/cli/commands/session.ts +64 -0
- package/src/cli/commands/types.ts +11 -0
- package/src/cli/index.ts +158 -0
- package/src/cli/prompts.ts +64 -0
- package/src/cli/response.ts +44 -0
- package/src/core/appium/client.ts +248 -0
- package/src/core/index.ts +5 -0
- package/src/core/selectors/generate-candidates.ts +155 -0
- package/src/core/selectors/score-candidates.ts +184 -0
- package/src/core/types.ts +79 -0
- package/src/core/xml/parse-source.ts +197 -0
- package/src/index.ts +7 -0
- package/src/server/appium-client.ts +24 -0
- package/src/server/index.ts +6 -0
- package/src/server/interaction-recorder.ts +74 -0
- package/src/server/proxy-middleware.ts +68 -0
- package/src/server/routes.ts +53 -0
- package/src/server/server.ts +43 -0
- package/src/server/types.ts +34 -0
- package/src/ui/bun.lock +311 -0
- package/src/ui/index.html +16 -0
- package/src/ui/package.json +20 -0
- package/src/ui/src/App.css +12 -0
- package/src/ui/src/App.tsx +41 -0
- package/src/ui/src/components/ActionCarousel.css +128 -0
- package/src/ui/src/components/ActionCarousel.tsx +92 -0
- package/src/ui/src/components/Inspector.css +314 -0
- package/src/ui/src/components/Inspector.tsx +265 -0
- package/src/ui/src/components/InteractionCard.css +159 -0
- package/src/ui/src/components/InteractionCard.tsx +60 -0
- package/src/ui/src/components/MainInspector.css +304 -0
- package/src/ui/src/components/MainInspector.tsx +304 -0
- package/src/ui/src/components/Stats.css +27 -0
- package/src/ui/src/components/Timeline.css +31 -0
- package/src/ui/src/components/Timeline.tsx +37 -0
- package/src/ui/src/hooks/useInteractions.ts +73 -0
- package/src/ui/src/index.tsx +11 -0
- package/src/ui/src/services/api.ts +41 -0
- package/src/ui/src/styles/tokens.css +126 -0
- package/src/ui/src/types.ts +34 -0
- package/src/ui/src/utils/__tests__/locators.test.ts +304 -0
- package/src/ui/src/utils/__tests__/xml-parser.test.ts +326 -0
- package/src/ui/src/utils/locators.ts +14 -0
- package/src/ui/src/utils/xml-parser.ts +45 -0
- package/src/ui/tsconfig.json +34 -0
- package/src/ui/tsconfig.node.json +11 -0
- package/src/ui/vite.config.ts +22 -0
- package/tests/cli/arg-parser.test.ts +397 -0
- package/tests/cli/drive-commands.test.ts +151 -0
- package/tests/cli/selectors-best.test.ts +42 -0
- package/tests/cli/session-commands.test.ts +53 -0
- package/tests/core/selector-candidates.test.ts +83 -0
- package/tests/core/selector-scoring.test.ts +75 -0
- package/tests/core/xml-parser.test.ts +56 -0
- package/tests/server/appium-client.test.ts +229 -0
- package/tests/server/interaction-recorder.test.ts +377 -0
- package/tests/server/proxy-middleware.test.ts +343 -0
- package/tests/server/routes.test.ts +305 -0
- package/tsconfig.json +26 -0
- package/vitest.config.ts +16 -0
- package/vitest.ui.config.ts +15 -0
- package/workflow.gif +0 -0
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "appium-session-recorder",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Interactive Appium session recorder with modern UI",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"appium-recorder": "./src/index.ts"
|
|
8
|
+
},
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=18.0.0",
|
|
11
|
+
"bun": ">=1.0.0"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"appium",
|
|
15
|
+
"mobile-testing",
|
|
16
|
+
"test-automation",
|
|
17
|
+
"session-recorder",
|
|
18
|
+
"element-inspector",
|
|
19
|
+
"ios-testing",
|
|
20
|
+
"android-testing",
|
|
21
|
+
"qa-tools"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"cli": "bun run src/index.ts",
|
|
25
|
+
"dev": "bun run src/index.ts",
|
|
26
|
+
"build": "bun run build:ui && bun build src/index.ts --outdir dist --target bun",
|
|
27
|
+
"build:ui": "cd src/ui && bun run build",
|
|
28
|
+
"test": "vitest run",
|
|
29
|
+
"test:watch": "vitest",
|
|
30
|
+
"test:ui": "vitest run --config vitest.ui.config.ts",
|
|
31
|
+
"test:all": "vitest run && vitest run --config vitest.ui.config.ts",
|
|
32
|
+
"test:coverage": "vitest run --coverage"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@clack/prompts": "^1.0.0",
|
|
36
|
+
"@kobalte/core": "^0.13.11",
|
|
37
|
+
"express": "^5.2.1",
|
|
38
|
+
"fast-diff": "^1.3.0",
|
|
39
|
+
"fast-xml-parser": "^5.3.4",
|
|
40
|
+
"http-proxy-middleware": "^3.0.5",
|
|
41
|
+
"solid-js": "^1.9.11"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/bun": "^1.3.8",
|
|
45
|
+
"@types/express": "^5.0.6",
|
|
46
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
47
|
+
"jsdom": "^28.0.0",
|
|
48
|
+
"typescript": "^5.9.3",
|
|
49
|
+
"vite": "^6.3.5",
|
|
50
|
+
"vite-plugin-solid": "^2.11.10",
|
|
51
|
+
"vitest": "^4.0.18"
|
|
52
|
+
},
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
},
|
|
56
|
+
"author": "JustasMonkev <> (https://github.com/JustasMonkev)",
|
|
57
|
+
"license": "MIT",
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "git+https://github.com/JustasMonkev/appium-session-recorder"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: appium-cli-selector-navigator
|
|
3
|
+
description: Navigate apps via appium-recorder CLI with minimal round-trips. Prefer deterministic paths (direct URL navigation) before selector discovery.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Appium CLI Selector Navigator
|
|
7
|
+
|
|
8
|
+
Use this skill to perform Appium-based mobile automation from the terminal with the fewest possible LLM-to-CLI calls.
|
|
9
|
+
|
|
10
|
+
## Setup
|
|
11
|
+
|
|
12
|
+
1. **Appium server** must be running and reachable (default: `http://127.0.0.1:4723`).
|
|
13
|
+
2. **appium-recorder** must be installed.
|
|
14
|
+
3. **jq** must be available for JSON parsing.
|
|
15
|
+
4. Prepare a capabilities file (e.g., `caps.json`):
|
|
16
|
+
|
|
17
|
+
**iOS Safari:**
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"platformName": "iOS",
|
|
21
|
+
"appium:automationName": "XCUITest",
|
|
22
|
+
"appium:deviceName": "iPhone 16",
|
|
23
|
+
"appium:browserName": "Safari"
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**iOS native app:**
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"platformName": "iOS",
|
|
31
|
+
"appium:automationName": "XCUITest",
|
|
32
|
+
"appium:deviceName": "iPhone 16",
|
|
33
|
+
"appium:bundleId": "com.apple.mobilesafari"
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Android Chrome:**
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"platformName": "Android",
|
|
41
|
+
"appium:automationName": "UiAutomator2",
|
|
42
|
+
"appium:deviceName": "emulator-5554",
|
|
43
|
+
"appium:browserName": "Chrome"
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Android native app:**
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"platformName": "Android",
|
|
51
|
+
"appium:automationName": "UiAutomator2",
|
|
52
|
+
"appium:deviceName": "emulator-5554",
|
|
53
|
+
"appium:appPackage": "com.example.app",
|
|
54
|
+
"appium:appActivity": ".MainActivity"
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Capabilities can also be passed inline with `--caps-json '{"platformName":"iOS", ...}'`.
|
|
59
|
+
|
|
60
|
+
## Execution Rules
|
|
61
|
+
|
|
62
|
+
1. Write command output to files with `--output /tmp/<step>.json`.
|
|
63
|
+
2. Never print raw XML source or base64 screenshots to stdout — always parse with `jq`.
|
|
64
|
+
3. Skip `screen elements` and `selectors best` when you can guess selectors from the task context.
|
|
65
|
+
4. Retry each failed action at most twice.
|
|
66
|
+
5. Always delete the session when finished, whether the task succeeded or failed.
|
|
67
|
+
6. **Chain commands in a single bash call** using `&&` to reduce round-trips.
|
|
68
|
+
|
|
69
|
+
## Session Lifecycle
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
APPIUM_URL="http://127.0.0.1:4723"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Create session and capture ID (one bash call):**
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
appium-recorder session create \
|
|
79
|
+
--appium-url "$APPIUM_URL" \
|
|
80
|
+
--caps-file ./caps.json \
|
|
81
|
+
--output /tmp/session.json \
|
|
82
|
+
&& SESSION_ID="$(jq -r '.result.sessionId' /tmp/session.json)"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Delete session:**
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
appium-recorder session delete \
|
|
89
|
+
--appium-url "$APPIUM_URL" \
|
|
90
|
+
--session-id "$SESSION_ID" \
|
|
91
|
+
--output /tmp/session.delete.json
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Workflow Selection
|
|
95
|
+
|
|
96
|
+
Choose the simplest path that fits:
|
|
97
|
+
|
|
98
|
+
| Request type | Path |
|
|
99
|
+
|---|---|
|
|
100
|
+
| Native app with guessable labels | Direct Action Path |
|
|
101
|
+
| Open or navigate to a website | URL Fast Path |
|
|
102
|
+
| Unknown UI, no obvious selectors | Selector Discovery Path |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Direct Action Path (Preferred, 3 Bash Calls)
|
|
107
|
+
|
|
108
|
+
Use when you can infer selectors from the task description. Most native app elements use `accessibility id` matching their visible label (e.g., "Save", "Cancel", "Search", "Done", "Delete"). Chain all actions into a single bash call with `&&`:
|
|
109
|
+
|
|
110
|
+
### Bash Call 1 — Create session
|
|
111
|
+
|
|
112
|
+
See Session Lifecycle above.
|
|
113
|
+
|
|
114
|
+
### Bash Call 2 — Chain all actions
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
appium-recorder drive tap \
|
|
118
|
+
--appium-url "$APPIUM_URL" \
|
|
119
|
+
--session-id "$SESSION_ID" \
|
|
120
|
+
--using "accessibility id" \
|
|
121
|
+
--value "<BUTTON_LABEL>" \
|
|
122
|
+
--output /tmp/drive.1.json \
|
|
123
|
+
&& appium-recorder drive type \
|
|
124
|
+
--appium-url "$APPIUM_URL" \
|
|
125
|
+
--session-id "$SESSION_ID" \
|
|
126
|
+
--using "accessibility id" \
|
|
127
|
+
--value "<FIELD_LABEL>" \
|
|
128
|
+
--text "<TEXT>" \
|
|
129
|
+
--clear-first \
|
|
130
|
+
--output /tmp/drive.2.json \
|
|
131
|
+
&& appium-recorder drive tap \
|
|
132
|
+
--appium-url "$APPIUM_URL" \
|
|
133
|
+
--session-id "$SESSION_ID" \
|
|
134
|
+
--using "accessibility id" \
|
|
135
|
+
--value "<CONFIRM_LABEL>" \
|
|
136
|
+
--output /tmp/drive.3.json
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
If any step returns `ok: false`, the chain stops. Check the last output file, then fall back to the Selector Discovery Path for that step.
|
|
140
|
+
|
|
141
|
+
### Bash Call 3 — Delete session
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## URL Fast Path (3–5 CLI Commands, 2–3 Bash Calls)
|
|
146
|
+
|
|
147
|
+
Use for browser navigation. Do not run discovery commands if this path succeeds.
|
|
148
|
+
|
|
149
|
+
### Bash Call 1 — Create session
|
|
150
|
+
|
|
151
|
+
See Session Lifecycle above.
|
|
152
|
+
|
|
153
|
+
### Bash Call 2 — Type URL and verify
|
|
154
|
+
|
|
155
|
+
Try these address-field selectors in order until one succeeds:
|
|
156
|
+
|
|
157
|
+
| Priority | Strategy | Value | Platform |
|
|
158
|
+
|---|---|---|---|
|
|
159
|
+
| 1 | `id` | `URL` | iOS Safari |
|
|
160
|
+
| 2 | `accessibility id` | `Address` | iOS Safari |
|
|
161
|
+
| 3 | `accessibility id` | `TabBarItemTitle` | iOS Safari |
|
|
162
|
+
| 4 | `id` | `com.android.chrome:id/url_bar` | Android Chrome |
|
|
163
|
+
| 5 | `accessibility id` | `Search or type web address` | Android Chrome |
|
|
164
|
+
|
|
165
|
+
Append `\n` to the text to submit the URL automatically:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
appium-recorder drive type \
|
|
169
|
+
--appium-url "$APPIUM_URL" \
|
|
170
|
+
--session-id "$SESSION_ID" \
|
|
171
|
+
--using "id" \
|
|
172
|
+
--value "URL" \
|
|
173
|
+
--text "https://example.com\n" \
|
|
174
|
+
--clear-first \
|
|
175
|
+
--output /tmp/drive.type.json
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
If `ok: false`, retry with the next selector from the table. If the URL field remains active after typing, tap the Go button:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
appium-recorder drive tap \
|
|
182
|
+
--appium-url "$APPIUM_URL" \
|
|
183
|
+
--session-id "$SESSION_ID" \
|
|
184
|
+
--using "accessibility id" \
|
|
185
|
+
--value "Go" \
|
|
186
|
+
--output /tmp/drive.tap.go.json
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
To verify navigation, take a snapshot and check for the expected domain:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
appium-recorder screen snapshot \
|
|
193
|
+
--appium-url "$APPIUM_URL" \
|
|
194
|
+
--session-id "$SESSION_ID" \
|
|
195
|
+
--output /tmp/screen.snapshot.json \
|
|
196
|
+
&& jq -r '.result.source' /tmp/screen.snapshot.json | grep -c "example.com"
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Skip verification if the `drive type` command already returned `ok: true` and the task does not require confirmation.
|
|
200
|
+
|
|
201
|
+
### Bash Call 3 — Delete session
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Selector Discovery Path (Fallback)
|
|
206
|
+
|
|
207
|
+
Use when the fast path does not apply or has failed.
|
|
208
|
+
|
|
209
|
+
### Step 1 — Create session
|
|
210
|
+
|
|
211
|
+
See Session Lifecycle above.
|
|
212
|
+
|
|
213
|
+
### Step 2 — Get actionable elements and inspect them (one bash call)
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
appium-recorder screen elements \
|
|
217
|
+
--appium-url "$APPIUM_URL" \
|
|
218
|
+
--session-id "$SESSION_ID" \
|
|
219
|
+
--only-actionable \
|
|
220
|
+
--limit 80 \
|
|
221
|
+
--output /tmp/screen.elements.json \
|
|
222
|
+
&& jq -r '.result.elements[] | [.elementRef, .type, .name, .label, .resourceId] | @tsv' \
|
|
223
|
+
/tmp/screen.elements.json
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Step 3 — Get the best selector for the target element (one bash call)
|
|
227
|
+
|
|
228
|
+
Pick the `elementRef` that matches your target from Step 2, then:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
appium-recorder selectors best \
|
|
232
|
+
--appium-url "$APPIUM_URL" \
|
|
233
|
+
--session-id "$SESSION_ID" \
|
|
234
|
+
--element-ref "<ELEMENT_REF>" \
|
|
235
|
+
--output /tmp/selectors.best.json \
|
|
236
|
+
&& jq -r '.result.topSelectors[] | select(.matchCount == 1) | [.strategy, .value] | @tsv' \
|
|
237
|
+
/tmp/selectors.best.json
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Use the first selector where `matchCount` equals 1.
|
|
241
|
+
|
|
242
|
+
### Step 4 — Perform the action
|
|
243
|
+
|
|
244
|
+
**Tap:**
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
appium-recorder drive tap \
|
|
248
|
+
--appium-url "$APPIUM_URL" \
|
|
249
|
+
--session-id "$SESSION_ID" \
|
|
250
|
+
--using "<STRATEGY>" \
|
|
251
|
+
--value "<SELECTOR>" \
|
|
252
|
+
--output /tmp/drive.tap.json
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**Type:**
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
appium-recorder drive type \
|
|
259
|
+
--appium-url "$APPIUM_URL" \
|
|
260
|
+
--session-id "$SESSION_ID" \
|
|
261
|
+
--using "<STRATEGY>" \
|
|
262
|
+
--value "<SELECTOR>" \
|
|
263
|
+
--text "<TEXT>" \
|
|
264
|
+
--clear-first \
|
|
265
|
+
--output /tmp/drive.type.json
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Back:**
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
appium-recorder drive back \
|
|
272
|
+
--appium-url "$APPIUM_URL" \
|
|
273
|
+
--session-id "$SESSION_ID" \
|
|
274
|
+
--output /tmp/drive.back.json
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Swipe:**
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
appium-recorder drive swipe \
|
|
281
|
+
--appium-url "$APPIUM_URL" \
|
|
282
|
+
--session-id "$SESSION_ID" \
|
|
283
|
+
--from 500,1800 \
|
|
284
|
+
--to 500,400 \
|
|
285
|
+
--duration-ms 350 \
|
|
286
|
+
--output /tmp/drive.swipe.json
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
**Scroll:**
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
appium-recorder drive scroll \
|
|
293
|
+
--appium-url "$APPIUM_URL" \
|
|
294
|
+
--session-id "$SESSION_ID" \
|
|
295
|
+
--direction down \
|
|
296
|
+
--output /tmp/drive.scroll.json
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Directions: `up`, `down`, `left`, `right`. Optional `--duration-ms` (default 300).
|
|
300
|
+
|
|
301
|
+
### Scrolling to find elements
|
|
302
|
+
|
|
303
|
+
If an action fails with `no such element`, the target may be off-screen. Scroll down and retry:
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
appium-recorder drive scroll \
|
|
307
|
+
--appium-url "$APPIUM_URL" \
|
|
308
|
+
--session-id "$SESSION_ID" \
|
|
309
|
+
--direction down \
|
|
310
|
+
--output /tmp/drive.scroll.json \
|
|
311
|
+
&& appium-recorder drive tap \
|
|
312
|
+
--appium-url "$APPIUM_URL" \
|
|
313
|
+
--session-id "$SESSION_ID" \
|
|
314
|
+
--using "<STRATEGY>" \
|
|
315
|
+
--value "<SELECTOR>" \
|
|
316
|
+
--output /tmp/drive.tap.json
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Try scrolling up to 3 times before giving up. After each scroll, retry the original action.
|
|
320
|
+
|
|
321
|
+
### Step 5 — On failure, retry once
|
|
322
|
+
|
|
323
|
+
1. Take one snapshot to refresh state.
|
|
324
|
+
2. Try the next selector from `selectors best`.
|
|
325
|
+
3. Stop after two retries and report the blocker.
|
|
326
|
+
|
|
327
|
+
### Step 6 — Delete session
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Error Handling
|
|
332
|
+
|
|
333
|
+
- `ok: false` means the command failed. Branch on `error.code`.
|
|
334
|
+
- `no such element` or `stale element reference`: take a fresh snapshot and retry with the next selector.
|
|
335
|
+
- Connection errors: verify Appium is reachable, then retry the command once.
|
|
336
|
+
- After the retry budget is exhausted, stop and report:
|
|
337
|
+
1. Last successful step.
|
|
338
|
+
2. Last failed command and `error.code`.
|
|
339
|
+
3. Last selector attempted.
|
|
340
|
+
4. Whether session cleanup succeeded.
|
|
341
|
+
|
|
342
|
+
## Call Budget
|
|
343
|
+
|
|
344
|
+
| Path | Max CLI commands | Target bash calls |
|
|
345
|
+
|---|---|---|
|
|
346
|
+
| Direct action (chained) | N actions | 3 (create, all actions, delete) |
|
|
347
|
+
| URL fast path | 5 (create, type, [tap Go], [verify], delete) | 3 |
|
|
348
|
+
| Discovery per interaction | 4 (elements, selectors, action, [verify]) | 3 |
|
|
349
|
+
| Max retries per task | 2 | — |
|