android-emu-agent 0.1.3__tar.gz

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 (50) hide show
  1. android_emu_agent-0.1.3/.gitignore +76 -0
  2. android_emu_agent-0.1.3/LICENSE +21 -0
  3. android_emu_agent-0.1.3/PKG-INFO +375 -0
  4. android_emu_agent-0.1.3/README.md +345 -0
  5. android_emu_agent-0.1.3/pyproject.toml +116 -0
  6. android_emu_agent-0.1.3/src/android_emu_agent/__init__.py +3 -0
  7. android_emu_agent-0.1.3/src/android_emu_agent/actions/__init__.py +1 -0
  8. android_emu_agent-0.1.3/src/android_emu_agent/actions/executor.py +288 -0
  9. android_emu_agent-0.1.3/src/android_emu_agent/actions/selector.py +122 -0
  10. android_emu_agent-0.1.3/src/android_emu_agent/actions/wait.py +193 -0
  11. android_emu_agent-0.1.3/src/android_emu_agent/artifacts/__init__.py +1 -0
  12. android_emu_agent-0.1.3/src/android_emu_agent/artifacts/manager.py +125 -0
  13. android_emu_agent-0.1.3/src/android_emu_agent/artifacts/py.typed +0 -0
  14. android_emu_agent-0.1.3/src/android_emu_agent/cli/__init__.py +1 -0
  15. android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/__init__.py +1 -0
  16. android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/action.py +158 -0
  17. android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/app_cmd.py +95 -0
  18. android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/artifact.py +81 -0
  19. android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/daemon.py +62 -0
  20. android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/device.py +122 -0
  21. android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/emulator.py +46 -0
  22. android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/file.py +139 -0
  23. android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/reliability.py +310 -0
  24. android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/session.py +65 -0
  25. android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/ui.py +112 -0
  26. android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/wait.py +132 -0
  27. android_emu_agent-0.1.3/src/android_emu_agent/cli/daemon_client.py +185 -0
  28. android_emu_agent-0.1.3/src/android_emu_agent/cli/main.py +52 -0
  29. android_emu_agent-0.1.3/src/android_emu_agent/cli/utils.py +171 -0
  30. android_emu_agent-0.1.3/src/android_emu_agent/daemon/__init__.py +1 -0
  31. android_emu_agent-0.1.3/src/android_emu_agent/daemon/core.py +62 -0
  32. android_emu_agent-0.1.3/src/android_emu_agent/daemon/health.py +177 -0
  33. android_emu_agent-0.1.3/src/android_emu_agent/daemon/models.py +244 -0
  34. android_emu_agent-0.1.3/src/android_emu_agent/daemon/server.py +1644 -0
  35. android_emu_agent-0.1.3/src/android_emu_agent/db/__init__.py +1 -0
  36. android_emu_agent-0.1.3/src/android_emu_agent/db/models.py +229 -0
  37. android_emu_agent-0.1.3/src/android_emu_agent/device/__init__.py +1 -0
  38. android_emu_agent-0.1.3/src/android_emu_agent/device/manager.py +522 -0
  39. android_emu_agent-0.1.3/src/android_emu_agent/device/session.py +129 -0
  40. android_emu_agent-0.1.3/src/android_emu_agent/errors.py +232 -0
  41. android_emu_agent-0.1.3/src/android_emu_agent/files/__init__.py +1 -0
  42. android_emu_agent-0.1.3/src/android_emu_agent/files/manager.py +311 -0
  43. android_emu_agent-0.1.3/src/android_emu_agent/py.typed +0 -0
  44. android_emu_agent-0.1.3/src/android_emu_agent/reliability/__init__.py +1 -0
  45. android_emu_agent-0.1.3/src/android_emu_agent/reliability/manager.py +244 -0
  46. android_emu_agent-0.1.3/src/android_emu_agent/ui/__init__.py +1 -0
  47. android_emu_agent-0.1.3/src/android_emu_agent/ui/context.py +169 -0
  48. android_emu_agent-0.1.3/src/android_emu_agent/ui/ref_resolver.py +149 -0
  49. android_emu_agent-0.1.3/src/android_emu_agent/ui/snapshotter.py +236 -0
  50. android_emu_agent-0.1.3/src/android_emu_agent/validation.py +59 -0
@@ -0,0 +1,76 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual environments
24
+ .venv/
25
+ venv/
26
+ ENV/
27
+
28
+ # uv
29
+ .python-version
30
+
31
+ # IDE
32
+ .idea/
33
+ .vscode/
34
+ .claude/
35
+ *.swp
36
+ *.swo
37
+ *~
38
+
39
+ # Node
40
+ node_modules/
41
+
42
+ # Testing
43
+ .pytest_cache/
44
+ .coverage
45
+ htmlcov/
46
+ .tox/
47
+ .nox/
48
+
49
+ # Type checking
50
+ .mypy_cache/
51
+ .dmypy.json
52
+ dmypy.json
53
+
54
+ # Ruff
55
+ .ruff_cache/
56
+
57
+ # Project specific
58
+ .android-agent/
59
+ .android-agent-artifacts/
60
+ *.db
61
+
62
+ # Logs
63
+ *.log
64
+ logs/
65
+
66
+ # Environment
67
+ .env
68
+ .env.local
69
+ .env.*.local
70
+
71
+ # OS
72
+ .DS_Store
73
+ Thumbs.db
74
+
75
+ docs/plan/
76
+ /artifacts/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Android Agent Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,375 @@
1
+ Metadata-Version: 2.4
2
+ Name: android-emu-agent
3
+ Version: 0.1.3
4
+ Summary: CLI + daemon for LLM-driven Android UI control on emulators and rooted devices
5
+ Project-URL: Homepage, https://github.com/alehkot/android-emu-agent
6
+ Author-email: Oleg Kot <kot.oleg@gmail.com>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Keywords: android,automation,llm,ui-testing
10
+ Requires-Python: >=3.11
11
+ Requires-Dist: adbutils>=2.0.0
12
+ Requires-Dist: aiosqlite>=0.19.0
13
+ Requires-Dist: fastapi>=0.128.1
14
+ Requires-Dist: httpx>=0.27.0
15
+ Requires-Dist: lxml>=5.0.0
16
+ Requires-Dist: pydantic>=2.5.0
17
+ Requires-Dist: structlog>=24.0.0
18
+ Requires-Dist: typer>=0.9.0
19
+ Requires-Dist: uiautomator2>=3.0.0
20
+ Requires-Dist: uvicorn[standard]>=0.27.0
21
+ Provides-Extra: dev
22
+ Requires-Dist: lxml-stubs>=0.5.0; extra == 'dev'
23
+ Requires-Dist: mypy>=1.8.0; extra == 'dev'
24
+ Requires-Dist: pyright>=1.1.0; extra == 'dev'
25
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
26
+ Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
27
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
28
+ Requires-Dist: ruff>=0.2.0; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # Android Emu Agent
32
+
33
+ A CLI + daemon system for LLM-driven Android UI control on emulators and rooted devices.
34
+
35
+ ## Overview
36
+
37
+ Android Emu Agent automates Android apps using a fast observe-act-verify loop:
38
+
39
+ 1. Observe: capture a compact UI snapshot (interactive elements only)
40
+ 2. Act: issue commands using ephemeral element refs like `@a1`
41
+ 3. Verify: re-snapshot when needed
42
+
43
+ The CLI is a thin client. A long-running daemon handles all device I/O.
44
+
45
+ ## Inspiration
46
+
47
+ Inspired by [agent-browser](https://github.com/vercel-labs/agent-browser), a fast headless browser
48
+ automation CLI for AI agents.
49
+
50
+ ## Requirements
51
+
52
+ - Python 3.11+
53
+ - `uv` package manager
54
+ - Android SDK with `adb` on PATH
55
+ - Android emulator or rooted device (primary target)
56
+
57
+ ## Install
58
+
59
+ ```bash
60
+ # Clone the repository
61
+ git clone https://github.com/alehkot/android-emu-agent.git
62
+ cd android-emu-agent
63
+
64
+ # Install dependencies
65
+ uv sync
66
+ ```
67
+
68
+ Inside this repo, prefer `uv run android-emu-agent <command>`.
69
+
70
+ ## Quick Start (2 minutes)
71
+
72
+ ```bash
73
+ # 1. Start the daemon (optional, CLI will auto-start by default)
74
+ uv run android-emu-agent daemon start
75
+
76
+ # 2. List connected devices
77
+ uv run android-emu-agent device list
78
+
79
+ # 3. Start a session (prints the session id)
80
+ uv run android-emu-agent session start --device emulator-5554
81
+
82
+ # 4. Take a compact snapshot and read refs
83
+ uv run android-emu-agent ui snapshot s-abc123 --format text
84
+
85
+ # 5. Tap an element using a ref
86
+ uv run android-emu-agent action tap s-abc123 @a1
87
+
88
+ # 6. Stop the session
89
+ uv run android-emu-agent session stop s-abc123
90
+ ```
91
+
92
+ Most commands accept `--json` for machine-readable output.
93
+
94
+ Example `--json` output for `session start`:
95
+
96
+ ```json
97
+ {
98
+ "status": "done",
99
+ "session_id": "s-abc123",
100
+ "device_serial": "emulator-5554",
101
+ "generation": 0
102
+ }
103
+ ```
104
+
105
+ ## Core Concepts
106
+
107
+ Sessions
108
+
109
+ - Sessions tie actions to a specific device. Most commands accept a session id.
110
+ - `session start` returns a session id. `session stop` releases it.
111
+
112
+ Snapshots and refs
113
+
114
+ - `ui snapshot` returns `@refs` that are stable only for that snapshot.
115
+ - If you get `ERR_STALE_REF`, take a new snapshot and use fresh refs.
116
+
117
+ Selectors
118
+
119
+ - `action tap` accepts an `@ref` or a selector.
120
+ - `long-tap`, `set-text`, and `clear` require an `@ref`.
121
+
122
+ Selector examples:
123
+
124
+ ```text
125
+ @a1
126
+ text:"Sign in"
127
+ id:com.example:id/login_btn
128
+ desc:"Open navigation"
129
+ coords:120,450
130
+ ```
131
+
132
+ ## Snapshot Format
133
+
134
+ Compact snapshot output includes context and interactive elements only:
135
+
136
+ ```json
137
+ {
138
+ "schema_version": 1,
139
+ "session_id": "s-abc123",
140
+ "generation": 42,
141
+ "context": {
142
+ "package": "com.example.app",
143
+ "activity": ".MainActivity",
144
+ "orientation": "PORTRAIT",
145
+ "ime_visible": false
146
+ },
147
+ "elements": [
148
+ {
149
+ "ref": "@a1",
150
+ "role": "button",
151
+ "label": "Sign in",
152
+ "resource_id": "com.example:id/login_btn",
153
+ "bounds": [100, 200, 300, 250],
154
+ "state": { "clickable": true, "enabled": true }
155
+ }
156
+ ]
157
+ }
158
+ ```
159
+
160
+ ## Daemon and State
161
+
162
+ - Socket: `/tmp/android-emu-agent.sock`
163
+ - Logs: `~/.android-emu-agent/daemon.log`
164
+ - PID file: `~/.android-emu-agent/daemon.pid`
165
+
166
+ The CLI auto-starts the daemon on first request. Use these to debug:
167
+
168
+ ```bash
169
+ uv run android-emu-agent daemon status --json
170
+ uv run android-emu-agent daemon stop
171
+ uv run android-emu-agent daemon start
172
+ ```
173
+
174
+ ## Common Workflows
175
+
176
+ Login flow
177
+
178
+ ```bash
179
+ uv run android-emu-agent app launch s-abc123 com.example.app
180
+ uv run android-emu-agent wait idle s-abc123 --timeout-ms 5000
181
+ uv run android-emu-agent ui snapshot s-abc123 --format text
182
+ uv run android-emu-agent action set-text s-abc123 @a3 "user@example.com"
183
+ uv run android-emu-agent action set-text s-abc123 @a4 "hunter2"
184
+ uv run android-emu-agent action tap s-abc123 @a5
185
+ ```
186
+
187
+ When elements are missing
188
+
189
+ ```bash
190
+ uv run android-emu-agent ui snapshot s-abc123 --full
191
+ uv run android-emu-agent wait idle s-abc123 --timeout-ms 3000
192
+ uv run android-emu-agent ui snapshot s-abc123
193
+ ```
194
+
195
+ Visual debug
196
+
197
+ ```bash
198
+ uv run android-emu-agent ui screenshot --device emulator-5554 --pull --output ./screen.png
199
+ uv run android-emu-agent artifact bundle s-abc123
200
+ ```
201
+
202
+ Emulator snapshots
203
+
204
+ ```bash
205
+ uv run android-emu-agent emulator snapshot save emulator-5554 clean
206
+ uv run android-emu-agent emulator snapshot restore emulator-5554 clean
207
+ ```
208
+
209
+ These commands require an emulator serial (`emulator-5554`). If you pass a non-emulator serial, you
210
+ will see `ERR_NOT_EMULATOR`.
211
+
212
+ ## Real Devices (Non-Root)
213
+
214
+ The project targets emulators and rooted devices, but many commands do not enforce root and can work
215
+ on real devices as long as `adb` is connected and uiautomator2 can attach (ATX server on port 7912).
216
+ In practice, these are usually safe on non-root devices:
217
+
218
+ - UI snapshots and screenshots
219
+ - Actions (tap, set-text, swipe, scroll, back/home/recents)
220
+ - Wait commands
221
+ - App list/launch/force-stop/reset/deeplink
222
+ - File `push` and `pull` to shared storage
223
+
224
+ Emulator-only commands are `emulator snapshot save|restore`. Root-required commands are listed
225
+ below.
226
+
227
+ ## Root-Required Operations
228
+
229
+ The following require a rooted device or emulator with root access:
230
+
231
+ - `reliability oom-adj`
232
+ - `reliability pull anr`
233
+ - `reliability pull tombstones`
234
+ - `reliability pull dropbox`
235
+ - `file find`
236
+ - `file list`
237
+ - `file app push`
238
+ - `file app pull`
239
+
240
+ If root is missing, you will see `ERR_PERMISSION`.
241
+
242
+ ## Artifacts
243
+
244
+ Artifacts are written to `~/.android-emu-agent/artifacts` by default.
245
+
246
+ - Reliability outputs: `~/.android-emu-agent/artifacts/reliability`
247
+ - File transfers: `~/.android-emu-agent/artifacts/files`
248
+
249
+ ## Troubleshooting
250
+
251
+ Quick checks
252
+
253
+ ```bash
254
+ uv run android-emu-agent device list
255
+ adb devices
256
+ uv run android-emu-agent daemon status --json
257
+ ```
258
+
259
+ Common errors
260
+
261
+ | Error Code | Meaning | Fix |
262
+ | --------------------- | ------------------------ | ----------------------------------------------- |
263
+ | `ERR_STALE_REF` | Ref from an old snapshot | Take a new snapshot |
264
+ | `ERR_NOT_FOUND` | Element not found | Verify screen, use `--full` or a selector |
265
+ | `ERR_BLOCKED_INPUT` | Dialog/IME blocking | `wait idle` or `back` |
266
+ | `ERR_TIMEOUT` | Wait condition not met | Increase `--timeout-ms` or check condition |
267
+ | `ERR_DEVICE_OFFLINE` | Device disconnected | Reconnect and re-run `device list` |
268
+ | `ERR_SESSION_EXPIRED` | Session is gone | Start a new session |
269
+ | `ERR_PERMISSION` | Root required | Use a rooted device/emulator |
270
+ | `ERR_ADB_NOT_FOUND` | `adb` not on PATH | Install Android SDK and ensure `adb` is on PATH |
271
+ | `ERR_ADB_COMMAND` | ADB command failed | Check device connectivity and retry |
272
+
273
+ For deeper guidance, see `skills/android-emu-agent/references/troubleshooting.md`.
274
+
275
+ ## CLI Reference
276
+
277
+ A concise command list lives at `skills/android-emu-agent/references/command-reference.md`.
278
+
279
+ If you prefer an interactive guide:
280
+
281
+ ```bash
282
+ uv run android-emu-agent --help
283
+ uv run android-emu-agent <group> --help
284
+ ```
285
+
286
+ ## Architecture
287
+
288
+ ```text
289
+ ┌─────────────────┐ Unix Socket ┌──────────────────────────────────┐
290
+ │ │ ◄────────────────► │ Daemon │
291
+ │ CLI Client │ │ ┌────────────────────────────┐ │
292
+ │ │ │ │ Device Manager │ │
293
+ └─────────────────┘ │ │ (adbutils, uiautomator2) │ │
294
+ │ └────────────────────────────┘ │
295
+ │ ┌────────────────────────────┐ │
296
+ │ │ Session Manager │ │
297
+ │ │ (refs, state, SQLite) │ │
298
+ │ └────────────────────────────┘ │
299
+ │ ┌────────────────────────────┐ │
300
+ │ │ UI Snapshotter │ │
301
+ │ │ (lxml, filtering) │ │
302
+ │ └────────────────────────────┘ │
303
+ └──────────────────────────────────┘
304
+
305
+
306
+ ┌──────────────────────────────────┐
307
+ │ Android Device/Emulator │
308
+ │ (ATX Server on port 7912) │
309
+ └──────────────────────────────────┘
310
+ ```
311
+
312
+ ## Development
313
+
314
+ ```bash
315
+ # Install with dev dependencies
316
+ uv sync --all-extras
317
+
318
+ # Run tests
319
+ uv run pytest tests/unit -v
320
+
321
+ # Run linter
322
+ uv run ruff check .
323
+
324
+ # Format code
325
+ uv run ruff format .
326
+
327
+ # Type check
328
+ uv run mypy src/
329
+
330
+ # Run all checks
331
+ ./scripts/dev.sh check
332
+ ```
333
+
334
+ ## Agent Skills
335
+
336
+ This repo ships an `android-emu-agent` skill in `skills/android-emu-agent/` for agent environments
337
+ that support skills. Use the install steps below.
338
+
339
+ ### Install for Codex
340
+
341
+ ```bash
342
+ export CODEX_HOME="$HOME/.codex"
343
+ mkdir -p "$CODEX_HOME/skills"
344
+ ln -sfn "$(pwd)/skills/android-emu-agent" "$CODEX_HOME/skills/android-emu-agent"
345
+ ```
346
+
347
+ ### Install for Claude Code
348
+
349
+ ```bash
350
+ mkdir -p ~/.claude/skills
351
+ ln -sfn "$(pwd)/skills/android-emu-agent" ~/.claude/skills/android-emu-agent
352
+ ```
353
+
354
+ If symlinks are not an option, copy the directory instead.
355
+
356
+ ### Using the Skill
357
+
358
+ After installation, the agent should be primed to start a session with your connected device before
359
+ you ask for specific actions. Begin with a direct initialization request, for example:
360
+
361
+ `I want to interact with my connected Android emulator.`
362
+
363
+ Once the agent has initialized the session, you can proceed with normal requests (snapshots,
364
+ tap/type actions, app launches, waits, etc.).
365
+
366
+ Prerequisites you may need (if the agent reports it cannot connect):
367
+
368
+ 1. Start the daemon: `uv run android-emu-agent daemon start`
369
+ 2. Confirm a device is visible: `uv run android-emu-agent device list`
370
+ 3. If needed, start a session explicitly:
371
+ `uv run android-emu-agent session start --device emulator-5554`
372
+
373
+ ## License
374
+
375
+ MIT. See `LICENSE`.