Component: agents/linux/ — Linux in-VM agent
Python 3.12+ package that runs inside a Linux VM. Implements the
TestAnyware agent HTTP surface on port 8648 using http.server (no
framework dependency) and AT-SPI2 via python3-pyatspi for
accessibility.
Layout
agents/linux/
└── testanyware_agent/
├── __init__.py
├── __main__.py # python -m testanyware_agent
├── server.py # HTTPRequestHandler, routing
├── accessibility.py # /windows, /snapshot, /inspect, /press, ...
├── system_endpoints.py # /exec, /upload, /download, /shutdown, /health
├── tree_walker.py # AT-SPI2 tree traversal
├── query_resolver.py # ElementQuery → element resolution
├── role_mapper.py # AT-SPI role → UnifiedRole mapping
└── models.py # Request/response dataclasses
Key design notes
- No framework — deliberately uses
http.serverto keep the dependency graph tiny. Ubuntu's stock Python is the runtime. - AT-SPI2 + xdotool fallback — AT-SPI2 is the primary API. For
GTK4 apps that return
(0,0)for all coordinates, the agent offsets viaxdotoolwindow search +_GTK_FRAME_EXTENTS(requiresWaylandEnable=falsein GDM). - No build — ships as Python source. A wrapper script invokes
python3 -m testanyware_agent.
Endpoint wiring
Routing lives in server.py:
GET /health
POST /windows, /snapshot, /inspect
POST /press, /set-value, /focus, /show-menu
POST /window-focus, /window-resize, /window-move, /window-close, /window-minimize
POST /wait
POST /exec, /upload, /download, /shutdown
Wire shapes are documented in docs/architecture/agent-protocol.md.
Build / test / run
No build step. Installed into the Linux golden image as Python
source; started by a systemd user service
(testanyware-agent.service).
cd agents/linux
python3 -m testanyware_agent # run locally for dev
python3 -m unittest discover testanyware_agent # (unit tests if present)
Systemd unit (installed by the golden-image script):
systemctl --user start testanyware-agent.service
systemctl --user status testanyware-agent.service
journalctl --user -u testanyware-agent.service
Common pitfalls
- Wayland vs X11. AT-SPI2 works on both, but
xdotool(used for window coordinate fallback) does not work on native Wayland sessions. The golden image forces X11 viaWaylandEnable=false. - Python 3.12+ required.
pyatspibindings match the system Python; don't try to run this inside a venv with a different version. - Electron apps render black. See
docs/user/troubleshooting.md. Launch with--disable-gpu. - Role mapping lives in code. Any addition to the host-side
UnifiedRoleenum needs a corresponding mapping inrole_mapper.py; otherwise the agent returnsunknown.