Repository navigation
feat(hardware-key): press volume, power, media, and TV keys on Android - #3817
mikolajadamowicz wants to merge 21 commits into
Conversation
31a9dc2 to
3204bcf
Compare
|
Rebased onto current main. Head is One lint failure is left and I want your call before touching it. #3804 pinned A new command has to add its descriptor to How do you want new commands to land under the new cap? Options I see: raise the cap here, split the registry first as a separate PR, or something else. I didn't want to move a cap you set this morning on my own. Everything else I could run locally is green: typecheck passes, and the gate stops at this one lint error. |
|
Thanks for the PR. I found no code defects at 3204bcf, but it is not ready yet: two CI failures come from this diff, and I have a design question at the end. The live ADB run on phone and TV emulators is as you reported it; I did not reproduce it. No conflicts. Two checks fail, and the diff causes both. Lint fails because the +12 lines in packages/command-registry/src/registry.ts take the file from 2179, exactly the cap, to 2191. Integration fails because Before merge, please add a provider-scenario test for Not blocking: the six dropped suppressions in src/client/client-types.ts are unrelated to hardware-key, and I did not confirm they were stale. Could |
Add `agent-device hardware-key <key>` and `client.command.hardwareKey()`: one press of a volume (`volume-up`, `volume-down`, `mute`), power (`power`, `sleep`, `wake`), or media (`media-play-pause`, `media-next`, `media-previous`, `media-rewind`, `media-fast-forward`) key. It covers QA checks such as volume and mute handling, standby and wake during playback, and media-key handling in a video-streaming app. Android emulators and devices send the key as `adb shell input keyevent` with the numeric KeyEvent code, locally and on Limrun Android sessions, which ride the same Android interactor as `home` and `app-switcher`. The key vocabulary and its Android keycodes sit beside the TV remote table in `contracts/tv-remote.ts`, and the press joins the system-button family as its one control with an argument, so every owner that does not name the cell refuses it with that family's denial. Both homes are modules the CLI, daemon, and runtime closures already evaluate, so no eager closure grows. The Apple runner exposes only the home and Action Button presses, so iOS, tvOS, and macOS refuse the key, as do web, Linux, Vega OS, HarmonyOS, Limrun iOS, and the WebDriver (Appium) backend. Like `action-button`, the command declares no post-action observation: the key goes to the system and the media session, and power or sleep leaves the display off. Session events summarize the press with its key, and `help tv` points Android TV playback checks at it.
…ables The six-platform coverage declaration and its Android and Apple evidence rows, the runtime-binding conformance table, and the Apple provider output guard's driven set enumerate the public surface, so each one names `hardware-key`.
The generic dispatcher grew a dedicated hardware-key arm, which with the telephony and uninstall arms from main put resolveGenericRuntimeExecution past the cyclomatic bar. The system-button module now owns one entry point for its no-argument buttons and its keyed control, so the dispatcher keeps a single arm for the family, and the request positionals are read once instead of per arm.
Add channel-up, channel-down, last-channel, guide, info, captions, tv-input, and the four color keys to `hardware-key`. Each name maps to its standard Android KeyEvent keycode (166, 167, 229, 172, 165, 175, 178, 183-186), so a QA run on a streaming app's Android TV build can drive the channel and program-guide buttons a TV remote sends. `tv-remote` has none of them.
Vendor Android TV remotes carry buttons that no standard KeyEvent name covers, such as operator-specific channel or app keys. `hardware-key android-keycode:<n>` sends keycode n (1 to 2147483647) through the same `input keyevent` path as the named keys, so such a button can be driven without leaving agent-device for a raw adb call, and the press still lands in the session log and in replay scripts as a positional. The token rides the existing `key` input instead of a new flag: the parser, the Android keycode mapping, and the session-log reader each accept it, and the MCP input becomes a described string, because the schema vocabulary has no way to express "one of these names or this pattern". This commit stands alone and can be dropped without touching the rest of the command.
…ption The help topic and command description hand-listed keys the HARDWARE_KEY_DEFINITIONS table owns; the topic copy already omitted power, sleep, and wake. Render HARDWARE_KEY_USAGE instead and keep only what the usage line cannot say.
…ation Move the key vocabulary to contracts/hardware-key.ts and give hardwareKey its own operation, facts, and binder beside tv-remote. The daemon routes it through its own case in generic-runtime-execution, so the system-button family keeps one no-argument row per command.
…sKey Android admits hardware-key through the same route the keyboard Enter press uses. XCUITest has no key press, so the iOS leg still refuses.
Fallow reports no unused-type issue under these directives, so the gate charges the branch for them once client-types joins its change set. Verified stale on origin/main with the file alone in scope: removing the directives leaves the re-exports and the published surface unchanged.
…remote modules The CLI command metadata, the interactor catalog, and the unavailable-facts hub read the key table and binder synchronously, so a dedicated module grows each eager closure past its merge-base budget. tv-remote.ts and tv-remote-runtime.ts already sit in those closures. The Appium leg loads the keycode table on demand because its closure never reached tv-remote.
3204bcf to
ff08e4b
Compare
|
Rebased onto main 7861075. The head is Your two blockers
Design question
I didn't keep a dedicated The Appium Android leg now admits the key through Other changes
Live run at ff08e4b (Android TV emulator Local gate
|
…closure in budget
|
The earlier conflict is gone, and all 14 checks pass at 5ab777a. The earlier lint failure and the missing hardware-key provider scenario are fixed by the cap change in oxlint.config.ts and the new android-hardware-key test. One issue remains. The Appium Android support you added in 25e51da is not reflected in the help text. The hardware-key CLI detail still says "Android only (ADB key events, local or Limrun)", and the Apple refusal hint says the command is supported "through ADB key events". The docs at website/docs/docs/commands.md:131 already list Appium, so help and docs now disagree. Anyone who reads Not blocking, and you can take or leave these: the registry comment still calls hardwareKey a member of the system-button family, the I did not reproduce the Android TV emulator transcript, so I take it as you reported it for ff08e4b, which differs from this head only by a lazy import. I also did not run After the help text and hint name Appium Android alongside ADB, nothing else stops this merge. |
|
Head is now Help text and hints (32e4b08). Every hardware-key support statement now names the same backends that the runtime facts admit:
Not blocking (72d7e99). I took both:
Live Appium run. I couldn't do it. I have no BrowserStack, TestMu, or AWS Device Farm credentials, and no local Appium setup, so Gate at 72d7e99. |
Summary
Adds
hardware-key, a command that presses one hardware key. It accepts 22 named keys (volume, mute, power/sleep/wake, five media keys, channel/guide/info/captions/tv-input, and four color keys) plusandroid-keycode:<n>for vendor remote buttons that no name covers.tv-remotehandles D-pad navigation, but none of these keys had a route before, so agents fell back to rawadb shell input keyevent.hardwareKeyis its own keyed operation, with facts and a binder next totv-remoteand its own case ingeneric-runtime-execution. Local Android and Limrun Android sendinput keyevent <n>. Appium Android sendsmobile: pressKey. Every other owner refuses withUNSUPPORTED_OPERATION. About 520 production lines; the rest is tests, coverage tables, and docs.Validation
At 72d7e99 (on main 7861075). The device run was at ff08e4b. Later commits change only a lazy import, help text, and hints:
volume-downmoved stream 3 from 11 to 10,android-keycode:24moved it back to 11, andvolume-sidewaysreturnedINVALID_ARGS. Transcript is in the PR comments.android-hardware-key.test.ts.integration-progressreports 59/59.pnpm check:affected --run: everything passes except therunner-artifact-manifestsymlink tests, which fail the same way in a clean worktree. The fullunit-cisuite also passes locally apart from those tests and the matchingcode-signaturesymlink tests.mobile: pressKeyhas only the stub-client unit test.