mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
codex/runner-diagnostics-proxy-docs
11 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c32249503b |
test: cover least-tested parsing modules + verify public exports reach npm; drop dead daemon barrels (#749)
* test: cover least-tested CLI grammar and config parsing modules Add focused unit tests for the modules the coverage report flagged as least covered, exercising real behavior rather than padding metrics: - utils/source-value: env/config value parsing (booleans, enums, enum flags with setValue, int bounds, multiple) — 42% -> 100% lines - commands/cli-grammar/gesture: CLI<->daemon gesture argument translation for every gesture kind incl. error paths — 41% -> 100% - commands/cli-grammar/system: back/rotate/keyboard/clipboard/ react-native readers and writers incl. validation — 57% -> 100% - core/device-rotation: orientation parsing with aliases/errors — 100% - core/dispatch-payload: push payload loading from inline JSON and files, with temp-file I/O and JSON/shape error handling https://claude.ai/code/session_018i1mhcSe6sqM4mKLUKgYXe * chore: gitignore generated coverage report directory https://claude.ai/code/session_018i1mhcSe6sqM4mKLUKgYXe * test: verify public exports reach the npm build; drop dead daemon barrels Strengthen the package-exports test so it verifies the real publish-time invariant: every package.json "exports" subpath maps to a configured rslib build entry that points at an existing source module which actually exposes named exports. This catches a subpath being added to package.json without a matching build entry (which would ship a broken import), and keeps import/types targets in lockstep. Remove four internal re-export barrels under src/daemon that were pure 1:1 forwarders to their src/utils source, and repoint all importers at the real module so it is obvious where the code lives: - daemon/is-predicates.ts -> utils/selector-is-predicates.ts - daemon/selectors-build.ts -> utils/selector-build.ts - daemon/snapshot-diff.ts -> utils/snapshot-diff.ts - daemon/snapshot-processing.ts -> utils/snapshot-processing.ts The curated daemon/selectors.ts facade is kept; only blind forwarders were removed. No behavior change. https://claude.ai/code/session_018i1mhcSe6sqM4mKLUKgYXe --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
45cfad5cc5 |
feat: e2e command perf benchmark harness + nightly CI (#630)
* feat: add e2e command perf benchmark harness + nightly CI Adds scripts/perf, a cheap end-to-end perf benchmark that drives the built CLI through an ordered Settings tour of ~24 commands for N rounds, on a fully isolated daemon/state-dir and self-cleaning device, and emits JSON + Markdown reports. Per-command timing comes from wrapping each batchable command in its own single-step batch (daemon durationMs) plus wall-clock around the process. Wires a scheduled + workflow_dispatch CI job (perf-nightly.yml) that reuses the cached iOS XCUITest runner (setup-apple-replay) and the Android replay host, and runs the CLI from source via --experimental-strip-types (no dist build). * refactor(perf): drive the harness CLI via runCmdSync, not spawnSync Review (P2): repo rule is to spawn processes through src/utils/exec.ts, not node:child_process directly. Switch the perf harness's invokeCli to runCmdSync (allowFailure so non-zero exits are recorded as samples) and add a maxBuffer option to ExecOptions/runCmdSync (snapshot payloads exceed Node's ~1MB default). * perf(harness): warm the runner after open so the first measured command is clean The first interaction after open/relaunch pays the one-time iOS XCUITest runner startup (~10s+ cold) and a per-relaunch first-AX-query settle cost (~4s). That was landing on the first measured command each round (snapshot -i), inflating it ~10x vs the next snapshot. Run an untimed warmup snapshot -i after establishSession, after each round's reset-open, and after every freshRoot relaunch, so no measured command absorbs runner startup. Noted in the report header. * refactor(perf): address review + fix Fallow CI - exec.ts: extract spawnRejectionError + commandCloseFailure helpers, deduping the error/close handler clones (Fallow duplication ✗ that surfaced once the maxBuffer change pulled exec.ts into the audit scope). - .fallowrc: exclude scripts/perf/** (non-shipped benchmark tooling, like examples/ test-app) so its naturally-moderate functions don't trip the complexity gate. - config.ts: drop unused exports CLI_BIN/DEFAULT_OUT_DIR; add readIntValue so --n/--rounds/--warmup report the actual flag + reject non-integers clearly. - harness.ts: extract toSample(); type sampleError param as CliResult. - scenario.ts: ScenarioStep is now a discriminated union on execMode (removes step.step!/ step.args ?? []). - comment/legend rewords (platform defaults are local-convenience/CI-overridden; elements = node count). check:fallow now green; typecheck/lint/unit pass. * perf(harness): downgrade sample ok when a batch step reports ok:false Defensive belt-and-suspenders for the Codex review note: stop-only batch already surfaces a failed step as a top-level failure (caught by invokeCli), but if an on-error=continue mode ever keeps the batch ok while a step fails, don't silently count that step as a successful sample — derive ok from the step's own result.ok. |
||
|
|
47b981c8ad |
feat: add gesture command coverage (#576)
* feat: add gesture command coverage * fix: align iOS fling provider fixture * feat: group gesture commands * fix: clarify android gesture support * feat: add android multitouch gestures * fix: address gesture review feedback * refactor: simplify gesture plumbing * fix: keep gesture subcommands internal * fix: update iOS provider pan transcript |
||
|
|
d77a9211ab |
feat: add Android snapshot helper (#454)
* feat: add android snapshot helper * fix: harden android snapshot helper packaging * fix: harden android xml attribute parsing * fix: capture android helper window roots * fix: validate android helper install args * fix: harden android helper manifest and traversal * refactor: drop unused helper timeout parameter * feat: bundle android snapshot helper in npm package * feat: enable bundled android snapshot helper by default * refactor: simplify android snapshot helper resolution * fix: harden android snapshot helper artifacts * refactor: split android snapshot helper modules * fix: use type-only snapshot helper imports |
||
|
|
7c5b7670c8 | feat: add skillgym tests (#453) | ||
|
|
f07e82e308 |
chore: add fallow quality gate (#449)
* chore: add fallow quality gate * fix: refresh pnpm lockfile |
||
|
|
caf0e834b8 |
feat: add Linux desktop automation support via AT-SPI2 (#356)
* feat: add Linux desktop automation support via AT-SPI2 (Phase 1+2) Add Linux as a first-class platform using AT-SPI2 accessibility framework via node-gtk for accessibility tree snapshots. This mirrors the macOS desktop automation approach using accessibility snapshots. New files: - src/platforms/linux/atspi-bridge.ts: Core AT-SPI2 bridge using node-gtk with lazy loading, recursive tree traversal (max 1500 nodes, depth 12) - src/platforms/linux/role-map.ts: AT-SPI2 role normalization (~100 roles mapped to existing snapshot type conventions) - src/platforms/linux/snapshot.ts: Snapshot entry point with surface, scope, depth, and interactive-only filtering support - src/platforms/linux/devices.ts: Local device discovery for Linux - src/platforms/linux/node-gtk.d.ts: Type declarations for node-gtk Integration: - Extended Platform type with 'linux', backend union with 'linux-atspi' - Wired snapshot into dispatch.ts and snapshot-capture.ts - Added Linux device discovery to dispatch-resolve.ts - Added stub interactor (input actions deferred to Phase 3) - Added 'linux' to CLI --platform flag - node-gtk added as optional dependency (only installs on Linux) https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * refactor: code review cleanup for Linux platform support - Extract SnapshotBackend type alias to replace repeated string union across 5 files (snapshot.ts, snapshot-capture.ts, session-replay-heal.ts, interaction.test.ts) - Remove duplicate scope/interactive/depth filtering from linux/snapshot.ts — let the existing buildSnapshotState pipeline handle it, same as Android - Extract isDesktopBackend() helper in snapshot-capture.ts to consolidate the "skip mobile semantics" pattern for macos-helper and linux-atspi - Collapse 17 repetitive throw statements in Linux interactor stubs into a linuxStub() factory function https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * feat: Linux input synthesis, screenshots, and app lifecycle (Phase 3+4) Add xdotool/ydotool input actions (tap, swipe, scroll, type, fill, right/middle click, long press, double click), screenshot capture via grim/scrot, and app lifecycle management (open, close, back, home). Wire Linux interactors with real implementations and fix device discovery order so Linux doesn't displace Android in auto-selection. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * refactor: consolidate Linux env detection, simplify input actions - Extract linux-env.ts with cached display server + input tool detection so every action avoids repeated `which` lookups - Add moveTo/clickButton/sendKey helpers to eliminate repeated mousemove boilerplate across 5 mouse actions - Make scrollLinux respect amount/pixels options instead of hardcoded scroll count - Have backLinux/homeLinux reuse sendKey instead of duplicating tool detection https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * feat: add Linux CI smoke test with Xvfb and AT-SPI2 Add GitHub Actions workflow that boots a virtual X11 display (Xvfb), installs AT-SPI2 accessibility tooling and xdotool, opens gnome-calculator, takes screenshots, and captures an accessibility snapshot. Screenshots are uploaded as artifacts for visual verification. Also adds 'linux' to replay script metadata platforms and a test:replay:linux script to package.json. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * fix: remove pre-session screenshot from Linux replay test The replay runner requires an active session before any commands can run. Move the screenshot after the open command that creates the session. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * fix: Linux CI — add missing node-gtk build deps and AT-SPI2 env - Add gobject-introspection, libcairo2-dev, build-essential for node-gtk native compilation - Split AT-SPI2 registry start into its own step so it picks up DBUS_SESSION_BUS_ADDRESS from GITHUB_ENV - Set GTK_A11Y=atspi, GTK_MODULES=gail:atk-bridge, NO_AT_BRIDGE=0 to ensure GTK apps expose their accessibility tree on headless CI - Set GSETTINGS_BACKEND=memory to avoid dconf failures - Add node-gtk verification step to catch build failures early https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * fix: explicitly rebuild node-gtk native module in Linux CI pnpm install silently skips failed optional dependency builds and the pnpm cache may not include the native binary. Force a rebuild after install to ensure the node-gtk .node binding is compiled against the system GI/cairo headers. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * fix: use node-pre-gyp directly to build node-gtk from source pnpm rebuild doesn't trigger node-pre-gyp properly for optional deps. Run node-pre-gyp install --fallback-to-build --update-binary directly inside the node-gtk package directory to force compilation when no prebuilt binary exists for the current Node ABI (v127 / Node 22). https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * refactor: replace node-gtk with Python subprocess for AT-SPI2 node-gtk is a native C++ addon that requires compilation against specific Node ABI versions and GObject Introspection headers. This proved unreliable on CI (no prebuilt binaries for Node 22 ABI v127, silent optional dep build failures, pnpm cache staleness). Replace it with a Python helper script (atspi-dump.py) that uses PyGObject — the reference GObject Introspection consumer. python3-gi is trivially installable on any Linux distro with no compilation step. The Node bridge spawns `python3 atspi-dump.py` and parses JSON output. - Remove node-gtk from optionalDependencies - Remove node-gtk.d.ts type stub - Add atspi-dump.py (~200 lines) doing the same tree traversal - Rewrite atspi-bridge.ts to use subprocess instead of in-process GI - Simplify CI workflow: no more native build deps or rebuild steps https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * chore: drop pre-installed packages from Linux CI apt-get python3-gi, gir1.2-atspi-2.0, at-spi2-core, and dbus-x11 are already present on Ubuntu GitHub Actions runners. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * feat: surface support for Linux, unit tests, stronger CI assertions - Allow --surface desktop and --surface frontmost-app on Linux (previously only macOS could use --surface) - Add unit tests for atspi-bridge (9 tests: JSON parsing, role normalization, null coercion, error handling, arg forwarding) - Add unit tests for role-map (3 tests: common roles, case normalization, PascalCase fallback) - Improve .py script path resolution (walk upward instead of hardcoded relative paths) - CI replay test now asserts snapshot contains calculator UI nodes via is-exists https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * docs: add cross-platform snapshot traversal contract Document the shared schema, traversal rules, surface semantics, and normalized role types that all snapshot backends (Swift, Python, Android) must conform to. This serves as the single source of truth when adding or modifying platform backends. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * fix: update lockfile after removing node-gtk optional dependency pnpm-lock.yaml still referenced node-gtk after it was removed from package.json, causing pnpm install --frozen-lockfile to fail in CI. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * fix: address review findings in Linux platform code - atspi-dump.py: use ctx dict for traversal limits instead of globals, fix rect filter (width/height <= 0 should use `or`), add surface validation - input-actions.ts: make sendKey scancodes required to prevent silent no-op on ydotool, fix ydotool longPress/swipe to use click --down/--up - app-lifecycle.ts: use pkill -x (exact match) instead of pkill -f - linux-env.ts: emit diagnostic warning when falling back to xdotool on Wayland https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * fix(ci): explicitly install all Linux a11y dependencies Ubuntu runners may not have at-spi2-core, python3-gi, gir1.2-atspi-2.0, or dbus-x11 pre-installed. Install them explicitly instead of assuming they exist. Also make the verify step's tree dump non-fatal since no apps are running at that point. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * fix: quote multi-word role value in Linux smoke test selector The selector parser tokenizes on whitespace, so `role=push button` was split into two tokens causing a parse failure. Use single quotes inside the selector: `role='push button'`. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * fix: use valid selector keys in Linux smoke test appName is not a valid selector key. The supported keys are: id, role, text, label, value, visible, hidden, editable, selected, enabled, hittable. Simplified to use label and role only. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * chore: cleanup pass — menubar warning, fix contract doc example - snapshot.ts: emit diagnostic warning when menubar surface is requested on Linux (falls back to desktop silently otherwise) - SNAPSHOT_CONTRACT.md: fix unmapped role example to use a role that isn't actually mapped (was "color chooser" which maps to Dialog) https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * chore: add Python bytecache to gitignore https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * feat: harden Linux platform — capability matrix, CI, error handling P0: Add explicit Linux capability matrix with 3-way platform routing (Apple/Linux/Android) in isCommandSupportedOnDevice. Linux now correctly blocks unsupported commands (clipboard, rotate, scrollIntoView, etc.) at capability level rather than throwing at runtime. Includes tests. P0: Expand Linux CI to run typecheck + unit tests before smoke tests. Add AT-SPI2 registry health probe with fail-fast on missing registry. P1: Harden atspi-dump.py — arg parsing now produces JSON errors on bad int values, and a top-level catch wraps unexpected exceptions in JSON. P1: Add 10s per-action timeout to xdotool/ydotool input commands to prevent indefinite hangs. P1: Tighten smoke test selectors to calculator-specific signals (digit labels) instead of generic role='push button'. P2: Document Linux surface mapping, supported commands, and known limitations in SNAPSHOT_CONTRACT.md. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * fix: apply depth/interactive filtering to Linux snapshots Linux snapshots were bypassing snapshotInteractiveOnly and snapshotDepth filtering that macOS-helper gets via shapeDesktopSurfaceSnapshot. Route Linux through the same function so snapshot -i and --depth flags work. Renamed shapeMacOsSurfaceSnapshot → shapeDesktopSurfaceSnapshot since it's now shared between macOS and Linux desktop backends. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * fix: address review findings — error reporting, Wayland, timeout - app-lifecycle.ts: emit diagnostic on fire-and-forget app launch failure instead of silently swallowing errors - linux-env.ts: make xdotool on Wayland a hard error instead of a broken fallback (xdotool doesn't work on Wayland) - atspi-bridge.ts: increase Python subprocess timeout from 15s to 30s for safety on slow/loaded systems with large a11y trees https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * feat: appName/windowTitle selectors, clipboard, input-action tests Selectors: - Add appname and windowtitle as selector keys for desktop platforms. Both macOS and Linux snapshots already populate these fields — now they're usable in selector expressions (e.g., "label=OK appname=Calc"). Keys are case-insensitive. Clipboard: - Implement readLinuxClipboard/writeLinuxClipboard using xclip/xsel (X11) or wl-copy/wl-paste (Wayland) with descriptive TOOL_MISSING errors. Enable clipboard in Linux capability matrix. 7 unit tests. Input action tests: - Add 18 unit tests covering xdotool and ydotool code paths: press, right/middle click, double click, sendKey, type, scroll, swipe, focus, fill. Tests mock runCmd and verify correct tool + args. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT * chore: cache tool detection for screenshot/clipboard, extract get_app_info helper Avoid repeated `which` calls on every screenshot/clipboard operation by caching the resolved tool on first use, matching the input-action pattern. Extract duplicated app_name/pid retrieval in atspi-dump.py into get_app_info. https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
d1d2f3852a |
refactor: migrate leaf modules from test-only DI to vitest mocking (#289)
* refactor: migrate leaf modules from test-only DI to vitest mocking Drop optional DI parameters from 6 production modules that existed solely as test seams. Replace with vi.mock() in new vitest test files. Production files simplified: - recording-telemetry.ts: remove writeTelemetry? - find.ts: remove dispatch?, use dispatchCommand directly - install-source.ts: remove entire deps? object (7 params) - session-runtime-command.ts: remove clearRuntimeHints? - android-system-dialog.ts: remove 4 DI params, simplify internals - record-trace-recording.ts: remove writeRecordingTelemetry from deps Closes #281 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: restore DI seams broken by premature removal, fix test script - request-router.ts: remove 4 dead DI params (snapshotAndroidUi, reopenAndroidApp, readAndroidAppState, execCommand) from RequestRouterDeps since recoverAndroidBlockingSystemDialog no longer accepts them - session-runtime-command.ts: restore clearRuntimeHints? param that handleSessionCommands threads through — removing it broke callers that override the seam - session.ts: restore clearRuntimeHints pass-through to runtime branch - session.test.ts: restore the end-to-end runtime clear DI test - package.json: include vitest in the default `test` script Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: rename *.vitest.test.ts → *.vitest.ts to avoid node:test collision Node's default test discovery matches *.test.ts, which picked up vitest files and crashed. Rename to *.vitest.ts so the two runners have disjoint file sets without needing find-based exclusions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use vi.mocked().mock.calls instead of module-level mutable state Replace manual clearCalls array with direct assertion on the mock, consistent with the pattern used in request-router-android-modal.vitest.ts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
3ddd3a1ef5 |
Complete issue #39 boot diagnostics, telemetry, and boot command (#46)
* Complete issue #39 phase diagnostics telemetry and boot command * Address review findings for boot diagnostics and command gating * Use agent-device boot preflight in iOS CI workflow * Run iOS boot preflight via source CLI in CI |
||
|
|
fb53d72b63 | feat: AX snapshot goes brrrr | ||
|
|
4da4745a6c | initial commit |