@swmansion/argent 0.32.0 → 0.32.1-next.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/bin/argent-android-devtools-0.3.0.apk +0 -0
- package/bin/darwin/ax-service +0 -0
- package/bin/darwin/tvos-ax-service +0 -0
- package/bin/darwin/tvos-hid-daemon +0 -0
- package/bin/network-inspector/network-inspector.jar +0 -0
- package/bin/tcp/ax-service +0 -0
- package/dist/cli-cmds.mjs +1 -1
- package/dist/installer.mjs +7 -7
- package/dist/mcp-server.mjs +1 -1
- package/dist/tool-args.generated.d.ts +178 -178
- package/dist/tool-server.cjs +1281 -1459
- package/dylibs/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/libKeyboardPatch.dylib +0 -0
- package/dylibs/libNativeDevtoolsIos.dylib +0 -0
- package/dylibs/tcp/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/tcp/libKeyboardPatch.dylib +0 -0
- package/dylibs/tcp/libNativeDevtoolsIos.dylib +0 -0
- package/dylibs/tvos/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/tvos/libKeyboardPatch.dylib +0 -0
- package/dylibs/tvos/libNativeDevtoolsIos.dylib +0 -0
- package/package.json +1 -1
- package/rules/argent.md +19 -183
- package/skills/argent-android-emulator-setup/SKILL.md +5 -13
- package/skills/argent-create-e2e/SKILL.md +1 -1
- package/skills/argent-create-e2e/references/e2e-yaml.md +12 -17
- package/skills/argent-create-e2e/references/live-authoring.md +25 -65
- package/skills/argent-create-e2e/references/reliability-and-recovery.md +8 -8
- package/skills/argent-device-interact/SKILL.md +65 -367
- package/skills/argent-device-interact/references/chromium.md +4 -19
- package/skills/argent-device-interact/references/foldables.md +8 -0
- package/skills/argent-device-interact/references/harmonyos.md +13 -50
- package/skills/argent-ios-device-interact/SKILL.md +0 -1
- package/skills/argent-ios-device-setup/SKILL.md +1 -1
- package/skills/argent-ios-simulator-setup/SKILL.md +3 -9
- package/skills/argent-lens/SKILL.md +20 -75
- package/skills/argent-metro-debugger/SKILL.md +35 -101
- package/skills/argent-native-profiler/SKILL.md +23 -92
- package/skills/argent-qa-e2e/SKILL.md +5 -5
- package/skills/argent-react-native-app-workflow/SKILL.md +34 -203
- package/skills/argent-react-native-optimization/SKILL.md +10 -26
- package/skills/argent-react-native-optimization/references/fix-reference.md +11 -11
- package/skills/argent-react-native-optimization/references/lint-rules.md +4 -5
- package/skills/argent-react-native-optimization/references/semantic-checklist.md +2 -2
- package/skills/argent-react-native-profiler/SKILL.md +46 -110
- package/skills/argent-screen-recording/SKILL.md +18 -37
- package/skills/argent-screenshot-diff/SKILL.md +8 -52
- package/skills/argent-settings-permissions/SKILL.md +15 -117
- package/skills/argent-test-ui-flow/SKILL.md +20 -90
- package/skills/argent-tv-interact/SKILL.md +9 -34
- package/skills/argent-tv-interact/references/vega.md +23 -0
- package/agents/argent-environment-inspector.md +0 -107
- package/agents/references/quality-control-checklist.md +0 -45
- package/skills/argent-device-interact/references/gesture-examples.md +0 -114
- package/skills/argent-device-interact/references/secrets.md +0 -23
- package/skills/argent-metro-debugger/references/failure-scenarios.md +0 -14
- package/skills/argent-metro-debugger/references/source-maps.md +0 -27
- package/skills/argent-react-native-profiler/references/diagnostic-tools.md +0 -101
|
@@ -1,401 +1,99 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: argent-device-interact
|
|
3
|
-
description: Interact with an iOS simulator, Android emulator, or Chromium (CDP) app using argent MCP tools. Use when tapping UI elements, performing gestures, scrolling/swiping, typing text, pressing hardware buttons, launching apps, opening URLs, taking screenshots, waiting for an element to appear or disappear, or checking visible app state after interactions. Not for TV targets.
|
|
3
|
+
description: Interact with an iOS simulator or iPhone, Android emulator or phone, or Chromium (CDP) app using argent MCP tools. Use when tapping UI elements, performing gestures, scrolling/swiping, typing text, pressing hardware buttons, launching apps, opening URLs, taking screenshots, waiting for an element to appear or disappear, or checking visible app state after interactions. Not for TV targets.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
All interaction tools below accept a `udid` parameter and auto-dispatch iOS vs Android based on its shape (UUID → iOS simulator, `chromium-cdp-<port>` → Chromium (CDP) app, anything else → Android adb serial). You use the same tool names on every platform.
|
|
9
|
-
|
|
10
|
-
**Chromium (CDP) app** = an Electron app or a Chromium-family browser (Chrome/Brave/Edge) exposing a Chrome DevTools Protocol endpoint. The same describe/tap/keyboard/screenshot surface drives it, but scrolling, tabs, cookies and storage differ: **read `references/chromium.md` before driving a `chromium` target.**
|
|
6
|
+
Each tool's own description carries its parameters, defaults, return shape and examples. This skill covers choosing between tools and the gotchas those descriptions don't state.
|
|
11
7
|
|
|
12
8
|
## 1. Before You Start
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
## 2. Best Practices
|
|
21
|
-
|
|
22
|
-
1. **Always refer to tapping_rule** from your argent.md rule before tapping.
|
|
23
|
-
2. Before performing interactions, consider whether they can be **dispatched sequentially** - more on that in `run-sequence`.
|
|
24
|
-
3. **Use `gesture-swipe` for lists/scrolling**, not `gesture-custom`, unless you need non-linear movement. On Chromium use `gesture-scroll` instead; `gesture-swipe` is touch-only. Consider whether you need multiple swipes, if yes - use `run-sequence`. Pass `momentum: false` when the swipe should decelerate before ending for a precise movement.
|
|
25
|
-
4. **Tap a text field before typing**, then use `keyboard` to enter text.
|
|
26
|
-
5. **Coordinates are normalized**: always 0.0–1.0, not pixels.
|
|
27
|
-
6. **For app navigation, use the element tree returned after each action** (`--- Elements after action (describe) ---`); call `describe` only when no fresh tree is available for the current screen. It works on any screen without app restart. Do not navigate from screenshot pixels on regular in-app screens unless the tree failed to expose a reliable target. Use `native-describe-screen` only when you need app-scoped UIKit properties.
|
|
28
|
-
|
|
29
|
-
## 3. Opening Apps
|
|
30
|
-
|
|
31
|
-
**Never navigate to an app by tapping home-screen icons.** Use `launch-app` or `open-url`: they are instant and reliable.
|
|
32
|
-
|
|
33
|
-
### launch-app: by bundle ID
|
|
34
|
-
|
|
35
|
-
```json
|
|
36
|
-
{ "udid": "<UDID>", "bundleId": "com.apple.MobileSMS" }
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
Common IDs: `com.apple.MobileSMS` (Messages), `com.apple.mobilesafari` (Safari), `com.apple.Preferences` (Settings), `com.apple.Maps`, `com.apple.mobileslideshow` (Photos), `com.apple.MobileAddressBook` (Contacts)
|
|
40
|
-
|
|
41
|
-
### open-url: by URL scheme
|
|
42
|
-
|
|
43
|
-
```json
|
|
44
|
-
{ "udid": "<UDID>", "url": "messages://" }
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
Common schemes: `messages://`, `settings://`, `maps://?q=<query>`, `tel://<number>`, `mailto:<address>`, `https://...` (Safari)
|
|
48
|
-
|
|
49
|
-
## 4. Choosing the Right Tool
|
|
50
|
-
|
|
51
|
-
| Action | Tool | Notes |
|
|
52
|
-
| ----------------- | ------------------- | ----------------------------------------------------------------- |
|
|
53
|
-
| Multiple actions | `run-sequence` | Batch steps in one call (no intermediate screenshots) |
|
|
54
|
-
| Open an app | `launch-app` | **Always: never tap home-screen icons** |
|
|
55
|
-
| Restart an app | `restart-app` | Terminate and relaunch by bundle ID |
|
|
56
|
-
| Open URL/scheme | `open-url` | Web pages, deep links, URL schemes |
|
|
57
|
-
| Single tap | `gesture-tap` | Buttons, links, checkboxes |
|
|
58
|
-
| Scroll/swipe | `gesture-swipe` | Straight-line scroll or swipe |
|
|
59
|
-
| Scroll (Chromium) | `gesture-scroll` | Wheel-based; deltas are window fractions, positive deltaY = down |
|
|
60
|
-
| Drag (Chromium) | `gesture-drag` | Sliders, drag-and-drop, text selection |
|
|
61
|
-
| Long press | `gesture-custom` | Context menus, drag start |
|
|
62
|
-
| Drag & drop | `gesture-custom` | Complex drag interactions |
|
|
63
|
-
| Pinch/zoom | `gesture-pinch` | Two-finger pinch with auto-interpolation |
|
|
64
|
-
| Rotation | `gesture-rotate` | Two-finger rotation with auto-interpolation |
|
|
65
|
-
| Custom gesture | `gesture-custom` | Arbitrary touch sequences, optional interpolation |
|
|
66
|
-
| Hardware key | `button` | Home, back, power, volume, appSwitch, actionButton |
|
|
67
|
-
| Type text | `keyboard` | Every platform. Text or one named key per call, never both |
|
|
68
|
-
| Paste text | `paste` | Only where a user would paste (OTP code, long link). Sim/emu only |
|
|
69
|
-
| Rotate device | `rotate` | Orientation changes |
|
|
70
|
-
| Fold device | `fold` | Foldable simulator/emulator: closed / half-open / open, or angle |
|
|
71
|
-
| Shake device | `shake` | Shake handlers (sim/emu only), Undo-typing prompt, RN dev menu |
|
|
72
|
-
| Wait for UI | `await-ui-element` | Block until an element is visible/hidden/exists/contains text |
|
|
73
|
-
| Wait for idle | `await-screen-idle` | Block until a non-empty screen tree stops changing |
|
|
74
|
-
|
|
75
|
-
## 5. Finding Tap Targets
|
|
76
|
-
|
|
77
|
-
IMPORTANT. When moved to a different screen after an action or do not know the coordinates of component, **always** perform proper discovery first.
|
|
78
|
-
|
|
79
|
-
| App type | Discovery tool | What it returns |
|
|
80
|
-
| --------------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
81
|
-
| Target app discovery | `describe` | Accessibility element tree for the current device screen (iOS AX-service, Android uiautomator, or Chromium DOM walker) with normalized frame coordinates. Works on any app, system dialogs, and Home screen; no app restart or `bundleId` required |
|
|
82
|
-
| React Native | `debugger-component-tree` | React component tree with names, text, testID, and (tap: x,y) |
|
|
83
|
-
| App-scoped native | `native-describe-screen` | Low-level app-scoped accessibility elements with normalized and raw coordinates; requires `bundleId` |
|
|
84
|
-
| Permission / system modal overlay | `describe` | `describe` detects system dialogs automatically and returns dialog buttons with tap coordinates. Fall back to `screenshot` only if `describe` does not expose the controls |
|
|
85
|
-
| Final visual fallback | `screenshot` | Use only when discovery tools cannot inspect the current UI reliably. Do not derive routine in-app navigation targets from screenshots |
|
|
86
|
-
|
|
87
|
-
Point follow-up native diagnostics after you already have a candidate point:
|
|
88
|
-
|
|
89
|
-
- `native-user-interactable-view-at-point`: deepest native view that would receive touch at a known raw iOS point; requires `bundleId`
|
|
90
|
-
- `native-view-at-point`: deepest visible native view at a known raw iOS point; requires `bundleId`
|
|
91
|
-
|
|
92
|
-
### If `describe` Tool Fails
|
|
93
|
-
|
|
94
|
-
Read the exact error and choose the action that matches it:
|
|
95
|
-
|
|
96
|
-
- Error mentions `ax-service` not available or daemon startup failure:
|
|
97
|
-
the ax-service daemon could not start. Check that the simulator is booted. Use `screenshot` as a temporary fallback, or use `native-describe-screen` with an explicit `bundleId` if the app has native devtools injected.
|
|
98
|
-
- `describe` returns an empty element list:
|
|
99
|
-
the screen may be blank, loading, or showing content without accessibility labels. Use `screenshot` to see what is visible, then retry after the content has loaded.
|
|
100
|
-
- `describe` succeeds but is not detailed enough for a React Native app:
|
|
101
|
-
use `debugger-component-tree` next.
|
|
102
|
-
- You need app-scoped inspection with full UIKit properties (`accessibilityIdentifier`, `viewClassName`):
|
|
103
|
-
use `native-describe-screen` with an explicit `bundleId`. This requires native devtools (dylib) injection.
|
|
104
|
-
- You already have a candidate point and want to confirm what would actually receive touch:
|
|
105
|
-
use `native-user-interactable-view-at-point`. Use `native-view-at-point` when you want the visually deepest view instead of the hit-test target.
|
|
106
|
-
|
|
107
|
-
## 6. Tool Usage
|
|
108
|
-
|
|
109
|
-
### gesture-tap: Single tap at a point
|
|
110
|
-
|
|
111
|
-
```json
|
|
112
|
-
{ "udid": "<UDID>", "x": 0.5, "y": 0.5 }
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
Coordinates: `0.0` = left/top, `1.0` = right/bottom.
|
|
116
|
-
|
|
117
|
-
Before tapping near the bottom of the screen in React Native apps, check that "Open Debugger to View Warnings" banners are not visible: tapping them breaks the debugger connection. Close them with the X icon if present.
|
|
118
|
-
|
|
119
|
-
### gesture-swipe: Straight-line gesture
|
|
120
|
-
|
|
121
|
-
```json
|
|
122
|
-
{ "udid": "<UDID>", "fromX": 0.5, "fromY": 0.7, "toX": 0.5, "toY": 0.3 }
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
Swipe **up** (`fromY > toY`) = scroll content **down**. Default duration: 300ms. Optional: `"durationMs": 500` for slower swipe.
|
|
126
|
-
|
|
127
|
-
`"momentum"` defaults to `true` (a natural flinging swipe). Pass `"momentum": false` for a momentum-free swipe: the finger decelerates into the end point, resulting in little to no fling. It needs `durationMs` of at least 150 and is rejected below it.
|
|
128
|
-
|
|
129
|
-
### gesture-pinch: Two-finger pinch
|
|
130
|
-
|
|
131
|
-
```json
|
|
132
|
-
{ "udid": "<UDID>", "centerX": 0.5, "centerY": 0.5, "startDistance": 0.2, "endDistance": 0.6 }
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
All values are normalized 0.0–1.0 (fractions of screen, not pixels), same as all other gesture tools. `startDistance: 0.2` means fingers start 20% of the screen apart; `endDistance: 0.6` means they end 60% apart. `startDistance < endDistance` = pinch out (zoom in). `startDistance > endDistance` = pinch in (zoom out). Defaults: `angle: 0` (horizontal), `durationMs: 300`. Optional: `"angle": 90` for vertical axis, `"durationMs": 500` for slower pinch, `"endCenterX"`/`"endCenterY"` to let the centroid drift to a new center over the gesture (omitted = fixed center).
|
|
136
|
-
|
|
137
|
-
### gesture-rotate: Two-finger rotation
|
|
138
|
-
|
|
139
|
-
```json
|
|
140
|
-
{
|
|
141
|
-
"udid": "<UDID>",
|
|
142
|
-
"centerX": 0.5,
|
|
143
|
-
"centerY": 0.5,
|
|
144
|
-
"radius": 0.15,
|
|
145
|
-
"startAngle": 0,
|
|
146
|
-
"endAngle": 90
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
All positions and radii are normalized 0.0–1.0 (fractions of screen, not pixels). `radius: 0.15` means each finger is 15% of the screen away from center. `endAngle > startAngle` = clockwise. Default duration: 300ms. Optional: `"durationMs": 500` for slower rotation, and `"radiusX"`/`"radiusY"` (fractions of screen width/height; give both: they override `radius`) with `radiusX·width = radiusY·height` for a physically circular orbit; a single `radius` traces a physical ellipse on a non-square screen, coupling a slight pinch into the turn.
|
|
151
|
-
|
|
152
|
-
### gesture-custom: Custom touch sequence
|
|
153
|
-
|
|
154
|
-
For long-press, drag-and-drop, and other complex sequences, see `references/gesture-examples.md`. Set `"interpolate": 10` to auto-generate smooth intermediate Move events between keyframes.
|
|
155
|
-
|
|
156
|
-
### button: Hardware button press
|
|
157
|
-
|
|
158
|
-
```json
|
|
159
|
-
{ "udid": "<UDID>", "button": "home" }
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
Values: `home`, `back`, `power`, `volumeUp`, `volumeDown`, `appSwitch`, `actionButton`
|
|
163
|
-
|
|
164
|
-
### keyboard: Type text or press special keys
|
|
165
|
-
|
|
166
|
-
```json
|
|
167
|
-
{ "udid": "<UDID>", "text": "search query" }
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
One call does one action. `text` and `key` are mutually exclusive, and a call that carries both is rejected with nothing typed. To type and then submit, send two `keyboard` steps in one `run-sequence` (§ 8): `{ "text": "search query" }`, then `{ "key": "enter" }`. Two separate calls do the same work, but cost an extra round-trip.
|
|
171
|
-
|
|
172
|
-
**React Native: the first tap after typing may only close the keyboard.** Inside a scroll view with the default `keyboardShouldPersistTaps="never"`, React Native uses a tap outside the focused field to dismiss the keyboard and does not pass it on (with `"handled"` or `"always"` the tap reaches the button), so a button tapped right after typing may need a second tap; check the returned tree. When the field submits on return, `{ "key": "enter" }` avoids the extra tap.
|
|
173
|
-
|
|
174
|
-
Special keys: `enter`, `escape`, `backspace`, `tab`, `space`, `arrow-up`, `arrow-down`, `arrow-left`, `arrow-right`, `f1`–`f12`. Optional: `"delayMs": 100` between keystrokes (default 50ms); applies to the iOS simulator and Chromium; it is ignored on Android phones/tablets (typed via `adb input text`, no per-key cadence), on Vega, and on TV targets.
|
|
175
|
-
|
|
176
|
-
**Typing secrets.** To enter a credential without its plaintext ever entering your context, transcript, or logs, use a secret placeholder in `text` (works in `keyboard`, `paste`, `run-sequence` keyboard steps, and e2e `type` steps):
|
|
10
|
+
- Get a target id from `list-devices`; if none is ready, `boot-device` one. Full setup flow: `argent-ios-simulator-setup` / `argent-ios-device-setup` / `argent-android-emulator-setup`. The same tool names drive iOS, Android and Chromium; each takes the `udid` from `list-devices`.
|
|
11
|
+
- Physical iPhone (`kind: "device"`): read `argent-ios-device-interact` first. Only the tools it lists exist there, and `describe` sees only the app `launch-app` registered.
|
|
12
|
+
- Read the matching reference before driving these targets: `references/chromium.md` for a `chromium` target, `references/harmonyos.md` for a `harmony` target, `references/foldables.md` for a device `list-devices` marks `foldable: true` (or before calling `fold`).
|
|
13
|
+
- Load a deferred tool's schema with ToolSearch before its first call (e.g. `gesture-pinch`, `gesture-rotate`, `gesture-custom`); without it, numbers go out as strings and fail validation.
|
|
14
|
+
- If you delegate device tasks to sub-agents, make sure they have MCP permissions.
|
|
177
15
|
|
|
178
|
-
|
|
179
|
-
{ "udid": "<UDID>", "text": "{{secret:APP_PASSWORD}}" }
|
|
180
|
-
```
|
|
16
|
+
## 2. Choosing the Right Tool
|
|
181
17
|
|
|
182
|
-
|
|
18
|
+
| Action | Tool | Notes |
|
|
19
|
+
| ------------------------------ | ------------------- | -------------------------------------------------------------- |
|
|
20
|
+
| Several known steps | `run-sequence` | One call, one screenshot at the end (§5) |
|
|
21
|
+
| Open an app | `launch-app` | **Never tap home-screen icons** |
|
|
22
|
+
| Restart an app | `restart-app` | Clean in-memory state |
|
|
23
|
+
| Open URL / deep link | `open-url` | Web pages, deep links, URL schemes |
|
|
24
|
+
| Tap | `gesture-tap` | Buttons, links, checkboxes |
|
|
25
|
+
| Scroll / swipe | `gesture-swipe` | Touch targets; not Chromium |
|
|
26
|
+
| Scroll (Chromium) | `gesture-scroll` | Mouse wheel |
|
|
27
|
+
| Drag (Chromium) | `gesture-drag` | Sliders, drag-and-drop, text selection |
|
|
28
|
+
| Long press, drag & drop | `gesture-custom` | Also any other non-linear touch sequence |
|
|
29
|
+
| Pinch / zoom | `gesture-pinch` | |
|
|
30
|
+
| Two-finger rotation | `gesture-rotate` | |
|
|
31
|
+
| Hardware key | `button` | Home, back, power, volume, appSwitch, actionButton |
|
|
32
|
+
| Type text or press a named key | `keyboard` | Every platform; text or one key per call (§6) |
|
|
33
|
+
| Paste text | `paste` | Only where a user would paste (§6). Sim/emu only |
|
|
34
|
+
| Rotate device | `rotate` | Orientation changes |
|
|
35
|
+
| Fold device | `fold` | Foldables only: `references/foldables.md` |
|
|
36
|
+
| Shake device | `shake` | Shake handlers (sim/emu only), Undo-typing prompt, RN dev menu |
|
|
37
|
+
| Wait for UI | `await-ui-element` | Block until an element is visible/hidden/exists/contains text |
|
|
38
|
+
| Wait for idle | `await-screen-idle` | Block until a non-empty screen tree stops changing (§4) |
|
|
183
39
|
|
|
184
|
-
|
|
40
|
+
## 3. Finding Tap Targets
|
|
185
41
|
|
|
186
|
-
|
|
187
|
-
{ "udid": "<UDID>", "text": "482913" }
|
|
188
|
-
```
|
|
42
|
+
After an action moves you to a different screen, or whenever you don't know an element's coordinates, discover before tapping. Interaction results already carry the element tree (`--- Elements after action (describe) ---`): use it, and call a discovery tool only when no fresh tree covers the current screen.
|
|
189
43
|
|
|
190
|
-
|
|
44
|
+
| Need | Tool |
|
|
45
|
+
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
46
|
+
| Any screen: app, system dialog, Home screen | `describe` |
|
|
47
|
+
| App-scoped UIKit properties (iOS simulator) | `native-describe-screen` (needs `bundleId`) |
|
|
48
|
+
| What sits at a known raw point (iOS simulator) | `native-user-interactable-view-at-point` (the view that receives touch) or `native-view-at-point` (the visually deepest view) |
|
|
49
|
+
| Final visual fallback | `screenshot`, only when the tools above cannot expose the control. Do not derive routine in-app navigation targets from pixels |
|
|
191
50
|
|
|
192
|
-
|
|
51
|
+
If `describe` returns an empty tree, follow its `hint`; with no hint, the screen is blank, loading or unlabeled: check the attached screenshot and retry once content has loaded.
|
|
193
52
|
|
|
194
|
-
|
|
53
|
+
For a React Native testID or component name that `describe` does not show, use `debugger-component-tree`; take tap points from `describe`.
|
|
195
54
|
|
|
196
|
-
|
|
55
|
+
**React Native:** LogBox toasts sit over the bottom of the screen and catch taps meant for what is under them. Argent hides them when a `debugger-*` tool connects and after `debugger-reload-metro`; after `restart-app`, call a `debugger-*` tool again. After any other reload they come back: close each by tapping the right end of its `describe` frame (the X), not its middle.
|
|
197
56
|
|
|
198
|
-
|
|
199
|
-
{ "udid": "<UDID>", "orientation": "LandscapeLeft" }
|
|
200
|
-
```
|
|
57
|
+
**System and permission dialogs:** on a simulator or emulator, `describe` returns a visible dialog's buttons with tap coordinates; keep using it for in-app modals too. Fall back to `screenshot` only if it does not expose the controls: then tap one obvious button (`Allow`, `OK`, `Don't Allow`, `Not Now`, `Continue`) at a time, check the returned screenshot, and go back to `describe` once the dialog is gone.
|
|
201
58
|
|
|
202
|
-
|
|
59
|
+
> **Prefer the dialog over the Settings tool.** When the app triggers its own permission prompt, answering it is the real user path. Use `settings-permissions` only when you can't make the change through the app: set a permission _before_ the app asks, re-enable one the user denied (iOS won't re-prompt), or reset it so the prompt reappears. See `argent-settings-permissions`.
|
|
203
60
|
|
|
204
|
-
|
|
61
|
+
## 4. Waiting: `await-ui-element` and `await-screen-idle`
|
|
205
62
|
|
|
206
|
-
|
|
63
|
+
**Never poll `screenshot`/`describe` in a loop to wait for something.** `await-ui-element` blocks server-side on the same tree `describe` reads. It has no bare-timer mode; for a plain pause, use your own harness sleep. Its description covers conditions, selector matching and defaults. What it does not tell you:
|
|
207
64
|
|
|
208
|
-
|
|
209
|
-
{ "udid": "<UDID>", "posture": "open" }
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
Give `posture` (`closed`, `half-open` or `open`) or `angle` (0–180). Do not give both.
|
|
213
|
-
|
|
214
|
-
Use `fold` only on a foldable iOS simulator (the iPhone Duo) or Android emulator (a Pixel Fold or generic foldable AVD). `list-devices` marks them with `foldable: true`. Other devices reject the call.
|
|
215
|
-
|
|
216
|
-
Closed, the cover panel shows the UI. Half-open and open, the inner panel shows the UI. All tools use the active panel (the panel that shows the UI), also after a fold made outside argent. `fold` returns when the device accepts input again, so the next tap lands. This is also true for the next step in `run-sequence`.
|
|
217
|
-
|
|
218
|
-
Rules:
|
|
219
|
-
|
|
220
|
-
- The coordinates change with the panel. Before you tap, read the element tree in the `fold` result, or run `describe` again. Do not use frames from before the fold.
|
|
221
|
-
- The screenshot size changes with the panel. Keep one screenshot-diff baseline for each posture.
|
|
222
|
-
- iOS: unfolded, the UI is landscape. The screenshot shows the UI turned 90 degrees, and the `describe` frames use the same axes, as on a rotated iPhone.
|
|
223
|
-
- iOS: a fold between two angles that are not 0 or 180 can keep the current panel. The result names the active panel. To change panels, fold to `closed` or `open`.
|
|
224
|
-
- Fold between gestures, not during a gesture. A gesture stays on the panel where it started.
|
|
225
|
-
- Android: the result gives `deviceState` (`CLOSED`, `HALF_OPENED`, `OPENED`). A lock screen that the fold to closed shows is dismissed; a `warning` says when it cannot be, or when a lock screen is up after the fold. Unlock the device before the next action.
|
|
226
|
-
- Android: only a Pixel Fold AVD has a cover panel. When a generic foldable AVD is closed, the emulator shows only the left part of the display. `describe` frames do not match tap coordinates. Argent can reliably tap only an element that covers the visible part, for example a full-width row. Use a Pixel Fold AVD to test the cover panel.
|
|
227
|
-
- iOS: if argent cannot find the active panel, it uses the cover panel. The tool result then has a `warning`, and a screenshot-diff summary has a `panel:` line. Take a screenshot to see what the device shows, then do the check that the warning gives.
|
|
228
|
-
|
|
229
|
-
### await-ui-element: Block until a UI element reaches a state
|
|
230
|
-
|
|
231
|
-
**Never poll `screenshot`/`describe` in a loop to wait for something.** Use `await-ui-element`: it blocks server-side on the same tree `describe` reads. It has no bare-timer mode by design; for a plain pause, use your own harness sleep.
|
|
232
|
-
|
|
233
|
-
```json
|
|
234
|
-
{ "udid": "<UDID>", "condition": "visible", "selector": { "text": "Continue" } }
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
The tool's own description carries the conditions, selector matching, defaults and return shape. What it does not tell you:
|
|
238
|
-
|
|
239
|
-
- A `hidden` check that succeeds **immediately** may be a false pass: its `note` then says the selector never matched anything at all. Treat that as a failed check and fix the selector; do not read it as "the element went away".
|
|
65
|
+
- A `hidden` check that succeeds **immediately** may be a false pass: its `note` then says the selector never matched anything. Treat that as a failed check and fix the selector; it does not mean "the element went away".
|
|
240
66
|
- The synthetic `ROOT` container `describe` prints is never matched, so a `role` like `AXGroup`/`html` won't trivially "match the screen".
|
|
241
|
-
- To disambiguate a loose selector, pin
|
|
242
|
-
- On a `text` timeout the `note` quotes the text of the element the check actually read, so you can see which match it landed on.
|
|
243
|
-
|
|
244
|
-
### await-screen-idle: Block until the screen stops changing
|
|
245
|
-
|
|
246
|
-
Use after launch/navigation and before a raw tap, when an early-painted element may still be moving:
|
|
247
|
-
|
|
248
|
-
```json
|
|
249
|
-
{ "udid": "<UDID>", "timeoutMs": 3000, "minStableMs": 250 }
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
On local iOS, Android, and Chromium, the tool waits for a non-empty `describe` tree to stop changing. Continue only when `settled: true`. Pair it with a destination-specific `await-ui-element`; stillness does not identify a screen.
|
|
253
|
-
|
|
254
|
-
Use it only for live diagnosis. Do not record it or put it in `run-sequence`. E2E tests use `await: { idle: true }`, which also compares pixels. This live tool can return during a presentation-layer animation.
|
|
255
|
-
|
|
256
|
-
---
|
|
257
|
-
|
|
258
|
-
## 7. Screenshots
|
|
259
|
-
|
|
260
|
-
Use the explicit `screenshot` tool only when:
|
|
261
|
-
|
|
262
|
-
- You need the initial screen state before any action.
|
|
263
|
-
- You are about to edit visible UI and need a baseline capture before making changes.
|
|
264
|
-
- The auto-attached screenshot shows a transitional or loading frame.
|
|
265
|
-
- You require extra context.
|
|
266
|
-
- You want to check state after a delay (e.g. waiting for a network response).
|
|
267
|
-
- A permission dialog, system alert, or native modal overlay is visible and `describe` did not expose reliable targets.
|
|
268
|
-
|
|
269
|
-
When using `screenshot` for permission or native modal navigation:
|
|
270
|
-
|
|
271
|
-
- Do not switch to screenshot-driven navigation just because a modal is visible. On regular app screens and in-app modals, keep using `describe`.
|
|
272
|
-
- Prefer obvious, centered alert buttons such as `Allow`, `OK`, `Don't Allow`, `Not Now`, or `Continue`.
|
|
273
|
-
- Tap one control at a time and inspect the returned auto-screenshot before doing anything else.
|
|
274
|
-
- After the modal is dismissed, return to normal discovery with `describe`, `native-describe-screen`, or `debugger-component-tree`.
|
|
275
|
-
|
|
276
|
-
> **Prefer the dialog over the Settings tool.** When the app triggers its own permission prompt, answering it here is the real user path; do that. Reach for the `settings-permissions` tool only when you can't get to the change through the app: pre-authorize/deny a permission _before_ the app asks, re-enable one the user already denied (iOS won't re-prompt), or reset it so the prompt reappears. See the `argent-settings-permissions` skill.
|
|
277
|
-
|
|
278
|
-
Optional rotation parameter: `{ "udid": "<UDID>", "rotation": "LandscapeLeft" }`: rotates the capture without changing simulator orientation.
|
|
67
|
+
- To disambiguate a loose selector, pin `role` to a text role like `StaticText`; that skips a same-named button.
|
|
279
68
|
|
|
280
|
-
|
|
69
|
+
`await-screen-idle` is for live diagnosis after a launch or navigation, before a raw tap on an element that may still be moving. Continue only when `settled: true`, and pair it with an `await-ui-element` for the destination: stillness does not identify a screen, and the tool can return during a presentation-layer animation. Do not record it in an e2e test; tests use `await: { idle: true }`, which also compares pixels.
|
|
281
70
|
|
|
282
|
-
|
|
71
|
+
## 5. Action Sequencing with `run-sequence`
|
|
283
72
|
|
|
284
|
-
|
|
285
|
-
{ "udid": "<UDID>", "scale": 1.0, "includeImageInContext": false }
|
|
286
|
-
```
|
|
73
|
+
Use `run-sequence` when every step is known in advance; if a step depends on what the previous one shows, use separate calls. Its description lists the allowed tools and their arguments. Typical batches:
|
|
287
74
|
|
|
288
|
-
|
|
75
|
+
- "scroll to bottom", "scroll until X": 3-5 swipes
|
|
76
|
+
- "clear and retype a field": triple-tap to select all, then type the new value
|
|
77
|
+
- typing then submitting: a `keyboard` text step, then a `keyboard` `enter` step (one call cannot carry both)
|
|
78
|
+
- "submit form": fill every field, then tap submit
|
|
79
|
+
- "go back to X": a known tap path
|
|
289
80
|
|
|
290
|
-
|
|
81
|
+
Gate a step that depends on a screen transition with an `await-ui-element` step rather than a fixed `delayMs`. If its condition is not met before the timeout, the sequence **stops there** and the later steps do not run, so a tap can't fire against a screen that never appeared. Any failing step also stops the sequence, with partial results.
|
|
291
82
|
|
|
292
|
-
|
|
293
|
-
| ----------------------- | ------------------------------------------------------------- |
|
|
294
|
-
| Screenshot times out | Restart the simulator-server via `stop-simulator-server` tool |
|
|
295
|
-
| No booted iOS simulator | Call `boot-device` with the iOS `udid` |
|
|
296
|
-
| No ready Android device | Call `boot-device` with `avdName` |
|
|
83
|
+
## 6. Text Entry and Secrets
|
|
297
84
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
Use `run-sequence` to batch multiple interaction steps into **a single tool call**. Only one screenshot is returned, after all steps complete.
|
|
303
|
-
|
|
304
|
-
Do **not** use `run-sequence` when any step depends on observing the result of a previous step.
|
|
305
|
-
|
|
306
|
-
### Use cases
|
|
307
|
-
|
|
308
|
-
- "scroll to bottom", "scroll to top", "scroll until X" -> sequence 3-5 scrolls
|
|
309
|
-
- form interactions, "clear and retype field" -> triple-tap to select all, then type the new value
|
|
310
|
-
- "submit form" → fill all fields in sequence, tap submit
|
|
311
|
-
- "go back to X" → defined tap sequence for the navigation
|
|
312
|
-
|
|
313
|
-
### Allowed tools inside `run-sequence`
|
|
314
|
-
|
|
315
|
-
`gesture-tap`, `gesture-swipe`, `gesture-scroll`, `gesture-drag`, `gesture-custom`, `gesture-pinch`, `gesture-rotate`, `button`, `keyboard`, `paste`, `rotate`, `shake`, `fold`, `tv-remote`, `await-ui-element`
|
|
316
|
-
|
|
317
|
-
The `udid` is shared; do **not** include it in each step's `args`. Optional `delayMs` per step (default 100ms).
|
|
318
|
-
|
|
319
|
-
Add an `await-ui-element` step to gate a later tap on a screen transition (e.g. tap → wait for the next screen's button → tap it). If its condition is **not** met before the timeout, the sequence stops at that step and the following steps do **not** run, so a mistimed tap can't fire against a screen that never settled.
|
|
320
|
-
|
|
321
|
-
### Examples
|
|
322
|
-
|
|
323
|
-
Scroll down three times:
|
|
324
|
-
|
|
325
|
-
```json
|
|
326
|
-
{
|
|
327
|
-
"udid": "<UDID>",
|
|
328
|
-
"steps": [
|
|
329
|
-
{ "tool": "gesture-swipe", "args": { "fromX": 0.5, "fromY": 0.7, "toX": 0.5, "toY": 0.3 } },
|
|
330
|
-
{ "tool": "gesture-swipe", "args": { "fromX": 0.5, "fromY": 0.7, "toX": 0.5, "toY": 0.3 } },
|
|
331
|
-
{ "tool": "gesture-swipe", "args": { "fromX": 0.5, "fromY": 0.7, "toX": 0.5, "toY": 0.3 } }
|
|
332
|
-
]
|
|
333
|
-
}
|
|
334
|
-
```
|
|
85
|
+
- Tap the field first. Typing or pasting with no focused field is a silent no-op.
|
|
86
|
+
- `paste` is **not** a faster `keyboard`. `keyboard` types the way a user types and stays the default for every text entry. Use `paste` only where a real user would paste: a 2FA / OTP code from another app, a long link or token, or testing how the app handles pasted input. That it can carry text `keyboard` can't type on a platform (multi-line text, non-ASCII on Android) is not a reason on its own.
|
|
87
|
+
- **Credentials:** type them as a `{{secret:<NAME>}}` placeholder in `text` (`keyboard`, `paste`, `run-sequence` keyboard steps, e2e `type` steps), never as plaintext, and never ask the user for the value. Do **not** `describe` or `screenshot` a non-secure field you just filled with a secret: submit or navigate away first, then verify the resulting screen.
|
|
335
88
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
```json
|
|
339
|
-
{
|
|
340
|
-
"udid": "<UDID>",
|
|
341
|
-
"steps": [
|
|
342
|
-
{ "tool": "keyboard", "args": { "text": "hello world" } },
|
|
343
|
-
{ "tool": "keyboard", "args": { "key": "enter" } }
|
|
344
|
-
]
|
|
345
|
-
}
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
Tap a known button, then scroll down:
|
|
349
|
-
|
|
350
|
-
```json
|
|
351
|
-
{
|
|
352
|
-
"udid": "<UDID>",
|
|
353
|
-
"steps": [
|
|
354
|
-
{ "tool": "gesture-tap", "args": { "x": 0.5, "y": 0.15 } },
|
|
355
|
-
{
|
|
356
|
-
"tool": "gesture-swipe",
|
|
357
|
-
"args": { "fromX": 0.5, "fromY": 0.7, "toX": 0.5, "toY": 0.3 },
|
|
358
|
-
"delayMs": 300
|
|
359
|
-
}
|
|
360
|
-
]
|
|
361
|
-
}
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
Tap, wait for the next screen, then act on it: the `await-ui-element` step **gates** the tap after it:
|
|
365
|
-
|
|
366
|
-
```json
|
|
367
|
-
{
|
|
368
|
-
"udid": "<UDID>",
|
|
369
|
-
"steps": [
|
|
370
|
-
{ "tool": "gesture-tap", "args": { "x": 0.5, "y": 0.9 } },
|
|
371
|
-
{
|
|
372
|
-
"tool": "await-ui-element",
|
|
373
|
-
"args": { "condition": "visible", "selector": { "text": "Continue" } }
|
|
374
|
-
},
|
|
375
|
-
{ "tool": "gesture-tap", "args": { "x": 0.5, "y": 0.5 } }
|
|
376
|
-
]
|
|
377
|
-
}
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
Prefer this over a fixed `delayMs` when a step depends on a screen transition: it adapts to real load time, and if the condition is not met before the timeout the sequence **stops there** so the next tap can't fire against a screen that never settled.
|
|
381
|
-
|
|
382
|
-
Stops on the first error (or unmet `await-ui-element` condition) and returns partial results.
|
|
383
|
-
|
|
384
|
-
---
|
|
385
|
-
|
|
386
|
-
## 9. Platform-specific notes
|
|
387
|
-
|
|
388
|
-
### Android
|
|
89
|
+
## 7. Screenshots
|
|
389
90
|
|
|
390
|
-
|
|
391
|
-
- **First-launch permission prompts**: `reinstall-app` on Android always installs with `-g` so runtime permissions are pre-granted on first launch; no flag to pass.
|
|
392
|
-
- **Locked screen / secure surfaces**: `describe` throws a clear error if it can't capture (keyguard, DRM, Play Integrity). Unlock the device or fall back to `screenshot`.
|
|
393
|
-
- **APK vs .app in `reinstall-app`**: pass `.apk` absolute path on Android; `.app` directory on iOS.
|
|
91
|
+
Interaction tools already attach a screenshot. Call `screenshot` for the initial state, for a baseline before you change visible UI, to check state after a delay, or when the attached capture shows a transitional or loading frame.
|
|
394
92
|
|
|
395
|
-
|
|
93
|
+
Keep the default downscaled capture for UI context and state checks; do not use `scale: 1.0` as a readability or tapping aid. Full resolution is only for saving baseline/current PNGs for comparison (`scale: 1.0` with `includeImageInContext: false`); for visual regression checks use the `argent-screenshot-diff` skill.
|
|
396
94
|
|
|
397
|
-
|
|
95
|
+
If `screenshot` times out, restart the device transport with `stop-simulator-server`.
|
|
398
96
|
|
|
399
|
-
|
|
97
|
+
## 8. Android notes
|
|
400
98
|
|
|
401
|
-
|
|
99
|
+
- **First-launch permission prompts**: `reinstall-app` on Android installs with `-g`, so runtime permissions are pre-granted on first launch.
|
|
@@ -2,23 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Everything in the related SKILL.md still applies; this page covers what differs.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A Chromium (CDP) target is an Electron app or a Chromium-family browser (Chrome/Brave/Edge) exposing a Chrome DevTools Protocol endpoint. `describe`, `gesture-tap`, `keyboard` and `screenshot` work as on a phone. What differs:
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Note: a cross-process navigation (some redirects) can swap a tab's underlying CDP target; re-run `chromium-tabs action=list` to pick it up under a fresh id.
|
|
12
|
-
|
|
13
|
-
## Cookies & storage
|
|
14
|
-
|
|
15
|
-
`chromium-cookies` reads/writes cookies via the Network domain (so HttpOnly cookies are visible):
|
|
16
|
-
|
|
17
|
-
- `action=get` (optionally scoped by `url`)
|
|
18
|
-
- `set` (`name`, `value`, + `url`/`domain`, optional `secure`/`httpOnly`/`sameSite`/`expires`)
|
|
19
|
-
- `delete` (`name`)
|
|
20
|
-
- `clear` (all)
|
|
21
|
-
|
|
22
|
-
`chromium-storage` reads/writes Web Storage for the active page: `store=local|session`, `action=get` (one `key` or all entries), `set`, `remove`, `clear`.
|
|
23
|
-
|
|
24
|
-
Both are per-origin / active-tab. Handy for seeding auth before an e2e test or asserting app state after one.
|
|
7
|
+
- Scroll with `gesture-scroll` and drag with `gesture-drag`; `gesture-swipe` is touch-only.
|
|
8
|
+
- Tabs and windows: `chromium-tabs`. Every other tool acts on the **active** tab, so `select` before driving a different one. A cross-process navigation (some redirects) can swap a tab's CDP target; `list` again to pick it up under a fresh id.
|
|
9
|
+
- Cookies, HttpOnly included: `chromium-cookies`. Web Storage: `chromium-storage`. Use them to seed auth before an e2e test or assert app state after one.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Foldable Devices
|
|
2
|
+
|
|
3
|
+
Read this for a device `list-devices` marks `foldable: true`: a foldable iOS simulator (the iPhone Duo) or Android emulator. Everything in the related SKILL.md still applies, and the `fold` description covers postures, panels and the result fields. What it does not say:
|
|
4
|
+
|
|
5
|
+
- Keep one screenshot-diff baseline per posture: the screenshot size changes with the panel.
|
|
6
|
+
- Fold between gestures, not during one. A gesture stays on the panel where it started.
|
|
7
|
+
- iOS: if argent cannot find the active panel, it uses the cover panel and sets `warning` (a screenshot-diff summary gets a `panel:` line). Take a screenshot to see what the device shows, then do the check the warning names.
|
|
8
|
+
- Android: on a closed generic foldable AVD, tap only full-width rows; test the cover panel on a Pixel Fold AVD.
|