Repository navigation
chore: bump @metamask/device-mcp to ^0.6.0 - #69
Merged
cryptotavares merged 1 commit intoOct 29, 2026
Merged
cryptotavares merged 1 commit into
cryptotavares merged 1 commit into
Conversation
0.6.0 adds: - iOS: read the nested `idb ui describe-all` format, so the element tree keeps its hierarchy (MetaMask/device-mcp#38). - Android: the default snapshot mode is now `helper-first`. The ADB backend installs a signed test-only helper APK on the device on first use (`adb install -t`, then a signer check) and captures without waiting for idle, with `uiautomator dump` as the fallback. This is faster and correct on busy screens, where `uiautomator dump` times out or returns "could not get idle state" (MetaMask/device-mcp#39). `DEVICE_MCP_ADB_SNAPSHOT=dump` keeps the old behaviour. The flat mobile tree (`feat!: flat mobile a11y tree without layout-only nodes`) and the mobile snapshot changes (`feat: filter mobile status/nav bars and dev overlay`) were measured against these device-mcp changes. Core does not use the new `snapshotMode`, `source` or `captureMs` fields. The README notes the helper install and the opt-out.
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
cryptotavares
marked this pull request as ready for review
October 28, 2026 13:37
itsyoboieltr
approved these changes
Oct 28, 2026
This was referenced Oct 28, 2026
cryptotavares
added a commit
that referenced
this pull request
Oct 29, 2026
…TimeoutMs cap (#71) > **Summary:** Fix the review comments on #62, #64 and #65 in one PR on top of the stack. The approved PRs stay unchanged. **Stack context:** mm CLI v2, Phase 1, **P1-43**. Base: [#69](#69), the top of the stack. ## Problem | Comment | Problem | |---|---| | [#65: off-screen animations](#65 (comment)) | The browser settle ignored animations whose target was outside the viewport or had zero size. A drawer sliding in, a bottom sheet or an accordion opening from height 0 start that way, so the observation caught them mid-move. | | [#64: late click](#64 (comment)) | `click` / `type` checked the request signal only before the target wait. When the request timed out during the wait, the agent got "timed out", but the click still ran once the target appeared. | | [#64: batchTimeoutMs](#64 (comment)) | `batchTimeoutMs` accepted up to 300 s, but the queue and the CLI stop `run_steps` after 30 s. | | [#62: refs after `none`](#62 (comment)) | `--observe none` does not refresh refs; some refs can then click a different element. Not documented. | | [#62: reads and animations](#62 (comment)) | Reads do not wait for animations, even with `--observe full`. Not documented. | ## Solution ```mermaid flowchart TD A[click / type] --> B[Wait for target] B --> C{Request timed out?} C -->|yes| D[MM_REQUEST_ABORTED, no action] C -->|no| E[Click / tap / type] E --> F[Mutating observation] F --> G[Wait for every running finite animation, max 1 s] G --> H[Read tree] classDef new fill:#fff3cd,stroke:#d39e00 class C,D,G new ``` Yellow boxes are new or changed. ## What changes | Commit | Change | |---|---| | `fix: wait for animations that start off screen or at zero size` | `animationsSettled` waits for every running, finite animation of an element. Infinite animations are still ignored; the 1 s cap is unchanged. | | `fix: do not click or type after the request timed out` | `IPlatformDriver.click` / `type` take an optional `signal`. Both drivers call `signal.throwIfAborted()` after the target wait, right before the action (mobile `type` also after the focus tap). The tools pass `context.signal` and return `MM_REQUEST_ABORTED`. | | `fix!: cap run_steps batchTimeoutMs at 30 s` | Schema range 1000–30000, like the `cdp` `timeoutMs`. | | `docs: …` | README, SKILL.md and CLI help: refs after `--observe none`, reads and animations, abort limits, `batchTimeoutMs`. | ## Decisions for reviewers | Decision | Reason | |---|---| | One new PR instead of changing #62/#64/#65 | Pushing to an approved PR dismisses its approval, and the restack would change every PR above it. | | An action that already started is not cancelled | `@metamask/device-mcp` takes no signal (`waitForElement`, `tapElement`, `typeText`), and Playwright's actionability checks are part of `locator.click`. The driver checks the signal between steps. Cancelling inside device-mcp needs a device-mcp change (follow-up). | | Cap `batchTimeoutMs` at 30 s instead of raising the request budget for batches | Matches the CLI and queue default; long flows can be split into several batches. | | Reads stay without the animation wait (docs only) | It is a less exact snapshot, not a wrong action. Can be revisited. | | The 5 s testId collection cap stays | Agreed with the reviewer: watch real usage first. | ## Breaking changes `run_steps` rejects `batchTimeoutMs` above 30000 (validation error), also when a server raised `requestTimeoutMs`. ## Review guide | # | File | What to check | |---|---|---| | 1 | `src/tools/utils/in-page.ts` | `animationsSettled` without the viewport/size filter. | | 2 | `src/platform/playwright-driver.ts`, `src/platform/mobile-platform-driver.ts`, `src/platform/types.ts` | `throwIfAborted()` placement. | | 3 | `src/tools/interaction.ts` | Signal passed; abort mapped to `MM_REQUEST_ABORTED`. | | 4 | `src/validation/schemas.ts` | `batchTimeoutMs` range and description. | | 5 | `README.md`, `SKILL.md`, `src/cli/mm.ts` | Docs. | <details> <summary>Testing</summary> `yarn test`: 51 files, 1809 tests pass. `yarn lint` passes. Each commit passes the tests on its own. **Extension** (e2e fixture wallet, headless), before = #69, after = this branch: | Check | Before | After | |---|---|---| | Drawer sliding in from off screen (400 ms): observationMs | 515–516 (did not wait) | 914–929 (waited) | | Accordion from height 0 (400 ms): observationMs | 515–516 | 916–917 | | Home click observationMs | 513–514 | 512–515 | | Send / account list click observationMs | 12–183 / 14–164 | 14–212 / 15–164 | | `run_steps` click whose target appears 1 s after the 30 s queue timeout | **clicked** | **not clicked** | **Android** (device-mcp 0.6.0, real funds, benign taps): all smoke and ref checks pass, same as #69. **iOS** (device-mcp 0.6.0, real funds, benign taps): all smoke and ref checks pass, same as #69. (A first attempt hit the stale idb companion after a simulator reboot, `dtuhidd connection ... invalidated`; fixed by restarting the companion. See MetaMask/device-mcp#43 and #70.) </details>
cryptotavares
added a commit
that referenced
this pull request
Oct 29, 2026
> **Summary:** Upgrade `@metamask/device-mcp` to `^0.7.0`. 0.7.0 declares `DeviceBackend.dispose()`, so the mobile driver calls it without a type cast. iOS sessions get private IDB companion teardown and recovery. ## Problem Core pins `@metamask/device-mcp` `^0.6.0`. On 0.x a caret range does not pick up 0.7.0. - The `DeviceBackend` type in 0.6.0 has no `dispose()`. #70 therefore calls the hook through a structural cast in `MobilePlatformDriver.dispose()`. - The README says core "does not update the core dependency range" and that older device-mcp versions stay compatible. That text was correct before 0.7.0 was released. ## Solution Adopt the device-mcp 0.7.0 release. Remove the cast and the temporary README text. 0.7.0 contains: - [device-mcp#43](MetaMask/device-mcp#43): optional `DeviceBackend.dispose()` and `reconnect()`, one private IDB companion per iOS backend, and recovery when the companion or the simulator HID connection is lost. - [device-mcp#44](MetaMask/device-mcp#44): correct recovery error reporting, and no resend of commands that can change the device. - [device-mcp#42](MetaMask/device-mcp#42): Android clipboard helper. ```mermaid flowchart TD A[mm cleanup / launch --force / stop] --> B[DriverLifecycle] B --> C[MobilePlatformDriver.dispose] C --> D{backend.dispose?} D -->|IdbBackend 0.7.0| E[Stop the private companion and recording] D -->|AdbBackend: no hook| F[Nothing to release] classDef new fill:#fff3cd,stroke:#d39e00 class C,E new ``` Yellow boxes change: the driver calls the typed hook, and the 0.7.0 iOS backend releases its companion. ## What changes | Boundary | Before | After | |---|---|---| | `package.json` dependency range | `@metamask/device-mcp ^0.6.0` | `^0.7.0` | | `yarn.lock` resolution | npm 0.6.0 | npm 0.7.0 (dependencies unchanged) | | `MobilePlatformDriver.dispose()` | Casts the backend to `DeviceBackend & { dispose?() }` | Calls `this.#backend.dispose?.()` on the typed `DeviceBackend` | | `README.md` teardown paragraph | Older device-mcp versions are compatible; the range is not updated | Core requires 0.7.0 or later; iOS releases its companion; Android has no hook | | Disposal test name | "supports device-mcp versions without disposal" | "completes for backends without a disposal hook" | ## Decisions for reviewers | Decision | Reason | |---|---| | Keep the optional call `dispose?.()` | `dispose()` is still optional in the 0.7.0 `DeviceBackend` type. `IdbBackend` implements it; `AdbBackend` and `AppiumBackend` do not. | | Keep the test for a backend without the hook | It now covers the ADB backend, not an older device-mcp version. | | Async IIFE instead of `Promise.resolve().then(...)` | Same behaviour, simpler, and the same style as device-mcp. | | `chore:`, not breaking | Core's own API does not change. Every symbol core imports from device-mcp still exists. The `selectDevice()` break in 0.7.0 is on `LazyDeviceBackend`, which core does not use. | | No changelog entry | Matches the previous bump (#69). | ## Review guide | # | File | What to check | |---|---|---| | 1 | `package.json`, `yarn.lock` | The range is `^0.7.0`. Only the device-mcp entry and the workspace range change. | | 2 | `src/platform/mobile-platform-driver.ts` | The cast is gone. Shared concurrent disposal and retry after failure are unchanged. | | 3 | `README.md` | The teardown paragraph under "Session-scoped device teardown". | | 4 | `src/platform/mobile-platform-driver.dispose.test.ts` | Only the test name changes. | <details> <summary>Testing</summary> Device-mcp 0.7.0 is installed from npm, without yalc. - `yarn build` passes. - `yarn lint` passes, including ESLint, formatting, constraints, dependency and dedupe checks, and changelog validation. - `yarn test` passes: 53 files and 1,835 tests. Typechecking and coverage thresholds pass. Thresholds are unchanged. - `tsc --noEmit -p tsconfig.test.json` reports 8 errors on `main` and 8 on this branch. All 8 already exist on `main`. - In the installed package, `dist/backends/types.d.mts` declares `dispose?(): Promise<void>` and `reconnect?(): Promise<void>` on `DeviceBackend`. `IdbBackend` declares `dispose()`; `AdbBackend` and `AppiumBackend` do not. No device run for this PR. The live teardown and recovery checks are in device-mcp#43 and #70, and they used the same code. </details>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack context: mm CLI v2, Phase 1, P1-30. Base: #68, the top of the stack; review that first.
Problem
Core pins
@metamask/device-mcp^0.5.0(#58). On 0.x a caret range does not pick up 0.6.0. Without 0.6.0:idb ui describe-allformat, so the element tree loses its hierarchy (device-mcp#38).uiautomator dump. On busy screens this waits about 11 s for an idle state, then fails with "could not get idle state" (device-mcp#39).#44 (flat mobile tree) and #67 (mobile snapshot filtering) were measured against yalc builds of those two device-mcp PRs.
Solution
Adopt the device-mcp 0.6.0 release through the dependency range and the lockfile. Add one README sentence about the new Android helper install.
flowchart TD A[Mobile describe / observation] --> B[Core MobilePlatformDriver] B --> C{device-mcp 0.6.0 snapshot} C -->|iOS| D[idb describe-all, nested format read] C -->|Android default helper-first| E[Signed helper APK, no idle wait] E -->|non-trust failure| F[1 uiautomator dump attempt] D --> G[Core flat tree, refs, testIds] E --> G F --> G classDef new fill:#fff3cd,stroke:#d39e00 class D,E,F newYellow boxes are new in 0.6.0.
What changes
package.jsondependency range@metamask/device-mcp ^0.5.0^0.6.0yarn.lockresolutionuiautomator dumpfirstDEVICE_MCP_ADB_SNAPSHOT=dumprestores the old pathREADME.mdDecisions for reviewers
chore:, not breakingSnapshotResultonly gains optional fields (source,captureMs), and core reads onlyhierarchy. The new Android default is a dependency runtime change on the consumer's backend, not a change to core's API.snapshotModeDeviceBackend(Mobile usesAdbBackenddirectly). Core only documents the default and the opt-out.Review guide
package.json^0.6.0.yarn.lockREADME.mdTesting
Unit and lint (at afaf75c, device-mcp 0.6.0 from npm, no yalc):
yarn buildOK,yarn test51 files / 1793 tests pass,yarn lintpasses (including the dedupe and constraints checks).Device proof: Mobile with this branch's core (yalc) and device-mcp 0.6.0 from npm (no yalc device-mcp). Real-funds wallets; only read actions, tab bar Home/Explore, account list open/back and settings list (no row opened).
Node counts are identical to the yalc device-mcp measurements used for #44 (
measure-tree.sh):Android helper path: the emulator had helper 0.5.0. On the first snapshot, device-mcp 0.6.0 installed its bundled, signed 0.6.0 helper, and the signer check passed. During the smoke run, logcat shows 106 helper runs and 0
uiautomatorruns.Known and unchanged: on Android, 3 of 4 navigation observations still show the previous screen (same as before this bump). That is tracked separately.